Tablet.js 105 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922
  1. o2.widget = o2.widget || {};
  2. o2.xDesktop.requireApp("Template", "MSelector", null, false);
  3. o2.xDesktop.requireApp("Template", "widget.ColorPicker", null, false);
  4. o2.widget.Tablet = o2.Tablet = new Class({
  5. Implements: [Options, Events],
  6. Extends: o2.widget.Common,
  7. options: {
  8. "style": "default",
  9. "path": o2.session.path+"/widget/$Tablet/",
  10. "iconfontEnable": false,
  11. "mainColorEnable": false,
  12. "contentWidth" : 0, //绘图区域宽度,不制定则基础 this.node的宽度
  13. "contentHeight" : 0, //绘图区域高度,不制定则基础 this.node的高度 - 操作条高度
  14. "lineWidth" : 1, //铅笔粗细
  15. "eraserRadiusSize": 20, //橡皮大小
  16. "color" : "#000000", //画笔颜色
  17. "zIndex": 20003,
  18. tools : [
  19. "save", "|",
  20. "undo",
  21. "redo", "|",
  22. "eraser", //橡皮
  23. "input", //输入法
  24. "pen", "|", //笔画
  25. "eraserRadius",
  26. "size",
  27. "color",
  28. "fontSize", "|",
  29. // "fontFamily",
  30. "image",
  31. "imageClipper", "|",
  32. "reset",
  33. "cancel"
  34. ],
  35. "toolHidden": [],
  36. "description" : "", //描述文字
  37. "imageSrc": "",
  38. "eraserEnable": true,
  39. "inputEnable": false,
  40. "action" : null, //uploadImage方法的上传服务,可选,如果不设置,使用公共图片服务
  41. "method": "", //使用action 的方法
  42. "parameter": {}, //action 时的url参数
  43. "data": null, //formdata 的data
  44. "reference": "", //uploadImage方法的使用 使用公共图片服务上传时的参数
  45. "referenceType" : "", //使用公共图片服务上传时的参数, 目前支持 processPlatformJob, processPlatformForm, portalPage, cmsDocument, forumDocument
  46. "resultMaxSize" : 0, //使用 reference 时有效
  47. "rotateWithMobile": true,
  48. "toolsScale": 1
  49. },
  50. initialize: function(node, options, app){
  51. this.node = node;
  52. this.app = app;
  53. this.fileName = "untitled.png";
  54. this.fileType = "image/png";
  55. this.reset();
  56. this.setOptions(options);
  57. if( !this.options.toolHidden )this.options.toolHidden = [];
  58. if( !this.options.eraserEnable ){
  59. this.options.toolHidden.push("eraser");
  60. this.options.toolHidden.push("eraserRadius");
  61. }
  62. if( !this.options.inputEnable ){
  63. this.options.toolHidden.push("input");
  64. this.options.toolHidden.push("fontSize");
  65. this.options.toolHidden.push("fontFamily");
  66. }
  67. this.path = this.options.path || (o2.session.path+"/widget/$Tablet/");
  68. this.cssPath = this.path + this.options.style+"/css.wcss";
  69. this.inMobileDevice = COMMON && COMMON.Browser && COMMON.Browser.Platform.isMobile;
  70. this.lp = {
  71. "save" : o2.LP.widget.save,
  72. "reset" : o2.LP.widget.empty,
  73. "undo" : o2.LP.widget.undo,
  74. "redo" : o2.LP.widget.redo,
  75. "eraser": o2.LP.widget.eraser,
  76. "input": o2.LP.widget.input,
  77. "fontSize": o2.LP.widget.fontSize,
  78. "fontFamily": o2.LP.widget.fontFamily,
  79. "pen": o2.LP.widget.pen,
  80. "eraserRadius": o2.LP.widget.eraserRadius,
  81. "size" : o2.LP.widget.thickness,
  82. "color" : o2.LP.widget.color,
  83. "image" : o2.LP.widget.insertImage,
  84. "imageClipper" : o2.LP.widget.imageClipper,
  85. "cancel": o2.LP.widget.cancel
  86. };
  87. this._loadCss();
  88. if( this.options.iconfontEnable ){
  89. this.node.loadCss(this.path + this.options.style+"/style.css");
  90. }
  91. this.fireEvent("init");
  92. },
  93. load: function( ){
  94. if( layout.mobile && this.options.rotateWithMobile ){
  95. this.rotate = true;
  96. }
  97. //存储当前表面状态数组-上一步
  98. this.preDrawAry = [];
  99. //存储当前表面状态数组-下一步
  100. this.nextDrawAry = [];
  101. //中间数组
  102. this.middleAry = [];
  103. this.mode = "writing"; //writing表示写状态,erasing表示擦除状态, inputing表示输入法
  104. this.currentColor = this.options.color;
  105. this.currentFontFamily = "宋体,SimSun";
  106. this.currentFontSize = "16px";
  107. this.container = new Element("div.container", {
  108. styles : this.css.container
  109. }).inject(this.node);
  110. if( this.rotate ){ //强制横屏显示
  111. this.detectOrient();
  112. }
  113. this.loadToolBar();
  114. this.contentNode = new Element("div.contentNode", { styles : this.css.contentNode}).inject(this.container);
  115. this.contentNode.addEvent("selectstart", function(e){
  116. if( this.mode !== "inputing" ){
  117. e.preventDefault();
  118. e.stopPropagation();
  119. }
  120. }.bind(this));
  121. this.loadDescription();
  122. this.setContentSize();
  123. if( this.checkBroswer() ){
  124. this.loadContent();
  125. }
  126. //this.imageNode = new Element("img",{
  127. //}).inject(this.contentNode);
  128. //this.imageNode.setStyles({
  129. // "display" : "none"
  130. //});
  131. if( this.app ){
  132. this.resizeFun = this.setContentSize.bind(this);
  133. this.app.addEvent( "resize", this.resizeFun );
  134. }
  135. },
  136. loadDescription : function(){
  137. if( this.options.description ){
  138. this.descriptionNode = new Element("div",{
  139. "styles": this.css.descriptionNode,
  140. "text": this.options.description
  141. }).inject( this.container )
  142. }
  143. },
  144. setContentSize : function(){
  145. this.computeContentSize();
  146. this.contentNode.setStyle("width", this.contentWidth );
  147. this.contentNode.setStyle("height", this.contentHeight );
  148. if(this.canvasWrap){
  149. this.canvasWrap.setStyles({
  150. width : this.contentWidth+"px",
  151. height : this.contentHeight+"px"
  152. });
  153. }
  154. if( this.canvas ){
  155. var d = this.ctx.getImageData(0,0,this.canvas.clientWidth,this.canvas.clientHeight);
  156. this.canvas.set("width", this.contentWidth );
  157. this.canvas.set("height", this.contentHeight );
  158. this.ctx.putImageData(d,0,0);
  159. }
  160. },
  161. computeContentSize: function(){
  162. var toolbarSize,descriptionSize, m1,m2,m3;
  163. var nodeSize = this.node.getSize();
  164. if( this.rotate && this.transform > 0 ){
  165. this.contentWidth = this.options.contentHeight || nodeSize.y;
  166. if( this.contentWidth < 150 )this.contentWidth = 150;
  167. if( this.options.contentWidth ){
  168. this.contentHeight = this.options.contentWidth;
  169. }else{
  170. toolbarSize = this.toolbarNode ? this.toolbarNode.getSize() : { x : 0, y : 0 };
  171. descriptionSize = this.descriptionNode ? this.descriptionNode.getSize() : { x : 0, y : 0 };
  172. m1 = this.getOffsetX(this.toolbarNode);
  173. m2 = this.getOffsetX(this.descriptionNode);
  174. m3 = this.getOffsetX(this.contentNode);
  175. this.contentOffSetX = toolbarSize.x + descriptionSize.x + m1 + m2 + m3;
  176. this.contentHeight = nodeSize.x - toolbarSize.x - descriptionSize.x - m1 - m2 - m3;
  177. }
  178. if( this.contentHeight < 100 )this.contentHeight = 100;
  179. }else{
  180. this.contentWidth = this.options.contentWidth || nodeSize.x;
  181. if( this.contentWidth < 100 )this.contentWidth = 100;
  182. if( this.options.contentHeight ){
  183. this.contentHeight = this.options.contentHeight;
  184. }else{
  185. toolbarSize = this.toolbarNode ? this.toolbarNode.getSize() : { x : 0, y : 0 };
  186. descriptionSize = this.descriptionNode ? this.descriptionNode.getSize() : { x : 0, y : 0 };
  187. m1 = this.getOffsetY(this.toolbarNode);
  188. m2 = this.getOffsetY(this.descriptionNode);
  189. m3 = this.getOffsetY(this.contentNode);
  190. this.contentHeight = nodeSize.y - toolbarSize.y - descriptionSize.y - m1 - m2 - m3;
  191. }
  192. if( this.contentHeight < 150 )this.contentHeight = 150;
  193. }
  194. },
  195. getOffsetY : function(node){
  196. if( !node )return 0;
  197. return (node.getStyle("margin-top").toInt() || 0 ) +
  198. (node.getStyle("margin-bottom").toInt() || 0 ) +
  199. (node.getStyle("padding-top").toInt() || 0 ) +
  200. (node.getStyle("padding-bottom").toInt() || 0 )+
  201. (node.getStyle("border-top-width").toInt() || 0 ) +
  202. (node.getStyle("border-bottom-width").toInt() || 0 );
  203. },
  204. getOffsetX : function(node){
  205. if( !node )return 0;
  206. return (node.getStyle("margin-left").toInt() || 0 ) +
  207. (node.getStyle("margin-right").toInt() || 0 ) +
  208. (node.getStyle("padding-left").toInt() || 0 ) +
  209. (node.getStyle("padding-right").toInt() || 0 )+
  210. (node.getStyle("border-left-width").toInt() || 0 ) +
  211. (node.getStyle("border-right-width").toInt() || 0 );
  212. },
  213. loadToolBar: function(){
  214. if( layout.mobile ){ //this.rotate && this.transform > 0
  215. this.toolbar = new o2.widget.Tablet.ToolbarMobile( this );
  216. this.toolbar.load();
  217. }else{
  218. this.toolbarNode = new Element("div.toolbar", {
  219. "styles" : this.css.toolbar
  220. }).inject(this.container);
  221. this.toolbar = new o2.widget.Tablet.Toolbar( this , this.toolbarNode );
  222. this.toolbar.load();
  223. }
  224. },
  225. storeToPreArray : function(preData){
  226. //当前绘图表面状态
  227. if(!preData)preData= this.ctx.getImageData(0,0,this.contentWidth,this.contentHeight);
  228. //当前绘图表面进栈
  229. this.preDrawAry.push(preData);
  230. },
  231. storeToMiddleArray : function( preData ){
  232. //当前绘图表面状态
  233. if( !preData )preData= this.ctx.getImageData(0,0,this.contentWidth,this.contentHeight);
  234. if( this.nextDrawAry.length==0){
  235. //当前绘图表面进栈
  236. this.middleAry.push(preData);
  237. }else{
  238. this.middleAry=[];
  239. this.middleAry=this.middleAry.concat(this.preDrawAry);
  240. this.middleAry.push(preData);
  241. this.nextDrawAry=[];
  242. this.toolbar.enableItem("redo");
  243. }
  244. if(this.preDrawAry.length){
  245. this.toolbar.enableItem("undo");
  246. this.toolbar.enableItem("reset");
  247. }
  248. },
  249. loadContent : function( ){
  250. debugger;
  251. var _self = this;
  252. this.canvasWrap = new Element("div.canvasWrap", { styles : this.css.canvasWrap}).inject(this.contentNode);
  253. this.canvasWrap.setStyles({
  254. width : this.contentWidth+"px",
  255. height : this.contentHeight+"px"
  256. });
  257. if( !this.rotate ){
  258. this.canvasWrap.setStyle("position", "relative");
  259. }
  260. this.canvas = new Element("canvas", {
  261. width : this.contentWidth,
  262. height : this.contentHeight
  263. }).inject( this.canvasWrap );
  264. this.ctx = this.canvas.getContext("2d");
  265. if( this.options.imageSrc ){
  266. var img = new Element("img", {
  267. "crossOrigin": "",
  268. "src": this.options.imageSrc,
  269. "events": {
  270. "load": function () {
  271. _self.ctx.drawImage(this, 0, 0);
  272. var preData=_self.ctx.getImageData(0,0,_self.contentWidth,_self.contentHeight);
  273. _self.middleAry.push(preData);
  274. _self.toolbar.enableItem("reset");
  275. }
  276. }
  277. })
  278. }else{
  279. var preData=this.ctx.getImageData(0,0,this.contentWidth,this.contentHeight);
  280. this.middleAry.push(preData);
  281. }
  282. this.canvas.ontouchstart = this.canvas.onmousedown = function(ev){
  283. var flag;
  284. if( this.currentInput ){
  285. this.currentInput.readMode();
  286. this.currentInput = null;
  287. flag = true;
  288. }
  289. if( this.mode === "inputing" ){
  290. if(flag)return;
  291. this.doInput(ev)
  292. }else{
  293. this.doWritOrErase(ev)
  294. }
  295. }.bind(this)
  296. },
  297. doInput: function(event){
  298. var _self = this;
  299. if( !this.inputList )this.inputList = [];
  300. var x,y;
  301. if(event.touches){
  302. var touch=event.touches[0];
  303. x=touch.clientX;
  304. y=touch.clientY;
  305. }else{
  306. x=event.clientX;
  307. y=event.clientY;
  308. }
  309. var coordinate = this.canvasWrap.getCoordinates();
  310. x = x - coordinate.left;
  311. y = y- coordinate.top;
  312. this.currentInput = new o2.widget.Tablet.Input( this, this.canvasWrap , {
  313. top: y,
  314. left: x,
  315. onPostDraw : function( image ){
  316. Promise.resolve(image).then(function () {
  317. var input = this;
  318. var globalCompositeOperation = _self.ctx.globalCompositeOperation;
  319. _self.ctx.globalCompositeOperation = "source-over";
  320. var coordinate = input.getCoordinates();
  321. _self.storeToPreArray();
  322. _self.ctx.drawImage(image, coordinate.left, coordinate.top, coordinate.width, coordinate.height);
  323. _self.storeToMiddleArray();
  324. if(globalCompositeOperation)_self.ctx.globalCompositeOperation = globalCompositeOperation;
  325. }.bind(this));
  326. },
  327. onPostCancel: function(){
  328. // if(this.globalCompositeOperation)this.ctx.globalCompositeOperation = this.globalCompositeOperation;
  329. // this.globalCompositeOperation = null;
  330. }.bind(this),
  331. });
  332. this.currentInput.load();
  333. this.inputList.push( this.currentInput );
  334. },
  335. loadImage: function(url){
  336. return new Promise(function(resolve, reject){
  337. var img = new Element("img");
  338. img.crossOrigin="anonymous";
  339. img.addEvent('load', function(){ resolve(img)});
  340. img.addEvent('error', function(err){ reject(err) });
  341. img.src = url;
  342. })
  343. },
  344. doWritOrErase: function(ev){
  345. var _self = this;
  346. ev = ev || event;
  347. var ctx = this.ctx;
  348. var canvas = this.canvas;
  349. var container = this.contentNode;
  350. var position = this.canvasWrap.getPosition();
  351. var doc = $(document);
  352. if( this.mode === "erasing" ) {
  353. if(this.inputList)this.inputList.each(function (input) {
  354. input.hide();
  355. });
  356. ctx.lineCap = "round";  //设置线条两端为圆弧
  357. ctx.lineJoin = "round";  //设置线条转折为圆弧
  358. ctx.lineWidth = this.currentEraserRadius || this.options.eraserRadiusSize;
  359. ctx.globalCompositeOperation = "destination-out";
  360. }else{
  361. //ctx.strokeStyle="#0000ff" 线条颜色; 默认 #000000
  362. if( this.options.color )ctx.strokeStyle= this.currentColor || this.options.color; // 线条颜色; 默认 #000000
  363. if( this.options.lineWidth )ctx.lineWidth= this.currentWidth || this.options.lineWidth; //默认1 像素
  364. ctx.lineCap = "butt";  //设置线条两端为平直的边缘
  365. ctx.lineJoin = "miter";  //设置线条转折为圆弧
  366. ctx.globalCompositeOperation = "source-over";
  367. }
  368. if( this.mode === "erasing" ){
  369. var radius = this.currentEraserRadius || this.options.eraserRadiusSize;
  370. var hRadius = radius / 2;
  371. this.eraseIcon = new Element("div", {
  372. styles: {
  373. "border": "1px solid #333",
  374. "height": radius,
  375. "width": radius,
  376. "border-radius": radius,
  377. "position": "absolute",
  378. "background": "#fff"
  379. }
  380. }).inject(this.canvasWrap);
  381. }
  382. ctx.beginPath();
  383. var x , y;
  384. if(this.rotate && _self.transform > 0){
  385. var clientY = ev.type.indexOf('touch') !== -1 ? ev.touches[0].clientY : ev.clientY;
  386. var clientX = ev.type.indexOf('touch') !== -1 ? ev.touches[0].clientX : ev.clientX;
  387. var newX = clientY;
  388. var newY = _self.canvas.height - clientX; //y轴旋转偏移 // - parseInt(_self.transformOrigin)
  389. }else{
  390. x = ev.clientX-position.x;
  391. y = ev.clientY-position.y
  392. }
  393. ctx.moveTo(x, y);
  394. if( this.mode === "erasing" ){
  395. this.eraseIcon.setStyles({
  396. "top": ( y - hRadius)+"px",
  397. "left":( x - hRadius)+"px"
  398. });
  399. ctx.arc(x, y, 1, 0, 2*Math.PI);
  400. ctx.fill();
  401. }
  402. this.storeToPreArray();
  403. var mousemove = function(ev){
  404. var mx , my;
  405. if(_self.rotate && _self.transform > 0){
  406. mx = ev.client.y;
  407. my = _self.canvas.height - ev.client.x //y轴旋转偏移 // - + parseInt(_self.transformOrigin);
  408. }else{
  409. mx = ev.client.x - position.x;
  410. my = ev.client.y - position.y;
  411. }
  412. ctx.lineTo(mx, my);
  413. ctx.stroke();
  414. if( _self.mode === "erasing" ) {
  415. _self.eraseIcon.setStyles({
  416. "top": ( my - hRadius) + "px",
  417. "left": ( mx - hRadius) + "px"
  418. });
  419. }
  420. };
  421. doc.addEvent( "mousemove", mousemove );
  422. doc.addEvent( "touchmove", mousemove );
  423. var mouseup = function(ev){
  424. //document.onmousemove = document.onmouseup = null;
  425. doc.removeEvent("mousemove", mousemove);
  426. doc.removeEvent("mouseup", mouseup);
  427. doc.removeEvent("touchmove", mousemove);
  428. doc.removeEvent("touchend", mouseup);
  429. this.storeToMiddleArray();
  430. ctx.closePath();
  431. if(_self.eraseIcon)_self.eraseIcon.destroy();
  432. if( _self.mode === "erasing" ) {
  433. if (_self.inputList) _self.inputList.each(function (input) {
  434. input.show();
  435. });
  436. }
  437. }.bind(this);
  438. doc.addEvent("mouseup", mouseup);
  439. doc.addEvent("touchend", mouseup);
  440. //document.onmouseup = function(ev){
  441. // document.onmousemove = document.onmouseup = null;
  442. // ctx.closePath();
  443. //}
  444. },
  445. detectOrient: function(){
  446. // 利用 CSS3 旋转 对根容器逆时针旋转 90 度
  447. var size = $(document.body).getSize();
  448. var width = size.x,
  449. height = size.y,
  450. styles = {};
  451. if( width >= height ){ // 横屏
  452. this.transform = 0;
  453. this.transformOrigin = 0;
  454. styles = {
  455. "width": width+"px",
  456. "height": height+"px",
  457. "webkit-transform": "rotate(0)",
  458. "transform": "rotate(0)",
  459. "webkit-transform-origin": "0 0",
  460. "transform-origin": "0 0"
  461. }
  462. }
  463. else{ // 竖屏
  464. this.options.lineWidth = 1.5;
  465. this.transform = 90;
  466. this.transformOrigin = width / 2;
  467. styles = {
  468. "width": height+"px",
  469. "height": width+"px",
  470. "webkit-transform": "rotate(90deg)",
  471. "transform": "rotate(90deg)",
  472. "webkit-transform-origin": ( this.transformOrigin + "px " + this.transformOrigin + "px"),
  473. "transform-origin": ( this.transformOrigin + "px " + this.transformOrigin + "px")
  474. }
  475. }
  476. this.container.setStyles(styles);
  477. },
  478. uploadImage: function( success, failure ){
  479. var image = this.getImage( null, true );
  480. Promise.resolve( image ).then(function(image){
  481. if( image ){
  482. if( this.options.action ){
  483. this.action = (typeOf(this.options.action)=="string") ? o2.Actions.get(this.options.action).action : this.options.action;
  484. this.action.invoke({
  485. "name": this.options.method,
  486. "async": true,
  487. "data": this.getFormData( image ),
  488. "file": image,
  489. "parameter": this.options.parameter,
  490. "success": function(json){
  491. success(json)
  492. }.bind(this)
  493. });
  494. }else if( this.options.reference && this.options.referenceType ){
  495. //公共图片上传服务
  496. var maxSize = this.options.resultMaxSize;
  497. o2.xDesktop.uploadImageByScale(
  498. this.options.reference,
  499. this.options.referenceType,
  500. maxSize,
  501. this.getFormData( image ),
  502. image,
  503. success,
  504. failure
  505. );
  506. }
  507. }else{
  508. }
  509. })
  510. },
  511. getFormData : function( image ){
  512. if( !image )image = this.getImage();
  513. return Promise.resolve( image ).then(function(){
  514. var formData = new FormData();
  515. formData.append('file', image, this.fileName );
  516. if( this.options.data ){
  517. Object.each(this.options.data, function(v, k){
  518. formData.append(k, v)
  519. });
  520. }
  521. return formData;
  522. }.bind(this));
  523. },
  524. getImage : function( base64Code, ignoreResultSize ){
  525. var src = base64Code || this.getBase64Code( ignoreResultSize);
  526. return Promise.resolve( src ).then(function( src ){
  527. src=window.atob(src);
  528. var ia = new Uint8Array(src.length);
  529. for (var i = 0; i < src.length; i++) {
  530. ia[i] = src.charCodeAt(i);
  531. }
  532. var blob = new Blob([ia], {type: this.fileType });
  533. var fileName = "image_"+new Date().getTime();
  534. if( this.fileType && this.fileType.contains("/") ) {
  535. blob.name = fileName + "." + this.fileType.split("/")[1];
  536. }else{
  537. blob.name = fileName + ".unknow";
  538. }
  539. return blob;
  540. }.bind(this));
  541. },
  542. getBase64Code : function( ignoreResultSize ){
  543. if( !ignoreResultSize && this.options.resultMaxSize ){
  544. return Promise.resolve( this.drawInput() ).then(function() {
  545. var src = this.canvas.toDataURL(this.fileType);
  546. src = src.split(',')[1];
  547. return src = 'data:' + this.fileType + ';base64,' + src;
  548. }.bind(this)).then( function( src ){
  549. return this.loadImage( src );
  550. }.bind(this)).then(function( tmpImageNode ){
  551. var ctx = this.ctx;
  552. var canvas = this.canvas;
  553. var width, height;
  554. width = Math.min(this.contentWidth, this.options.resultMaxSize);
  555. height = (width / this.contentWidth) * this.contentHeight;
  556. var tmpCanvas = new Element("canvas", {
  557. width : width,
  558. height : height
  559. }).inject( this.contentNode );
  560. var tmpCtx = tmpCanvas.getContext("2d");
  561. tmpCtx.drawImage(tmpImageNode,0,0, this.contentWidth,this.contentHeight,0,0,width,height);
  562. var tmpsrc= tmpCanvas.toDataURL( this.fileType );
  563. tmpsrc=tmpsrc.split(',')[1];
  564. tmpImageNode.destroy();
  565. tmpCanvas.destroy();
  566. tmpCtx = null;
  567. if(!tmpsrc){
  568. return "";
  569. }else{
  570. return tmpsrc
  571. }
  572. }.bind(this));
  573. }else{
  574. return Promise.resolve( this.drawInput() ).then(function(){
  575. var src= this.canvas.toDataURL( this.fileType );
  576. src=src.split(',')[1];
  577. if(!src){
  578. return "";
  579. }else{
  580. return src;
  581. }
  582. }.bind(this))
  583. }
  584. },
  585. getBase64Image: function( base64Code, ignoreResultSize ){
  586. if( !base64Code )base64Code = this.getBase64Code( ignoreResultSize );
  587. return Promise.resolve( base64Code ).then(function( base64Code ){
  588. if( !base64Code )return null;
  589. return 'data:'+ this.fileType +';base64,' + base64Code;
  590. }.bind(this));
  591. },
  592. drawInput: function(){
  593. if( this.inputList ){
  594. var list = this.inputList.map(function (input) {
  595. return input.draw();
  596. });
  597. return Promise.all( list );
  598. }else{
  599. return "";
  600. }
  601. },
  602. close : function(){
  603. if( this.inputList ){
  604. this.inputList.each(function (input) {
  605. input.close( true );
  606. })
  607. }
  608. this.container.destroy();
  609. delete this;
  610. },
  611. checkBroswer : function(){
  612. if( window.Uint8Array && window.HTMLCanvasElement && window.atob && window.Blob){
  613. this.available = true;
  614. return true;
  615. }else{
  616. this.available = false;
  617. this.container.set("html", "<p>"+o2.LP.widget.explorerNotSupportFeatures+"</p><ul><li>canvas</li><li>Blob</li><li>Uint8Array</li><li>FormData</li><li>atob</li></ul>");
  618. return false;
  619. }
  620. },
  621. isBlank: function(){
  622. var canvas = this.canvas;
  623. var blank = new Element("canvas", {
  624. width : canvas.width,
  625. height : canvas.height
  626. });
  627. // var blank = document.createElement('canvas');//系统获取一个空canvas对象
  628. // blank.width = canvas.width;
  629. // blank.height = canvas.height;
  630. return canvas.toDataURL() == blank.toDataURL(); //比较值相等则为空
  631. },
  632. save : function(){
  633. var _slef = this;
  634. Promise.resolve( this.getBase64Code() ).then(function ( base64code ) {
  635. _slef.getImage( base64code ).then(function( imageFile ){
  636. _slef.getBase64Image( base64code ).then(function (base64Image) {
  637. _slef.options.imageSrc = base64Image;
  638. _slef.fireEvent("save", [ base64code, base64Image, imageFile]);
  639. });
  640. })
  641. })
  642. // var imageFile = this.getImage( base64code );
  643. // var base64Image = this.getBase64Image( base64code );
  644. // this.fireEvent("save", [ base64code, base64Image, imageFile]);
  645. },
  646. reset : function( itemNode ){
  647. this.fileName = "untitled.png";
  648. this.fileType = "image/png";
  649. if( this.ctx ){
  650. var canvas = this.canvas;
  651. this.ctx.clearRect(0,0,canvas.clientWidth,canvas.clientHeight);
  652. }
  653. if( this.inputList ){
  654. this.inputList.each(function (input) {
  655. input.close();
  656. })
  657. this.currentInput = null;
  658. }
  659. this.fireEvent("reset");
  660. },
  661. undo : function( itemNode ){
  662. if(this.preDrawAry.length>0){
  663. var popData=this.preDrawAry.pop();
  664. var midData=this.middleAry[this.preDrawAry.length+1];
  665. this.nextDrawAry.push(midData);
  666. this.ctx.putImageData(popData,0,0);
  667. }
  668. this.toolbar.setAllItemsStatus();
  669. },
  670. redo : function( itemNode ){
  671. if(this.nextDrawAry.length){
  672. var popData=this.nextDrawAry.pop();
  673. var midData=this.middleAry[this.middleAry.length-this.nextDrawAry.length-2];
  674. this.preDrawAry.push(midData);
  675. this.ctx.putImageData(popData,0,0);
  676. }
  677. this.toolbar.setAllItemsStatus();
  678. },
  679. size : function( itemNode ){
  680. if( !this.sizeSelector ){
  681. var container = this.inMobileDevice ? $(document.body) : this.container;
  682. this.sizeSelector = new o2.widget.Tablet.SizePicker(container, itemNode, null, {}, {
  683. "onSelect": function (width) {
  684. this.currentWidth = width;
  685. }.bind(this),
  686. "onHide": function () {
  687. itemNode.fireEvent("mouseout");
  688. },
  689. "event" : this.inMobileDevice ? "click" : "mouseenter",
  690. "hasMask": false,
  691. "zoom": this.options.toolsScale || 1
  692. });
  693. }
  694. },
  695. eraserRadius : function( itemNode ){
  696. if( !this.eraserRadiusSelector ){
  697. var container = this.inMobileDevice ? $(document.body) : this.container;
  698. this.eraserRadiusSelector = new o2.widget.Tablet.EraserRadiusPicker(container, itemNode, null, {}, {
  699. "onSelect": function (width) {
  700. this.currentEraserRadius = width;
  701. }.bind(this),
  702. "onHide": function () {
  703. itemNode.fireEvent("mouseout");
  704. },
  705. "event" : this.inMobileDevice ? "click" : "mouseenter",
  706. "hasMask": false,
  707. "zoom": this.options.toolsScale || 1
  708. });
  709. }
  710. },
  711. color : function( itemNode ){
  712. if( !this.colorSelector ){
  713. var container = this.inMobileDevice ? $(document.body) : this.container;
  714. this.colorSelector = new o2.xApplication.Template.widget.ColorPicker( container, itemNode, null, {}, {
  715. "lineWidth" : 1,
  716. "onSelect": function (color) {
  717. this.currentColor = color;
  718. if( this.currentInput ){
  719. this.currentInput.setColor(color);
  720. }
  721. }.bind(this),
  722. "onHide": function () {
  723. itemNode.fireEvent("mouseout");
  724. },
  725. "event" : this.inMobileDevice ? "click" : "mouseenter",
  726. "hasMask": false,
  727. "zoom": this.options.toolsScale || 1
  728. });
  729. }
  730. },
  731. fontFamily: function (itemNode) {
  732. if( !this.fontfamilySelector ){
  733. var container = this.inMobileDevice ? $(document.body) : this.container;
  734. this.fontfamilySelector = new o2.widget.Tablet.FontFamily(itemNode, {
  735. "onSelectItem": function (node, d) {
  736. this.currentFontFamily = d.val;
  737. if( this.currentInput ){
  738. this.currentInput.setFontFamily(d.val);
  739. }
  740. }.bind(this),
  741. "tooltipsOptions": {
  742. "onHide": function () {
  743. itemNode.fireEvent("mouseout");
  744. },
  745. "event" : this.inMobileDevice ? "click" : "mouseenter", //事件类型,有target 时有效, mouseenter对应mouseleave,click 对应 container 的 click
  746. "hasMask": false,
  747. "zoom": this.options.toolsScale || 1
  748. }
  749. }, null, null, container);
  750. this.fontfamilySelector.load();
  751. }
  752. },
  753. fontSize: function (itemNode) {
  754. if( !this.fontsizeSelector ){
  755. var container = this.inMobileDevice ? $(document.body) : this.container;
  756. this.fontsizeSelector = new o2.widget.Tablet.FontSize(itemNode, {
  757. "onSelectItem": function (node, d) {
  758. this.currentFontSize = d.value +"px";
  759. if( this.currentInput ){
  760. this.currentInput.setFontSize(d.value+"px");
  761. }
  762. }.bind(this),
  763. "tooltipsOptions": {
  764. "onHide": function () {
  765. itemNode.fireEvent("mouseout");
  766. },
  767. "event" : this.inMobileDevice ? "click" : "mouseenter", //事件类型,有target 时有效, mouseenter对应mouseleave,click 对应 container 的 click
  768. "hasMask": false,
  769. "zoom": this.options.toolsScale || 1
  770. }
  771. }, null, null, container);
  772. this.fontsizeSelector.load();
  773. }
  774. },
  775. getImageSize : function(naturalWidth, naturalHeight ){
  776. var ratio = naturalWidth / naturalHeight;
  777. var ww = this.contentWidth,
  778. wh = this.contentHeight;
  779. var flag = ( naturalWidth / parseInt(ww) ) > ( naturalHeight / parseInt(wh) );
  780. if( flag ){
  781. var width = Math.min( naturalWidth, parseInt( ww ) );
  782. return { width : width, height : width / ratio }
  783. }else{
  784. var height = Math.min( naturalHeight, parseInt( wh ) );
  785. return { width : height * ratio, height : height }
  786. }
  787. },
  788. parseFileToImage : function( file, callback ){
  789. var imageNode = new Element("img");
  790. var onImageLoad = function(){
  791. var nh = imageNode.naturalHeight,
  792. nw = imageNode.naturalWidth;
  793. if( isNaN(nh) || isNaN(nw) || nh == 0 || nw == 0 ){
  794. setTimeout( function(){ onImageLoad(); }.bind(this), 100 );
  795. }else{
  796. _onImageLoad();
  797. }
  798. };
  799. var _onImageLoad = function(){
  800. var nh = imageNode.naturalHeight,
  801. nw = imageNode.naturalWidth;
  802. var size = this.getImageSize( nw, nh );
  803. imageNode.setStyles({
  804. width : size.width,
  805. height : size.height
  806. });
  807. var mover = new o2.widget.Tablet.ImageMover( this, imageNode, this.canvasWrap , {
  808. onPostOk : function(){
  809. var coordinate = mover.getCoordinates();
  810. this.storeToPreArray();
  811. this.ctx.drawImage(imageNode, coordinate.left, coordinate.top, coordinate.width, coordinate.height);
  812. this.storeToMiddleArray();
  813. if(this.globalCompositeOperation)this.ctx.globalCompositeOperation = this.globalCompositeOperation;
  814. this.globalCompositeOperation = null;
  815. }.bind(this),
  816. onPostCancel: function(){
  817. if(this.globalCompositeOperation)this.ctx.globalCompositeOperation = this.globalCompositeOperation;
  818. this.globalCompositeOperation = null;
  819. }.bind(this),
  820. });
  821. mover.load();
  822. if( callback )callback();
  823. }.bind(this);
  824. var reader=new FileReader();
  825. reader.onload=function(){
  826. imageNode.src=reader.result;
  827. reader = null;
  828. onImageLoad();
  829. }.bind(this);
  830. reader.readAsDataURL(file);
  831. },
  832. image : function( itemNode ){
  833. var uploadFileAreaNode = new Element("div");
  834. var html = "<input name=\"file\" type=\"file\" />"; //accept=\"images/*\"
  835. uploadFileAreaNode.set("html", html);
  836. var fileUploadNode = uploadFileAreaNode.getFirst();
  837. fileUploadNode.addEvent("change", function () {
  838. var file = fileUploadNode.files[0];
  839. this.globalCompositeOperation = this.ctx.globalCompositeOperation;
  840. this.ctx.globalCompositeOperation = "source-over";
  841. this.parseFileToImage( file, function(){
  842. uploadFileAreaNode.destroy();
  843. })
  844. }.bind(this));
  845. fileUploadNode.click();
  846. },
  847. imageClipper : function( itemNode ){
  848. var clipper = new o2.widget.Tablet.ImageClipper(this.app, {
  849. "style": "default",
  850. "aspectRatio" : 0,
  851. "onOk" : function( img ){
  852. this.globalCompositeOperation = this.ctx.globalCompositeOperation;
  853. this.ctx.globalCompositeOperation = "source-over";
  854. this.parseFileToImage( img );
  855. }.bind(this)
  856. }, this);
  857. clipper.load();
  858. },
  859. input: function( itemNode ){
  860. this.mode = "inputing";
  861. this.toolbar.enableItem("pen");
  862. this.toolbar.enableItem("eraser");
  863. this.toolbar.activeItem("input");
  864. this.toolbar.hideItem("eraserRadius");
  865. this.toolbar.hideItem("size");
  866. this.toolbar.showItem("fontSize");
  867. this.toolbar.showItem("fontFamily");
  868. this.toolbar.showItem("color");
  869. },
  870. eraseInput: function(input){
  871. this.inputList.erase(input);
  872. },
  873. eraser : function( itemNode ){
  874. this.mode = "erasing";
  875. this.toolbar.enableItem("pen");
  876. this.toolbar.activeItem("eraser");
  877. this.toolbar.showItem("eraserRadius");
  878. this.toolbar.hideItem("size");
  879. this.toolbar.hideItem("color");
  880. this.toolbar.hideItem("fontSize");
  881. this.toolbar.hideItem("fontFamily");
  882. this.toolbar.enableItem("input");
  883. },
  884. pen : function( itemNode ){
  885. this.mode = "writing";
  886. this.toolbar.activeItem("pen");
  887. this.toolbar.enableItem("input");
  888. this.toolbar.enableItem("eraser");
  889. this.toolbar.hideItem("eraserRadius");
  890. this.toolbar.hideItem("fontSize");
  891. this.toolbar.hideItem("fontFamily");
  892. this.toolbar.showItem("size");
  893. this.toolbar.showItem("color");
  894. },
  895. cancel: function(){
  896. var _self = this;
  897. this.reset();
  898. if( this.options.imageSrc ){
  899. var img = new Element("img", {
  900. "crossOrigin": "",
  901. "src": this.options.imageSrc,
  902. "events": {
  903. "load": function () {
  904. _self.ctx.drawImage(this, 0, 0);
  905. var preData=_self.ctx.getImageData(0,0,_self.contentWidth,_self.contentHeight);
  906. _self.middleAry.push(preData);
  907. _self.toolbar.enableItem("reset");
  908. }
  909. }
  910. })
  911. }
  912. this.fireEvent("cancel");
  913. }
  914. });
  915. o2.widget.Tablet.Toolbar = new Class({
  916. Implements: [Options, Events],
  917. initialize: function (tablet, container) {
  918. this.tablet = tablet;
  919. this.container = container;
  920. this.css = tablet.css;
  921. this.lp = this.tablet.lp;
  922. this.imagePath = o2.session.path+"/widget/$Tablet/"+ this.tablet.options.style +"/icon/";
  923. this.items = {};
  924. this.itemsEnableFun = {
  925. save : {
  926. enable : function(){ return true }
  927. },
  928. reset : {
  929. enable : function(){ return this.tablet.preDrawAry.length > 0}.bind(this)
  930. },
  931. undo : {
  932. enable : function(){ return this.tablet.preDrawAry.length > 0 }.bind(this)
  933. },
  934. redo : {
  935. enable : function(){ return this.tablet.nextDrawAry.length > 0 }.bind(this)
  936. },
  937. eraser : {
  938. enable : function(){ return true },
  939. active : function(){ return this.tablet.mode === "erasing" }.bind(this)
  940. },
  941. eraserRadius: {
  942. enable : function(){ return true },
  943. show : function(){ return this.tablet.mode === "erasing" }.bind(this)
  944. },
  945. input: {
  946. enable : function(){ return true },
  947. active : function(){ return this.tablet.mode === "inputing" }.bind(this)
  948. },
  949. pen: {
  950. enable : function(){ return true },
  951. active : function(){ return this.tablet.mode === "writing" }.bind(this)
  952. },
  953. size : {
  954. enable : function(){ return true },
  955. show : function(){ return this.tablet.mode === "writing" }.bind(this)
  956. },
  957. fontSize : {
  958. enable : function(){ return true },
  959. show : function(){ return this.tablet.mode === "inputing" }.bind(this)
  960. },
  961. fontFamily : {
  962. enable : function(){ return true },
  963. show : function(){ return this.tablet.mode === "inputing" }.bind(this)
  964. },
  965. color : {
  966. enable : function(){ return true },
  967. show : function(){ return this.tablet.mode === "writing" || this.tablet.mode === "inputing" }.bind(this)
  968. },
  969. image : {
  970. enable : function(){ return true }
  971. },
  972. imageClipper : {
  973. enable : function(){ return true }
  974. }
  975. }
  976. },
  977. getHtml : function(){
  978. var items;
  979. var tools = this.tablet.options.tools;
  980. if( tools ){
  981. items = tools;
  982. }else{
  983. items = [
  984. "save", "|",
  985. "reset", "|",
  986. "undo", "|",
  987. "redo", "|",
  988. "eraser", "|",
  989. "input", "|",
  990. "pen", "|",
  991. "eraserRadius","|",
  992. "size", "|",
  993. "color", "|",
  994. "fontSize", "|",
  995. "fontFamily", "|",
  996. "image", "|",
  997. "imageClipper"
  998. ];
  999. }
  1000. if( this.tablet.options.toolHidden.contains("eraser") && this.tablet.options.toolHidden.contains("input")){
  1001. this.tablet.options.toolHidden.push("pen");
  1002. }
  1003. if( this.tablet.options.toolHidden.contains("eraser")){
  1004. this.tablet.options.toolHidden.push("eraserRadius");
  1005. }
  1006. if( this.tablet.options.toolHidden.contains("input")){
  1007. this.tablet.options.toolHidden.push("fontSize");
  1008. this.tablet.options.toolHidden.push("fontFamily");
  1009. }
  1010. items = items.filter(function(tool){
  1011. return !this.tablet.options.toolHidden.contains(tool)
  1012. }.bind(this));
  1013. items = items.clean();
  1014. for( var i=1; i<items.length; i++ ){
  1015. if( items[i-1]==="|" && items[i]==="|")items[i-1] = null;
  1016. }
  1017. items = items.clean();
  1018. var html = "";
  1019. var style = this.tablet.options.iconfontEnable ? "toolItemIconfont" : "toolItem";
  1020. var styleRight = this.tablet.options.iconfontEnable ? "toolRightItemIconfont" : "toolRightItem";
  1021. items.each( function( item ){
  1022. switch( item ){
  1023. case "|":
  1024. html += "<div styles='" + "separator" + "'></div>";
  1025. break;
  1026. case "save" :
  1027. html += "<div item='save' styles='" + style + "'>"+ this.lp.save +"</div>";
  1028. break;
  1029. case "reset" :
  1030. html += "<div item='reset' styles='" + style + "'>"+ this.lp.reset +"</div>";
  1031. break;
  1032. case "undo" :
  1033. html += "<div item='undo' styles='" + style + "'>"+ this.lp.undo +"</div>";
  1034. break;
  1035. case "redo" :
  1036. html += "<div item='redo' styles='" + style + "'>"+ this.lp.redo +"</div>";
  1037. break;
  1038. case "eraser" :
  1039. html += "<div item='eraser' styles='" + style + "'>"+ this.lp.eraser +"</div>";
  1040. break;
  1041. case "eraserRadius" :
  1042. html += "<div item='eraserRadius' styles='" + style + "'>"+ this.lp.eraserRadius +"</div>";
  1043. break;
  1044. case "input" :
  1045. html += "<div item='input' styles='" + style + "'>"+ this.lp.input +"</div>";
  1046. break;
  1047. case "pen" :
  1048. html += "<div item='pen' styles='" + style + "'>"+ this.lp.pen +"</div>";
  1049. break;
  1050. case "size" :
  1051. html += "<div item='size' styles='" + style + "'>"+ this.lp.size +"</div>";
  1052. break;
  1053. case "color" :
  1054. html += "<div item='color' styles='" + style + "'>"+ this.lp.color +"</div>";
  1055. break;
  1056. case "fontSize" :
  1057. html += "<div item='fontSize' style='float: left;margin-top:20px;margin-left: 5px;'></div>";
  1058. break;
  1059. case "fontFamily" :
  1060. html += "<div item='fontFamily' style='float: left;margin-top:20px;margin-left: 5px;'></div>";
  1061. break;
  1062. case "image" :
  1063. html += "<div item='image' styles='" + style + "'>"+ this.lp.image +"</div>";
  1064. break;
  1065. case "imageClipper" :
  1066. html += "<div item='imageClipper' styles='" + style + "'>"+ this.lp.imageClipper +"</div>";
  1067. break;
  1068. case "cancel" :
  1069. html += "<div item='cancel' styles='"+ styleRight +"'>"+ this.lp.cancel +"</div>";
  1070. break;
  1071. }
  1072. }.bind(this));
  1073. return html;
  1074. },
  1075. load: function () {
  1076. var _self = this;
  1077. var imagePath = this.imagePath;
  1078. this.items = {};
  1079. var html = this.getHtml();
  1080. this.container.set("html", html);
  1081. this.container.getElements("[styles]").each(function (el) {
  1082. el.setStyles(_self.css[el.get("styles")]);
  1083. var item = el.get("item");
  1084. if ( item ) {
  1085. this.items[ item ] = el;
  1086. if( _self.tablet.options.iconfontEnable ){
  1087. var text = el.get("text");
  1088. el.set("text", "");
  1089. new Element("i.o2icon-"+item, {styles: this.css.toolItemIconfont_icon}).inject( el, "top" );
  1090. new Element("div", {text: text, styles: this.css.toolItemIconfont_text}).inject( el );
  1091. }else{
  1092. el.setStyle("background-image","url("+ imagePath + item +"_normal.png)");
  1093. }
  1094. el.addEvents({
  1095. mouseover : function(){
  1096. _self._setItemNodeActive(this.el);
  1097. }.bind({ item : item, el : el }),
  1098. mouseout : function(){
  1099. var active = false;
  1100. if( _self.itemsEnableFun[item] && _self.itemsEnableFun[item].active ){
  1101. active = _self.itemsEnableFun[item].active();
  1102. }
  1103. if(!active)_self._setItemNodeNormal(this.el);
  1104. }.bind({ item : item, el : el }),
  1105. click : function( ev ){
  1106. if( _self["tablet"][this.item] )_self["tablet"][this.item]( this.el );
  1107. }.bind({ item : item, el : el })
  1108. });
  1109. if( item == "color" || item == "size" || item == "eraserRadius" ){
  1110. if( _self["tablet"][item] )_self["tablet"][item]( el );
  1111. }
  1112. }
  1113. }.bind(this));
  1114. var fontSizeItem = this.container.getElement("[item='fontSize']");
  1115. if(fontSizeItem){
  1116. this.items["fontSize"] = fontSizeItem;
  1117. this.tablet.fontSize(fontSizeItem);
  1118. }
  1119. var fontFamilyItem = this.container.getElement("[item='fontFamily']");
  1120. if(fontFamilyItem){
  1121. this.items["fontFamily"] = fontFamilyItem;
  1122. this.tablet.fontFamily(fontFamilyItem);
  1123. }
  1124. this.setAllItemsStatus();
  1125. this.setAllItemsShow();
  1126. this.setAllItemsActive();
  1127. },
  1128. setAllItemsShow : function(){
  1129. for( var item in this.items ){
  1130. var node = this.items[item];
  1131. if( this.itemsEnableFun[item] && this.itemsEnableFun[item].show ){
  1132. if( !this.itemsEnableFun[item].show() ){
  1133. this.hideItem( item );
  1134. }
  1135. }
  1136. }
  1137. },
  1138. setAllItemsActive : function(){
  1139. for( var item in this.items ){
  1140. var node = this.items[item];
  1141. if( this.itemsEnableFun[item] && this.itemsEnableFun[item].active ){
  1142. if( this.itemsEnableFun[item].active() ){
  1143. this.activeItem( item );
  1144. }
  1145. }
  1146. }
  1147. },
  1148. setAllItemsStatus : function(){
  1149. for( var item in this.items ){
  1150. var node = this.items[item];
  1151. if( this.itemsEnableFun[item] ){
  1152. if( this.itemsEnableFun[item].enable() ){
  1153. this.enableItem( item )
  1154. }else{
  1155. this.disableItem( item );
  1156. }
  1157. }
  1158. }
  1159. },
  1160. showItem: function( itemName ){
  1161. var itemNode = this.items[ itemName ];
  1162. if(itemNode)itemNode.show();
  1163. },
  1164. hideItem: function( itemName ){
  1165. var itemNode = this.items[ itemName ];
  1166. if(itemNode)itemNode.hide();
  1167. },
  1168. disableItem : function( itemName ){
  1169. var itemNode = this.items[ itemName ];
  1170. if(itemNode){
  1171. itemNode.store("status", "disable");
  1172. this._setItemNodeDisable( itemNode, itemName );
  1173. }
  1174. },
  1175. enableItem : function( itemName ){
  1176. var itemNode = this.items[ itemName ];
  1177. if(itemNode) {
  1178. itemNode.store("status", "enable");
  1179. this._setItemNodeNormal(itemNode, itemName);
  1180. }
  1181. },
  1182. activeItem: function( itemName ){
  1183. var itemNode = this.items[ itemName ];
  1184. if(itemNode) {
  1185. itemNode.store("status", "active");
  1186. this._setItemNodeActive(itemNode, itemName);
  1187. }
  1188. },
  1189. _setItemNodeDisable : function( itemNode, itemName ){
  1190. var item = itemNode.get("item");
  1191. if(item){
  1192. if( ["fontSize","fontFamily"].contains( itemName ) ){
  1193. itemNode.hide();
  1194. }else{
  1195. if( this.tablet.options.iconfontEnable ){
  1196. itemNode.setStyles(this.css.toolItemIconfont_disable);
  1197. if( this.tablet.options.mainColorEnable )itemNode.removeClass("mainColor_color");
  1198. }else {
  1199. itemNode.setStyles(this.css.toolItem_disable);
  1200. itemNode.setStyle("background-image", "url(" + this.imagePath + item + "_disable.png)");
  1201. }
  1202. }
  1203. }
  1204. },
  1205. _setItemNodeActive: function( itemNode, itemName ){
  1206. if( itemNode.retrieve("status") == "disable" )return;
  1207. var item = itemNode.get("item");
  1208. if(item){
  1209. if( ["fontSize","fontFamily"].contains( itemName ) ){
  1210. if( this.itemsEnableFun[itemName] && this.itemsEnableFun[itemName].show ){
  1211. if( this.itemsEnableFun[item].show() ){
  1212. itemNode.show();
  1213. }
  1214. }
  1215. }else{
  1216. if( this.tablet.options.iconfontEnable ){
  1217. itemNode.setStyles(this.css.toolItemIconfont_over);
  1218. if( this.tablet.options.mainColorEnable )itemNode.addClass("mainColor_color");
  1219. }else {
  1220. itemNode.setStyles(this.css.toolItem_over);
  1221. itemNode.setStyle("background-image", "url(" + this.imagePath + item + "_active.png)");
  1222. }
  1223. }
  1224. }
  1225. },
  1226. _setItemNodeNormal: function( itemNode, itemName ){
  1227. if( itemNode.retrieve("status") == "disable" )return;
  1228. var item = itemNode.get("item");
  1229. if(item){
  1230. if( ["fontSize","fontFamily"].contains( itemName ) ){
  1231. if( this.itemsEnableFun[itemName] && this.itemsEnableFun[itemName].show ){
  1232. if( this.itemsEnableFun[item].show() ){
  1233. itemNode.show();
  1234. }
  1235. }
  1236. }else{
  1237. var style = itemNode.get("styles");
  1238. if( this.tablet.options.iconfontEnable ){
  1239. itemNode.setStyles(this.css[style]);
  1240. if( this.tablet.options.mainColorEnable )itemNode.removeClass("mainColor_color");
  1241. }else{
  1242. itemNode.setStyles( this.css[style] );
  1243. itemNode.setStyle("background-image","url("+ this.imagePath+ item +"_normal.png)");
  1244. }
  1245. }
  1246. }
  1247. }
  1248. });
  1249. o2.widget.Tablet.ToolbarMobile = new Class({
  1250. Extends: o2.widget.Tablet.Toolbar,
  1251. Implements: [Options, Events],
  1252. load: function(){
  1253. this.tablet.container.setStyle("position","relative");
  1254. Array.each([{
  1255. "name": "cancel", "text": this.lp.cancel
  1256. },{
  1257. "name": "save", "text": this.lp.save
  1258. },{
  1259. "name": "undo"
  1260. },{
  1261. "name": "redo"
  1262. },{
  1263. "name": "reset"
  1264. }], function (item) {
  1265. this.items[item.name] = new Element("div",{
  1266. styles : this.css[item.name+"_mobile"],
  1267. events: {
  1268. click: function () {
  1269. if( this.tablet[item.name] )this.tablet[item.name]( this.items[item.name] );
  1270. }.bind(this)
  1271. }
  1272. }).inject(this.tablet.container);
  1273. if(item.text)this.items[item.name].set("text", item.text);
  1274. if( item.name === "save" )this.items[item.name].addClass("mainColor_color");
  1275. }.bind(this));
  1276. this.setAllItemsStatus();
  1277. },
  1278. _setItemNodeDisable : function( itemNode, itemName ){
  1279. var item = itemNode.get("item");
  1280. itemNode.setStyles( this.css[itemName+"_mobile_disable"] );
  1281. },
  1282. _setItemNodeActive: function( itemNode, itemName ){
  1283. if( itemNode.retrieve("status") == "disable" )return;
  1284. var item = itemNode.get("item");
  1285. itemNode.setStyles( this.css[itemName+"_mobile_over"] );
  1286. },
  1287. _setItemNodeNormal: function( itemNode, itemName ){
  1288. if( itemNode.retrieve("status") == "disable" )return;
  1289. var item = itemNode.get("item");
  1290. itemNode.setStyles( this.css[itemName+"_mobile"] );
  1291. }
  1292. });
  1293. o2.xDesktop.requireApp("Template", "MTooltips", null, false);
  1294. o2.widget.Tablet.SizePicker = new Class({
  1295. Implements: [Options, Events],
  1296. Extends: MTooltips,
  1297. options: {
  1298. style : "default",
  1299. axis: "y", //箭头在x轴还是y轴上展现
  1300. position : { //node 固定的位置
  1301. x : "auto", //x 轴上left center right, auto 系统自动计算
  1302. y : "auto" //y轴上top middle bottom, auto 系统自动计算
  1303. },
  1304. //event : "click", //事件类型,有target 时有效, mouseenter对应mouseleave,click 对应 container 的 click
  1305. nodeStyles : {
  1306. "min-width" : "260px"
  1307. },
  1308. lineWidth : 1
  1309. },
  1310. initialize : function( container, target, app, data, options, targetCoordinates ){
  1311. //可以传入target 或者 targetCoordinates,两种选一
  1312. //传入target,表示触发tooltip的节点,本类根据 this.options.event 自动绑定target的事件
  1313. //传入targetCoordinates,表示 出发tooltip的位置,本类不绑定触发事件
  1314. if( options ){
  1315. this.setOptions(options);
  1316. }
  1317. this.container = container;
  1318. this.target = target;
  1319. this.targetCoordinates = targetCoordinates;
  1320. this.app = app;
  1321. if(app)this.lp = app.lp;
  1322. this.data = data;
  1323. if( this.target ){
  1324. this.setTargetEvents();
  1325. }
  1326. },
  1327. _customNode : function( node ){
  1328. this.range = [1, 30];
  1329. this.ruleList = ["0.1","0.5","1","5","10", "15","20"];
  1330. o2.UD.getDataJson("sizePicker", function(json) {
  1331. this._loadContent(json);
  1332. }.bind(this));
  1333. },
  1334. changeValue: function(value){
  1335. if( value < 10 ){
  1336. this.lineWidth = (value / 10)
  1337. }else{
  1338. this.lineWidth = value - 9;
  1339. }
  1340. this.drawPreview( this.lineWidth );
  1341. this.fireEvent("select", this.lineWidth )
  1342. },
  1343. reset: function(){
  1344. this.lineWidth = this.options.lineWidth || 1;
  1345. var step;
  1346. if( this.lineWidth < 1 ){
  1347. step = this.lineWidth * 10
  1348. }else{
  1349. step = this.lineWidth + 9
  1350. }
  1351. this.slider.set( parseInt( step ) );
  1352. this.drawPreview( this.lineWidth );
  1353. this.fireEvent("select", this.lineWidth )
  1354. },
  1355. _loadContent: function(json){
  1356. this.rulerContainer = new Element("div",{
  1357. styles : {
  1358. "margin-left": " 23px",
  1359. "margin-right": " 1px",
  1360. "width" : "228px"
  1361. }
  1362. }).inject(this.node);
  1363. this.rulerTitleContainer = new Element("div",{
  1364. styles : { "overflow" : "hidden" }
  1365. }).inject( this.rulerContainer );
  1366. this.ruleList.each( function( rule ){
  1367. new Element("div", {
  1368. text : rule,
  1369. styles : {
  1370. width : "32px",
  1371. float : "left",
  1372. "text-align" : "center"
  1373. }
  1374. }).inject( this.rulerTitleContainer )
  1375. }.bind(this));
  1376. this.rulerContentContainer = new Element("div",{
  1377. styles : { "overflow" : "hidden" }
  1378. }).inject( this.rulerContainer );
  1379. new Element("div", {
  1380. styles : {
  1381. width : "14px",
  1382. height : "10px",
  1383. "text-align" : "center",
  1384. float : "left",
  1385. "border-right" : "1px solid #aaa"
  1386. }
  1387. }).inject( this.rulerContentContainer );
  1388. this.ruleList.each( function( rule, i ){
  1389. if( i == this.ruleList.length - 1 )return;
  1390. new Element("div", {
  1391. styles : {
  1392. width : "32px",
  1393. height : "10px",
  1394. "text-align" : "center",
  1395. float : "left",
  1396. "border-right" : "1px solid #aaa"
  1397. }
  1398. }).inject( this.rulerContentContainer )
  1399. }.bind(this));
  1400. this.silderContainer = new Element("div", {
  1401. "height" : "25px",
  1402. "line-height" : "25px",
  1403. "margin-top" : "4px"
  1404. }).inject( this.node );
  1405. this.sliderArea = new Element("div", {styles : {
  1406. "margin-top": "2px",
  1407. "margin-bottom": "10px",
  1408. "height": "10px",
  1409. "overflow": " hidden",
  1410. "margin-left": " 37px",
  1411. "margin-right": " 15px",
  1412. "border-top": "1px solid #999",
  1413. "border-left": "1px solid #999",
  1414. "border-bottom": "1px solid #E1E1E1",
  1415. "border-right": "1px solid #E1E1E1",
  1416. "background-color": "#EEE",
  1417. "width" : "200px"
  1418. }}).inject( this.silderContainer );
  1419. this.sliderKnob = new Element("div", {styles : {
  1420. "height": "8px",
  1421. "width": " 8px",
  1422. "background-color": "#999",
  1423. "z-index": " 99",
  1424. "border-top": "1px solid #DDD",
  1425. "border-left": "1px solid #DDD",
  1426. "border-bottom": "1px solid #777",
  1427. "border-right": "1px solid #777",
  1428. "cursor": "pointer"
  1429. } }).inject( this.sliderArea );
  1430. this.slider = new Slider(this.sliderArea, this.sliderKnob, {
  1431. range: this.range,
  1432. initialStep: 10,
  1433. onChange: function(value){
  1434. this.changeValue( value );
  1435. }.bind(this)
  1436. });
  1437. var previewContainer = new Element("div").inject(this.node);
  1438. new Element("div",{ text : o2.LP.widget.preview, styles : {
  1439. "float" : "left",
  1440. "margin-top" : "5px",
  1441. "width" : "30px"
  1442. }}).inject(this.silderContainer);
  1443. this.previewNode = new Element("div", {
  1444. styles : {
  1445. "margin" : "0px 0px 0px 37px",
  1446. "width" : "200px"
  1447. }
  1448. }).inject( this.node );
  1449. this.canvas = new Element("canvas", {
  1450. width : 200,
  1451. height : 30
  1452. }).inject( this.previewNode );
  1453. this.ctx = this.canvas.getContext("2d");
  1454. this.drawPreview();
  1455. new Element("button", {
  1456. text : o2.LP.widget.reset,
  1457. type : "button",
  1458. styles :{
  1459. "margin-left" : "40px",
  1460. "font-size" : "12px",
  1461. "border-radius" : "3px",
  1462. "cursor" : "pointer" ,
  1463. "border" : "1px solid #ccc",
  1464. "padding" : "5px 10px",
  1465. "background-color" : "#f7f7f7"
  1466. },
  1467. events : {
  1468. click : function(){
  1469. this.reset();
  1470. }.bind(this)
  1471. }
  1472. }).inject( this.node );
  1473. },
  1474. drawPreview : function( lineWidth ){
  1475. if( !lineWidth )lineWidth = this.options.lineWidth || 1;
  1476. var canvas = this.canvas;
  1477. var ctx = this.ctx;
  1478. ctx.clearRect(0,0,canvas.clientWidth,canvas.clientHeight);
  1479. var coordinates = this.previewNode.getCoordinates();
  1480. var doc = $(document);
  1481. ctx.strokeStyle="#000000"; //线条颜色; 默认 #000000
  1482. //ctx.strokeStyle= this.currentColor || this.options.color; // 线条颜色; 默认 #000000
  1483. ctx.lineWidth= lineWidth ; //默认1 像素
  1484. ctx.beginPath();
  1485. //ctx.moveTo( (coordinates.bottom-coordinates.top - lineWidth ) / 2, coordinates.left);
  1486. ctx.moveTo( 1 , 15 );
  1487. ctx.lineTo( 200, 15 );
  1488. ctx.stroke();
  1489. }
  1490. });
  1491. o2.widget.Tablet.EraserRadiusPicker = new Class({
  1492. Extends: o2.widget.Tablet.SizePicker,
  1493. options: {
  1494. lineWidth : 20,
  1495. nodeStyles : {
  1496. "min-width" : "260px"
  1497. },
  1498. },
  1499. _loadContent: function(json){
  1500. this.rulerContainer = new Element("div",{
  1501. styles : {
  1502. "margin-left": " 23px",
  1503. "margin-right": " 1px",
  1504. "width" : "228px"
  1505. }
  1506. }).inject(this.node);
  1507. this.rulerTitleContainer = new Element("div",{
  1508. styles : { "overflow" : "hidden" }
  1509. }).inject( this.rulerContainer );
  1510. this.ruleList.each( function( rule ){
  1511. new Element("div", {
  1512. text : rule,
  1513. styles : {
  1514. width : "24px",
  1515. float : "left",
  1516. "text-align" : "center"
  1517. }
  1518. }).inject( this.rulerTitleContainer )
  1519. }.bind(this));
  1520. this.rulerContentContainer = new Element("div",{
  1521. styles : { "overflow" : "hidden" }
  1522. }).inject( this.rulerContainer );
  1523. new Element("div", {
  1524. styles : {
  1525. width : "14px",
  1526. height : "10px",
  1527. "text-align" : "center",
  1528. float : "left",
  1529. "border-right" : "1px solid #aaa"
  1530. }
  1531. }).inject( this.rulerContentContainer );
  1532. this.ruleList.each( function( rule, i ){
  1533. if( i == this.ruleList.length - 1 )return;
  1534. new Element("div", {
  1535. styles : {
  1536. width : "24px",
  1537. height : "10px",
  1538. "text-align" : "center",
  1539. float : "left",
  1540. "border-right" : "1px solid #aaa"
  1541. }
  1542. }).inject( this.rulerContentContainer )
  1543. }.bind(this));
  1544. this.silderContainer = new Element("div", {
  1545. "height" : "25px",
  1546. "line-height" : "25px",
  1547. "margin-top" : "4px"
  1548. }).inject( this.node );
  1549. this.sliderArea = new Element("div", {styles : {
  1550. "margin-top": "2px",
  1551. "margin-bottom": "10px",
  1552. "height": "10px",
  1553. "overflow": " hidden",
  1554. "margin-left": " 37px",
  1555. "margin-right": " 15px",
  1556. "border-top": "1px solid #999",
  1557. "border-left": "1px solid #999",
  1558. "border-bottom": "1px solid #E1E1E1",
  1559. "border-right": "1px solid #E1E1E1",
  1560. "background-color": "#EEE",
  1561. "width" : "200px"
  1562. }}).inject( this.silderContainer );
  1563. this.sliderKnob = new Element("div", {styles : {
  1564. "height": "8px",
  1565. "width": " 8px",
  1566. "background-color": "#999",
  1567. "z-index": " 99",
  1568. "border-top": "1px solid #DDD",
  1569. "border-left": "1px solid #DDD",
  1570. "border-bottom": "1px solid #777",
  1571. "border-right": "1px solid #777",
  1572. "cursor": "pointer"
  1573. } }).inject( this.sliderArea );
  1574. this.slider = new Slider(this.sliderArea, this.sliderKnob, {
  1575. range: this.range,
  1576. initialStep: 20,
  1577. onChange: function(value){
  1578. this.changeValue( value );
  1579. }.bind(this)
  1580. });
  1581. var previewContainer = new Element("div", {"style":"overflow:hidden;"}).inject(this.node);
  1582. new Element("div",{ text : o2.LP.widget.preview, styles : {
  1583. "float" : "left",
  1584. "margin-top" : "15px",
  1585. "width" : "30px"
  1586. }}).inject(this.silderContainer);
  1587. this.previewNode = new Element("div", {
  1588. styles : {
  1589. "float" : "left",
  1590. "margin" : "0px 0px 0px 37px",
  1591. "width" : "100px"
  1592. }
  1593. }).inject( this.node );
  1594. this.canvas = new Element("canvas", {
  1595. width : 200,
  1596. height : 60
  1597. }).inject( this.previewNode );
  1598. this.ctx = this.canvas.getContext("2d");
  1599. this.drawPreview();
  1600. new Element("button", {
  1601. text : o2.LP.widget.reset,
  1602. type : "button",
  1603. styles :{
  1604. "float" : "left",
  1605. "margin-top" : "10px",
  1606. "font-size" : "12px",
  1607. "border-radius" : "3px",
  1608. "cursor" : "pointer" ,
  1609. "border" : "1px solid #ccc",
  1610. "padding" : "5px 10px",
  1611. "background-color" : "#f7f7f7"
  1612. },
  1613. events : {
  1614. click : function(){
  1615. this.reset();
  1616. }.bind(this)
  1617. }
  1618. }).inject( this.node );
  1619. },
  1620. _customNode : function( node ){
  1621. this.range = [1, 40];
  1622. this.ruleList = ["1","5","10", "15","20","25","30","35","40"];
  1623. o2.UD.getDataJson("eraserRadiusPicker", function(json) {
  1624. this._loadContent(json);
  1625. }.bind(this));
  1626. },
  1627. changeValue: function(value){
  1628. this.lineWidth = value;
  1629. this.drawPreview( this.lineWidth );
  1630. this.fireEvent("select", this.lineWidth )
  1631. },
  1632. reset: function(){
  1633. this.lineWidth = this.options.lineWidth || 20;
  1634. var step = this.lineWidth;
  1635. this.slider.set( parseInt( step ) );
  1636. this.drawPreview( this.lineWidth );
  1637. this.fireEvent("select", this.lineWidth )
  1638. },
  1639. drawPreview : function( lineWidth ){
  1640. if( !lineWidth )lineWidth = this.options.lineWidth || 20;
  1641. var canvas = this.canvas;
  1642. var ctx = this.ctx;
  1643. ctx.clearRect(0,0,canvas.clientWidth,canvas.clientHeight);
  1644. // ctx.strokeStyle="#000000"; //线条颜色; 默认 #000000
  1645. // ctx.lineCap = "round";  //设置线条两端为圆弧
  1646. // ctx.lineJoin = "round";  //设置线条转折为圆弧
  1647. // ctx.lineWidth= lineWidth ;
  1648. // ctx.beginPath();
  1649. // ctx.lineTo( 28, 25 );
  1650. // ctx.stroke();
  1651. ctx.beginPath();
  1652. ctx.arc(30, 30, lineWidth/2, 0, 2 * Math.PI, false);
  1653. //ctx.fillStyle = 'green';
  1654. ctx.fill();
  1655. // ctx.lineWidth = 5;
  1656. // ctx.strokeStyle = '#000000';
  1657. //ctx.stroke();
  1658. }
  1659. });
  1660. MWF.require("MWF.widget.ImageClipper", null, false);
  1661. o2.widget.Tablet.ImageClipper = new Class({
  1662. Implements: [Options, Events],
  1663. Extends: MWF.widget.Common,
  1664. options: {
  1665. "imageUrl" : "",
  1666. "resultMaxSize" : 700,
  1667. "description" : "",
  1668. "title": o2.LP.widget.imageClipper,
  1669. "style": "default",
  1670. "aspectRatio": 0
  1671. },
  1672. initialize: function(app, options, tablet){
  1673. this.setOptions(options);
  1674. this.app = app;
  1675. this.tablet = tablet;
  1676. this.path = "../x_component_process_Xform/widget/$ImageClipper/";
  1677. this.cssPath = "../x_component_process_Xform/widget/$ImageClipper/"+this.options.style+"/css.wcss";
  1678. this._loadCss();
  1679. },
  1680. load: function(data){
  1681. this.data = data;
  1682. var options = {};
  1683. var width = "700";
  1684. var height = "510";
  1685. width = width.toInt();
  1686. height = height.toInt();
  1687. var size = (( this.app && this.app.content ) || $(document.body) ).getSize();
  1688. var x = (size.x-width)/2;
  1689. var y = (size.y-height)/2;
  1690. if (x<0) x = 0;
  1691. if (y<0) y = 0;
  1692. if (layout.mobile){
  1693. x = 20;
  1694. y = 0;
  1695. }
  1696. var _self = this;
  1697. MWF.require("MWF.xDesktop.Dialog", function() {
  1698. var dlg = new MWF.xDesktop.Dialog({
  1699. "title": this.options.title || "Select Image",
  1700. "style": options.style || "user",
  1701. "top": y,
  1702. "left": x - 20,
  1703. "zindex": this.tablet.options.zIndex,
  1704. "fromTop": y,
  1705. "fromLeft": x - 20,
  1706. "width": width,
  1707. "height": height,
  1708. "html": "<div></div>",
  1709. "maskNode": this.app ? this.app.content : $(document.body),
  1710. "container": this.app ? this.app.content : $(document.body),
  1711. "buttonList": [
  1712. {
  1713. "text": MWF.LP.process.button.ok,
  1714. "action": function () {
  1715. var img = _self.image.getResizedImage();
  1716. _self.fireEvent("ok", [img] );
  1717. this.close();
  1718. }
  1719. },
  1720. {
  1721. "text": MWF.LP.process.button.cancel,
  1722. "action": function () {
  1723. this.close();
  1724. }
  1725. }
  1726. ],
  1727. "onPostShow" : function(){
  1728. //this.node.setStyle("z-index",1003);
  1729. this.content.setStyle("margin-left","20px");
  1730. }
  1731. });
  1732. dlg.show();
  1733. this.image = new MWF.widget.ImageClipper(dlg.content.getFirst(), {
  1734. "description" : this.options.description,
  1735. "resetEnable" : true
  1736. });
  1737. this.image.load(this.data);
  1738. }.bind(this))
  1739. }
  1740. });
  1741. o2.widget.Tablet.ImageMover = new Class({
  1742. Implements: [Options, Events],
  1743. options: {
  1744. imageMinSize : 100
  1745. },
  1746. initialize: function(tablet, imageNode, relativeNode, options){
  1747. this.setOptions(options);
  1748. this.tablet = tablet;
  1749. this.css = this.tablet.css;
  1750. this.imageNode = imageNode;
  1751. this.relativeNode = relativeNode;
  1752. this.path = this.tablet.path + this.tablet.options.style + "/"
  1753. },
  1754. load: function(){
  1755. this.maskNode = new Element("div.maskNode",{
  1756. styles : this.css.imageMoveMaskNode
  1757. }).inject($(document.body));
  1758. var coordinates = this.relativeNode.getCoordinates();
  1759. this.node = new Element( "div", {
  1760. styles : {
  1761. "width" : coordinates.width,
  1762. "height" : coordinates.height,
  1763. "position" : "absolute",
  1764. "top" : coordinates.top,
  1765. "left" : coordinates.left,
  1766. "background" : "rgba(255,255,255,0.5)",
  1767. "z-index" : this.tablet.options.zIndex + 3,
  1768. "-webkit-user-select": "none",
  1769. "-moz-user-select": "none",
  1770. "user-select" : "none"
  1771. }
  1772. }).inject($(document.body));
  1773. this.dragNode = new Element("div",{
  1774. styles : {
  1775. "cursor" : "move"
  1776. }
  1777. }).inject( this.node );
  1778. this.imageNode.inject( this.dragNode );
  1779. //this.maskNode.ondragstart = function(){
  1780. // return false;
  1781. //};
  1782. //this.node.ondragstart = function(){
  1783. // return false;
  1784. //};
  1785. //this.imageNode.ondragstart = function(){
  1786. // return false;
  1787. //};
  1788. this.originalImageSize = this.imageNode.getSize();
  1789. this.dragNode.setStyles({
  1790. width : this.originalImageSize.x,
  1791. height : this.originalImageSize.y
  1792. });
  1793. this.okNode = new Element("div",{
  1794. styles : this.css.imageMoveOkNode,
  1795. events : {
  1796. click : function(){
  1797. this.ok();
  1798. this.close();
  1799. }.bind(this)
  1800. }
  1801. }).inject(this.dragNode);
  1802. this.cancelNode = new Element("div",{
  1803. styles : this.css.imageMoveCancelNode,
  1804. events : {
  1805. click : function(){
  1806. this.fireEvent("postCancel");
  1807. this.close();
  1808. }.bind(this)
  1809. }
  1810. }).inject(this.dragNode);
  1811. this.drag = this.dragNode.makeDraggable({
  1812. "container" : this.node,
  1813. "handle": this.dragNode
  1814. });
  1815. this.resizeNode = new Element("div.resizeNode",{
  1816. styles : this.css.imageMoveResizeNode
  1817. }).inject(this.dragNode);
  1818. this.docBody = window.document.body;
  1819. this.resizeNode.addEvents({
  1820. "touchstart" : function(ev){
  1821. this.drag.detach();
  1822. this.dragNode.setStyle("cursor", "nw-resize" );
  1823. this.docBody.setStyle("cursor", "nw-resize" );
  1824. this.resizeMode = true;
  1825. this.getOffset(ev);
  1826. ev.stopPropagation();
  1827. }.bind(this),
  1828. "mousedown" : function(ev){
  1829. this.drag.detach();
  1830. this.dragNode.setStyle("cursor", "nw-resize" );
  1831. this.docBody.setStyle("cursor", "nw-resize" );
  1832. this.resizeMode = true;
  1833. this.getOffset(ev);
  1834. ev.stopPropagation();
  1835. }.bind(this),
  1836. "touchmove" : function(ev){
  1837. if(!this.lastPoint)return;
  1838. var offset= this.getOffset(ev);
  1839. this.resizeDragNode( offset );
  1840. ev.stopPropagation();
  1841. }.bind(this),
  1842. "mousemove" : function(ev){
  1843. if(!this.lastPoint)return;
  1844. var offset= this.getOffset(ev);
  1845. this.resizeDragNode( offset );
  1846. ev.stopPropagation();
  1847. }.bind(this),
  1848. "touchend" : function(ev){
  1849. this.drag.attach();
  1850. this.dragNode.setStyle("cursor", "move" );
  1851. this.docBody.setStyle("cursor", "default" );
  1852. this.resizeMode = false;
  1853. this.lastPoint=null;
  1854. ev.stopPropagation();
  1855. }.bind(this),
  1856. "mouseup" : function(ev){
  1857. this.drag.attach();
  1858. this.dragNode.setStyle("cursor", "move" );
  1859. this.docBody.setStyle("cursor", "default" );
  1860. this.resizeMode = false;
  1861. this.lastPoint=null;
  1862. ev.stopPropagation();
  1863. }.bind(this)
  1864. });
  1865. this.bodyMouseMoveFun = this.bodyMouseMove.bind(this);
  1866. this.docBody.addEvent("touchmove", this.bodyMouseMoveFun);
  1867. this.docBody.addEvent("mousemove", this.bodyMouseMoveFun);
  1868. this.bodyMouseEndFun = this.bodyMouseEnd.bind(this);
  1869. this.docBody.addEvent("touchend", this.bodyMouseEndFun);
  1870. this.docBody.addEvent("mouseup", this.bodyMouseEndFun);
  1871. },
  1872. bodyMouseMove: function(ev){
  1873. if(!this.lastPoint)return;
  1874. if( this.resizeMode ){
  1875. var offset= this.getOffset(ev);
  1876. this.resizeDragNode( offset );
  1877. }
  1878. },
  1879. bodyMouseEnd: function(ev){
  1880. this.lastPoint=null;
  1881. if( this.resizeMode ){
  1882. this.drag.attach();
  1883. this.dragNode.setStyle("cursor", "move" );
  1884. this.docBody.setStyle("cursor", "default" );
  1885. this.resizeMode = false;
  1886. }
  1887. },
  1888. resizeDragNode : function(offset){
  1889. var x=offset.x;
  1890. if( x == 0 )return;
  1891. var y=offset.y;
  1892. if( y == 0 )return;
  1893. var coordinates = this.dragNode.getCoordinates( this.node );
  1894. var containerSize = this.node.getSize();
  1895. var top=coordinates.top,
  1896. left=coordinates.left,
  1897. width=containerSize.x,
  1898. height=containerSize.y,
  1899. ratio = this.originalImageSize.x / this.originalImageSize.y,
  1900. w,
  1901. h;
  1902. //if( ratio ){
  1903. if( Math.abs(x)/Math.abs(y) > ratio ){
  1904. if( x+coordinates.width+left>width ){
  1905. return;
  1906. }else{
  1907. w = x + coordinates.width;
  1908. h = w / ratio;
  1909. if( h+top > height ){
  1910. return;
  1911. }
  1912. }
  1913. }else{
  1914. if(y+coordinates.height+top>height){
  1915. return;
  1916. }else{
  1917. h = y+ coordinates.height;
  1918. w = h * ratio;
  1919. }
  1920. if( w+left > width ){
  1921. return;
  1922. }
  1923. }
  1924. //}else{
  1925. // if( x+coordinates.width+left>width ){
  1926. // return;
  1927. // }else{
  1928. // w = x + coordinates.width
  1929. // }
  1930. // if(y+coordinates.height+top>height){
  1931. // return;
  1932. // }else{
  1933. // h = y+ coordinates.height;
  1934. // }
  1935. //}
  1936. var minWidth = this.options.imageMinSize;
  1937. var minHeight = this.options.imageMinSize;
  1938. w=w< minWidth ? minWidth:w;
  1939. h=h< minHeight ? minHeight:h;
  1940. this.dragNode.setStyles({
  1941. width:w+'px',
  1942. height:h+'px'
  1943. });
  1944. this.imageNode.setStyles({
  1945. width:w+'px',
  1946. height:h+'px'
  1947. });
  1948. },
  1949. getOffset: function(event){
  1950. event=event.event;
  1951. var x,y;
  1952. if(event.touches){
  1953. var touch=event.touches[0];
  1954. x=touch.clientX;
  1955. y=touch.clientY;
  1956. }else{
  1957. x=event.clientX;
  1958. y=event.clientY;
  1959. }
  1960. if(!this.lastPoint){
  1961. this.lastPoint={
  1962. x:x,
  1963. y:y
  1964. };
  1965. }
  1966. var offset={
  1967. x:x-this.lastPoint.x,
  1968. y:y-this.lastPoint.y
  1969. };
  1970. this.lastPoint={
  1971. x:x,
  1972. y:y
  1973. };
  1974. return offset;
  1975. },
  1976. getCoordinates : function(){
  1977. return this.imageNode.getCoordinates( this.node );
  1978. },
  1979. ok : function(){
  1980. this.fireEvent("postOk")
  1981. },
  1982. close : function(){
  1983. this.docBody.removeEvent("touchmove",this.bodyMouseMoveFun);
  1984. this.docBody.removeEvent("mousemove",this.bodyMouseMoveFun);
  1985. this.docBody.removeEvent("touchend",this.bodyMouseEndFun);
  1986. this.docBody.removeEvent("mouseup",this.bodyMouseEndFun);
  1987. //this.backgroundNode.destroy();
  1988. this.maskNode.destroy();
  1989. this.node.destroy();
  1990. delete this;
  1991. }
  1992. });
  1993. o2.widget.Tablet.Input = new Class({
  1994. Implements: [Options, Events],
  1995. options: {
  1996. minWidth: 100,
  1997. minHeight: 30,
  1998. width: 200,
  1999. height: 60,
  2000. top: 0,
  2001. left: 0,
  2002. isEditing: true,
  2003. editable: true,
  2004. text: "",
  2005. scale: 1
  2006. },
  2007. initialize: function (tablet, relativeNode, options, data) {
  2008. this.setOptions(options);
  2009. this.tablet = tablet;
  2010. this.css = this.tablet.css;
  2011. this.relativeNode = relativeNode;
  2012. this.path = this.tablet.path + this.tablet.options.style + "/";
  2013. this.data = data || {};
  2014. var styles = this.data.styles || {};
  2015. this.color = styles.color || this.tablet.currentColor;
  2016. this.fontSize = styles["font-size"] || this.tablet.currentFontSize;
  2017. this.fontFamily = styles["font-family"] || this.tablet.currentFontFamily;
  2018. },
  2019. readMode: function(){
  2020. if( this.editarea && !this.editarea.get("html") ){
  2021. this.close();
  2022. return;
  2023. }
  2024. this.options.isEditing = false;
  2025. // if(this.drag)this.drag.detach();
  2026. if( this.dragNode )this.dragNode.hide(); //.setStyle("cursor","none");
  2027. if( this.resizeNode )this.resizeNode.hide(); //.setStyle("cursor", "none" );
  2028. if( this.cancelNode )this.cancelNode.hide();
  2029. if( this.editareaWrap )this.editareaWrap.setStyle("border", "1px dashed transparent");
  2030. this.node.setStyle("background" , "rgba(255,255,255,0)")
  2031. },
  2032. editMode: function(){
  2033. if(this.tablet.currentInput)this.tablet.currentInput.readMode();
  2034. this.tablet.currentInput = this;
  2035. this.options.isEditing = true;
  2036. // if(this.drag)this.drag.attach();
  2037. if( this.dragNode )this.dragNode.show(); //.setStyle("cursor","move");
  2038. if( this.resizeNode )this.resizeNode.show(); //.setStyle("cursor", "nw-resize" );
  2039. if( this.editareaWrap )this.editareaWrap.setStyle("border", "1px dashed red");
  2040. if( this.cancelNode )this.cancelNode.show();
  2041. this.node.setStyle("background" , "rgba(255,255,255,0.5)")
  2042. },
  2043. scaleTo: function( scale ){
  2044. if( this.options.scale === scale )return;
  2045. this.options.scale = scale;
  2046. if( layout.mobile ){
  2047. var width = (24/this.options.scale);
  2048. if(this.cancelNode)this.cancelNode.setStyles({
  2049. "width" : width+"px",
  2050. "height" : width +"px",
  2051. "top": "-"+(width/2)+"px",
  2052. "right": "-"+(width/2)+"px",
  2053. "background-size": (16/this.options.scale)+"px " + (16/this.options.scale)+"px"
  2054. });
  2055. if(this.dragNode)this.dragNode.setStyles({
  2056. "width" : width+"px",
  2057. "height" : width +"px",
  2058. "top": "-"+(width/2)+"px",
  2059. "left": "-"+(width/2)+"px",
  2060. "background-size": (16/this.options.scale)+"px " + (16/this.options.scale)+"px"
  2061. });
  2062. if(this.resizeNode)this.resizeNode.setStyles({
  2063. "width" : width+"px",
  2064. "height" : width +"px",
  2065. "bottom": "-"+(width/2)+"px",
  2066. "right": "-"+(width/2)+"px",
  2067. "background-size": (16/this.options.scale)+"px " + (16/this.options.scale)+"px"
  2068. });
  2069. }
  2070. },
  2071. getUrl: function ( id ) {
  2072. var address = o2.Actions.getHost("x_processplatform_assemble_surface");
  2073. var serviceName = o2.Actions.load("x_processplatform_assemble_surface").AttachmentAction.action.serviceName;
  2074. var u = o2.Actions.load("x_processplatform_assemble_surface").AttachmentAction.action.actions.downloadTransfer.uri;
  2075. var url = u.replace("{flag}", id);
  2076. url = address + "/" + serviceName + url;
  2077. var uri = new URI( url );
  2078. uri.setData({"stream":"true"}, true);
  2079. if( !uri.getData( o2.tokenName ) ){
  2080. var token = {};
  2081. token[ o2.tokenName ] = this.getToken();
  2082. uri.setData(token, true);
  2083. }
  2084. return uri.toString();
  2085. },
  2086. getToken: function(){
  2087. var token = (layout.config && layout.config.sessionStorageEnable) ? sessionStorage.getItem("o2LayoutSessionToken") : "";
  2088. if (!token) {
  2089. if (layout.session && (layout.session.user || layout.session.token)) {
  2090. token = layout.session.token;
  2091. if (!token && layout.session.user && layout.session.user.token) token = layout.session.user.token;
  2092. }
  2093. }
  2094. return token;
  2095. },
  2096. draw: function( callback ){
  2097. var _self = this;
  2098. if( !this.editarea.offsetParent && this.image ){ //如果被隐藏了
  2099. return this.image || null;
  2100. }else {
  2101. var editareaSize = this.scaleSize(this.editarea.getSize());
  2102. var nodeSize = this.scaleSize(this.node.getSize());
  2103. var size = {
  2104. x : Math.max(editareaSize.x, nodeSize.x),
  2105. y: Math.max(editareaSize.y, nodeSize.y)
  2106. }
  2107. var div = new Element("div", {
  2108. "styles":{
  2109. "padding": "0px",
  2110. "margin": "0px",
  2111. "width": size.x + "px",
  2112. "height": size.y + "px",
  2113. },
  2114. "html": this.editarea.outerHTML
  2115. });
  2116. return o2.Actions.load("x_processplatform_assemble_surface").AttachmentAction.htmlToImage({
  2117. workHtml: div.outerHTML,
  2118. htmlWidth: size.x,
  2119. htmlHeight:size.y,
  2120. startX: 0,
  2121. startY: 0,
  2122. omitBackground: true
  2123. }).then(function (json) {
  2124. return _self.tablet.loadImage( _self.getUrl(json.data.id) );
  2125. // o2.Actions.load(x_processplatform_assemble_surface).AttachmentAction.downloadTransfer(json.data.id,function () {
  2126. //
  2127. // })
  2128. }).then(function (image) {
  2129. _self.image = image;
  2130. _self.fireEvent("postDraw", [image]);
  2131. return image;
  2132. });
  2133. }
  2134. },
  2135. // draw: function( callback ){
  2136. // var _self = this;
  2137. // if( !this.editarea.offsetParent && this.image ){ //如果被隐藏了
  2138. // return this.image || null;
  2139. // }else {
  2140. // var opt = {
  2141. // useCORS: true,
  2142. // allowTaint: true,
  2143. // backgroundColor: null
  2144. // };
  2145. // var scale = this.tablet.options.scale;
  2146. // if( scale && scale !== 1 ){
  2147. // opt.fontScale = scale;
  2148. // //opt.scale = 1;
  2149. // }
  2150. // return window.html2canvas(this.editarea, opt).then(function (canvas) {
  2151. // var src = canvas.toDataURL(_self.tablet.fileType);
  2152. // src = src.split(',')[1];
  2153. // src = 'data:' + _self.tablet.fileType + ';base64,' + src;
  2154. // canvas.destroy();
  2155. // return src
  2156. // }).then(function (src) {
  2157. // return _self.tablet.loadImage(src)
  2158. // }).then(function (image) {
  2159. // _self.image = image;
  2160. // _self.fireEvent("postDraw", [image]);
  2161. // return image;
  2162. // });
  2163. // }
  2164. // },
  2165. // load: function(){
  2166. // o2.load("../o2_lib/html2canvas/html2canvas.js", function() {
  2167. // this._load();
  2168. // }.bind(this))
  2169. // },
  2170. load: function(){
  2171. // var coordinates = this.relativeNode.getCoordinates();
  2172. this.relativeCoordinates = this.scaleSize( this.relativeNode.getCoordinates() );
  2173. var top, left, width, height;
  2174. if( this.data.coordinates ){
  2175. top = this.data.coordinates.top;
  2176. left = this.data.coordinates.left;
  2177. width = this.data.coordinates.width;
  2178. height = this.data.coordinates.height;
  2179. }else{
  2180. var top = this.options.top;
  2181. if( top + this.options.height > this.relativeCoordinates.height ){
  2182. top = this.relativeCoordinates.height - this.options.height;
  2183. this.options.top = top;
  2184. }
  2185. var left = this.options.left;
  2186. if( left + this.options.width > this.relativeCoordinates.width ){
  2187. left = this.relativeCoordinates.width - this.options.width;
  2188. this.options.left = left;
  2189. }
  2190. width = this.options.width;
  2191. height = this.options.height;
  2192. }
  2193. this.node = new Element( "div", {
  2194. styles : {
  2195. "width" : width+"px",
  2196. "min-height" : height+"px",
  2197. "position" : "absolute",
  2198. "top" : top+"px",
  2199. "left" : left+"px",
  2200. "background" : "rgba(255,255,255,0.5)",
  2201. // "z-index" : 1003,
  2202. "-webkit-user-select": "none",
  2203. "-moz-user-select": "none",
  2204. "user-select" : "none"
  2205. },
  2206. events:{
  2207. "touchstart": function (ev) {
  2208. if( !this.options.editable )return;
  2209. if( !this.options.isEditing )this.editMode();
  2210. if( this.tablet.mode !== "inputing" )this.tablet.input();
  2211. ev.stopPropagation();
  2212. }.bind(this),
  2213. "mousedown": function (ev) {
  2214. if( !this.options.editable )return;
  2215. if( !this.options.isEditing )this.editMode();
  2216. if( this.tablet.mode !== "inputing" )this.tablet.input();
  2217. ev.stopPropagation();
  2218. }.bind(this)
  2219. }
  2220. }).inject(this.relativeNode);
  2221. this.editareaWrap = new Element("div", { styles: this.css.inputEditareaWrap }).inject(this.node);
  2222. this.editarea = new Element("div", {
  2223. "contenteditable": true,
  2224. "styles": this.css.inputEditarea
  2225. }).inject( this.editareaWrap );
  2226. this.editarea.setStyles({
  2227. "color": this.color,
  2228. "font-family": this.fontFamily,
  2229. "font-size": this.fontSize
  2230. });
  2231. if( this.data.html )this.editarea.set("html", this.data.html);
  2232. if( this.options.editable ){
  2233. this.editarea.addEvent("blur", function(e){
  2234. this.checkPosition();
  2235. }.bind(this));
  2236. }
  2237. // if(Browser && Browser.name === "ie" ){
  2238. // if( window.MutationObserver ){
  2239. // var mo = new window.MutationObserver(function(e) {
  2240. // this.checkPosition();
  2241. // }.bind(this));
  2242. // mo.observe(this.editarea, { childList: true, subtree: true, characterData: true });
  2243. // }
  2244. // }else{
  2245. // this.editarea.addEvent("input", function(e){
  2246. // this.checkPosition();
  2247. // }.bind(this));
  2248. // }
  2249. if( this.options.editable ){
  2250. this.cancelNode = new Element("div",{
  2251. styles : this.css[ layout.mobile? "inputCancelNode_mobile" : "inputCancelNode"],
  2252. events : {
  2253. click : function(){
  2254. this.fireEvent("postCancel");
  2255. this.tablet.currentInput = null;
  2256. this.close();
  2257. }.bind(this)
  2258. }
  2259. }).inject(this.editareaWrap);
  2260. if( layout.mobile ){
  2261. var width = (24/this.options.scale);
  2262. this.cancelNode.setStyles({
  2263. "width" : width+"px",
  2264. "height" : width +"px",
  2265. "top": "-"+(width/2)+"px",
  2266. "right": "-"+(width/2)+"px",
  2267. "background-size": (16/this.options.scale)+"px " + (16/this.options.scale)+"px"
  2268. });
  2269. }
  2270. this.loadDragNode();
  2271. this.loadResizeNode();
  2272. }
  2273. if( this.options.isEditing ){
  2274. window.setTimeout(function () {
  2275. this.editarea.focus();
  2276. }.bind(this), 100)
  2277. }else{
  2278. this.readMode();
  2279. }
  2280. },
  2281. loadDragNode: function(){
  2282. this.dragNode = new Element("div.dragNode",{
  2283. styles : this.css[ layout.mobile? "inputDragNode_mobile" : "inputDragNode"]
  2284. }).inject(this.editareaWrap);
  2285. if( layout.mobile ){
  2286. var width = (24/this.options.scale);
  2287. this.dragNode.setStyles({
  2288. "width" : width+"px",
  2289. "height" : width +"px",
  2290. "top": "-"+(width/2)+"px",
  2291. "left": "-"+(width/2)+"px",
  2292. "background-size": (16/this.options.scale)+"px " + (16/this.options.scale)+"px"
  2293. });
  2294. }
  2295. this.dragBody = this.relativeNode; //window.document.body;
  2296. var startFun = function(ev){
  2297. if( !this.options.isEditing )return;
  2298. this.dragBody.setStyle("cursor", "move" );
  2299. this.relativeCoordinates = this.scaleSize( this.relativeNode.getCoordinates() );
  2300. this.dragMode = true;
  2301. this.fireEvent("dragStart");
  2302. ev.stopPropagation();
  2303. }.bind(this);
  2304. var moveFun = function(ev){
  2305. if( !this.dragMode )return;
  2306. var point = this.getLastPoint(ev);
  2307. this.drag( point );
  2308. this.fireEvent("drag");
  2309. ev.stopPropagation();
  2310. }.bind(this);
  2311. var endFun = function(ev){
  2312. this.dragBody.setStyle("cursor", "default" );
  2313. this.dragMode = false;
  2314. this.lastPoint=null;
  2315. this.fireEvent("dragComplete");
  2316. ev.stopPropagation();
  2317. }.bind(this);
  2318. this.dragNode.addEvents({
  2319. "touchstart" : startFun,
  2320. "mousedown" : startFun,
  2321. "touchmove" : moveFun,
  2322. "mousemove" : moveFun,
  2323. "touchend" : endFun,
  2324. "mouseup" : endFun
  2325. });
  2326. this.bodyDragMoveFun = this.bodyDragMove.bind(this);
  2327. this.dragBody.addEvent("touchmove", this.bodyDragMoveFun);
  2328. this.dragBody.addEvent("mousemove", this.bodyDragMoveFun);
  2329. this.bodyDragEndFun = this.bodyDragEnd.bind(this);
  2330. this.dragBody.addEvent("touchend", this.bodyDragEndFun);
  2331. this.dragBody.addEvent("mouseup", this.bodyDragEndFun);
  2332. // this.drag = this.node.makeDraggable({
  2333. // "container" : this.relativeNode,
  2334. // "handle": this.dragNode,
  2335. // "onStart": function(el, e){
  2336. // this.draging = true;
  2337. // this.fireEvent("dragStart");
  2338. // }.bind(this),
  2339. // "onComplete": function(e){
  2340. // this.draging = false;
  2341. // this.fireEvent("dragComplete");
  2342. // }.bind(this),
  2343. // "onDrag": function(el, e) {
  2344. // this.fireEvent("drag");
  2345. // }.bind(this)
  2346. // });
  2347. },
  2348. bodyDragMove: function(ev){
  2349. if(!this.lastPoint)return;
  2350. if( this.dragMode ){
  2351. var point = this.getLastPoint(ev);
  2352. this.drag( point );
  2353. }
  2354. },
  2355. bodyDragEnd: function(ev){
  2356. this.lastPoint=null;
  2357. if( this.dragMode ){
  2358. this.docBody.setStyle("cursor", "default" );
  2359. this.dragMode = false;
  2360. }
  2361. },
  2362. drag : function(lastPoint){
  2363. var x=lastPoint.x;
  2364. var y=lastPoint.y;
  2365. var nodeSize = this.scaleSize( this.node.getSize() );
  2366. var inputSize = this.scaleSize( this.editarea.getSize() );
  2367. // var top=coordinates.top,
  2368. // left=coordinates.left,
  2369. var lft,
  2370. tp,
  2371. size = {
  2372. x: Math.max( nodeSize.x, inputSize.x ),
  2373. y: Math.max( nodeSize.y, inputSize.y )
  2374. };
  2375. if( x < this.relativeCoordinates.left ){
  2376. lft = 0;
  2377. }else if( x + size.x > this.relativeCoordinates.right ){
  2378. lft = this.relativeCoordinates.width - size.x;
  2379. }else{
  2380. lft = x - this.relativeCoordinates.left;
  2381. }
  2382. if( y < this.relativeCoordinates.top ){
  2383. tp = 0;
  2384. }else if( y + size.y > this.relativeCoordinates.bottom){
  2385. tp = this.relativeCoordinates.height - size.y
  2386. }else{
  2387. tp = y - this.relativeCoordinates.top;
  2388. }
  2389. this.node.setStyles({
  2390. "top":tp+'px',
  2391. "left":lft+'px'
  2392. });
  2393. },
  2394. loadResizeNode: function(){
  2395. this.resizeNode = new Element("div.resizeNode",{
  2396. styles : this.css[ layout.mobile? "inputResizeNode_mobile" : "inputResizeNode"]
  2397. }).inject(this.editareaWrap);
  2398. if( layout.mobile ){
  2399. var width = (24/this.options.scale);
  2400. this.resizeNode.setStyles({
  2401. "width" : width+"px",
  2402. "height" : width +"px",
  2403. "bottom": "-"+(width/2)+"px",
  2404. "right": "-"+(width/2)+"px",
  2405. "background-size": (16/this.options.scale)+"px " + (16/this.options.scale)+"px"
  2406. });
  2407. }
  2408. this.docBody = this.relativeNode; //window.document.body;
  2409. var startFun = function(ev){
  2410. if( !this.options.isEditing )return;
  2411. // this.drag.detach();
  2412. this.dragNode.setStyle("cursor", "nw-resize" );
  2413. this.docBody.setStyle("cursor", "nw-resize" );
  2414. this.relativeCoordinates = this.scaleSize( this.relativeNode.getCoordinates() );
  2415. this.resizeMode = true;
  2416. this.fireEvent("resizeStart");
  2417. ev.stopPropagation();
  2418. }.bind(this);
  2419. var moveFun = function(ev){
  2420. if( !this.resizeMode )return;
  2421. var point = this.getLastPoint(ev);
  2422. this.resize( point );
  2423. this.fireEvent("resizeMove");
  2424. ev.stopPropagation();
  2425. }.bind(this);
  2426. var endFun = function(ev){
  2427. // this.drag.attach();
  2428. this.dragNode.setStyle("cursor", "move" );
  2429. this.docBody.setStyle("cursor", "default" );
  2430. this.resizeMode = false;
  2431. this.lastPoint=null;
  2432. this.fireEvent("resizeEnd");
  2433. ev.stopPropagation();
  2434. }.bind(this);
  2435. this.resizeNode.addEvents({
  2436. "touchstart" : startFun,
  2437. "mousedown" : startFun,
  2438. "touchmove" : moveFun,
  2439. "mousemove" : moveFun,
  2440. "touchend" : endFun,
  2441. "mouseup" : endFun
  2442. });
  2443. this.bodyMouseMoveFun = this.bodyMouseMove.bind(this);
  2444. this.docBody.addEvent("touchmove", this.bodyMouseMoveFun);
  2445. this.docBody.addEvent("mousemove", this.bodyMouseMoveFun);
  2446. this.bodyMouseEndFun = this.bodyMouseEnd.bind(this);
  2447. this.docBody.addEvent("touchend", this.bodyMouseEndFun);
  2448. this.docBody.addEvent("mouseup", this.bodyMouseEndFun);
  2449. },
  2450. bodyMouseMove: function(ev){
  2451. if(!this.lastPoint)return;
  2452. if( this.resizeMode ){
  2453. var point = this.getLastPoint(ev);
  2454. this.resize( point );
  2455. }
  2456. },
  2457. bodyMouseEnd: function(ev){
  2458. this.lastPoint=null;
  2459. if( this.resizeMode ){
  2460. // this.drag.attach();
  2461. this.dragNode.setStyle("cursor", "move" );
  2462. this.docBody.setStyle("cursor", "default" );
  2463. this.resizeMode = false;
  2464. }
  2465. },
  2466. resize : function(lastPoint){
  2467. var x=lastPoint.x;
  2468. if( x == 0 )return;
  2469. var y=lastPoint.y;
  2470. if( y == 0 )return;
  2471. var coordinates = this.scaleSize( this.node.getCoordinates() );
  2472. var inputSize = this.scaleSize( this.editarea.getSize() );
  2473. var top=coordinates.top,
  2474. left=coordinates.left,
  2475. w,
  2476. h;
  2477. if( x > this.relativeCoordinates.right ){
  2478. return;
  2479. }else{
  2480. w = x - left;
  2481. }
  2482. if( y > this.relativeCoordinates.bottom){
  2483. return;
  2484. }else{
  2485. h = y - top;
  2486. }
  2487. if( inputSize.y > h ){
  2488. h = inputSize.y;
  2489. }
  2490. var minWidth = this.scaleSize( this.options.minWidth );
  2491. var minHeight = this.scaleSize( this.options.minHeight );
  2492. w=w< minWidth ? minWidth:w;
  2493. h=h< minHeight ? minHeight:h;
  2494. this.node.setStyles({
  2495. "width":w+'px',
  2496. "min-height":h+'px'
  2497. });
  2498. },
  2499. getLastPoint: function(event){
  2500. event=event.event;
  2501. var x,y;
  2502. if(event.touches){
  2503. var touch=event.touches[0];
  2504. x=touch.clientX;
  2505. y=touch.clientY;
  2506. }else{
  2507. x=event.clientX;
  2508. y=event.clientY;
  2509. }
  2510. this.lastPoint= this.scaleSize({
  2511. x:x,
  2512. y:y
  2513. });
  2514. return this.lastPoint;
  2515. },
  2516. checkPosition: function(){
  2517. var coordinates = this.scaleSize( this.editarea.getCoordinates( this.relativeNode ));
  2518. var containerSize = this.scaleSize( this.relativeNode.getSize() );
  2519. if( coordinates.height > containerSize.y ){
  2520. this.node.setStyle("top", "0px");
  2521. }else if( coordinates.bottom > containerSize.y ){
  2522. this.node.setStyle("top", containerSize.y - coordinates.height );
  2523. }
  2524. // if( this.isChecking )return;
  2525. // this.isChecking = true;
  2526. // window.setTimeout(function () {
  2527. // var coordinates = this.editarea.getCoordinates( this.canvasWrap );
  2528. // console.log(coordinates);
  2529. // this.isChecking = false;
  2530. // }.bind(this), 100)
  2531. },
  2532. setColor: function( color ){
  2533. this.color = color;
  2534. this.editarea.setStyle("color", color);
  2535. },
  2536. setFontFamily: function( fontFamily ){
  2537. this.fontFamily = fontFamily;
  2538. this.editarea.setStyle("font-family", fontFamily);
  2539. },
  2540. setFontSize: function( fontSize ){
  2541. this.fontSize = fontSize;
  2542. this.editarea.setStyle("font-size", fontSize);
  2543. },
  2544. getCoordinates: function(){
  2545. return this.editarea.getCoordinates( this.relativeNode );
  2546. },
  2547. getDrawImageCoordinates : function(){
  2548. var size = this.scaleSize(this.editarea.getSize());
  2549. var coordinates = this.scaleSize(this.node.getCoordinates( this.relativeNode ));
  2550. coordinates.width = Math.max(coordinates.width, size.x);
  2551. coordinates.height = Math.max(coordinates.height, size.y);
  2552. coordinates.top = coordinates.top - 7; //后台服务的偏差
  2553. coordinates.left = coordinates.left - 7; //后台服务的偏差
  2554. return coordinates;
  2555. },
  2556. ok : function(){
  2557. this.fireEvent("postOk")
  2558. },
  2559. close : function( flag ){
  2560. if(!flag)this.tablet.eraseInput(this);
  2561. this.docBody.removeEvent("touchmove",this.bodyMouseMoveFun);
  2562. this.docBody.removeEvent("mousemove",this.bodyMouseMoveFun);
  2563. this.docBody.removeEvent("touchend",this.bodyMouseEndFun);
  2564. this.docBody.removeEvent("mouseup",this.bodyMouseEndFun);
  2565. //this.backgroundNode.destroy();
  2566. this.node.destroy();
  2567. delete this;
  2568. },
  2569. getData: function () {
  2570. // var coordinates;
  2571. // if( this.node.getBoundingClientRect ){
  2572. // var size = this.node.getSize();
  2573. // var rectOut = this.relativeNode.getBoundingClientRect();
  2574. // var rectIn = this.node.getBoundingClientRect();
  2575. // coordinates = {
  2576. // "top": rectIn.top - rectOut.top,
  2577. // "left": rectIn.left - rectOut.left,
  2578. // "height": size.y,
  2579. // "width": size.x
  2580. // }
  2581. // }else{
  2582. // coordinates = this.node.getCoordinates( this.relativeNode );
  2583. // }
  2584. return {
  2585. coordinates : this.scaleSize( this.node.getCoordinates( this.relativeNode ) ), //coordinates
  2586. styles: {
  2587. "color": this.color,
  2588. "font-family": this.fontFamily,
  2589. "font-size": this.fontSize
  2590. },
  2591. html: this.editarea.get("html")
  2592. }
  2593. },
  2594. show: function () {
  2595. this.node.show();
  2596. },
  2597. hide: function () {
  2598. this.node.hide();
  2599. },
  2600. scaleSize: function (size) {
  2601. var s;
  2602. if( this.options.scale !== 1 ){
  2603. var t = o2.typeOf( size );
  2604. if( t === "number" ){
  2605. s = size/this.options.scale;
  2606. }else if( t === "object" ){
  2607. s = {};
  2608. for( var k in size ){
  2609. s[k] = size[k]/this.options.scale;
  2610. }
  2611. }
  2612. }
  2613. return s || size;
  2614. }
  2615. })
  2616. o2.widget.Tablet.FontFamily = new Class({
  2617. Extends: MSelector,
  2618. options : {
  2619. "containerIsTarget": false,
  2620. "style": "minderFont",
  2621. "width": "120px",
  2622. "height": "28px",
  2623. "defaultOptionLp" : "字体",
  2624. "textField" : "name",
  2625. "valueField" : "val",
  2626. "event" : "mouseenter",
  2627. "isSetSelectedValue" : true,
  2628. "isChangeOptionStyle" : true,
  2629. "emptyOptionEnable" : false,
  2630. "tooltipsOptions": {
  2631. "displayDelay" : 300,
  2632. "event": "mouseenter" //事件类型,有target 时有效, mouseenter对应mouseleave,click 对应 container 的 click
  2633. }
  2634. },
  2635. _selectItem : function( itemNode, itemData ){
  2636. },
  2637. _loadData : function( callback ){
  2638. var fontFamilyList = [{
  2639. name: '宋体',
  2640. val: '宋体,SimSun'
  2641. }, {
  2642. name: '微软雅黑',
  2643. val: '微软雅黑,Microsoft YaHei'
  2644. }, {
  2645. name: '楷体',
  2646. val: '楷体,楷体_GB2312,SimKai'
  2647. }, {
  2648. name: '黑体',
  2649. val: '黑体, SimHei'
  2650. }, {
  2651. name: '隶书',
  2652. val: '隶书, SimLi'
  2653. }, {
  2654. name: 'Andale Mono',
  2655. val: 'andale mono'
  2656. }, {
  2657. name: 'Arial',
  2658. val: 'arial,helvetica,sans-serif'
  2659. }, {
  2660. name: 'arialBlack',
  2661. val: 'arial black,avant garde'
  2662. }, {
  2663. name: 'Comic Sans Ms',
  2664. val: 'comic sans ms'
  2665. }, {
  2666. name: 'Impact',
  2667. val: 'impact,chicago'
  2668. }, {
  2669. name: 'TimesNewRoman',
  2670. val: 'times new roman'
  2671. }, {
  2672. name: 'Sans-Serif',
  2673. val: 'sans-serif'
  2674. }];
  2675. if(callback)callback( fontFamilyList );
  2676. },
  2677. _postCreateItem: function( itemNode, data ){
  2678. itemNode.setStyles( {
  2679. "font-family": data.val,
  2680. "font-size" : "13px",
  2681. "min-height" : "30px",
  2682. "line-height" : "30px"
  2683. } );
  2684. }
  2685. });
  2686. o2.widget.Tablet.FontSize = new Class({
  2687. Extends: MSelector,
  2688. options : {
  2689. "containerIsTarget": false,
  2690. "style": "minderFont",
  2691. "width": "60px",
  2692. "height": "28px",
  2693. "defaultOptionLp" : "16",
  2694. "defaultVaue": "16",
  2695. "isSetSelectedValue" : true,
  2696. "isChangeOptionStyle" : true,
  2697. "emptyOptionEnable" : false,
  2698. "event" : "mouseenter",
  2699. "tooltipsOptions": {
  2700. "displayDelay" : 300,
  2701. "event": "mouseenter" //事件类型,有target 时有效, mouseenter对应mouseleave,click 对应 container 的 click
  2702. }
  2703. },
  2704. _selectItem : function( itemNode, itemData ){
  2705. },
  2706. _loadData : function( callback ){
  2707. var fontSizeList = ["10", "12", "14", "16", "18", "24", "32", "48"];
  2708. if(callback)callback( fontSizeList );
  2709. },
  2710. _postCreateItem: function( itemNode, data ){
  2711. itemNode.setStyles( {
  2712. "font-size" : "13px" //data.value +"px"
  2713. // "min-height" : ( parseInt(data.value) + 6) +"px",
  2714. // "line-height" : ( parseInt(data.value) + 6) +"px"
  2715. } );
  2716. }
  2717. });