Tablet.js 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259
  1. o2.widget = o2.widget || {};
  2. o2.xDesktop.requireApp("Template", "widget.ColorPicker", null, false);
  3. o2.widget.Tablet = o2.Tablet = new Class({
  4. Implements: [Options, Events],
  5. Extends: o2.widget.Common,
  6. options: {
  7. "style": "default",
  8. "path": o2.session.path+"/widget/$Tablet/",
  9. "contentWidth" : 0, //绘图区域宽度,不制定则基础 this.node的宽度
  10. "contentHeight" : 0, //绘图区域高度,不制定则基础 this.node的高度 - 操作条高度
  11. "lineWidth" : 1, //铅笔粗细
  12. "color" : "#000000", //画笔颜色
  13. tools : [
  14. "save", "|",
  15. "undo",
  16. "redo", "|",
  17. "size",
  18. "color", "|",
  19. "image",
  20. "imageClipper", "|",
  21. "reset",
  22. //"clear" //橡皮
  23. "cancel"
  24. ],
  25. "description" : "", //描述文字
  26. "action" : null, //uploadImage方法的上传服务,可选,如果不设置,使用公共图片服务
  27. "method": "", //使用action 的方法
  28. "parameter": {}, //action 时的url参数
  29. "data": null, //formdata 的data
  30. "reference": "", //uploadImage方法的使用 使用公共图片服务上传时的参数
  31. "referenceType" : "", //使用公共图片服务上传时的参数, 目前支持 processPlatformJob, processPlatformForm, portalPage, cmsDocument, forumDocument
  32. "resultMaxSize" : 0 //使用 reference 时有效
  33. },
  34. initialize: function(node, options, app){
  35. this.node = node;
  36. this.app = app;
  37. this.reset();
  38. this.setOptions(options);
  39. this.path = this.options.path || (o2.session.path+"/widget/$Tablet/");
  40. this.cssPath = this.path + this.options.style+"/css.wcss";
  41. this.lp = {
  42. save : "保存",
  43. reset : "清空",
  44. undo : "撤销",
  45. redo : "重做",
  46. size : "粗细",
  47. color : "颜色",
  48. image : "插入图片",
  49. imageClipper : "裁剪图片",
  50. //clear : "橡皮"
  51. "cancel": "取消"
  52. };
  53. this._loadCss();
  54. this.fireEvent("init");
  55. },
  56. load: function( ){
  57. //存储当前表面状态数组-上一步
  58. this.preDrawAry = [];
  59. //存储当前表面状态数组-下一步
  60. this.nextDrawAry = [];
  61. //中间数组
  62. this.middleAry = [];
  63. this.container = new Element("div.container", {
  64. styles : this.css.container
  65. }).inject(this.node);
  66. this.loadToolBar();
  67. this.contentNode = new Element("div.contentNode", { styles : this.css.contentNode}).inject(this.container);
  68. this.contentNode.addEvent("selectstart", function(e){
  69. e.preventDefault();
  70. e.stopPropagation();
  71. });
  72. this.loadDescription();
  73. this.setContentSize();
  74. if( this.checkBroswer() ){
  75. this.loadContent();
  76. }
  77. //this.imageNode = new Element("img",{
  78. //}).inject(this.contentNode);
  79. //this.imageNode.setStyles({
  80. // "display" : "none"
  81. //});
  82. if( this.app ){
  83. this.resizeFun = this.setContentSize.bind(this);
  84. this.app.addEvent( "resize", this.resizeFun );
  85. }
  86. },
  87. loadDescription : function(){
  88. if( this.options.description ){
  89. this.descriptionNode = new Element("div",{
  90. "styles": this.css.descriptionNode,
  91. "text": this.options.description
  92. }).inject( this.container )
  93. }
  94. },
  95. setContentSize : function(){
  96. var nodeSize = this.node.getSize();
  97. this.contentWidth = this.options.contentWidth || nodeSize.x;
  98. if( this.contentWidth < 100 )this.contentWidth = 100;
  99. this.contentNode.setStyle("width", this.contentWidth );
  100. if( this.options.contentHeight ){
  101. this.contentHeight = this.options.contentHeight;
  102. }else{
  103. var toolbarSize = this.toolbarNode ? this.toolbarNode.getSize() : { x : 0, y : 0 };
  104. var descriptionSize = this.descriptionNode ? this.descriptionNode.getSize() : { x : 0, y : 0 };
  105. var toolbarMargin = this.toolbarNode ? this.toolbarNode.getStyles("margin-top", "margin-bottom", "padding-top", "padding-bottom", "bordrt-top-width", "bordrt-bottom-width") : null;
  106. var m1 = (toolbarMargin) ? toolbarMargin["margin-top"].toInt()+toolbarMargin["margin-bottom"].toInt()+
  107. toolbarMargin["padding-bottom"].toInt()+toolbarMargin["padding-top"].toInt()+
  108. (toolbarMargin["bordrt-top-width"].toInt() || 0)+(toolbarMargin["bordrt-bottom-width"].toInt() || 0) : 0;
  109. var descriptionMargin = this.descriptionNode ? this.descriptionNode.getStyles("margin-top", "margin-bottom", "padding-top", "padding-bottom", "bordrt-top-width", "bordrt-bottom-width") : null;
  110. var m2 = (descriptionMargin) ? descriptionMargin["margin-top"].toInt()+descriptionMargin["margin-bottom"].toInt()+
  111. descriptionMargin["padding-bottom"].toInt()+descriptionMargin["padding-top"].toInt()+
  112. (descriptionMargin["bordrt-top-width"].toInt() || 0)+(descriptionMargin["bordrt-bottom-width"].toInt() || 0) : 0;
  113. var contentMargin = this.contentNode.getStyles("margin-top", "margin-bottom", "padding-top", "padding-bottom", "bordrt-top-width", "bordrt-bottom-width");
  114. var m3 = contentMargin["margin-top"].toInt()+contentMargin["margin-bottom"].toInt()+
  115. contentMargin["padding-bottom"].toInt()+contentMargin["padding-top"].toInt()+
  116. (contentMargin["bordrt-top-width"].toInt() || 0)+(contentMargin["bordrt-bottom-width"].toInt() || 0);
  117. this.contentHeight = nodeSize.y - toolbarSize.y - descriptionSize.y - m1 - m2 - m3;
  118. }
  119. if( this.contentHeight < 150 )this.contentHeight = 150;
  120. this.contentNode.setStyle("height", this.contentHeight );
  121. if( this.canvas ){
  122. var d = this.ctx.getImageData(0,0,this.canvas.clientWidth,this.canvas.clientHeight);
  123. this.canvas.set("width", this.contentWidth );
  124. this.canvas.set("height", this.contentHeight );
  125. this.ctx.putImageData(d,0,0);
  126. }
  127. },
  128. loadToolBar: function(){
  129. this.toolbarNode = new Element("div.toolbar", {
  130. "styles" : this.css.toolbar
  131. }).inject(this.container);
  132. this.toolbar = new o2.widget.Tablet.Toolbar( this , this.toolbarNode );
  133. this.toolbar.load();
  134. },
  135. storeToPreArray : function(){
  136. //当前绘图表面状态
  137. var preData= this.ctx.getImageData(0,0,this.contentWidth,this.contentHeight);
  138. //当前绘图表面进栈
  139. this.preDrawAry.push(preData);
  140. },
  141. storeToMiddleArray : function(){
  142. //当前绘图表面状态
  143. var preData= this.ctx.getImageData(0,0,this.contentWidth,this.contentHeight);
  144. if( this.nextDrawAry.length==0){
  145. //当前绘图表面进栈
  146. this.middleAry.push(preData);
  147. }else{
  148. this.middleAry=[];
  149. this.middleAry=this.middleAry.concat(this.preDrawAry);
  150. this.middleAry.push(preData);
  151. this.nextDrawAry=[];
  152. this.toolbar.enableItem("redo");
  153. }
  154. if(this.preDrawAry.length){
  155. this.toolbar.enableItem("undo");
  156. this.toolbar.enableItem("reset");
  157. }
  158. },
  159. loadContent : function( ){
  160. this.canvas = new Element("canvas", {
  161. width : this.contentWidth,
  162. height : this.contentHeight
  163. }).inject( this.contentNode );
  164. this.ctx = this.canvas.getContext("2d");
  165. var preData=this.ctx.getImageData(0,0,this.contentWidth,this.contentHeight);
  166. //空绘图表面进栈
  167. this.middleAry.push(preData);
  168. this.canvas.ontouchstart = this.canvas.onmousedown = function(ev){
  169. var ev = ev || event;
  170. var ctx = this.ctx;
  171. var canvas = this.canvas;
  172. var container = this.contentNode;
  173. var position = this.contentNode.getPosition();
  174. var doc = $(document);
  175. //ctx.strokeStyle="#0000ff" 线条颜色; 默认 #000000
  176. if( this.options.color )ctx.strokeStyle= this.currentColor || this.options.color; // 线条颜色; 默认 #000000
  177. if( this.options.lineWidth )ctx.lineWidth= this.currentWidth || this.options.lineWidth; //默认1 像素
  178. ctx.beginPath();
  179. ctx.moveTo(ev.clientX-position.x,ev.clientY-position.y);
  180. this.storeToPreArray();
  181. var mousemove = function(ev){
  182. ctx.lineTo(ev.client.x - position.x,ev.client.y - position.y);
  183. ctx.stroke();
  184. };
  185. doc.addEvent( "mousemove", mousemove );
  186. doc.addEvent( "touchmove", mousemove );
  187. var mouseup = function(ev){
  188. //document.onmousemove = document.onmouseup = null;
  189. doc.removeEvent("mousemove", mousemove);
  190. doc.removeEvent("mouseup", mouseup);
  191. doc.removeEvent("touchmove", mousemove);
  192. doc.removeEvent("touchend", mouseup);
  193. this.storeToMiddleArray();
  194. ctx.closePath();
  195. }.bind(this);
  196. doc.addEvent("mouseup", mouseup);
  197. doc.addEvent("touchend", mouseup);
  198. //document.onmouseup = function(ev){
  199. // document.onmousemove = document.onmouseup = null;
  200. // ctx.closePath();
  201. //}
  202. }.bind(this)
  203. },
  204. uploadImage: function( success, failure ){
  205. var image = this.getImage();
  206. if( image ){
  207. if( this.options.action ){
  208. this.action = (typeOf(this.options.action)=="string") ? o2.Actions.get(action).action : this.options.action;
  209. this.action.invoke({
  210. "name": this.options.method,
  211. "async": true,
  212. "data": this.getFormData( image ),
  213. "file": image,
  214. "parameter": this.options.parameter,
  215. "success": function(json){
  216. success(json)
  217. }.bind(this)
  218. });
  219. }else if( this.options.reference && this.options.referenceType ){
  220. //公共图片上传服务
  221. var maxSize = this.options.resultMaxSize;
  222. o2.xDesktop.uploadImageByScale(
  223. this.options.reference,
  224. this.options.referenceType,
  225. maxSize,
  226. this.getFormData( image ),
  227. image,
  228. success,
  229. failure
  230. );
  231. }
  232. }else{
  233. }
  234. },
  235. getFormData : function( image ){
  236. if( !image )image = this.getImage();
  237. var formData = new FormData();
  238. formData.append('file', image, this.fileName );
  239. if( this.options.data ){
  240. Object.each(this.options.data, function(v, k){
  241. formData.append(k, v)
  242. });
  243. }
  244. return formData;
  245. },
  246. getImage : function( base64Code ){
  247. var src = base64Code || this.getBase64Code();
  248. src=window.atob(src);
  249. var ia = new Uint8Array(src.length);
  250. for (var i = 0; i < src.length; i++) {
  251. ia[i] = src.charCodeAt(i);
  252. }
  253. return new Blob([ia], {type: this.fileType });
  254. },
  255. getBase64Code : function(){
  256. var ctx = this.ctx;
  257. var canvas = this.canvas;
  258. //var container = this.contentNode;
  259. //var size = this.options.size;
  260. var width, height;
  261. //if( this.options.resultMaxSize ){
  262. // if( this.contentWidth > )
  263. //}else{
  264. // width = this.contentWidth;
  265. // height = this.contentHeight
  266. //}
  267. width = this.contentWidth;
  268. height = this.contentHeight;
  269. //ctx.drawImage(this.imageNode,0,0, this.contentWidth,this.contentHeight,0,0,width,height);
  270. var src=canvas.toDataURL( this.fileType );
  271. src=src.split(',')[1];
  272. if(!src){
  273. return "";
  274. }else{
  275. return src
  276. }
  277. },
  278. getBase64Image: function( base64Code ){
  279. if( !base64Code )base64Code = this.getBase64Code();
  280. if( !base64Code )return null;
  281. return 'data:'+ this.fileType +';base64,' + base64Code;
  282. },
  283. close : function(){
  284. this.container.destroy();
  285. delete this;
  286. },
  287. checkBroswer : function(){
  288. if( window.Uint8Array && window.HTMLCanvasElement && window.atob && window.Blob){
  289. this.available = true;
  290. return true;
  291. }else{
  292. this.available = false;
  293. this.container.set("html", "<p>您的浏览器不支持以下特性:</p><ul><li>canvas</li><li>Blob</li><li>Uint8Array</li><li>FormData</li><li>atob</li></ul>");
  294. return false;
  295. }
  296. },
  297. save : function(){
  298. var base64code = this.getBase64Code();
  299. var imageFile = this.getImage( base64code );
  300. var base64Image = this.getBase64Image( base64code );
  301. this.fireEvent("save", [ base64code, base64Image, imageFile]);
  302. },
  303. reset : function( itemNode ){
  304. this.fileName = "untitled.png";
  305. this.fileType = "image/png";
  306. if( this.ctx ){
  307. var canvas = this.canvas;
  308. this.ctx.clearRect(0,0,canvas.clientWidth,canvas.clientHeight);
  309. }
  310. },
  311. undo : function( itemNode ){
  312. if(this.preDrawAry.length>0){
  313. var popData=this.preDrawAry.pop();
  314. var midData=this.middleAry[this.preDrawAry.length+1];
  315. this.nextDrawAry.push(midData);
  316. this.ctx.putImageData(popData,0,0);
  317. }
  318. this.toolbar.setAllItemsStatus();
  319. },
  320. redo : function( itemNode ){
  321. if(this.nextDrawAry.length){
  322. var popData=this.nextDrawAry.pop();
  323. var midData=this.middleAry[this.middleAry.length-this.nextDrawAry.length-2];
  324. this.preDrawAry.push(midData);
  325. this.ctx.putImageData(popData,0,0);
  326. }
  327. this.toolbar.setAllItemsStatus();
  328. },
  329. size : function( itemNode ){
  330. if( !this.sizeSelector ){
  331. this.sizeSelector = new o2.widget.Tablet.SizePicker(this.container, itemNode, null, {}, {
  332. "onSelect": function (width) {
  333. this.currentWidth = width;
  334. }.bind(this)
  335. });
  336. }
  337. },
  338. color : function( itemNode ){
  339. if( !this.colorSelector ){
  340. this.colorSelector = new o2.xApplication.Template.widget.ColorPicker( this.container, itemNode, null, {}, {
  341. "lineWidth" : 1,
  342. "onSelect": function (color) {
  343. this.currentColor = color;
  344. }.bind(this)
  345. });
  346. }
  347. },
  348. getImageSize : function(naturalWidth, naturalHeight ){
  349. var ratio = naturalWidth / naturalHeight;
  350. var ww = this.contentWidth,
  351. wh = this.contentHeight;
  352. var flag = ( naturalWidth / parseInt(ww) ) > ( naturalHeight / parseInt(wh) );
  353. if( flag ){
  354. var width = Math.min( naturalWidth, parseInt( ww ) );
  355. return { width : width, height : width / ratio }
  356. }else{
  357. var height = Math.min( naturalHeight, parseInt( wh ) );
  358. return { width : height * ratio, height : height }
  359. }
  360. },
  361. parseFileToImage : function( file, callback ){
  362. var imageNode = new Element("img");
  363. var onImageLoad = function(){
  364. var nh = imageNode.naturalHeight,
  365. nw = imageNode.naturalWidth;
  366. if( isNaN(nh) || isNaN(nw) || nh == 0 || nw == 0 ){
  367. setTimeout( function(){ onImageLoad(); }.bind(this), 100 );
  368. }else{
  369. _onImageLoad();
  370. }
  371. };
  372. var _onImageLoad = function(){
  373. var nh = imageNode.naturalHeight,
  374. nw = imageNode.naturalWidth;
  375. var size = this.getImageSize( nw, nh );
  376. imageNode.setStyles({
  377. width : size.width,
  378. height : size.height
  379. });
  380. var mover = new o2.widget.Tablet.ImageMover( this, imageNode, this.contentNode , {
  381. onPostOk : function(){
  382. var coordinate = mover.getCoordinage();
  383. this.storeToPreArray();
  384. this.ctx.drawImage(imageNode, coordinate.left, coordinate.top, coordinate.width, coordinate.height);
  385. this.storeToMiddleArray();
  386. }.bind(this)
  387. });
  388. mover.load();
  389. if( callback )callback();
  390. }.bind(this);
  391. var reader=new FileReader();
  392. reader.onload=function(){
  393. imageNode.src=reader.result;
  394. reader = null;
  395. onImageLoad();
  396. }.bind(this);
  397. reader.readAsDataURL(file);
  398. },
  399. image : function( itemNode ){
  400. var uploadFileAreaNode = new Element("div");
  401. var html = "<input name=\"file\" type=\"file\" />"; //accept=\"images/*\"
  402. uploadFileAreaNode.set("html", html);
  403. var fileUploadNode = uploadFileAreaNode.getFirst();
  404. fileUploadNode.addEvent("change", function () {
  405. var file = fileUploadNode.files[0];
  406. this.parseFileToImage( file, function(){
  407. uploadFileAreaNode.destroy();
  408. })
  409. }.bind(this));
  410. fileUploadNode.click();
  411. },
  412. imageClipper : function( itemNode ){
  413. var clipper = new o2.widget.Tablet.ImageClipper(this.app, {
  414. "style": "default",
  415. "aspectRatio" : 0,
  416. "onOk" : function( img ){
  417. this.parseFileToImage( img );
  418. }.bind(this)
  419. });
  420. clipper.load();
  421. },
  422. clear : function( itemNode ){
  423. },
  424. cancel: function(){
  425. this.reset();
  426. this.fireEvent("cancel");
  427. }
  428. });
  429. o2.widget.Tablet.Toolbar = new Class({
  430. Implements: [Options, Events],
  431. initialize: function (tablet, container) {
  432. this.tablet = tablet;
  433. this.container = container;
  434. this.css = tablet.css;
  435. this.lp = this.tablet.lp;
  436. this.imagePath = o2.session.path+"/widget/$Tablet/"+ this.tablet.options.style +"/icon/";
  437. this.items = {};
  438. this.itemsEnableFun = {
  439. save : {
  440. enable : function(){ return true }
  441. },
  442. reset : {
  443. enable : function(){ return this.tablet.preDrawAry.length > 0}.bind(this)
  444. },
  445. undo : {
  446. enable : function(){ return this.tablet.preDrawAry.length > 0 }.bind(this)
  447. },
  448. redo : {
  449. enable : function(){ return this.tablet.nextDrawAry.length > 0 }.bind(this)
  450. },
  451. size : {
  452. enable : function(){ return true }
  453. },
  454. color : {
  455. enable : function(){ return true }
  456. },
  457. image : {
  458. enable : function(){ return true }
  459. },
  460. imageClipper : {
  461. enable : function(){ return true }
  462. }
  463. }
  464. },
  465. getHtml : function(){
  466. var items;
  467. var tools = this.tablet.options.tools;
  468. if( tools ){
  469. items = tools;
  470. }else{
  471. items = [
  472. "save", "|",
  473. "reset", "|",
  474. "undo", "|",
  475. "redo", "|",
  476. "size", "|",
  477. "color", "|",
  478. "image", "|",
  479. "imageClipper"
  480. //"clear" //橡皮
  481. ];
  482. }
  483. var html = "";
  484. var style = "toolItem";
  485. items.each( function( item ){
  486. switch( item ){
  487. case "|":
  488. html += "<div styles='" + "separator" + "'></div>";
  489. break;
  490. case "save" :
  491. html += "<div item='save' styles='" + style + "'>"+ this.lp.save +"</div>";
  492. break;
  493. case "reset" :
  494. html += "<div item='reset' styles='" + style + "'>"+ this.lp.reset +"</div>";
  495. break;
  496. case "undo" :
  497. html += "<div item='undo' styles='" + style + "'>"+ this.lp.undo +"</div>";
  498. break;
  499. case "redo" :
  500. html += "<div item='redo' styles='" + style + "'>"+ this.lp.redo +"</div>";
  501. break;
  502. case "size" :
  503. html += "<div item='size' styles='" + style + "'>"+ this.lp.size +"</div>";
  504. break;
  505. case "color" :
  506. html += "<div item='color' styles='" + style + "'>"+ this.lp.color +"</div>";
  507. break;
  508. case "image" :
  509. html += "<div item='image' styles='" + style + "'>"+ this.lp.image +"</div>";
  510. break;
  511. case "imageClipper" :
  512. html += "<div item='imageClipper' styles='" + style + "'>"+ this.lp.imageClipper +"</div>";
  513. break;
  514. case "clear" :
  515. html += "<div item='clear' styles='" + style + "'>"+ this.lp.clear +"</div>";
  516. break;
  517. case "cancel" :
  518. html += "<div item='cancel' styles='toolRightItem'>"+ this.lp.cancel +"</div>";
  519. break;
  520. }
  521. }.bind(this));
  522. return html;
  523. },
  524. load: function () {
  525. var _self = this;
  526. var imagePath = this.imagePath;
  527. this.items = {};
  528. var html = this.getHtml();
  529. this.container.set("html", html);
  530. this.container.getElements("[styles]").each(function (el) {
  531. el.setStyles(_self.css[el.get("styles")]);
  532. var item = el.get("item");
  533. if ( item ) {
  534. this.items[ item ] = el;
  535. el.setStyle("background-image","url("+ imagePath + item +"_normal.png)");
  536. el.addEvents({
  537. mouseover : function(){
  538. _self._setItemNodeActive(this.el);
  539. }.bind({ item : item, el : el }),
  540. mouseout : function(){
  541. _self._setItemNodeNormal(this.el);
  542. }.bind({ item : item, el : el }),
  543. click : function( ev ){
  544. if( _self["tablet"][this.item] )_self["tablet"][this.item]( this.el );
  545. }.bind({ item : item, el : el })
  546. });
  547. if( item == "color" || item == "size" ){
  548. if( _self["tablet"][item] )_self["tablet"][item]( el );
  549. }
  550. }
  551. }.bind(this));
  552. this.setAllItemsStatus();
  553. },
  554. setAllItemsStatus : function(){
  555. for( var item in this.items ){
  556. var node = this.items[item];
  557. if( this.itemsEnableFun[item] ){
  558. if( this.itemsEnableFun[item].enable() ){
  559. this.enableItem( item )
  560. }else{
  561. this.disableItem( item );
  562. }
  563. }
  564. }
  565. },
  566. disableItem : function( itemName ){
  567. var itemNode = this.items[ itemName ]; //this.container.getElement("[item='+itemName+']");
  568. itemNode.store("status", "disable");
  569. this._setItemNodeDisable( itemNode );
  570. },
  571. enableItem : function( itemName ){
  572. var itemNode = this.items[ itemName ];
  573. itemNode.store("status", "enable");
  574. this._setItemNodeNormal( itemNode );
  575. },
  576. _setItemNodeDisable : function( itemNode ){
  577. var item = itemNode.get("item");
  578. itemNode.setStyles( this.css.toolItem_disable );
  579. itemNode.setStyle("background-image","url("+ this.imagePath+ item +"_disable.png)");
  580. },
  581. _setItemNodeActive: function( itemNode ){
  582. if( itemNode.retrieve("status") == "disable" )return;
  583. var item = itemNode.get("item");
  584. itemNode.setStyles( this.css.toolItem_over );
  585. itemNode.setStyle("background-image","url("+ this.imagePath+ item +"_active.png)");
  586. },
  587. _setItemNodeNormal: function( itemNode ){
  588. if( itemNode.retrieve("status") == "disable" )return;
  589. var item = itemNode.get("item");
  590. var style = itemNode.get("styles");
  591. itemNode.setStyles( this.css[style] );
  592. itemNode.setStyle("background-image","url("+ this.imagePath+ item +"_normal.png)");
  593. }
  594. });
  595. o2.xDesktop.requireApp("Template", "MTooltips", null, false);
  596. o2.widget.Tablet.SizePicker = new Class({
  597. Implements: [Options, Events],
  598. Extends: MTooltips,
  599. options: {
  600. style : "default",
  601. axis: "y", //箭头在x轴还是y轴上展现
  602. position : { //node 固定的位置
  603. x : "auto", //x 轴上left center right, auto 系统自动计算
  604. y : "auto" //y轴上top middle bottom, auto 系统自动计算
  605. },
  606. //event : "click", //事件类型,有target 时有效, mouseenter对应mouseleave,click 对应 container 的 click
  607. nodeStyles : {
  608. "min-width" : "260px"
  609. },
  610. lineWidth : 1
  611. },
  612. initialize : function( container, target, app, data, options, targetCoordinates ){
  613. //可以传入target 或者 targetCoordinates,两种选一
  614. //传入target,表示触发tooltip的节点,本类根据 this.options.event 自动绑定target的事件
  615. //传入targetCoordinates,表示 出发tooltip的位置,本类不绑定触发事件
  616. if( options ){
  617. this.setOptions(options);
  618. }
  619. this.container = container;
  620. this.target = target;
  621. this.targetCoordinates = targetCoordinates;
  622. this.app = app;
  623. if(app)this.lp = app.lp;
  624. this.data = data;
  625. if( this.target ){
  626. this.setTargetEvents();
  627. }
  628. },
  629. _customNode : function( node ){
  630. o2.UD.getDataJson("sizePicker", function(json) {
  631. this.rulerContainer = new Element("div",{
  632. styles : {
  633. "margin-left": " 23px",
  634. "margin-right": " 1px",
  635. "width" : "228px"
  636. }
  637. }).inject(this.node);
  638. this.ruleList = ["0.1","0.5","1","5","10", "15","20"];
  639. this.rulerTitleContainer = new Element("div",{
  640. styles : { "overflow" : "hidden" }
  641. }).inject( this.rulerContainer );
  642. this.ruleList.each( function( rule ){
  643. new Element("div", {
  644. text : rule,
  645. styles : {
  646. width : "32px",
  647. float : "left",
  648. "text-align" : "center"
  649. }
  650. }).inject( this.rulerTitleContainer )
  651. }.bind(this));
  652. this.rulerContentContainer = new Element("div",{
  653. styles : { "overflow" : "hidden" }
  654. }).inject( this.rulerContainer );
  655. new Element("div", {
  656. styles : {
  657. width : "14px",
  658. height : "10px",
  659. "text-align" : "center",
  660. float : "left",
  661. "border-right" : "1px solid #aaa"
  662. }
  663. }).inject( this.rulerContentContainer );
  664. this.ruleList.each( function( rule, i ){
  665. if( i == this.ruleList.length - 1 )return;
  666. new Element("div", {
  667. styles : {
  668. width : "32px",
  669. height : "10px",
  670. "text-align" : "center",
  671. float : "left",
  672. "border-right" : "1px solid #aaa"
  673. }
  674. }).inject( this.rulerContentContainer )
  675. }.bind(this));
  676. this.silderContainer = new Element("div", {
  677. "height" : "25px",
  678. "line-height" : "25px",
  679. "margin-top" : "4px"
  680. }).inject( this.node );
  681. this.sliderArea = new Element("div", {styles : {
  682. "margin-top": "2px",
  683. "margin-bottom": "10px",
  684. "height": "10px",
  685. "overflow": " hidden",
  686. "margin-left": " 37px",
  687. "margin-right": " 15px",
  688. "border-top": "1px solid #999",
  689. "border-left": "1px solid #999",
  690. "border-bottom": "1px solid #E1E1E1",
  691. "border-right": "1px solid #E1E1E1",
  692. "background-color": "#EEE",
  693. "width" : "200px"
  694. }}).inject( this.silderContainer );
  695. this.sliderKnob = new Element("div", {styles : {
  696. "height": "8px",
  697. "width": " 8px",
  698. "background-color": "#999",
  699. "z-index": " 99",
  700. "border-top": "1px solid #DDD",
  701. "border-left": "1px solid #DDD",
  702. "border-bottom": "1px solid #777",
  703. "border-right": "1px solid #777",
  704. "cursor": "pointer"
  705. } }).inject( this.sliderArea );
  706. this.slider = new Slider(this.sliderArea, this.sliderKnob, {
  707. range: [1, 30],
  708. initialStep: 10,
  709. onChange: function(value){
  710. if( value < 10 ){
  711. this.lineWidth = (value / 10)
  712. }else{
  713. this.lineWidth = value - 9;
  714. }
  715. this.drawPreview( this.lineWidth );
  716. this.fireEvent("select", this.lineWidth )
  717. }.bind(this)
  718. });
  719. previewContainer = new Element("div").inject(this.node);
  720. new Element("div",{ text : "预览", styles : {
  721. "float" : "left",
  722. "margin-top" : "5px",
  723. "width" : "30px"
  724. }}).inject(this.silderContainer);
  725. this.previewNode = new Element("div", {
  726. styles : {
  727. "margin" : "0px 0px 0px 37px",
  728. "width" : "200px"
  729. }
  730. }).inject( this.node );
  731. this.canvas = new Element("canvas", {
  732. width : 200,
  733. height : 30
  734. }).inject( this.previewNode );
  735. this.ctx = this.canvas.getContext("2d");
  736. this.drawPreview();
  737. new Element("button", {
  738. text : "重置",
  739. type : "button",
  740. styles :{
  741. "margin-left" : "40px",
  742. "font-size" : "12px",
  743. "border-radius" : "3px",
  744. "cursor" : "pointer" ,
  745. "border" : "1px solid #ccc",
  746. "padding" : "5px 10px",
  747. "background-color" : "#f7f7f7"
  748. },
  749. events : {
  750. click : function(){
  751. this.lineWidth = this.options.lineWidth || 1;
  752. var step;
  753. if( this.lineWidth < 1 ){
  754. step = this.lineWidth * 10
  755. }else{
  756. step = this.lineWidth + 9
  757. }
  758. this.slider.set( parseInt( step ) );
  759. this.drawPreview( this.lineWidth );
  760. this.fireEvent("select", this.lineWidth )
  761. }.bind(this)
  762. }
  763. }).inject( this.node );
  764. }.bind(this));
  765. //this.resultInput = new Element("input").inject(this.contentNode);
  766. },
  767. drawPreview : function( lineWidth ){
  768. if( !lineWidth )lineWidth = this.options.lineWidth || 1;
  769. var canvas = this.canvas;
  770. var ctx = this.ctx;
  771. ctx.clearRect(0,0,canvas.clientWidth,canvas.clientHeight);
  772. var coordinates = this.previewNode.getCoordinates();
  773. var doc = $(document);
  774. ctx.strokeStyle="#000000"; //线条颜色; 默认 #000000
  775. //ctx.strokeStyle= this.currentColor || this.options.color; // 线条颜色; 默认 #000000
  776. ctx.lineWidth= lineWidth ; //默认1 像素
  777. ctx.beginPath();
  778. //ctx.moveTo( (coordinates.bottom-coordinates.top - lineWidth ) / 2, coordinates.left);
  779. ctx.moveTo( 1 , 15 );
  780. ctx.lineTo( 200, 15 );
  781. ctx.stroke();
  782. }
  783. });
  784. MWF.require("MWF.widget.ImageClipper", null, false);
  785. o2.widget.Tablet.ImageClipper = new Class({
  786. Implements: [Options, Events],
  787. Extends: MWF.widget.Common,
  788. options: {
  789. "imageUrl" : "",
  790. "resultMaxSize" : 800,
  791. "description" : "",
  792. "title": "裁剪图片",
  793. "style": "default",
  794. "aspectRatio": 0
  795. },
  796. initialize: function(app, options){
  797. this.setOptions(options);
  798. this.app = app;
  799. this.path = "/x_component_process_Xform/widget/$ImageClipper/";
  800. this.cssPath = "/x_component_process_Xform/widget/$ImageClipper/"+this.options.style+"/css.wcss";
  801. this._loadCss();
  802. },
  803. load: function(data){
  804. this.data = data;
  805. var options = {};
  806. var width = "668";
  807. var height = "510";
  808. width = width.toInt();
  809. height = height.toInt();
  810. var size = (( this.app && this.app.content ) || $(document.body) ).getSize();
  811. var x = (size.x-width)/2;
  812. var y = (size.y-height)/2;
  813. if (x<0) x = 0;
  814. if (y<0) y = 0;
  815. if (layout.mobile){
  816. x = 20;
  817. y = 0;
  818. }
  819. var _self = this;
  820. MWF.require("MWF.xDesktop.Dialog", function() {
  821. var dlg = new MWF.xDesktop.Dialog({
  822. "title": this.options.title || "Select Image",
  823. "style": options.style || "user",
  824. "top": y,
  825. "left": x - 20,
  826. "fromTop": y,
  827. "fromLeft": x - 20,
  828. "width": width,
  829. "height": height,
  830. "html": "<div></div>",
  831. "maskNode": this.app ? this.app.content : $(document.body),
  832. "container": this.app ? this.app.content : $(document.body),
  833. "buttonList": [
  834. {
  835. "text": MWF.LP.process.button.ok,
  836. "action": function () {
  837. var img = _self.image.getResizedImage();
  838. _self.fireEvent("ok", [img] );
  839. this.close();
  840. }
  841. },
  842. {
  843. "text": MWF.LP.process.button.cancel,
  844. "action": function () {
  845. this.close();
  846. }
  847. }
  848. ],
  849. "onPostShow" : function(){
  850. this.node.setStyle("z-index",1003);
  851. this.content.setStyle("margin-left","20px");
  852. }
  853. });
  854. dlg.show();
  855. this.image = new MWF.widget.ImageClipper(dlg.content.getFirst(), {
  856. "description" : this.options.description,
  857. "resetEnable" : true
  858. });
  859. this.image.load(this.data);
  860. }.bind(this))
  861. }
  862. });
  863. o2.widget.Tablet.ImageMover = new Class({
  864. Implements: [Options, Events],
  865. options: {
  866. imageMinSize : 100
  867. },
  868. initialize: function(tablet, imageNode, relativeNode, options){
  869. this.setOptions(options);
  870. this.tablet = tablet;
  871. this.imageNode = imageNode;
  872. this.relativeNode = relativeNode;
  873. this.path = this.tablet.path + this.tablet.options.style + "/"
  874. },
  875. load: function(){
  876. this.maskNode = new Element("div.maskNode",{
  877. styles : {
  878. "width": "100%",
  879. "height": "100%",
  880. "opacity": 0.6,
  881. "position": "absolute",
  882. "background-color": "#CCC",
  883. "top": "0px",
  884. "left": "0px",
  885. "z-index" : 1002,
  886. "-webkit-user-select": "none",
  887. "-moz-user-select": "none",
  888. "user-select" : "none"
  889. }
  890. }).inject($(document.body));
  891. var coordinates = this.relativeNode.getCoordinates();
  892. this.node = new Element( "div", {
  893. styles : {
  894. "width" : coordinates.width,
  895. "height" : coordinates.height,
  896. "position" : "absolute",
  897. "top" : coordinates.top,
  898. "left" : coordinates.left,
  899. "background" : "rgba(255,255,255,0.5)",
  900. "z-index" : 1003,
  901. "-webkit-user-select": "none",
  902. "-moz-user-select": "none",
  903. "user-select" : "none"
  904. }
  905. }).inject($(document.body));
  906. this.dragNode = new Element("div",{
  907. styles : {
  908. "cursor" : "move"
  909. }
  910. }).inject( this.node );
  911. this.imageNode.inject( this.dragNode );
  912. //this.maskNode.ondragstart = function(){
  913. // return false;
  914. //};
  915. //this.node.ondragstart = function(){
  916. // return false;
  917. //};
  918. //this.imageNode.ondragstart = function(){
  919. // return false;
  920. //};
  921. this.originalImageSize = this.imageNode.getSize();
  922. this.dragNode.setStyles({
  923. width : this.originalImageSize.x,
  924. height : this.originalImageSize.y
  925. });
  926. this.okNode = new Element("div",{
  927. styles : {
  928. "background" : "url("+ this.path + "icon/ok.png) no-repeat",
  929. "width" : "16px",
  930. "height" : "16px",
  931. "right" : "-20px",
  932. "top" : "5px",
  933. "position" : "absolute",
  934. "cursor" : "pointer"
  935. },
  936. events : {
  937. click : function(){
  938. this.ok();
  939. this.close();
  940. }.bind(this)
  941. }
  942. }).inject(this.dragNode);
  943. this.cancelNode = new Element("div",{
  944. styles : {
  945. "background" : "url("+ this.path + "icon/cancel.png) no-repeat",
  946. "width" : "16px",
  947. "height" : "16px",
  948. "right" : "-20px",
  949. "top" : "30px",
  950. "position" : "absolute",
  951. "cursor" : "pointer"
  952. },
  953. events : {
  954. click : function(){
  955. this.close();
  956. }.bind(this)
  957. }
  958. }).inject(this.dragNode);
  959. this.drag = this.dragNode.makeDraggable({
  960. "container" : this.node,
  961. "handle": this.dragNode
  962. });
  963. this.reizeNode = new Element("div.reizeNode",{ styles : {
  964. "cursor" : "nw-resize",
  965. "position": "absolute",
  966. "bottom": "0px",
  967. "right": "0px",
  968. "border" : "2px solid #52a3f5",
  969. "width" : "8px",
  970. "height" : "8px"
  971. }}).inject(this.dragNode);
  972. this.docBody = window.document.body;
  973. this.reizeNode.addEvents({
  974. "touchstart" : function(ev){
  975. this.drag.detach();
  976. this.dragNode.setStyle("cursor", "nw-resize" );
  977. this.docBody.setStyle("cursor", "nw-resize" );
  978. this.resizeMode = true;
  979. this.getOffset(ev);
  980. ev.stopPropagation();
  981. }.bind(this),
  982. "mousedown" : function(ev){
  983. this.drag.detach();
  984. this.dragNode.setStyle("cursor", "nw-resize" );
  985. this.docBody.setStyle("cursor", "nw-resize" );
  986. this.resizeMode = true;
  987. this.getOffset(ev);
  988. ev.stopPropagation();
  989. }.bind(this),
  990. "touchmove" : function(ev){
  991. if(!this.lastPoint)return;
  992. var offset= this.getOffset(ev);
  993. this.resizeDragNode( offset );
  994. ev.stopPropagation();
  995. }.bind(this),
  996. "mousemove" : function(ev){
  997. if(!this.lastPoint)return;
  998. var offset= this.getOffset(ev);
  999. this.resizeDragNode( offset );
  1000. ev.stopPropagation();
  1001. }.bind(this),
  1002. "touchend" : function(ev){
  1003. this.drag.attach();
  1004. this.dragNode.setStyle("cursor", "move" );
  1005. this.docBody.setStyle("cursor", "default" );
  1006. this.resizeMode = false;
  1007. this.lastPoint=null;
  1008. ev.stopPropagation();
  1009. }.bind(this),
  1010. "mouseup" : function(ev){
  1011. this.drag.attach();
  1012. this.dragNode.setStyle("cursor", "move" );
  1013. this.docBody.setStyle("cursor", "default" );
  1014. this.resizeMode = false;
  1015. this.lastPoint=null;
  1016. ev.stopPropagation();
  1017. }.bind(this)
  1018. });
  1019. this.bodyMouseMoveFun = this.bodyMouseMove.bind(this);
  1020. this.docBody.addEvent("touchmove", this.bodyMouseMoveFun);
  1021. this.docBody.addEvent("mousemove", this.bodyMouseMoveFun);
  1022. this.bodyMouseEndFun = this.bodyMouseEnd.bind(this);
  1023. this.docBody.addEvent("touchend", this.bodyMouseEndFun);
  1024. this.docBody.addEvent("mouseup", this.bodyMouseEndFun);
  1025. },
  1026. bodyMouseMove: function(ev){
  1027. if(!this.lastPoint)return;
  1028. if( this.resizeMode ){
  1029. var offset= this.getOffset(ev);
  1030. this.resizeDragNode( offset );
  1031. }
  1032. },
  1033. bodyMouseEnd: function(ev){
  1034. this.lastPoint=null;
  1035. if( this.resizeMode ){
  1036. this.drag.attach();
  1037. this.dragNode.setStyle("cursor", "move" );
  1038. this.docBody.setStyle("cursor", "default" );
  1039. this.resizeMode = false;
  1040. }
  1041. },
  1042. resizeDragNode : function(offset){
  1043. var x=offset.x;
  1044. if( x == 0 )return;
  1045. var y=offset.y;
  1046. if( y == 0 )return;
  1047. debugger;
  1048. var coordinates = this.dragNode.getCoordinates( this.node );
  1049. var containerSize = this.node.getSize();
  1050. var top=coordinates.top,
  1051. left=coordinates.left,
  1052. width=containerSize.x,
  1053. height=containerSize.y,
  1054. ratio = this.originalImageSize.x / this.originalImageSize.y,
  1055. w,
  1056. h;
  1057. //if( ratio ){
  1058. if( Math.abs(x)/Math.abs(y) > ratio ){
  1059. if( x+coordinates.width+left>width ){
  1060. return;
  1061. }else{
  1062. w = x + coordinates.width;
  1063. h = w / ratio;
  1064. if( h+top > height ){
  1065. return;
  1066. }
  1067. }
  1068. }else{
  1069. if(y+coordinates.height+top>height){
  1070. return;
  1071. }else{
  1072. h = y+ coordinates.height;
  1073. w = h * ratio;
  1074. }
  1075. if( w+left > width ){
  1076. return;
  1077. }
  1078. }
  1079. //}else{
  1080. // if( x+coordinates.width+left>width ){
  1081. // return;
  1082. // }else{
  1083. // w = x + coordinates.width
  1084. // }
  1085. // if(y+coordinates.height+top>height){
  1086. // return;
  1087. // }else{
  1088. // h = y+ coordinates.height;
  1089. // }
  1090. //}
  1091. var minWidth = this.options.imageMinSize;
  1092. var minHeight = this.options.imageMinSize;
  1093. w=w< minWidth ? minWidth:w;
  1094. h=h< minHeight ? minHeight:h;
  1095. this.dragNode.setStyles({
  1096. width:w+'px',
  1097. height:h+'px'
  1098. });
  1099. this.imageNode.setStyles({
  1100. width:w+'px',
  1101. height:h+'px'
  1102. });
  1103. },
  1104. getOffset: function(event){
  1105. event=event.event;
  1106. var x,y;
  1107. if(event.touches){
  1108. var touch=event.touches[0];
  1109. x=touch.clientX;
  1110. y=touch.clientY;
  1111. }else{
  1112. x=event.clientX;
  1113. y=event.clientY;
  1114. }
  1115. if(!this.lastPoint){
  1116. this.lastPoint={
  1117. x:x,
  1118. y:y
  1119. };
  1120. }
  1121. var offset={
  1122. x:x-this.lastPoint.x,
  1123. y:y-this.lastPoint.y
  1124. };
  1125. this.lastPoint={
  1126. x:x,
  1127. y:y
  1128. };
  1129. return offset;
  1130. },
  1131. getCoordinage : function(){
  1132. return this.imageNode.getCoordinates( this.node );
  1133. },
  1134. ok : function(){
  1135. this.fireEvent("postOk")
  1136. },
  1137. close : function(){
  1138. this.docBody.removeEvent("touchmove",this.bodyMouseMoveFun);
  1139. this.docBody.removeEvent("mousemove",this.bodyMouseMoveFun);
  1140. this.docBody.removeEvent("touchend",this.bodyMouseEndFun);
  1141. this.docBody.removeEvent("mouseup",this.bodyMouseEndFun);
  1142. //this.backgroundNode.destroy();
  1143. this.maskNode.destroy();
  1144. this.node.destroy();
  1145. delete this;
  1146. }
  1147. });