o2.widget = o2.widget || {};
o2.xDesktop.requireApp("Template", "widget.ColorPicker", null, false);
o2.widget.Tablet = o2.Tablet = new Class({
Implements: [Options, Events],
Extends: o2.widget.Common,
options: {
"style": "default",
"path": o2.session.path+"/widget/$Tablet/",
"contentWidth" : 0, //绘图区域宽度,不制定则基础 this.node的宽度
"contentHeight" : 0, //绘图区域高度,不制定则基础 this.node的高度 - 操作条高度
"lineWidth" : 1, //铅笔粗细
"color" : "#000000", //画笔颜色
tools : [
"save", "|",
"undo",
"redo", "|",
"size",
"color", "|",
"reset",//,
//"clear" //橡皮
"cancel"
],
"description" : "", //描述文字
"action" : null, //uploadImage方法的上传服务,可选,如果不设置,使用公共图片服务
"method": "", //使用action 的方法
"parameter": {}, //action 时的url参数
"data": null, //formdata 的data
"reference": "", //uploadImage方法的使用 使用公共图片服务上传时的参数
"referenceType" : "", //使用公共图片服务上传时的参数, 目前支持 processPlatformJob, processPlatformForm, portalPage, cmsDocument, forumDocument
"resultMaxSize" : 0 //使用 reference 时有效
},
initialize: function(node, options, app){
this.node = node;
this.app = app;
this.reset();
this.setOptions(options);
this.path = this.options.path || (o2.session.path+"/widget/$Tablet/");
this.cssPath = this.path + this.options.style+"/css.wcss";
this.lp = {
save : "保存",
reset : "清空",
undo : "撤销",
redo : "重做",
size : "粗细",
color : "颜色",//,
//clear : "橡皮"
"cancel": "取消"
};
this._loadCss();
this.fireEvent("init");
},
load: function( ){
//存储当前表面状态数组-上一步
this.preDrawAry = [];
//存储当前表面状态数组-下一步
this.nextDrawAry = [];
//中间数组
this.middleAry = [];
this.container = new Element("div.container", {
styles : this.css.container
}).inject(this.node);
this.loadToolBar();
this.contentNode = new Element("div.contentNode", { styles : this.css.contentNode}).inject(this.container);
this.contentNode.addEvent("selectstart", function(e){
e.preventDefault();
e.stopPropagation();
});
this.loadDescription();
this.setContentSize();
if( this.checkBroswer() ){
this.loadContent();
}
//this.imageNode = new Element("img",{
//}).inject(this.contentNode);
//this.imageNode.setStyles({
// "display" : "none"
//});
if( this.app ){
this.resizeFun = this.setContentSize.bind(this);
this.app.addEvent( "resize", this.resizeFun );
}
},
loadDescription : function(){
if( this.options.description ){
this.descriptionNode = new Element("div",{
"styles": this.css.descriptionNode,
"text": this.options.description
}).inject( this.container )
}
},
setContentSize : function(){
var nodeSize = this.node.getSize();
this.contentWidth = this.options.contentWidth || nodeSize.x;
if( this.contentWidth < 100 )this.contentWidth = 100;
this.contentNode.setStyle("width", this.contentWidth );
if( this.options.contentHeight ){
this.contentHeight = this.options.contentHeight;
}else{
var toolbarSize = this.toolbarNode ? this.toolbarNode.getSize() : { x : 0, y : 0 };
var descriptionSize = this.descriptionNode ? this.descriptionNode.getSize() : { x : 0, y : 0 };
var toolbarMargin = this.toolbarNode ? this.toolbarNode.getStyles("margin-top", "margin-bottom", "padding-top", "padding-bottom", "bordrt-top-width", "bordrt-bottom-width") : null;
var m1 = (toolbarMargin) ? toolbarMargin["margin-top"].toInt()+toolbarMargin["margin-bottom"].toInt()+
toolbarMargin["padding-bottom"].toInt()+toolbarMargin["padding-top"].toInt()+
(toolbarMargin["bordrt-top-width"].toInt() || 0)+(toolbarMargin["bordrt-bottom-width"].toInt() || 0) : 0;
var descriptionMargin = this.descriptionNode ? this.descriptionNode.getStyles("margin-top", "margin-bottom", "padding-top", "padding-bottom", "bordrt-top-width", "bordrt-bottom-width") : null;
var m2 = (descriptionMargin) ? descriptionMargin["margin-top"].toInt()+descriptionMargin["margin-bottom"].toInt()+
descriptionMargin["padding-bottom"].toInt()+descriptionMargin["padding-top"].toInt()+
(descriptionMargin["bordrt-top-width"].toInt() || 0)+(descriptionMargin["bordrt-bottom-width"].toInt() || 0) : 0;
var contentMargin = this.contentNode.getStyles("margin-top", "margin-bottom", "padding-top", "padding-bottom", "bordrt-top-width", "bordrt-bottom-width");
var m3 = contentMargin["margin-top"].toInt()+contentMargin["margin-bottom"].toInt()+
contentMargin["padding-bottom"].toInt()+contentMargin["padding-top"].toInt()+
(contentMargin["bordrt-top-width"].toInt() || 0)+(contentMargin["bordrt-bottom-width"].toInt() || 0);
this.contentHeight = nodeSize.y - toolbarSize.y - descriptionSize.y - m1 - m2 - m3;
}
if( this.contentHeight < 150 )this.contentHeight = 150;
this.contentNode.setStyle("height", this.contentHeight );
if( this.canvas ){
var d = this.ctx.getImageData(0,0,this.canvas.clientWidth,this.canvas.clientHeight);
this.canvas.set("width", this.contentWidth );
this.canvas.set("height", this.contentHeight );
this.ctx.putImageData(d,0,0);
}
},
loadToolBar: function(){
this.toolbarNode = new Element("div.toolbar", {
"styles" : this.css.toolbar
}).inject(this.container);
this.toolbar = new o2.widget.Tablet.Toolbar( this , this.toolbarNode );
this.toolbar.load();
},
loadContent : function( ){
this.canvas = new Element("canvas", {
width : this.contentWidth,
height : this.contentHeight
}).inject( this.contentNode );
this.ctx = this.canvas.getContext("2d");
var preData=this.ctx.getImageData(0,0,this.contentWidth,this.contentHeight);
//空绘图表面进栈
this.middleAry.push(preData);
this.canvas.ontouchstart = this.canvas.onmousedown = function(ev){
var ev = ev || event;
var ctx = this.ctx;
var canvas = this.canvas;
var container = this.contentNode;
var position = this.contentNode.getPosition();
var doc = $(document);
//ctx.strokeStyle="#0000ff" 线条颜色; 默认 #000000
if( this.options.color )ctx.strokeStyle= this.currentColor || this.options.color; // 线条颜色; 默认 #000000
if( this.options.lineWidth )ctx.lineWidth= this.currentWidth || this.options.lineWidth; //默认1 像素
ctx.beginPath();
ctx.moveTo(ev.clientX-position.x,ev.clientY-position.y);
//当前绘图表面状态
var preData= ctx.getImageData(0,0,this.contentWidth,this.contentHeight);
//当前绘图表面进栈
this.preDrawAry.push(preData);
var mousemove = function(ev){
ctx.lineTo(ev.client.x - position.x,ev.client.y - position.y);
ctx.stroke();
};
doc.addEvent( "mousemove", mousemove );
doc.addEvent( "touchmove", mousemove );
var mouseup = function(ev){
//document.onmousemove = document.onmouseup = null;
doc.removeEvent("mousemove", mousemove);
doc.removeEvent("mouseup", mouseup);
doc.removeEvent("touchmove", mousemove);
doc.removeEvent("touchend", mouseup);
//当前绘图表面状态
var preData= ctx.getImageData(0,0,this.contentWidth,this.contentHeight);
if( this.nextDrawAry.length==0){
//当前绘图表面进栈
this.middleAry.push(preData);
}else{
this.middleAry=[];
this.middleAry=this.middleAry.concat(this.preDrawAry);
this.middleAry.push(preData);
this.nextDrawAry=[];
this.toolbar.enableItem("redo");
}
if(this.preDrawAry.length){
this.toolbar.enableItem("undo");
this.toolbar.enableItem("reset");
}
ctx.closePath();
}.bind(this);
doc.addEvent("mouseup", mouseup);
doc.addEvent("touchend", mouseup);
//document.onmouseup = function(ev){
// document.onmousemove = document.onmouseup = null;
// ctx.closePath();
//}
}.bind(this)
},
uploadImage: function( success, failure ){
var image = this.getImage();
if( image ){
if( this.options.action ){
this.action = (typeOf(this.options.action)=="string") ? o2.Actions.get(action).action : this.options.action;
this.action.invoke({
"name": this.options.method,
"async": true,
"data": this.getFormData( image ),
"file": image,
"parameter": this.options.parameter,
"success": function(json){
success(json)
}.bind(this)
});
}else if( this.options.reference && this.options.referenceType ){
//公共图片上传服务
var maxSize = this.options.resultMaxSize;
o2.xDesktop.uploadImageByScale(
this.options.reference,
this.options.referenceType,
maxSize,
this.getFormData( image ),
image,
success,
failure
);
}
}else{
}
},
getFormData : function( image ){
if( !image )image = this.getImage();
var formData = new FormData();
formData.append('file', image, this.fileName );
if( this.options.data ){
Object.each(this.options.data, function(v, k){
formData.append(k, v)
});
}
return formData;
},
getImage : function( base64Code ){
var src = base64Code || this.getBase64Code();
src=window.atob(src);
var ia = new Uint8Array(src.length);
for (var i = 0; i < src.length; i++) {
ia[i] = src.charCodeAt(i);
}
return new Blob([ia], {type: this.fileType });
},
getBase64Code : function(){
var ctx = this.ctx;
var canvas = this.canvas;
//var container = this.contentNode;
//var size = this.options.size;
var width, height;
//if( this.options.resultMaxSize ){
// if( this.contentWidth > )
//}else{
// width = this.contentWidth;
// height = this.contentHeight
//}
width = this.contentWidth;
height = this.contentHeight;
//ctx.drawImage(this.imageNode,0,0, this.contentWidth,this.contentHeight,0,0,width,height);
var src=canvas.toDataURL( this.fileType );
src=src.split(',')[1];
if(!src){
return "";
}else{
return src
}
},
getBase64Image: function( base64Code ){
if( !base64Code )base64Code = this.getBase64Code();
if( !base64Code )return null;
return 'data:'+ this.fileType +';base64,' + base64Code;
},
close : function(){
this.container.destroy();
delete this;
},
checkBroswer : function(){
if( window.Uint8Array && window.HTMLCanvasElement && window.atob && window.Blob){
this.available = true;
return true;
}else{
this.available = false;
this.container.set("html", "
您的浏览器不支持以下特性:
- canvas
- Blob
- Uint8Array
- FormData
- atob
");
return false;
}
},
save : function(){
var base64code = this.getBase64Code();
var imageFile = this.getImage( base64code );
var base64Image = this.getBase64Image( base64code );
this.fireEvent("save", [ base64code, base64Image, imageFile]);
},
reset : function( itemNode ){
this.fileName = "untitled.png";
this.fileType = "image/png";
if( this.ctx ){
var canvas = this.canvas;
this.ctx.clearRect(0,0,canvas.clientWidth,canvas.clientHeight);
}
},
undo : function( itemNode ){
if(this.preDrawAry.length>0){
var popData=this.preDrawAry.pop();
var midData=this.middleAry[this.preDrawAry.length+1];
this.nextDrawAry.push(midData);
this.ctx.putImageData(popData,0,0);
}
this.toolbar.setAllItemsStatus();
},
redo : function( itemNode ){
if(this.nextDrawAry.length){
var popData=this.nextDrawAry.pop();
var midData=this.middleAry[this.middleAry.length-this.nextDrawAry.length-2];
this.preDrawAry.push(midData);
this.ctx.putImageData(popData,0,0);
}
this.toolbar.setAllItemsStatus();
},
size : function( itemNode ){
if( !this.sizeSelector ){
this.sizeSelector = new o2.widget.Tablet.SizePicker(this.container, itemNode, null, {}, {
"onSelect": function (width) {
this.currentWidth = width;
}.bind(this)
});
}
},
color : function( itemNode ){
if( !this.colorSelector ){
this.colorSelector = new o2.xApplication.Template.widget.ColorPicker( this.container, itemNode, null, {}, {
"lineWidth" : 1,
"onSelect": function (color) {
this.currentColor = color;
}.bind(this)
});
}
},
clear : function( itemNode ){
},
cancel: function(){
this.reset();
this.fireEvent("cancel");
}
});
o2.widget.Tablet.Toolbar = new Class({
Implements: [Options, Events],
initialize: function (tablet, container) {
this.tablet = tablet;
this.container = container;
this.css = tablet.css;
this.lp = this.tablet.lp;
this.imagePath = o2.session.path+"/widget/$Tablet/"+ this.tablet.options.style +"/icon/";
this.items = {};
this.itemsEnableFun = {
save : {
enable : function(){ return true }
},
reset : {
enable : function(){ return this.tablet.preDrawAry.length > 0}.bind(this)
},
undo : {
enable : function(){ return this.tablet.preDrawAry.length > 0 }.bind(this)
},
redo : {
enable : function(){ return this.tablet.nextDrawAry.length > 0 }.bind(this)
},
size : {
enable : function(){ return true }
},
color : {
enable : function(){ return true }
}
}
},
getHtml : function(){
var items;
var tools = this.tablet.options.tools;
if( tools ){
items = tools;
}else{
items = [
"save", "|",
"reset", "|",
"undo", "|",
"redo", "|",
"size", "|",
"color"//, "|",
//"clear" //橡皮
];
}
var html = "";
var style = "toolItem";
items.each( function( item ){
switch( item ){
case "|":
html += "";
break;
case "save" :
html += ""+ this.lp.save +"
";
break;
case "reset" :
html += ""+ this.lp.reset +"
";
break;
case "undo" :
html += ""+ this.lp.undo +"
";
break;
case "redo" :
html += ""+ this.lp.redo +"
";
break;
case "size" :
html += ""+ this.lp.size +"
";
break;
case "color" :
html += ""+ this.lp.color +"
";
break;
case "clear" :
html += ""+ this.lp.clear +"
";
break;
case "cancel" :
html += ""+ this.lp.cancel +"
";
break;
}
}.bind(this));
return html;
},
load: function () {
var _self = this;
var imagePath = this.imagePath;
this.items = {};
var html = this.getHtml();
this.container.set("html", html);
this.container.getElements("[styles]").each(function (el) {
el.setStyles(_self.css[el.get("styles")]);
var item = el.get("item");
if ( item ) {
this.items[ item ] = el;
el.setStyle("background-image","url("+ imagePath + item +"_normal.png)");
el.addEvents({
mouseover : function(){
_self._setItemNodeActive(this.el);
}.bind({ item : item, el : el }),
mouseout : function(){
_self._setItemNodeNormal(this.el);
}.bind({ item : item, el : el }),
click : function( ev ){
if( _self["tablet"][this.item] )_self["tablet"][this.item]( this.el );
}.bind({ item : item, el : el })
});
if( item == "color" || item == "size" ){
if( _self["tablet"][item] )_self["tablet"][item]( el );
}
}
}.bind(this));
this.setAllItemsStatus();
},
setAllItemsStatus : function(){
for( var item in this.items ){
var node = this.items[item];
if( this.itemsEnableFun[item] ){
if( this.itemsEnableFun[item].enable() ){
this.enableItem( item )
}else{
this.disableItem( item );
}
}
}
},
disableItem : function( itemName ){
var itemNode = this.items[ itemName ]; //this.container.getElement("[item='+itemName+']");
itemNode.store("status", "disable");
this._setItemNodeDisable( itemNode );
},
enableItem : function( itemName ){
var itemNode = this.items[ itemName ];
itemNode.store("status", "enable");
this._setItemNodeNormal( itemNode );
},
_setItemNodeDisable : function( itemNode ){
var item = itemNode.get("item");
itemNode.setStyles( this.css.toolItem_disable );
itemNode.setStyle("background-image","url("+ this.imagePath+ item +"_disable.png)");
},
_setItemNodeActive: function( itemNode ){
if( itemNode.retrieve("status") == "disable" )return;
var item = itemNode.get("item");
itemNode.setStyles( this.css.toolItem_over );
itemNode.setStyle("background-image","url("+ this.imagePath+ item +"_active.png)");
},
_setItemNodeNormal: function( itemNode ){
if( itemNode.retrieve("status") == "disable" )return;
var item = itemNode.get("item");
var style = itemNode.get("styles");
itemNode.setStyles( this.css[style] );
itemNode.setStyle("background-image","url("+ this.imagePath+ item +"_normal.png)");
}
});
o2.xDesktop.requireApp("Template", "MTooltips", null, false);
o2.widget.Tablet.SizePicker = new Class({
Implements: [Options, Events],
Extends: MTooltips,
options: {
style : "default",
axis: "y", //箭头在x轴还是y轴上展现
position : { //node 固定的位置
x : "auto", //x 轴上left center right, auto 系统自动计算
y : "auto" //y轴上top middle bottom, auto 系统自动计算
},
//event : "click", //事件类型,有target 时有效, mouseenter对应mouseleave,click 对应 container 的 click
nodeStyles : {
"min-width" : "260px"
},
lineWidth : 1
},
initialize : function( container, target, app, data, options, targetCoordinates ){
//可以传入target 或者 targetCoordinates,两种选一
//传入target,表示触发tooltip的节点,本类根据 this.options.event 自动绑定target的事件
//传入targetCoordinates,表示 出发tooltip的位置,本类不绑定触发事件
if( options ){
this.setOptions(options);
}
this.container = container;
this.target = target;
this.targetCoordinates = targetCoordinates;
this.app = app;
if(app)this.lp = app.lp;
this.data = data;
if( this.target ){
this.setTargetEvents();
}
},
_customNode : function( node ){
o2.UD.getDataJson("sizePicker", function(json) {
this.rulerContainer = new Element("div",{
styles : {
"margin-left": " 23px",
"margin-right": " 1px",
"width" : "228px"
}
}).inject(this.node);
this.ruleList = ["0.1","0.5","1","5","10", "15","20"];
this.rulerTitleContainer = new Element("div",{
styles : { "overflow" : "hidden" }
}).inject( this.rulerContainer );
this.ruleList.each( function( rule ){
new Element("div", {
text : rule,
styles : {
width : "32px",
float : "left",
"text-align" : "center"
}
}).inject( this.rulerTitleContainer )
}.bind(this));
this.rulerContentContainer = new Element("div",{
styles : { "overflow" : "hidden" }
}).inject( this.rulerContainer );
new Element("div", {
styles : {
width : "14px",
height : "10px",
"text-align" : "center",
float : "left",
"border-right" : "1px solid #aaa"
}
}).inject( this.rulerContentContainer );
this.ruleList.each( function( rule, i ){
if( i == this.ruleList.length - 1 )return;
new Element("div", {
styles : {
width : "32px",
height : "10px",
"text-align" : "center",
float : "left",
"border-right" : "1px solid #aaa"
}
}).inject( this.rulerContentContainer )
}.bind(this));
this.silderContainer = new Element("div", {
"height" : "25px",
"line-height" : "25px",
"margin-top" : "4px"
}).inject( this.node );
this.sliderArea = new Element("div", {styles : {
"margin-top": "2px",
"margin-bottom": "10px",
"height": "10px",
"overflow": " hidden",
"margin-left": " 37px",
"margin-right": " 15px",
"border-top": "1px solid #999",
"border-left": "1px solid #999",
"border-bottom": "1px solid #E1E1E1",
"border-right": "1px solid #E1E1E1",
"background-color": "#EEE",
"width" : "200px"
}}).inject( this.silderContainer );
this.sliderKnob = new Element("div", {styles : {
"height": "8px",
"width": " 8px",
"background-color": "#999",
"z-index": " 99",
"border-top": "1px solid #DDD",
"border-left": "1px solid #DDD",
"border-bottom": "1px solid #777",
"border-right": "1px solid #777",
"cursor": "pointer"
} }).inject( this.sliderArea );
this.slider = new Slider(this.sliderArea, this.sliderKnob, {
range: [1, 30],
initialStep: 10,
onChange: function(value){
if( value < 10 ){
this.lineWidth = (value / 10)
}else{
this.lineWidth = value - 9;
}
this.drawPreview( this.lineWidth );
this.fireEvent("select", this.lineWidth )
}.bind(this)
});
previewContainer = new Element("div").inject(this.node);
new Element("div",{ text : "预览", styles : {
"float" : "left",
"margin-top" : "5px",
"width" : "30px"
}}).inject(this.silderContainer);
this.previewNode = new Element("div", {
styles : {
"margin" : "0px 0px 0px 37px",
"width" : "200px"
}
}).inject( this.node );
this.canvas = new Element("canvas", {
width : 200,
height : 30
}).inject( this.previewNode );
this.ctx = this.canvas.getContext("2d");
this.drawPreview();
new Element("button", {
text : "重置",
type : "button",
styles :{
"margin-left" : "40px",
"font-size" : "12px",
"border-radius" : "3px",
"cursor" : "pointer" ,
"border" : "1px solid #ccc",
"padding" : "5px 10px",
"background-color" : "#f7f7f7"
},
events : {
click : function(){
this.lineWidth = this.options.lineWidth || 1;
var step;
if( this.lineWidth < 1 ){
step = this.lineWidth * 10
}else{
step = this.lineWidth + 9
}
this.slider.set( parseInt( step ) );
this.drawPreview( this.lineWidth );
this.fireEvent("select", this.lineWidth )
}.bind(this)
}
}).inject( this.node );
}.bind(this));
//this.resultInput = new Element("input").inject(this.contentNode);
},
drawPreview : function( lineWidth ){
if( !lineWidth )lineWidth = this.options.lineWidth || 1;
var canvas = this.canvas;
var ctx = this.ctx;
ctx.clearRect(0,0,canvas.clientWidth,canvas.clientHeight);
var coordinates = this.previewNode.getCoordinates();
var doc = $(document);
ctx.strokeStyle="#000000"; //线条颜色; 默认 #000000
//ctx.strokeStyle= this.currentColor || this.options.color; // 线条颜色; 默认 #000000
ctx.lineWidth= lineWidth ; //默认1 像素
ctx.beginPath();
//ctx.moveTo( (coordinates.bottom-coordinates.top - lineWidth ) / 2, coordinates.left);
ctx.moveTo( 1 , 15 );
ctx.lineTo( 200, 15 );
ctx.stroke();
}
});