Tablet.js 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284
  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( null, true );
  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, ignoreResultSize ){
  247. var src = base64Code || this.getBase64Code( ignoreResultSize);
  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( ignoreResultSize ){
  256. var ctx = this.ctx;
  257. var canvas = this.canvas;
  258. //var container = this.contentNode;
  259. //var size = this.options.size;
  260. if( !ignoreResultSize && this.options.resultMaxSize ){
  261. var width, height;
  262. width = Math.min( this.contentWidth , this.options.resultMaxSize);
  263. height = ( width / this.contentWidth) * this.contentHeight;
  264. var src=canvas.toDataURL( this.fileType );
  265. src=src.split(',')[1];
  266. src = 'data:'+ this.fileType +';base64,' + src;
  267. var tmpImageNode = new Element("img", {
  268. width : this.contentWidth,
  269. height : this.contentHeight,
  270. src : src
  271. });
  272. var tmpCanvas = new Element("canvas", {
  273. width : width,
  274. height : height
  275. }).inject( this.contentNode );
  276. var tmpCtx = tmpCanvas.getContext("2d");
  277. tmpCtx.drawImage(tmpImageNode,0,0, this.contentWidth,this.contentHeight,0,0,width,height);
  278. var tmpsrc= tmpCanvas.toDataURL( this.fileType );
  279. tmpsrc=tmpsrc.split(',')[1];
  280. tmpImageNode.destroy();
  281. tmpCanvas.destroy();
  282. tmpCtx = null;
  283. if(!tmpsrc){
  284. return "";
  285. }else{
  286. return tmpsrc
  287. }
  288. }else{
  289. var src=canvas.toDataURL( this.fileType );
  290. src=src.split(',')[1];
  291. if(!src){
  292. return "";
  293. }else{
  294. return src
  295. }
  296. }
  297. },
  298. getBase64Image: function( base64Code, ignoreResultSize ){
  299. if( !base64Code )base64Code = this.getBase64Code( ignoreResultSize );
  300. if( !base64Code )return null;
  301. return 'data:'+ this.fileType +';base64,' + base64Code;
  302. },
  303. close : function(){
  304. this.container.destroy();
  305. delete this;
  306. },
  307. checkBroswer : function(){
  308. if( window.Uint8Array && window.HTMLCanvasElement && window.atob && window.Blob){
  309. this.available = true;
  310. return true;
  311. }else{
  312. this.available = false;
  313. this.container.set("html", "<p>您的浏览器不支持以下特性:</p><ul><li>canvas</li><li>Blob</li><li>Uint8Array</li><li>FormData</li><li>atob</li></ul>");
  314. return false;
  315. }
  316. },
  317. save : function(){
  318. var base64code = this.getBase64Code();
  319. var imageFile = this.getImage( base64code );
  320. var base64Image = this.getBase64Image( base64code );
  321. this.fireEvent("save", [ base64code, base64Image, imageFile]);
  322. },
  323. reset : function( itemNode ){
  324. this.fileName = "untitled.png";
  325. this.fileType = "image/png";
  326. if( this.ctx ){
  327. var canvas = this.canvas;
  328. this.ctx.clearRect(0,0,canvas.clientWidth,canvas.clientHeight);
  329. }
  330. },
  331. undo : function( itemNode ){
  332. if(this.preDrawAry.length>0){
  333. var popData=this.preDrawAry.pop();
  334. var midData=this.middleAry[this.preDrawAry.length+1];
  335. this.nextDrawAry.push(midData);
  336. this.ctx.putImageData(popData,0,0);
  337. }
  338. this.toolbar.setAllItemsStatus();
  339. },
  340. redo : function( itemNode ){
  341. if(this.nextDrawAry.length){
  342. var popData=this.nextDrawAry.pop();
  343. var midData=this.middleAry[this.middleAry.length-this.nextDrawAry.length-2];
  344. this.preDrawAry.push(midData);
  345. this.ctx.putImageData(popData,0,0);
  346. }
  347. this.toolbar.setAllItemsStatus();
  348. },
  349. size : function( itemNode ){
  350. if( !this.sizeSelector ){
  351. this.sizeSelector = new o2.widget.Tablet.SizePicker(this.container, itemNode, null, {}, {
  352. "onSelect": function (width) {
  353. this.currentWidth = width;
  354. }.bind(this)
  355. });
  356. }
  357. },
  358. color : function( itemNode ){
  359. if( !this.colorSelector ){
  360. this.colorSelector = new o2.xApplication.Template.widget.ColorPicker( this.container, itemNode, null, {}, {
  361. "lineWidth" : 1,
  362. "onSelect": function (color) {
  363. this.currentColor = color;
  364. }.bind(this)
  365. });
  366. }
  367. },
  368. getImageSize : function(naturalWidth, naturalHeight ){
  369. var ratio = naturalWidth / naturalHeight;
  370. var ww = this.contentWidth,
  371. wh = this.contentHeight;
  372. var flag = ( naturalWidth / parseInt(ww) ) > ( naturalHeight / parseInt(wh) );
  373. if( flag ){
  374. var width = Math.min( naturalWidth, parseInt( ww ) );
  375. return { width : width, height : width / ratio }
  376. }else{
  377. var height = Math.min( naturalHeight, parseInt( wh ) );
  378. return { width : height * ratio, height : height }
  379. }
  380. },
  381. parseFileToImage : function( file, callback ){
  382. var imageNode = new Element("img");
  383. var onImageLoad = function(){
  384. var nh = imageNode.naturalHeight,
  385. nw = imageNode.naturalWidth;
  386. if( isNaN(nh) || isNaN(nw) || nh == 0 || nw == 0 ){
  387. setTimeout( function(){ onImageLoad(); }.bind(this), 100 );
  388. }else{
  389. _onImageLoad();
  390. }
  391. };
  392. var _onImageLoad = function(){
  393. var nh = imageNode.naturalHeight,
  394. nw = imageNode.naturalWidth;
  395. var size = this.getImageSize( nw, nh );
  396. imageNode.setStyles({
  397. width : size.width,
  398. height : size.height
  399. });
  400. var mover = new o2.widget.Tablet.ImageMover( this, imageNode, this.contentNode , {
  401. onPostOk : function(){
  402. var coordinate = mover.getCoordinage();
  403. this.storeToPreArray();
  404. this.ctx.drawImage(imageNode, coordinate.left, coordinate.top, coordinate.width, coordinate.height);
  405. this.storeToMiddleArray();
  406. }.bind(this)
  407. });
  408. mover.load();
  409. if( callback )callback();
  410. }.bind(this);
  411. var reader=new FileReader();
  412. reader.onload=function(){
  413. imageNode.src=reader.result;
  414. reader = null;
  415. onImageLoad();
  416. }.bind(this);
  417. reader.readAsDataURL(file);
  418. },
  419. image : function( itemNode ){
  420. var uploadFileAreaNode = new Element("div");
  421. var html = "<input name=\"file\" type=\"file\" />"; //accept=\"images/*\"
  422. uploadFileAreaNode.set("html", html);
  423. var fileUploadNode = uploadFileAreaNode.getFirst();
  424. fileUploadNode.addEvent("change", function () {
  425. var file = fileUploadNode.files[0];
  426. this.parseFileToImage( file, function(){
  427. uploadFileAreaNode.destroy();
  428. })
  429. }.bind(this));
  430. fileUploadNode.click();
  431. },
  432. imageClipper : function( itemNode ){
  433. var clipper = new o2.widget.Tablet.ImageClipper(this.app, {
  434. "style": "default",
  435. "aspectRatio" : 0,
  436. "onOk" : function( img ){
  437. this.parseFileToImage( img );
  438. }.bind(this)
  439. });
  440. clipper.load();
  441. },
  442. clear : function( itemNode ){
  443. },
  444. cancel: function(){
  445. this.reset();
  446. this.fireEvent("cancel");
  447. }
  448. });
  449. o2.widget.Tablet.Toolbar = new Class({
  450. Implements: [Options, Events],
  451. initialize: function (tablet, container) {
  452. this.tablet = tablet;
  453. this.container = container;
  454. this.css = tablet.css;
  455. this.lp = this.tablet.lp;
  456. this.imagePath = o2.session.path+"/widget/$Tablet/"+ this.tablet.options.style +"/icon/";
  457. this.items = {};
  458. this.itemsEnableFun = {
  459. save : {
  460. enable : function(){ return true }
  461. },
  462. reset : {
  463. enable : function(){ return this.tablet.preDrawAry.length > 0}.bind(this)
  464. },
  465. undo : {
  466. enable : function(){ return this.tablet.preDrawAry.length > 0 }.bind(this)
  467. },
  468. redo : {
  469. enable : function(){ return this.tablet.nextDrawAry.length > 0 }.bind(this)
  470. },
  471. size : {
  472. enable : function(){ return true }
  473. },
  474. color : {
  475. enable : function(){ return true }
  476. },
  477. image : {
  478. enable : function(){ return true }
  479. },
  480. imageClipper : {
  481. enable : function(){ return true }
  482. }
  483. }
  484. },
  485. getHtml : function(){
  486. var items;
  487. var tools = this.tablet.options.tools;
  488. if( tools ){
  489. items = tools;
  490. }else{
  491. items = [
  492. "save", "|",
  493. "reset", "|",
  494. "undo", "|",
  495. "redo", "|",
  496. "size", "|",
  497. "color", "|",
  498. "image", "|",
  499. "imageClipper"
  500. //"clear" //橡皮
  501. ];
  502. }
  503. var html = "";
  504. var style = "toolItem";
  505. items.each( function( item ){
  506. switch( item ){
  507. case "|":
  508. html += "<div styles='" + "separator" + "'></div>";
  509. break;
  510. case "save" :
  511. html += "<div item='save' styles='" + style + "'>"+ this.lp.save +"</div>";
  512. break;
  513. case "reset" :
  514. html += "<div item='reset' styles='" + style + "'>"+ this.lp.reset +"</div>";
  515. break;
  516. case "undo" :
  517. html += "<div item='undo' styles='" + style + "'>"+ this.lp.undo +"</div>";
  518. break;
  519. case "redo" :
  520. html += "<div item='redo' styles='" + style + "'>"+ this.lp.redo +"</div>";
  521. break;
  522. case "size" :
  523. html += "<div item='size' styles='" + style + "'>"+ this.lp.size +"</div>";
  524. break;
  525. case "color" :
  526. html += "<div item='color' styles='" + style + "'>"+ this.lp.color +"</div>";
  527. break;
  528. case "image" :
  529. html += "<div item='image' styles='" + style + "'>"+ this.lp.image +"</div>";
  530. break;
  531. case "imageClipper" :
  532. html += "<div item='imageClipper' styles='" + style + "'>"+ this.lp.imageClipper +"</div>";
  533. break;
  534. case "clear" :
  535. html += "<div item='clear' styles='" + style + "'>"+ this.lp.clear +"</div>";
  536. break;
  537. case "cancel" :
  538. html += "<div item='cancel' styles='toolRightItem'>"+ this.lp.cancel +"</div>";
  539. break;
  540. }
  541. }.bind(this));
  542. return html;
  543. },
  544. load: function () {
  545. var _self = this;
  546. var imagePath = this.imagePath;
  547. this.items = {};
  548. var html = this.getHtml();
  549. this.container.set("html", html);
  550. this.container.getElements("[styles]").each(function (el) {
  551. el.setStyles(_self.css[el.get("styles")]);
  552. var item = el.get("item");
  553. if ( item ) {
  554. this.items[ item ] = el;
  555. el.setStyle("background-image","url("+ imagePath + item +"_normal.png)");
  556. el.addEvents({
  557. mouseover : function(){
  558. _self._setItemNodeActive(this.el);
  559. }.bind({ item : item, el : el }),
  560. mouseout : function(){
  561. _self._setItemNodeNormal(this.el);
  562. }.bind({ item : item, el : el }),
  563. click : function( ev ){
  564. if( _self["tablet"][this.item] )_self["tablet"][this.item]( this.el );
  565. }.bind({ item : item, el : el })
  566. });
  567. if( item == "color" || item == "size" ){
  568. if( _self["tablet"][item] )_self["tablet"][item]( el );
  569. }
  570. }
  571. }.bind(this));
  572. this.setAllItemsStatus();
  573. },
  574. setAllItemsStatus : function(){
  575. for( var item in this.items ){
  576. var node = this.items[item];
  577. if( this.itemsEnableFun[item] ){
  578. if( this.itemsEnableFun[item].enable() ){
  579. this.enableItem( item )
  580. }else{
  581. this.disableItem( item );
  582. }
  583. }
  584. }
  585. },
  586. disableItem : function( itemName ){
  587. var itemNode = this.items[ itemName ]; //this.container.getElement("[item='+itemName+']");
  588. itemNode.store("status", "disable");
  589. this._setItemNodeDisable( itemNode );
  590. },
  591. enableItem : function( itemName ){
  592. var itemNode = this.items[ itemName ];
  593. itemNode.store("status", "enable");
  594. this._setItemNodeNormal( itemNode );
  595. },
  596. _setItemNodeDisable : function( itemNode ){
  597. var item = itemNode.get("item");
  598. itemNode.setStyles( this.css.toolItem_disable );
  599. itemNode.setStyle("background-image","url("+ this.imagePath+ item +"_disable.png)");
  600. },
  601. _setItemNodeActive: function( itemNode ){
  602. if( itemNode.retrieve("status") == "disable" )return;
  603. var item = itemNode.get("item");
  604. itemNode.setStyles( this.css.toolItem_over );
  605. itemNode.setStyle("background-image","url("+ this.imagePath+ item +"_active.png)");
  606. },
  607. _setItemNodeNormal: function( itemNode ){
  608. if( itemNode.retrieve("status") == "disable" )return;
  609. var item = itemNode.get("item");
  610. var style = itemNode.get("styles");
  611. itemNode.setStyles( this.css[style] );
  612. itemNode.setStyle("background-image","url("+ this.imagePath+ item +"_normal.png)");
  613. }
  614. });
  615. o2.xDesktop.requireApp("Template", "MTooltips", null, false);
  616. o2.widget.Tablet.SizePicker = new Class({
  617. Implements: [Options, Events],
  618. Extends: MTooltips,
  619. options: {
  620. style : "default",
  621. axis: "y", //箭头在x轴还是y轴上展现
  622. position : { //node 固定的位置
  623. x : "auto", //x 轴上left center right, auto 系统自动计算
  624. y : "auto" //y轴上top middle bottom, auto 系统自动计算
  625. },
  626. //event : "click", //事件类型,有target 时有效, mouseenter对应mouseleave,click 对应 container 的 click
  627. nodeStyles : {
  628. "min-width" : "260px"
  629. },
  630. lineWidth : 1
  631. },
  632. initialize : function( container, target, app, data, options, targetCoordinates ){
  633. //可以传入target 或者 targetCoordinates,两种选一
  634. //传入target,表示触发tooltip的节点,本类根据 this.options.event 自动绑定target的事件
  635. //传入targetCoordinates,表示 出发tooltip的位置,本类不绑定触发事件
  636. if( options ){
  637. this.setOptions(options);
  638. }
  639. this.container = container;
  640. this.target = target;
  641. this.targetCoordinates = targetCoordinates;
  642. this.app = app;
  643. if(app)this.lp = app.lp;
  644. this.data = data;
  645. if( this.target ){
  646. this.setTargetEvents();
  647. }
  648. },
  649. _customNode : function( node ){
  650. o2.UD.getDataJson("sizePicker", function(json) {
  651. this.rulerContainer = new Element("div",{
  652. styles : {
  653. "margin-left": " 23px",
  654. "margin-right": " 1px",
  655. "width" : "228px"
  656. }
  657. }).inject(this.node);
  658. this.ruleList = ["0.1","0.5","1","5","10", "15","20"];
  659. this.rulerTitleContainer = new Element("div",{
  660. styles : { "overflow" : "hidden" }
  661. }).inject( this.rulerContainer );
  662. this.ruleList.each( function( rule ){
  663. new Element("div", {
  664. text : rule,
  665. styles : {
  666. width : "32px",
  667. float : "left",
  668. "text-align" : "center"
  669. }
  670. }).inject( this.rulerTitleContainer )
  671. }.bind(this));
  672. this.rulerContentContainer = new Element("div",{
  673. styles : { "overflow" : "hidden" }
  674. }).inject( this.rulerContainer );
  675. new Element("div", {
  676. styles : {
  677. width : "14px",
  678. height : "10px",
  679. "text-align" : "center",
  680. float : "left",
  681. "border-right" : "1px solid #aaa"
  682. }
  683. }).inject( this.rulerContentContainer );
  684. this.ruleList.each( function( rule, i ){
  685. if( i == this.ruleList.length - 1 )return;
  686. new Element("div", {
  687. styles : {
  688. width : "32px",
  689. height : "10px",
  690. "text-align" : "center",
  691. float : "left",
  692. "border-right" : "1px solid #aaa"
  693. }
  694. }).inject( this.rulerContentContainer )
  695. }.bind(this));
  696. this.silderContainer = new Element("div", {
  697. "height" : "25px",
  698. "line-height" : "25px",
  699. "margin-top" : "4px"
  700. }).inject( this.node );
  701. this.sliderArea = new Element("div", {styles : {
  702. "margin-top": "2px",
  703. "margin-bottom": "10px",
  704. "height": "10px",
  705. "overflow": " hidden",
  706. "margin-left": " 37px",
  707. "margin-right": " 15px",
  708. "border-top": "1px solid #999",
  709. "border-left": "1px solid #999",
  710. "border-bottom": "1px solid #E1E1E1",
  711. "border-right": "1px solid #E1E1E1",
  712. "background-color": "#EEE",
  713. "width" : "200px"
  714. }}).inject( this.silderContainer );
  715. this.sliderKnob = new Element("div", {styles : {
  716. "height": "8px",
  717. "width": " 8px",
  718. "background-color": "#999",
  719. "z-index": " 99",
  720. "border-top": "1px solid #DDD",
  721. "border-left": "1px solid #DDD",
  722. "border-bottom": "1px solid #777",
  723. "border-right": "1px solid #777",
  724. "cursor": "pointer"
  725. } }).inject( this.sliderArea );
  726. this.slider = new Slider(this.sliderArea, this.sliderKnob, {
  727. range: [1, 30],
  728. initialStep: 10,
  729. onChange: function(value){
  730. if( value < 10 ){
  731. this.lineWidth = (value / 10)
  732. }else{
  733. this.lineWidth = value - 9;
  734. }
  735. this.drawPreview( this.lineWidth );
  736. this.fireEvent("select", this.lineWidth )
  737. }.bind(this)
  738. });
  739. var previewContainer = new Element("div").inject(this.node);
  740. new Element("div",{ text : "预览", styles : {
  741. "float" : "left",
  742. "margin-top" : "5px",
  743. "width" : "30px"
  744. }}).inject(this.silderContainer);
  745. this.previewNode = new Element("div", {
  746. styles : {
  747. "margin" : "0px 0px 0px 37px",
  748. "width" : "200px"
  749. }
  750. }).inject( this.node );
  751. this.canvas = new Element("canvas", {
  752. width : 200,
  753. height : 30
  754. }).inject( this.previewNode );
  755. this.ctx = this.canvas.getContext("2d");
  756. this.drawPreview();
  757. new Element("button", {
  758. text : "重置",
  759. type : "button",
  760. styles :{
  761. "margin-left" : "40px",
  762. "font-size" : "12px",
  763. "border-radius" : "3px",
  764. "cursor" : "pointer" ,
  765. "border" : "1px solid #ccc",
  766. "padding" : "5px 10px",
  767. "background-color" : "#f7f7f7"
  768. },
  769. events : {
  770. click : function(){
  771. this.lineWidth = this.options.lineWidth || 1;
  772. var step;
  773. if( this.lineWidth < 1 ){
  774. step = this.lineWidth * 10
  775. }else{
  776. step = this.lineWidth + 9
  777. }
  778. this.slider.set( parseInt( step ) );
  779. this.drawPreview( this.lineWidth );
  780. this.fireEvent("select", this.lineWidth )
  781. }.bind(this)
  782. }
  783. }).inject( this.node );
  784. }.bind(this));
  785. //this.resultInput = new Element("input").inject(this.contentNode);
  786. },
  787. drawPreview : function( lineWidth ){
  788. if( !lineWidth )lineWidth = this.options.lineWidth || 1;
  789. var canvas = this.canvas;
  790. var ctx = this.ctx;
  791. ctx.clearRect(0,0,canvas.clientWidth,canvas.clientHeight);
  792. var coordinates = this.previewNode.getCoordinates();
  793. var doc = $(document);
  794. ctx.strokeStyle="#000000"; //线条颜色; 默认 #000000
  795. //ctx.strokeStyle= this.currentColor || this.options.color; // 线条颜色; 默认 #000000
  796. ctx.lineWidth= lineWidth ; //默认1 像素
  797. ctx.beginPath();
  798. //ctx.moveTo( (coordinates.bottom-coordinates.top - lineWidth ) / 2, coordinates.left);
  799. ctx.moveTo( 1 , 15 );
  800. ctx.lineTo( 200, 15 );
  801. ctx.stroke();
  802. }
  803. });
  804. MWF.require("MWF.widget.ImageClipper", null, false);
  805. o2.widget.Tablet.ImageClipper = new Class({
  806. Implements: [Options, Events],
  807. Extends: MWF.widget.Common,
  808. options: {
  809. "imageUrl" : "",
  810. "resultMaxSize" : 800,
  811. "description" : "",
  812. "title": "裁剪图片",
  813. "style": "default",
  814. "aspectRatio": 0
  815. },
  816. initialize: function(app, options){
  817. this.setOptions(options);
  818. this.app = app;
  819. this.path = "../x_component_process_Xform/widget/$ImageClipper/";
  820. this.cssPath = "../x_component_process_Xform/widget/$ImageClipper/"+this.options.style+"/css.wcss";
  821. this._loadCss();
  822. },
  823. load: function(data){
  824. this.data = data;
  825. var options = {};
  826. var width = "668";
  827. var height = "510";
  828. width = width.toInt();
  829. height = height.toInt();
  830. var size = (( this.app && this.app.content ) || $(document.body) ).getSize();
  831. var x = (size.x-width)/2;
  832. var y = (size.y-height)/2;
  833. if (x<0) x = 0;
  834. if (y<0) y = 0;
  835. if (layout.mobile){
  836. x = 20;
  837. y = 0;
  838. }
  839. var _self = this;
  840. MWF.require("MWF.xDesktop.Dialog", function() {
  841. var dlg = new MWF.xDesktop.Dialog({
  842. "title": this.options.title || "Select Image",
  843. "style": options.style || "user",
  844. "top": y,
  845. "left": x - 20,
  846. "fromTop": y,
  847. "fromLeft": x - 20,
  848. "width": width,
  849. "height": height,
  850. "html": "<div></div>",
  851. "maskNode": this.app ? this.app.content : $(document.body),
  852. "container": this.app ? this.app.content : $(document.body),
  853. "buttonList": [
  854. {
  855. "text": MWF.LP.process.button.ok,
  856. "action": function () {
  857. var img = _self.image.getResizedImage();
  858. _self.fireEvent("ok", [img] );
  859. this.close();
  860. }
  861. },
  862. {
  863. "text": MWF.LP.process.button.cancel,
  864. "action": function () {
  865. this.close();
  866. }
  867. }
  868. ],
  869. "onPostShow" : function(){
  870. this.node.setStyle("z-index",1003);
  871. this.content.setStyle("margin-left","20px");
  872. }
  873. });
  874. dlg.show();
  875. this.image = new MWF.widget.ImageClipper(dlg.content.getFirst(), {
  876. "description" : this.options.description,
  877. "resetEnable" : true
  878. });
  879. this.image.load(this.data);
  880. }.bind(this))
  881. }
  882. });
  883. o2.widget.Tablet.ImageMover = new Class({
  884. Implements: [Options, Events],
  885. options: {
  886. imageMinSize : 100
  887. },
  888. initialize: function(tablet, imageNode, relativeNode, options){
  889. this.setOptions(options);
  890. this.tablet = tablet;
  891. this.imageNode = imageNode;
  892. this.relativeNode = relativeNode;
  893. this.path = this.tablet.path + this.tablet.options.style + "/"
  894. },
  895. load: function(){
  896. this.maskNode = new Element("div.maskNode",{
  897. styles : {
  898. "width": "100%",
  899. "height": "100%",
  900. "opacity": 0.6,
  901. "position": "absolute",
  902. "background-color": "#CCC",
  903. "top": "0px",
  904. "left": "0px",
  905. "z-index" : 1002,
  906. "-webkit-user-select": "none",
  907. "-moz-user-select": "none",
  908. "user-select" : "none"
  909. }
  910. }).inject($(document.body));
  911. var coordinates = this.relativeNode.getCoordinates();
  912. this.node = new Element( "div", {
  913. styles : {
  914. "width" : coordinates.width,
  915. "height" : coordinates.height,
  916. "position" : "absolute",
  917. "top" : coordinates.top,
  918. "left" : coordinates.left,
  919. "background" : "rgba(255,255,255,0.5)",
  920. "z-index" : 1003,
  921. "-webkit-user-select": "none",
  922. "-moz-user-select": "none",
  923. "user-select" : "none"
  924. }
  925. }).inject($(document.body));
  926. this.dragNode = new Element("div",{
  927. styles : {
  928. "cursor" : "move"
  929. }
  930. }).inject( this.node );
  931. this.imageNode.inject( this.dragNode );
  932. //this.maskNode.ondragstart = function(){
  933. // return false;
  934. //};
  935. //this.node.ondragstart = function(){
  936. // return false;
  937. //};
  938. //this.imageNode.ondragstart = function(){
  939. // return false;
  940. //};
  941. this.originalImageSize = this.imageNode.getSize();
  942. this.dragNode.setStyles({
  943. width : this.originalImageSize.x,
  944. height : this.originalImageSize.y
  945. });
  946. this.okNode = new Element("div",{
  947. styles : {
  948. "background" : "url("+ this.path + "icon/ok.png) no-repeat",
  949. "width" : "16px",
  950. "height" : "16px",
  951. "right" : "-20px",
  952. "top" : "5px",
  953. "position" : "absolute",
  954. "cursor" : "pointer"
  955. },
  956. events : {
  957. click : function(){
  958. this.ok();
  959. this.close();
  960. }.bind(this)
  961. }
  962. }).inject(this.dragNode);
  963. this.cancelNode = new Element("div",{
  964. styles : {
  965. "background" : "url("+ this.path + "icon/cancel.png) no-repeat",
  966. "width" : "16px",
  967. "height" : "16px",
  968. "right" : "-20px",
  969. "top" : "30px",
  970. "position" : "absolute",
  971. "cursor" : "pointer"
  972. },
  973. events : {
  974. click : function(){
  975. this.close();
  976. }.bind(this)
  977. }
  978. }).inject(this.dragNode);
  979. this.drag = this.dragNode.makeDraggable({
  980. "container" : this.node,
  981. "handle": this.dragNode
  982. });
  983. this.reizeNode = new Element("div.reizeNode",{ styles : {
  984. "cursor" : "nw-resize",
  985. "position": "absolute",
  986. "bottom": "0px",
  987. "right": "0px",
  988. "border" : "2px solid #52a3f5",
  989. "width" : "8px",
  990. "height" : "8px"
  991. }}).inject(this.dragNode);
  992. this.docBody = window.document.body;
  993. this.reizeNode.addEvents({
  994. "touchstart" : function(ev){
  995. this.drag.detach();
  996. this.dragNode.setStyle("cursor", "nw-resize" );
  997. this.docBody.setStyle("cursor", "nw-resize" );
  998. this.resizeMode = true;
  999. this.getOffset(ev);
  1000. ev.stopPropagation();
  1001. }.bind(this),
  1002. "mousedown" : function(ev){
  1003. this.drag.detach();
  1004. this.dragNode.setStyle("cursor", "nw-resize" );
  1005. this.docBody.setStyle("cursor", "nw-resize" );
  1006. this.resizeMode = true;
  1007. this.getOffset(ev);
  1008. ev.stopPropagation();
  1009. }.bind(this),
  1010. "touchmove" : function(ev){
  1011. if(!this.lastPoint)return;
  1012. var offset= this.getOffset(ev);
  1013. this.resizeDragNode( offset );
  1014. ev.stopPropagation();
  1015. }.bind(this),
  1016. "mousemove" : function(ev){
  1017. if(!this.lastPoint)return;
  1018. var offset= this.getOffset(ev);
  1019. this.resizeDragNode( offset );
  1020. ev.stopPropagation();
  1021. }.bind(this),
  1022. "touchend" : function(ev){
  1023. this.drag.attach();
  1024. this.dragNode.setStyle("cursor", "move" );
  1025. this.docBody.setStyle("cursor", "default" );
  1026. this.resizeMode = false;
  1027. this.lastPoint=null;
  1028. ev.stopPropagation();
  1029. }.bind(this),
  1030. "mouseup" : function(ev){
  1031. this.drag.attach();
  1032. this.dragNode.setStyle("cursor", "move" );
  1033. this.docBody.setStyle("cursor", "default" );
  1034. this.resizeMode = false;
  1035. this.lastPoint=null;
  1036. ev.stopPropagation();
  1037. }.bind(this)
  1038. });
  1039. this.bodyMouseMoveFun = this.bodyMouseMove.bind(this);
  1040. this.docBody.addEvent("touchmove", this.bodyMouseMoveFun);
  1041. this.docBody.addEvent("mousemove", this.bodyMouseMoveFun);
  1042. this.bodyMouseEndFun = this.bodyMouseEnd.bind(this);
  1043. this.docBody.addEvent("touchend", this.bodyMouseEndFun);
  1044. this.docBody.addEvent("mouseup", this.bodyMouseEndFun);
  1045. },
  1046. bodyMouseMove: function(ev){
  1047. if(!this.lastPoint)return;
  1048. if( this.resizeMode ){
  1049. var offset= this.getOffset(ev);
  1050. this.resizeDragNode( offset );
  1051. }
  1052. },
  1053. bodyMouseEnd: function(ev){
  1054. this.lastPoint=null;
  1055. if( this.resizeMode ){
  1056. this.drag.attach();
  1057. this.dragNode.setStyle("cursor", "move" );
  1058. this.docBody.setStyle("cursor", "default" );
  1059. this.resizeMode = false;
  1060. }
  1061. },
  1062. resizeDragNode : function(offset){
  1063. var x=offset.x;
  1064. if( x == 0 )return;
  1065. var y=offset.y;
  1066. if( y == 0 )return;
  1067. debugger;
  1068. var coordinates = this.dragNode.getCoordinates( this.node );
  1069. var containerSize = this.node.getSize();
  1070. var top=coordinates.top,
  1071. left=coordinates.left,
  1072. width=containerSize.x,
  1073. height=containerSize.y,
  1074. ratio = this.originalImageSize.x / this.originalImageSize.y,
  1075. w,
  1076. h;
  1077. //if( ratio ){
  1078. if( Math.abs(x)/Math.abs(y) > ratio ){
  1079. if( x+coordinates.width+left>width ){
  1080. return;
  1081. }else{
  1082. w = x + coordinates.width;
  1083. h = w / ratio;
  1084. if( h+top > height ){
  1085. return;
  1086. }
  1087. }
  1088. }else{
  1089. if(y+coordinates.height+top>height){
  1090. return;
  1091. }else{
  1092. h = y+ coordinates.height;
  1093. w = h * ratio;
  1094. }
  1095. if( w+left > width ){
  1096. return;
  1097. }
  1098. }
  1099. //}else{
  1100. // if( x+coordinates.width+left>width ){
  1101. // return;
  1102. // }else{
  1103. // w = x + coordinates.width
  1104. // }
  1105. // if(y+coordinates.height+top>height){
  1106. // return;
  1107. // }else{
  1108. // h = y+ coordinates.height;
  1109. // }
  1110. //}
  1111. var minWidth = this.options.imageMinSize;
  1112. var minHeight = this.options.imageMinSize;
  1113. w=w< minWidth ? minWidth:w;
  1114. h=h< minHeight ? minHeight:h;
  1115. this.dragNode.setStyles({
  1116. width:w+'px',
  1117. height:h+'px'
  1118. });
  1119. this.imageNode.setStyles({
  1120. width:w+'px',
  1121. height:h+'px'
  1122. });
  1123. },
  1124. getOffset: function(event){
  1125. event=event.event;
  1126. var x,y;
  1127. if(event.touches){
  1128. var touch=event.touches[0];
  1129. x=touch.clientX;
  1130. y=touch.clientY;
  1131. }else{
  1132. x=event.clientX;
  1133. y=event.clientY;
  1134. }
  1135. if(!this.lastPoint){
  1136. this.lastPoint={
  1137. x:x,
  1138. y:y
  1139. };
  1140. }
  1141. var offset={
  1142. x:x-this.lastPoint.x,
  1143. y:y-this.lastPoint.y
  1144. };
  1145. this.lastPoint={
  1146. x:x,
  1147. y:y
  1148. };
  1149. return offset;
  1150. },
  1151. getCoordinage : function(){
  1152. return this.imageNode.getCoordinates( this.node );
  1153. },
  1154. ok : function(){
  1155. this.fireEvent("postOk")
  1156. },
  1157. close : function(){
  1158. this.docBody.removeEvent("touchmove",this.bodyMouseMoveFun);
  1159. this.docBody.removeEvent("mousemove",this.bodyMouseMoveFun);
  1160. this.docBody.removeEvent("touchend",this.bodyMouseEndFun);
  1161. this.docBody.removeEvent("mouseup",this.bodyMouseEndFun);
  1162. //this.backgroundNode.destroy();
  1163. this.maskNode.destroy();
  1164. this.node.destroy();
  1165. delete this;
  1166. }
  1167. });