From e5a81ef88665d932d8af056f6afc9d3411cba8e2 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Thu, 1 Oct 2015 16:20:35 +0200 Subject: [PATCH 01/31] widget boolean_switch POC --- web_widget_boolean_switch/README.rst | 77 ++++++++++++ web_widget_boolean_switch/__init__.py | 3 + web_widget_boolean_switch/__openerp__.py | 38 ++++++ .../demo/res_users_view.xml | 70 +++++++++++ .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/icon.svg | 79 +++++++++++++ .../src/js/web_widget_boolean_switch.js | 110 ++++++++++++++++++ .../src/xml/web_widget_boolean_switch.xml | 13 +++ 8 files changed, 390 insertions(+) create mode 100644 web_widget_boolean_switch/README.rst create mode 100644 web_widget_boolean_switch/__init__.py create mode 100644 web_widget_boolean_switch/__openerp__.py create mode 100644 web_widget_boolean_switch/demo/res_users_view.xml create mode 100644 web_widget_boolean_switch/static/description/icon.png create mode 100644 web_widget_boolean_switch/static/description/icon.svg create mode 100644 web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js create mode 100644 web_widget_boolean_switch/static/src/xml/web_widget_boolean_switch.xml diff --git a/web_widget_boolean_switch/README.rst b/web_widget_boolean_switch/README.rst new file mode 100644 index 00000000..5cc824ad --- /dev/null +++ b/web_widget_boolean_switch/README.rst @@ -0,0 +1,77 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +========================= +Web widget boolean switch +========================= + +This module add a widget to render boolean fields + +Installation +============ + +To install this module, you need to: + +* do this ... + +Configuration +============= + +To configure this module, you need to: + +* go to ... + +Usage +===== + +To use this module, you need to: + +* go to ... + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/{repo_id}/{branch} + +.. repo_id is available in https://github.com/OCA/maintainer-tools/blob/master/tools/repos_with_ids.txt +.. branch is "8.0" for example + +Known issues / Roadmap +====================== + +* ... + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed feedback `here `_. + + +Credits +======= + +Contributors +------------ + +* Pierre Verkest + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit http://odoo-community.org. diff --git a/web_widget_boolean_switch/__init__.py b/web_widget_boolean_switch/__init__.py new file mode 100644 index 00000000..87ba95e2 --- /dev/null +++ b/web_widget_boolean_switch/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +# © 2015 +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/web_widget_boolean_switch/__openerp__.py b/web_widget_boolean_switch/__openerp__.py new file mode 100644 index 00000000..a4c085df --- /dev/null +++ b/web_widget_boolean_switch/__openerp__.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# © +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + "name": "Web widget boolean switch", + "summary": "This module add widget to render boolean fields", + "version": "7.0.1.0.0", + "category": "web", + "website": "https://odoo-community.org/", + "author": ", Odoo Community Association (OCA)", + "license": "AGPL-3", + "application": False, + "installable": True, + "external_dependencies": { + "python": [], + "bin": [], + }, + "depends": [ + "base", + "web", + ], + "data": [ + ], + "js": [ + 'static/lib/bootstrap-switch/bootstrap-switch.js', + 'static/src/js/web_widget_boolean_switch.js', + ], + "css": [ + 'static/lib/bootstrap-switch/bootstrap-switch.css', + ], + 'qweb': [ + 'static/src/xml/web_widget_boolean_switch.xml', + ], + "demo": [ + 'demo/res_users_view.xml', + ], + 'description': """""", # TODO: copy README.rst +} diff --git a/web_widget_boolean_switch/demo/res_users_view.xml b/web_widget_boolean_switch/demo/res_users_view.xml new file mode 100644 index 00000000..1543c83a --- /dev/null +++ b/web_widget_boolean_switch/demo/res_users_view.xml @@ -0,0 +1,70 @@ + + + + + + res.users.search + res.users + + + + + + + + + + res.users.tree + res.users + 20 + + + + + + + + + res.users.form + res.users + + + + + + + + + + res.users.tree + res.users + + + + + + + + + + + + Tree Editable Users + ir.actions.act_window + res.users + form + + + + + + tree + + + + + + + diff --git a/web_widget_boolean_switch/static/description/icon.png b/web_widget_boolean_switch/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 zcmW++2RxMjAAjx~&dlBk9S+%}OXg)AGE&Cb*&}d0jUxM@u(PQx^-s)697TX`ehR4?GS^qbkof1cslKgkU)h65qZ9Oc=ml_0temigYLJfnz{IDzUf>bGs4N!v3=Z3jMq&A#7%rM5eQ#dc?k~! zVpnB`o+K7|Al`Q_U;eD$B zfJtP*jH`siUq~{KE)`jP2|#TUEFGRryE2`i0**z#*^6~AI|YzIWy$Cu#CSLW3q=GA z6`?GZymC;dCPk~rBS%eCb`5OLr;RUZ;D`}um=H)BfVIq%7VhiMr)_#G0N#zrNH|__ zc+blN2UAB0=617@>_u;MPHN;P;N#YoE=)R#i$k_`UAA>WWCcEVMh~L_ zj--gtp&|K1#58Yz*AHCTMziU1Jzt_jG0I@qAOHsk$2}yTmVkBp_eHuY$A9)>P6o~I z%aQ?!(GqeQ-Y+b0I(m9pwgi(IIZZzsbMv+9w{PFtd_<_(LA~0H(xz{=FhLB@(1&qHA5EJw1>>=%q2f&^X>IQ{!GJ4e9U z&KlB)z(84HmNgm2hg2C0>WM{E(DdPr+EeU_N@57;PC2&DmGFW_9kP&%?X4}+xWi)( z;)z%wI5>D4a*5XwD)P--sPkoY(a~WBw;E~AW`Yue4kFa^LM3X`8x|}ZUeMnqr}>kH zG%WWW>3ml$Yez?i%)2pbKPI7?5o?hydokgQyZsNEr{a|mLdt;X2TX(#B1j35xPnPW z*bMSSOauW>o;*=kO8ojw91VX!qoOQb)zHJ!odWB}d+*K?#sY_jqPdg{Sm2HdYzdEx zOGVPhVRTGPtv0o}RfVP;Nd(|CB)I;*t&QO8h zFfekr30S!-LHmV_Su-W+rEwYXJ^;6&3|L$mMC8*bQptyOo9;>Qb9Q9`ySe3%V$A*9 zeKEe+b0{#KWGp$F+tga)0RtI)nhMa-K@JS}2krK~n8vJ=Ngm?R!9G<~RyuU0d?nz# z-5EK$o(!F?hmX*2Yt6+coY`6jGbb7tF#6nHA zuKk=GGJ;ZwON1iAfG$E#Y7MnZVmrY|j0eVI(DN_MNFJmyZ|;w4tf@=CCDZ#5N_0K= z$;R~bbk?}TpfDjfB&aiQ$VA}s?P}xPERJG{kxk5~R`iRS(SK5d+Xs9swCozZISbnS zk!)I0>t=A<-^z(cmSFz3=jZ23u13X><0b)P)^1T_))Kr`e!-pb#q&J*Q`p+B6la%C zuVl&0duN<;uOsB3%T9Fp8t{ED108<+W(nOZd?gDnfNBC3>M8WE61$So|P zVvqH0SNtDTcsUdzaMDpT=Ty0pDHHNL@Z0w$Y`XO z2M-_r1S+GaH%pz#Uy0*w$Vdl=X=rQXEzO}d6J^R6zjM1u&c9vYLvLp?W7w(?np9x1 zE_0JSAJCPB%i7p*Wvg)pn5T`8k3-uR?*NT|J`eS#_#54p>!p(mLDvmc-3o0mX*mp_ zN*AeS<>#^-{S%W<*mz^!X$w_2dHWpcJ6^j64qFBft-o}o_Vx80o0>}Du;>kLts;$8 zC`7q$QI(dKYG`Wa8#wl@V4jVWBRGQ@1dr-hstpQL)Tl+aqVpGpbSfN>5i&QMXfiZ> zaA?T1VGe?rpQ@;+pkrVdd{klI&jVS@I5_iz!=UMpTsa~mBga?1r}aRBm1WS;TT*s0f0lY=JBl66Upy)-k4J}lh=P^8(SXk~0xW=T9v*B|gzIhN z>qsO7dFd~mgxAy4V?&)=5ieYq?zi?ZEoj)&2o)RLy=@hbCRcfT5jigwtQGE{L*8<@Yd{zg;CsL5mvzfDY}P-wos_6PfprFVaeqNE%h zKZhLtcQld;ZD+>=nqN~>GvROfueSzJD&BE*}XfU|H&(FssBqY=hPCt`d zH?@s2>I(|;fcW&YM6#V#!kUIP8$Nkdh0A(bEVj``-AAyYgwY~jB zT|I7Bf@%;7aL7Wf4dZ%VqF$eiaC38OV6oy3Z#TER2G+fOCd9Iaoy6aLYbPTN{XRPz z;U!V|vBf%H!}52L2gH_+j;`bTcQRXB+y9onc^wLm5wi3-Be}U>k_u>2Eg$=k!(l@I zcCg+flakT2Nej3i0yn+g+}%NYb?ta;R?(g5SnwsQ49U8Wng8d|{B+lyRcEDvR3+`O{zfmrmvFrL6acVP%yG98X zo&+VBg@px@i)%o?dG(`T;n*$S5*rnyiR#=wW}}GsAcfyQpE|>a{=$Hjg=-*_K;UtD z#z-)AXwSRY?OPefw^iI+ z)AXz#PfEjlwTes|_{sB?4(O@fg0AJ^g8gP}ex9Ucf*@_^J(s_5jJV}c)s$`Myn|Kd z$6>}#q^n{4vN@+Os$m7KV+`}c%4)4pv@06af4-x5#wj!KKb%caK{A&Y#Rfs z-po?Dcb1({W=6FKIUirH&(yg=*6aLCekcKwyfK^JN5{wcA3nhO(o}SK#!CINhI`-I z1)6&n7O&ZmyFMuNwvEic#IiOAwNkR=u5it{B9n2sAJV5pNhar=j5`*N!Na;c7g!l$ z3aYBqUkqqTJ=Re-;)s!EOeij=7SQZ3Hq}ZRds%IM*PtM$wV z@;rlc*NRK7i3y5BETSKuumEN`Xu_8GP1Ri=OKQ$@I^ko8>H6)4rjiG5{VBM>B|%`&&s^)jS|-_95&yc=GqjNo{zFkw%%HHhS~e=s zD#sfS+-?*t|J!+ozP6KvtOl!R)@@-z24}`9{QaVLD^9VCSR2b`b!KC#o;Ki<+wXB6 zx3&O0LOWcg4&rv4QG0)4yb}7BFSEg~=IR5#ZRj8kg}dS7_V&^%#Do==#`u zpy6{ox?jWuR(;pg+f@mT>#HGWHAJRRDDDv~@(IDw&R>9643kK#HN`!1vBJHnC+RM&yIh8{gG2q zA%e*U3|N0XSRa~oX-3EAneep)@{h2vvd3Xvy$7og(sayr@95+e6~Xvi1tUqnIxoIH zVWo*OwYElb#uyW{Imam6f2rGbjR!Y3`#gPqkv57dB6K^wRGxc9B(t|aYDGS=m$&S!NmCtrMMaUg(c zc2qC=2Z`EEFMW-me5B)24AqF*bV5Dr-M5ig(l-WPS%CgaPzs6p_gnCIvTJ=Y<6!gT zVt@AfYCzjjsMEGi=rDQHo0yc;HqoRNnNFeWZgcm?f;cp(6CNylj36DoL(?TS7eU#+ z7&mfr#y))+CJOXQKUMZ7QIdS9@#-}7y2K1{8)cCt0~-X0O!O?Qx#E4Og+;A2SjalQ zs7r?qn0H044=sDN$SRG$arw~n=+T_DNdSrarmu)V6@|?1-ZB#hRn`uilTGPJ@fqEy zGt(f0B+^JDP&f=r{#Y_wi#AVDf-y!RIXU^0jXsFpf>=Ji*TeqSY!H~AMbJdCGLhC) zn7Rx+sXw6uYj;WRYrLd^5IZq@6JI1C^YkgnedZEYy<&4(z%Q$5yv#Boo{AH8n$a zhb4Y3PWdr269&?V%uI$xMcUrMzl=;w<_nm*qr=c3Rl@i5wWB;e-`t7D&c-mcQl7x! zZWB`UGcw=Y2=}~wzrfLx=uet<;m3~=8I~ZRuzvMQUQdr+yTV|ATf1Uuomr__nDf=X zZ3WYJtHp_ri(}SQAPjv+Y+0=fH4krOP@S&=zZ-t1jW1o@}z;xk8 z(Nz1co&El^HK^NrhVHa-_;&88vTU>_J33=%{if;BEY*J#1n59=07jrGQ#IP>@u#3A z;!q+E1Rj3ZJ+!4bq9F8PXJ@yMgZL;>&gYA0%_Kbi8?S=XGM~dnQZQ!yBSgcZhY96H zrWnU;k)qy`rX&&xlDyA%(a1Hhi5CWkmg(`Gb%m(HKi-7Z!LKGRP_B8@`7&hdDy5n= z`OIxqxiVfX@OX1p(mQu>0Ai*v_cTMiw4qRt3~NBvr9oBy0)r>w3p~V0SCm=An6@3n)>@z!|o-$HvDK z|3D2ZMJkLE5loMKl6R^ez@Zz%S$&mbeoqH5`Bb){Ei21q&VP)hWS2tjShfFtGE+$z zzCR$P#uktu+#!w)cX!lWN1XU%K-r=s{|j?)Akf@q#3b#{6cZCuJ~gCxuMXRmI$nGtnH+-h z+GEi!*X=AP<|fG`1>MBdTb?28JYc=fGvAi2I<$B(rs$;eoJCyR6_bc~p!XR@O-+sD z=eH`-ye})I5ic1eL~TDmtfJ|8`0VJ*Yr=hNCd)G1p2MMz4C3^Mj?7;!w|Ly%JqmuW zlIEW^Ft%z?*|fpXda>Jr^1noFZEwFgVV%|*XhH@acv8rdGxeEX{M$(vG{Zw+x(ei@ zmfXb22}8-?Fi`vo-YVrTH*C?a8%M=Hv9MqVH7H^J$KsD?>!SFZ;ZsvnHr_gn=7acz z#W?0eCdVhVMWN12VV^$>WlQ?f;P^{(&pYTops|btm6aj>_Uz+hqpGwB)vWp0Cf5y< zft8-je~nn?W11plq}N)4A{l8I7$!ks_x$PXW-2XaRFswX_BnF{R#6YIwMhAgd5F9X zGmwdadS6(a^fjHtXg8=l?Rc0Sm%hk6E9!5cLVloEy4eh(=FwgP`)~I^5~pBEWo+F6 zSf2ncyMurJN91#cJTy_u8Y}@%!bq1RkGC~-bV@SXRd4F{R-*V`bS+6;W5vZ(&+I<9$;-V|eNfLa5n-6% z2(}&uGRF;p92eS*sE*oR$@pexaqr*meB)VhmIg@h{uzkk$9~qh#cHhw#>O%)b@+(| z^IQgqzuj~Sk(J;swEM-3TrJAPCq9k^^^`q{IItKBRXYe}e0Tdr=Huf7da3$l4PdpwWDop%^}n;dD#K4s#DYA8SHZ z&1!riV4W4R7R#C))JH1~axJ)RYnM$$lIR%6fIVA@zV{XVyx}C+a-Dt8Y9M)^KU0+H zR4IUb2CJ{Hg>CuaXtD50jB(_Tcx=Z$^WYu2u5kubqmwp%drJ6 z?Fo40g!Qd<-l=TQxqHEOuPX0;^z7iX?Ke^a%XT<13TA^5`4Xcw6D@Ur&VT&CUe0d} z1GjOVF1^L@>O)l@?bD~$wzgf(nxX1OGD8fEV?TdJcZc2KoUe|oP1#=$$7ee|xbY)A zDZq+cuTpc(fFdj^=!;{k03C69lMQ(|>uhRfRu%+!k&YOi-3|1QKB z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/web_widget_boolean_switch/static/description/icon.svg b/web_widget_boolean_switch/static/description/icon.svg new file mode 100644 index 00000000..a7a26d09 --- /dev/null +++ b/web_widget_boolean_switch/static/description/icon.svg @@ -0,0 +1,79 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js new file mode 100644 index 00000000..5b214e11 --- /dev/null +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -0,0 +1,110 @@ +'use strict'; +openerp.web_widget_boolean_switch = function(instance){ + + var inst = instance; + instance.web.form.widgets.add('boolean_switch', + 'instance.web.form.FieldBooleanSwitch'); + + $.fn.bootstrapSwitch.defaults.size = 'mini'; + $.fn.bootstrapSwitch.defaults.onColor = 'success'; + + instance.web.form.FieldBooleanSwitch = instance.web.form.AbstractField.extend( + instance.web.form.ReinitializeFieldMixin, { + + template: 'FieldBooleanSwitch', + init: function(field_manager, node) { + this._super(field_manager, node); + }, + start: function() { + var self = this; + this.$checkbox = $("input", this.$el); + this.$checkbox.bootstrapSwitch({ + onSwitchChange: _.bind(function(event, state) { + this.internal_set_value(this.$checkbox.is(':checked')); + event.preventDefault(); + }, this) + }); + + this.setupFocus(this.$checkbox); +// var check_readonly = function() { +// self.$checkbox.prop('disabled', self.get("effective_readonly")); +// }; +// this.on("change:effective_readonly", this, check_readonly); +// check_readonly.call(this); + this._super.apply(this, arguments); + }, + render_value: function() { + this.$checkbox.bootstrapSwitch('state', this.get('value'), true); + //this.$checkbox[0].checked = + }, + focus: function() { + var input = this.$checkbox && this.$checkbox[0]; + return input ? input.focus() : false; + } + }); + + /*instance.web.ListView.Groups.include({ + render: function(post_render){ + var self = this; + var prender = function(){ + self.init_widget_boolean_switch(); + if (post_render) { post_render(); } + }; + return this._super(prender); + }, + init_widget_boolean_switch: function(){ + var switch_fields = this.columns.filter(function(c){ + return c.widget === 'boolean_switch'; + }); + if(switch_fields.length > 0){ + // details lines + var checkboxes = this.view.$el.find( + '.oe_list_field_boolean_switch > input[type="checkbox"]'); + checkboxes.bootstrapSwitch({'readonly': false, + }); + // TODO: the Group-by line + } + }, + });*/ + instance.web.list.columns.add('field.boolean_switch', 'instance.web.list.FieldBooleanSwitch'); + + instance.web.list.FieldBooleanSwitch = instance.web.list.Column.extend({ + + _format: function (row_data, options) { + var quick_edit = false; + quick_edit = py.eval(this.options).quick_edit ? py.eval(this.options).quick_edit : false; + return _.str.sprintf('', + row_data[this.id].value ? 'checked="checked"' : '', + quick_edit ? '' : 'readonly="readonly"'); + } + }); + instance.web.ListView.include({ + reload_record: function(record){ + var self = this; + return this._super(record).then(function(){ + self.init_widget_boolean_switch(); + }); + }, + reload_content: function(){ + var self = this; + return this._super.apply(this, arguments).always( function (){ + self.init_widget_boolean_switch(); + }); + }, + + init_widget_boolean_switch:function(){ + var switch_fields = this.columns.filter(function(c){ + return c.widget === 'boolean_switch'; + }); + if(switch_fields.length > 0){ + // details lines + var checkboxes = this.$el.find( + '.oe_list_field_boolean_switch > input[type="checkbox"]'); + checkboxes.bootstrapSwitch({'readonly': false, + }); + // TODO: the Group-by line + } + }, + + }); +}; diff --git a/web_widget_boolean_switch/static/src/xml/web_widget_boolean_switch.xml b/web_widget_boolean_switch/static/src/xml/web_widget_boolean_switch.xml new file mode 100644 index 00000000..809fef2c --- /dev/null +++ b/web_widget_boolean_switch/static/src/xml/web_widget_boolean_switch.xml @@ -0,0 +1,13 @@ + + + + + + + + From 384e2453290cada5ddd37e8f5606e2490da801a5 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Thu, 1 Oct 2015 18:14:50 +0200 Subject: [PATCH 02/31] factorize creating a new object --- .../src/js/web_widget_boolean_switch.js | 118 +++++++++--------- 1 file changed, 62 insertions(+), 56 deletions(-) diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index 5b214e11..b7559c9b 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -1,24 +1,52 @@ 'use strict'; openerp.web_widget_boolean_switch = function(instance){ - var inst = instance; instance.web.form.widgets.add('boolean_switch', 'instance.web.form.FieldBooleanSwitch'); $.fn.bootstrapSwitch.defaults.size = 'mini'; $.fn.bootstrapSwitch.defaults.onColor = 'success'; + instance.web.BooleanSwitchWidget = instance.web.Class.extend({ + + init: function(checkboxes, options){ + var options = options ? options : {}; + this.checkboxes = checkboxes; + var switchOptions = { + 'readonly': options.hasOwnProperty('readonly') ? options.readonly : true, + }; + if(options.hasOwnProperty('readonly')){ + switchOptions.onSwitchChange = options.onSwitchChange + } + 'onSwitchChange' + this.checkboxes.bootstrapSwitch(switchOptions); + }, + start: function(){ + debugger; + }, + set_value: function(value){ + // the third parameter tell if we should skip to fire evnets + this.checkboxes.bootstrapSwitch('state', value, false); + }, +// set_readonly: function(value){ +// // the third parameter tell if we should skip to fire evnets +// this.checkboxes.bootstrapSwitch({'readonly': value}); +// }, + }); + + // Form view + instance.web.form.FieldBooleanSwitch = instance.web.form.AbstractField.extend( instance.web.form.ReinitializeFieldMixin, { template: 'FieldBooleanSwitch', - init: function(field_manager, node) { - this._super(field_manager, node); - }, + start: function() { var self = this; + //TODO: Get options from xmlview to init widget this.$checkbox = $("input", this.$el); - this.$checkbox.bootstrapSwitch({ + this.widget = new openerp.instances.instance0.web.BooleanSwitchWidget( + this.$checkbox, { onSwitchChange: _.bind(function(event, state) { this.internal_set_value(this.$checkbox.is(':checked')); event.preventDefault(); @@ -26,6 +54,7 @@ openerp.web_widget_boolean_switch = function(instance){ }); this.setupFocus(this.$checkbox); + //TODO: use initialize_content to change // var check_readonly = function() { // self.$checkbox.prop('disabled', self.get("effective_readonly")); // }; @@ -34,8 +63,8 @@ openerp.web_widget_boolean_switch = function(instance){ this._super.apply(this, arguments); }, render_value: function() { - this.$checkbox.bootstrapSwitch('state', this.get('value'), true); - //this.$checkbox[0].checked = + this.widget.set_value(this.get('value')); + //this.$checkbox.bootstrapSwitch('state', this.get('value'), true); }, focus: function() { var input = this.$checkbox && this.$checkbox[0]; @@ -43,68 +72,45 @@ openerp.web_widget_boolean_switch = function(instance){ } }); - /*instance.web.ListView.Groups.include({ + // List view + + function apply_helper(view, columns){ + var switch_fields = columns.filter(function(c){ + return c.widget === 'boolean_switch'; + }); + switch_fields.forEach(function(field){ + if(view.grouped){ + //Manage if it's grouped by boolean_switch widget field + var checkboxes = view.$el.find('th.oe_list_group_name input[type="checkbox"]'); + new openerp.instances.instance0.web.BooleanSwitchWidget(checkboxes, {'readonly': true}); + } + var quick_edit = false; + quick_edit = py.eval(field.options).quick_edit ? py.eval(field.options).quick_edit : false; + var checkboxes = view.$el.find( + 'td[data-field=' + field.name + '].oe_list_field_boolean_switch > input[type="checkbox"]'); + new openerp.instances.instance0.web.BooleanSwitchWidget(checkboxes, {'readonly': !quick_edit}); + }); + } + + instance.web.ListView.Groups.include({ render: function(post_render){ var self = this; var prender = function(){ - self.init_widget_boolean_switch(); + apply_helper(self.view, self.columns); if (post_render) { post_render(); } }; return this._super(prender); }, - init_widget_boolean_switch: function(){ - var switch_fields = this.columns.filter(function(c){ - return c.widget === 'boolean_switch'; - }); - if(switch_fields.length > 0){ - // details lines - var checkboxes = this.view.$el.find( - '.oe_list_field_boolean_switch > input[type="checkbox"]'); - checkboxes.bootstrapSwitch({'readonly': false, - }); - // TODO: the Group-by line - } - }, - });*/ - instance.web.list.columns.add('field.boolean_switch', 'instance.web.list.FieldBooleanSwitch'); - - instance.web.list.FieldBooleanSwitch = instance.web.list.Column.extend({ - - _format: function (row_data, options) { - var quick_edit = false; - quick_edit = py.eval(this.options).quick_edit ? py.eval(this.options).quick_edit : false; - return _.str.sprintf('', - row_data[this.id].value ? 'checked="checked"' : '', - quick_edit ? '' : 'readonly="readonly"'); - } }); + instance.web.ListView.include({ reload_record: function(record){ + // in case of editable list, only update record is reloaded + // after edition var self = this; return this._super(record).then(function(){ - self.init_widget_boolean_switch(); - }); - }, - reload_content: function(){ - var self = this; - return this._super.apply(this, arguments).always( function (){ - self.init_widget_boolean_switch(); + apply_helper(self, self.columns); }); }, - - init_widget_boolean_switch:function(){ - var switch_fields = this.columns.filter(function(c){ - return c.widget === 'boolean_switch'; - }); - if(switch_fields.length > 0){ - // details lines - var checkboxes = this.$el.find( - '.oe_list_field_boolean_switch > input[type="checkbox"]'); - checkboxes.bootstrapSwitch({'readonly': false, - }); - // TODO: the Group-by line - } - }, - }); }; From 7decad60707e8c54b269eed1fe0d7fca9e3a3974 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Thu, 1 Oct 2015 23:12:23 +0200 Subject: [PATCH 03/31] add missing lib --- .../static/lib/bootstrap-switch/README.md | 9 + .../lib/bootstrap-switch/bootstrap-switch.css | 195 +++++ .../lib/bootstrap-switch/bootstrap-switch.js | 744 ++++++++++++++++++ .../static/lib/bootstrap-switch/index.html | 34 + 4 files changed, 982 insertions(+) create mode 100644 web_widget_boolean_switch/static/lib/bootstrap-switch/README.md create mode 100644 web_widget_boolean_switch/static/lib/bootstrap-switch/bootstrap-switch.css create mode 100644 web_widget_boolean_switch/static/lib/bootstrap-switch/bootstrap-switch.js create mode 100644 web_widget_boolean_switch/static/lib/bootstrap-switch/index.html diff --git a/web_widget_boolean_switch/static/lib/bootstrap-switch/README.md b/web_widget_boolean_switch/static/lib/bootstrap-switch/README.md new file mode 100644 index 00000000..e9e1d96f --- /dev/null +++ b/web_widget_boolean_switch/static/lib/bootstrap-switch/README.md @@ -0,0 +1,9 @@ +Bootstrap-switch +================ + +from: https://github.com/nostalgiaz/bootstrap-switch + +``bootstrap-switch.js`` and ``bootstrap-switch.css`` files came from ``dist/`` +directories at this [revision](https://github.com/nostalgiaz/bootstrap-switch/ +tree/a39a1e9d6059822235bf4a9c0e7700a7e6a5ad19/dist) the september 30th 2015. + diff --git a/web_widget_boolean_switch/static/lib/bootstrap-switch/bootstrap-switch.css b/web_widget_boolean_switch/static/lib/bootstrap-switch/bootstrap-switch.css new file mode 100644 index 00000000..6c0cc1dd --- /dev/null +++ b/web_widget_boolean_switch/static/lib/bootstrap-switch/bootstrap-switch.css @@ -0,0 +1,195 @@ +/* ======================================================================== + * bootstrap-switch - v3.3.2 + * http://www.bootstrap-switch.org + * ======================================================================== + * Copyright 2012-2013 Mattia Larentis + * + * ======================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== + */ + +.bootstrap-switch { + display: inline-block; + direction: ltr; + cursor: pointer; + border-radius: 4px; + border: 1px solid; + border-color: #cccccc; + position: relative; + text-align: left; + overflow: hidden; + line-height: 8px; + z-index: 0; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + vertical-align: middle; + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.bootstrap-switch .bootstrap-switch-container { + display: inline-block; + top: 0; + border-radius: 4px; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} +.bootstrap-switch .bootstrap-switch-handle-on, +.bootstrap-switch .bootstrap-switch-handle-off, +.bootstrap-switch .bootstrap-switch-label { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + cursor: pointer; + display: inline-block !important; + height: 100%; + padding: 6px 12px; + font-size: 14px; + line-height: 20px; +} +.bootstrap-switch .bootstrap-switch-handle-on, +.bootstrap-switch .bootstrap-switch-handle-off { + text-align: center; + z-index: 1; +} +.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary, +.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary { + color: #fff; + background: #337ab7; +} +.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info, +.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info { + color: #fff; + background: #5bc0de; +} +.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success, +.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success { + color: #fff; + background: #5cb85c; +} +.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning, +.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning { + background: #f0ad4e; + color: #fff; +} +.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger, +.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger { + color: #fff; + background: #d9534f; +} +.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default, +.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default { + color: #000; + background: #eeeeee; +} +.bootstrap-switch .bootstrap-switch-label { + text-align: center; + margin-top: -1px; + margin-bottom: -1px; + z-index: 100; + color: #333333; + background: #ffffff; +} +.bootstrap-switch .bootstrap-switch-handle-on { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; +} +.bootstrap-switch .bootstrap-switch-handle-off { + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} +.bootstrap-switch input[type='radio'], +.bootstrap-switch input[type='checkbox'] { + position: absolute !important; + top: 0; + left: 0; + margin: 0; + z-index: -1; + opacity: 0; + filter: alpha(opacity=0); +} +.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-on, +.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-off, +.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-label { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; +} +.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-on, +.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-off, +.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-label { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-on, +.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-off, +.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-label { + padding: 6px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.bootstrap-switch.bootstrap-switch-disabled, +.bootstrap-switch.bootstrap-switch-readonly, +.bootstrap-switch.bootstrap-switch-indeterminate { + cursor: default !important; +} +.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-on, +.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-on, +.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-on, +.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-off, +.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-off, +.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-off, +.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-label, +.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-label, +.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-label { + opacity: 0.5; + filter: alpha(opacity=50); + cursor: default !important; +} +.bootstrap-switch.bootstrap-switch-animate .bootstrap-switch-container { + -webkit-transition: margin-left 0.5s; + -o-transition: margin-left 0.5s; + transition: margin-left 0.5s; +} +.bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-on { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} +.bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-off { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; +} +.bootstrap-switch.bootstrap-switch-focused { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +.bootstrap-switch.bootstrap-switch-on .bootstrap-switch-label, +.bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-off .bootstrap-switch-label { + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} +.bootstrap-switch.bootstrap-switch-off .bootstrap-switch-label, +.bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-on .bootstrap-switch-label { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; +} diff --git a/web_widget_boolean_switch/static/lib/bootstrap-switch/bootstrap-switch.js b/web_widget_boolean_switch/static/lib/bootstrap-switch/bootstrap-switch.js new file mode 100644 index 00000000..826263a4 --- /dev/null +++ b/web_widget_boolean_switch/static/lib/bootstrap-switch/bootstrap-switch.js @@ -0,0 +1,744 @@ +/* ======================================================================== + * bootstrap-switch - v3.3.2 + * http://www.bootstrap-switch.org + * ======================================================================== + * Copyright 2012-2013 Mattia Larentis + * + * ======================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== + */ + +(function() { + var slice = [].slice; + + (function($, window) { + "use strict"; + var BootstrapSwitch; + BootstrapSwitch = (function() { + function BootstrapSwitch(element, options) { + if (options == null) { + options = {}; + } + this.$element = $(element); + this.options = $.extend({}, $.fn.bootstrapSwitch.defaults, { + state: this.$element.is(":checked"), + size: this.$element.data("size"), + animate: this.$element.data("animate"), + disabled: this.$element.is(":disabled"), + readonly: this.$element.is("[readonly]"), + indeterminate: this.$element.data("indeterminate"), + inverse: this.$element.data("inverse"), + radioAllOff: this.$element.data("radio-all-off"), + onColor: this.$element.data("on-color"), + offColor: this.$element.data("off-color"), + onText: this.$element.data("on-text"), + offText: this.$element.data("off-text"), + labelText: this.$element.data("label-text"), + handleWidth: this.$element.data("handle-width"), + labelWidth: this.$element.data("label-width"), + baseClass: this.$element.data("base-class"), + wrapperClass: this.$element.data("wrapper-class") + }, options); + this.prevOptions = {}; + this.$wrapper = $("
", { + "class": (function(_this) { + return function() { + var classes; + classes = ["" + _this.options.baseClass].concat(_this._getClasses(_this.options.wrapperClass)); + classes.push(_this.options.state ? _this.options.baseClass + "-on" : _this.options.baseClass + "-off"); + if (_this.options.size != null) { + classes.push(_this.options.baseClass + "-" + _this.options.size); + } + if (_this.options.disabled) { + classes.push(_this.options.baseClass + "-disabled"); + } + if (_this.options.readonly) { + classes.push(_this.options.baseClass + "-readonly"); + } + if (_this.options.indeterminate) { + classes.push(_this.options.baseClass + "-indeterminate"); + } + if (_this.options.inverse) { + classes.push(_this.options.baseClass + "-inverse"); + } + if (_this.$element.attr("id")) { + classes.push(_this.options.baseClass + "-id-" + (_this.$element.attr("id"))); + } + return classes.join(" "); + }; + })(this)() + }); + this.$container = $("
", { + "class": this.options.baseClass + "-container" + }); + this.$on = $("", { + html: this.options.onText, + "class": this.options.baseClass + "-handle-on " + this.options.baseClass + "-" + this.options.onColor + }); + this.$off = $("", { + html: this.options.offText, + "class": this.options.baseClass + "-handle-off " + this.options.baseClass + "-" + this.options.offColor + }); + this.$label = $("", { + html: this.options.labelText, + "class": this.options.baseClass + "-label" + }); + this.$element.on("init.bootstrapSwitch", (function(_this) { + return function() { + return _this.options.onInit.apply(element, arguments); + }; + })(this)); + this.$element.on("switchChange.bootstrapSwitch", (function(_this) { + return function(e) { + if (false === _this.options.onSwitchChange.apply(element, arguments)) { + if (_this.$element.is(":radio")) { + return $("[name='" + (_this.$element.attr('name')) + "']").trigger("previousState.bootstrapSwitch", true); + } else { + return _this.$element.trigger("previousState.bootstrapSwitch", true); + } + } + }; + })(this)); + this.$container = this.$element.wrap(this.$container).parent(); + this.$wrapper = this.$container.wrap(this.$wrapper).parent(); + this.$element.before(this.options.inverse ? this.$off : this.$on).before(this.$label).before(this.options.inverse ? this.$on : this.$off); + if (this.options.indeterminate) { + this.$element.prop("indeterminate", true); + } + this._init(); + this._elementHandlers(); + this._handleHandlers(); + this._labelHandlers(); + this._formHandler(); + this._externalLabelHandler(); + this.$element.trigger("init.bootstrapSwitch", this.options.state); + } + + BootstrapSwitch.prototype._constructor = BootstrapSwitch; + + BootstrapSwitch.prototype.setPrevOptions = function() { + return this.prevOptions = $.extend(true, {}, this.options); + }; + + BootstrapSwitch.prototype.state = function(value, skip) { + if (typeof value === "undefined") { + return this.options.state; + } + if (this.options.disabled || this.options.readonly) { + return this.$element; + } + if (this.options.state && !this.options.radioAllOff && this.$element.is(":radio")) { + return this.$element; + } + if (this.$element.is(":radio")) { + $("[name='" + (this.$element.attr('name')) + "']").trigger("setPreviousOptions.bootstrapSwitch"); + } else { + this.$element.trigger("setPreviousOptions.bootstrapSwitch"); + } + if (this.options.indeterminate) { + this.indeterminate(false); + } + value = !!value; + this.$element.prop("checked", value).trigger("change.bootstrapSwitch", skip); + return this.$element; + }; + + BootstrapSwitch.prototype.toggleState = function(skip) { + if (this.options.disabled || this.options.readonly) { + return this.$element; + } + if (this.options.indeterminate) { + this.indeterminate(false); + return this.state(true); + } else { + return this.$element.prop("checked", !this.options.state).trigger("change.bootstrapSwitch", skip); + } + }; + + BootstrapSwitch.prototype.size = function(value) { + if (typeof value === "undefined") { + return this.options.size; + } + if (this.options.size != null) { + this.$wrapper.removeClass(this.options.baseClass + "-" + this.options.size); + } + if (value) { + this.$wrapper.addClass(this.options.baseClass + "-" + value); + } + this._width(); + this._containerPosition(); + this.options.size = value; + return this.$element; + }; + + BootstrapSwitch.prototype.animate = function(value) { + if (typeof value === "undefined") { + return this.options.animate; + } + value = !!value; + if (value === this.options.animate) { + return this.$element; + } + return this.toggleAnimate(); + }; + + BootstrapSwitch.prototype.toggleAnimate = function() { + this.options.animate = !this.options.animate; + this.$wrapper.toggleClass(this.options.baseClass + "-animate"); + return this.$element; + }; + + BootstrapSwitch.prototype.disabled = function(value) { + if (typeof value === "undefined") { + return this.options.disabled; + } + value = !!value; + if (value === this.options.disabled) { + return this.$element; + } + return this.toggleDisabled(); + }; + + BootstrapSwitch.prototype.toggleDisabled = function() { + this.options.disabled = !this.options.disabled; + this.$element.prop("disabled", this.options.disabled); + this.$wrapper.toggleClass(this.options.baseClass + "-disabled"); + return this.$element; + }; + + BootstrapSwitch.prototype.readonly = function(value) { + if (typeof value === "undefined") { + return this.options.readonly; + } + value = !!value; + if (value === this.options.readonly) { + return this.$element; + } + return this.toggleReadonly(); + }; + + BootstrapSwitch.prototype.toggleReadonly = function() { + this.options.readonly = !this.options.readonly; + this.$element.prop("readonly", this.options.readonly); + this.$wrapper.toggleClass(this.options.baseClass + "-readonly"); + return this.$element; + }; + + BootstrapSwitch.prototype.indeterminate = function(value) { + if (typeof value === "undefined") { + return this.options.indeterminate; + } + value = !!value; + if (value === this.options.indeterminate) { + return this.$element; + } + return this.toggleIndeterminate(); + }; + + BootstrapSwitch.prototype.toggleIndeterminate = function() { + this.options.indeterminate = !this.options.indeterminate; + this.$element.prop("indeterminate", this.options.indeterminate); + this.$wrapper.toggleClass(this.options.baseClass + "-indeterminate"); + this._containerPosition(); + return this.$element; + }; + + BootstrapSwitch.prototype.inverse = function(value) { + if (typeof value === "undefined") { + return this.options.inverse; + } + value = !!value; + if (value === this.options.inverse) { + return this.$element; + } + return this.toggleInverse(); + }; + + BootstrapSwitch.prototype.toggleInverse = function() { + var $off, $on; + this.$wrapper.toggleClass(this.options.baseClass + "-inverse"); + $on = this.$on.clone(true); + $off = this.$off.clone(true); + this.$on.replaceWith($off); + this.$off.replaceWith($on); + this.$on = $off; + this.$off = $on; + this.options.inverse = !this.options.inverse; + return this.$element; + }; + + BootstrapSwitch.prototype.onColor = function(value) { + var color; + color = this.options.onColor; + if (typeof value === "undefined") { + return color; + } + if (color != null) { + this.$on.removeClass(this.options.baseClass + "-" + color); + } + this.$on.addClass(this.options.baseClass + "-" + value); + this.options.onColor = value; + return this.$element; + }; + + BootstrapSwitch.prototype.offColor = function(value) { + var color; + color = this.options.offColor; + if (typeof value === "undefined") { + return color; + } + if (color != null) { + this.$off.removeClass(this.options.baseClass + "-" + color); + } + this.$off.addClass(this.options.baseClass + "-" + value); + this.options.offColor = value; + return this.$element; + }; + + BootstrapSwitch.prototype.onText = function(value) { + if (typeof value === "undefined") { + return this.options.onText; + } + this.$on.html(value); + this._width(); + this._containerPosition(); + this.options.onText = value; + return this.$element; + }; + + BootstrapSwitch.prototype.offText = function(value) { + if (typeof value === "undefined") { + return this.options.offText; + } + this.$off.html(value); + this._width(); + this._containerPosition(); + this.options.offText = value; + return this.$element; + }; + + BootstrapSwitch.prototype.labelText = function(value) { + if (typeof value === "undefined") { + return this.options.labelText; + } + this.$label.html(value); + this._width(); + this.options.labelText = value; + return this.$element; + }; + + BootstrapSwitch.prototype.handleWidth = function(value) { + if (typeof value === "undefined") { + return this.options.handleWidth; + } + this.options.handleWidth = value; + this._width(); + this._containerPosition(); + return this.$element; + }; + + BootstrapSwitch.prototype.labelWidth = function(value) { + if (typeof value === "undefined") { + return this.options.labelWidth; + } + this.options.labelWidth = value; + this._width(); + this._containerPosition(); + return this.$element; + }; + + BootstrapSwitch.prototype.baseClass = function(value) { + return this.options.baseClass; + }; + + BootstrapSwitch.prototype.wrapperClass = function(value) { + if (typeof value === "undefined") { + return this.options.wrapperClass; + } + if (!value) { + value = $.fn.bootstrapSwitch.defaults.wrapperClass; + } + this.$wrapper.removeClass(this._getClasses(this.options.wrapperClass).join(" ")); + this.$wrapper.addClass(this._getClasses(value).join(" ")); + this.options.wrapperClass = value; + return this.$element; + }; + + BootstrapSwitch.prototype.radioAllOff = function(value) { + if (typeof value === "undefined") { + return this.options.radioAllOff; + } + value = !!value; + if (value === this.options.radioAllOff) { + return this.$element; + } + this.options.radioAllOff = value; + return this.$element; + }; + + BootstrapSwitch.prototype.onInit = function(value) { + if (typeof value === "undefined") { + return this.options.onInit; + } + if (!value) { + value = $.fn.bootstrapSwitch.defaults.onInit; + } + this.options.onInit = value; + return this.$element; + }; + + BootstrapSwitch.prototype.onSwitchChange = function(value) { + if (typeof value === "undefined") { + return this.options.onSwitchChange; + } + if (!value) { + value = $.fn.bootstrapSwitch.defaults.onSwitchChange; + } + this.options.onSwitchChange = value; + return this.$element; + }; + + BootstrapSwitch.prototype.destroy = function() { + var $form; + $form = this.$element.closest("form"); + if ($form.length) { + $form.off("reset.bootstrapSwitch").removeData("bootstrap-switch"); + } + this.$container.children().not(this.$element).remove(); + this.$element.unwrap().unwrap().off(".bootstrapSwitch").removeData("bootstrap-switch"); + return this.$element; + }; + + BootstrapSwitch.prototype._width = function() { + var $handles, handleWidth; + $handles = this.$on.add(this.$off); + $handles.add(this.$label).css("width", ""); + handleWidth = this.options.handleWidth === "auto" ? Math.max(this.$on.width(), this.$off.width()) : this.options.handleWidth; + $handles.width(handleWidth); + this.$label.width((function(_this) { + return function(index, width) { + if (_this.options.labelWidth !== "auto") { + return _this.options.labelWidth; + } + if (width < handleWidth) { + return handleWidth; + } else { + return width; + } + }; + })(this)); + this._handleWidth = this.$on.outerWidth(); + this._labelWidth = this.$label.outerWidth(); + this.$container.width((this._handleWidth * 2) + this._labelWidth); + return this.$wrapper.width(this._handleWidth + this._labelWidth); + }; + + BootstrapSwitch.prototype._containerPosition = function(state, callback) { + if (state == null) { + state = this.options.state; + } + this.$container.css("margin-left", (function(_this) { + return function() { + var values; + values = [0, "-" + _this._handleWidth + "px"]; + if (_this.options.indeterminate) { + return "-" + (_this._handleWidth / 2) + "px"; + } + if (state) { + if (_this.options.inverse) { + return values[1]; + } else { + return values[0]; + } + } else { + if (_this.options.inverse) { + return values[0]; + } else { + return values[1]; + } + } + }; + })(this)); + if (!callback) { + return; + } + return setTimeout(function() { + return callback(); + }, 50); + }; + + BootstrapSwitch.prototype._init = function() { + var init, initInterval; + init = (function(_this) { + return function() { + _this.setPrevOptions(); + _this._width(); + return _this._containerPosition(null, function() { + if (_this.options.animate) { + return _this.$wrapper.addClass(_this.options.baseClass + "-animate"); + } + }); + }; + })(this); + if (this.$wrapper.is(":visible")) { + return init(); + } + return initInterval = window.setInterval((function(_this) { + return function() { + if (_this.$wrapper.is(":visible")) { + init(); + return window.clearInterval(initInterval); + } + }; + })(this), 50); + }; + + BootstrapSwitch.prototype._elementHandlers = function() { + return this.$element.on({ + "setPreviousOptions.bootstrapSwitch": (function(_this) { + return function(e) { + return _this.setPrevOptions(); + }; + })(this), + "previousState.bootstrapSwitch": (function(_this) { + return function(e) { + _this.options = _this.prevOptions; + if (_this.options.indeterminate) { + _this.$wrapper.addClass(_this.options.baseClass + "-indeterminate"); + } + return _this.$element.prop("checked", _this.options.state).trigger("change.bootstrapSwitch", true); + }; + })(this), + "change.bootstrapSwitch": (function(_this) { + return function(e, skip) { + var state; + e.preventDefault(); + e.stopImmediatePropagation(); + state = _this.$element.is(":checked"); + _this._containerPosition(state); + if (state === _this.options.state) { + return; + } + _this.options.state = state; + _this.$wrapper.toggleClass(_this.options.baseClass + "-off").toggleClass(_this.options.baseClass + "-on"); + if (!skip) { + if (_this.$element.is(":radio")) { + $("[name='" + (_this.$element.attr('name')) + "']").not(_this.$element).prop("checked", false).trigger("change.bootstrapSwitch", true); + } + return _this.$element.trigger("switchChange.bootstrapSwitch", [state]); + } + }; + })(this), + "focus.bootstrapSwitch": (function(_this) { + return function(e) { + e.preventDefault(); + return _this.$wrapper.addClass(_this.options.baseClass + "-focused"); + }; + })(this), + "blur.bootstrapSwitch": (function(_this) { + return function(e) { + e.preventDefault(); + return _this.$wrapper.removeClass(_this.options.baseClass + "-focused"); + }; + })(this), + "keydown.bootstrapSwitch": (function(_this) { + return function(e) { + if (!e.which || _this.options.disabled || _this.options.readonly) { + return; + } + switch (e.which) { + case 37: + e.preventDefault(); + e.stopImmediatePropagation(); + return _this.state(false); + case 39: + e.preventDefault(); + e.stopImmediatePropagation(); + return _this.state(true); + } + }; + })(this) + }); + }; + + BootstrapSwitch.prototype._handleHandlers = function() { + this.$on.on("click.bootstrapSwitch", (function(_this) { + return function(event) { + event.preventDefault(); + event.stopPropagation(); + _this.state(false); + return _this.$element.trigger("focus.bootstrapSwitch"); + }; + })(this)); + return this.$off.on("click.bootstrapSwitch", (function(_this) { + return function(event) { + event.preventDefault(); + event.stopPropagation(); + _this.state(true); + return _this.$element.trigger("focus.bootstrapSwitch"); + }; + })(this)); + }; + + BootstrapSwitch.prototype._labelHandlers = function() { + return this.$label.on({ + "click": function(e) { + return e.stopPropagation(); + }, + "mousedown.bootstrapSwitch touchstart.bootstrapSwitch": (function(_this) { + return function(e) { + if (_this._dragStart || _this.options.disabled || _this.options.readonly) { + return; + } + e.preventDefault(); + e.stopPropagation(); + _this._dragStart = (e.pageX || e.originalEvent.touches[0].pageX) - parseInt(_this.$container.css("margin-left"), 10); + if (_this.options.animate) { + _this.$wrapper.removeClass(_this.options.baseClass + "-animate"); + } + return _this.$element.trigger("focus.bootstrapSwitch"); + }; + })(this), + "mousemove.bootstrapSwitch touchmove.bootstrapSwitch": (function(_this) { + return function(e) { + var difference; + if (_this._dragStart == null) { + return; + } + e.preventDefault(); + difference = (e.pageX || e.originalEvent.touches[0].pageX) - _this._dragStart; + if (difference < -_this._handleWidth || difference > 0) { + return; + } + _this._dragEnd = difference; + return _this.$container.css("margin-left", _this._dragEnd + "px"); + }; + })(this), + "mouseup.bootstrapSwitch touchend.bootstrapSwitch": (function(_this) { + return function(e) { + var state; + if (!_this._dragStart) { + return; + } + e.preventDefault(); + if (_this.options.animate) { + _this.$wrapper.addClass(_this.options.baseClass + "-animate"); + } + if (_this._dragEnd) { + state = _this._dragEnd > -(_this._handleWidth / 2); + _this._dragEnd = false; + _this.state(_this.options.inverse ? !state : state); + } else { + _this.state(!_this.options.state); + } + return _this._dragStart = false; + }; + })(this), + "mouseleave.bootstrapSwitch": (function(_this) { + return function(e) { + return _this.$label.trigger("mouseup.bootstrapSwitch"); + }; + })(this) + }); + }; + + BootstrapSwitch.prototype._externalLabelHandler = function() { + var $externalLabel; + $externalLabel = this.$element.closest("label"); + return $externalLabel.on("click", (function(_this) { + return function(event) { + event.preventDefault(); + event.stopImmediatePropagation(); + if (event.target === $externalLabel[0]) { + return _this.toggleState(); + } + }; + })(this)); + }; + + BootstrapSwitch.prototype._formHandler = function() { + var $form; + $form = this.$element.closest("form"); + if ($form.data("bootstrap-switch")) { + return; + } + return $form.on("reset.bootstrapSwitch", function() { + return window.setTimeout(function() { + return $form.find("input").filter(function() { + return $(this).data("bootstrap-switch"); + }).each(function() { + return $(this).bootstrapSwitch("state", this.checked); + }); + }, 1); + }).data("bootstrap-switch", true); + }; + + BootstrapSwitch.prototype._getClasses = function(classes) { + var c, cls, i, len; + if (!$.isArray(classes)) { + return [this.options.baseClass + "-" + classes]; + } + cls = []; + for (i = 0, len = classes.length; i < len; i++) { + c = classes[i]; + cls.push(this.options.baseClass + "-" + c); + } + return cls; + }; + + return BootstrapSwitch; + + })(); + $.fn.bootstrapSwitch = function() { + var args, option, ret; + option = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; + ret = this; + this.each(function() { + var $this, data; + $this = $(this); + data = $this.data("bootstrap-switch"); + if (!data) { + $this.data("bootstrap-switch", data = new BootstrapSwitch(this, option)); + } + if (typeof option === "string") { + return ret = data[option].apply(data, args); + } + }); + return ret; + }; + $.fn.bootstrapSwitch.Constructor = BootstrapSwitch; + return $.fn.bootstrapSwitch.defaults = { + state: true, + size: null, + animate: true, + disabled: false, + readonly: false, + indeterminate: false, + inverse: false, + radioAllOff: false, + onColor: "primary", + offColor: "default", + onText: "ON", + offText: "OFF", + labelText: " ", + handleWidth: "auto", + labelWidth: "auto", + baseClass: "bootstrap-switch", + wrapperClass: "wrapper", + onInit: function() {}, + onSwitchChange: function() {} + }; + })(window.jQuery, window); + +}).call(this); diff --git a/web_widget_boolean_switch/static/lib/bootstrap-switch/index.html b/web_widget_boolean_switch/static/lib/bootstrap-switch/index.html new file mode 100644 index 00000000..463bed49 --- /dev/null +++ b/web_widget_boolean_switch/static/lib/bootstrap-switch/index.html @@ -0,0 +1,34 @@ + + + + + + + + + Bootstrap switch: test + + +
+ +
+
+ +
+ + + From af3d1ac5039ea997783a8eb13c2ac650b2bd2c85 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Thu, 1 Oct 2015 23:16:04 +0200 Subject: [PATCH 04/31] update lib to allow set value through javascrpti if switcher is readonly or disabled --- .../static/lib/bootstrap-switch/README.md | 2 ++ .../static/lib/bootstrap-switch/bootstrap-switch.js | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/web_widget_boolean_switch/static/lib/bootstrap-switch/README.md b/web_widget_boolean_switch/static/lib/bootstrap-switch/README.md index e9e1d96f..8cd08298 100644 --- a/web_widget_boolean_switch/static/lib/bootstrap-switch/README.md +++ b/web_widget_boolean_switch/static/lib/bootstrap-switch/README.md @@ -7,3 +7,5 @@ from: https://github.com/nostalgiaz/bootstrap-switch directories at this [revision](https://github.com/nostalgiaz/bootstrap-switch/ tree/a39a1e9d6059822235bf4a9c0e7700a7e6a5ad19/dist) the september 30th 2015. +The default library doesn't allow to change value through javascript if +switcher is set `readonly` or `disabled`. diff --git a/web_widget_boolean_switch/static/lib/bootstrap-switch/bootstrap-switch.js b/web_widget_boolean_switch/static/lib/bootstrap-switch/bootstrap-switch.js index 826263a4..82c904ea 100644 --- a/web_widget_boolean_switch/static/lib/bootstrap-switch/bootstrap-switch.js +++ b/web_widget_boolean_switch/static/lib/bootstrap-switch/bootstrap-switch.js @@ -135,9 +135,6 @@ if (typeof value === "undefined") { return this.options.state; } - if (this.options.disabled || this.options.readonly) { - return this.$element; - } if (this.options.state && !this.options.radioAllOff && this.$element.is(":radio")) { return this.$element; } From 9ce5e96ad82825b147d34e11d4b09dc8a9bf231c Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Thu, 1 Oct 2015 23:52:08 +0200 Subject: [PATCH 05/31] manage states (readonly/disabled) on form view --- .../src/js/web_widget_boolean_switch.js | 65 ++++++++++--------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index b7559c9b..ee006860 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -13,63 +13,64 @@ openerp.web_widget_boolean_switch = function(instance){ var options = options ? options : {}; this.checkboxes = checkboxes; var switchOptions = { - 'readonly': options.hasOwnProperty('readonly') ? options.readonly : true, + 'readonly': options.hasOwnProperty('readonly') ? options.readonly : false, + 'disabled': options.hasOwnProperty('disabled') ? options.disabled : false, }; - if(options.hasOwnProperty('readonly')){ + if(options.hasOwnProperty('onSwitchChange')){ switchOptions.onSwitchChange = options.onSwitchChange } - 'onSwitchChange' this.checkboxes.bootstrapSwitch(switchOptions); }, - start: function(){ - debugger; - }, set_value: function(value){ // the third parameter tell if we should skip to fire evnets - this.checkboxes.bootstrapSwitch('state', value, false); + this.checkboxes.bootstrapSwitch('state', value, true); + }, + set_readonly: function(value){ + this.checkboxes.bootstrapSwitch('readonly', value); + }, + set_disabled: function(value){ + this.checkboxes.bootstrapSwitch('disabled', value); }, -// set_readonly: function(value){ -// // the third parameter tell if we should skip to fire evnets -// this.checkboxes.bootstrapSwitch({'readonly': value}); -// }, }); // Form view - instance.web.form.FieldBooleanSwitch = instance.web.form.AbstractField.extend( - instance.web.form.ReinitializeFieldMixin, { + instance.web.form.FieldBooleanSwitch = instance.web.form.AbstractField.extend({ template: 'FieldBooleanSwitch', - start: function() { - var self = this; - //TODO: Get options from xmlview to init widget + init: function(field_manager, node){ + this._super(field_manager, node); + }, + start: function(){ this.$checkbox = $("input", this.$el); - this.widget = new openerp.instances.instance0.web.BooleanSwitchWidget( + var readonly = this.modifiers && + this.modifiers.hasOwnProperty('readonly') ? + this.modifiers.readonly : false; + this.quick_edit = this.options && + this.options.hasOwnProperty('quick_edit') ? + this.options.quick_edit : false; + var disabled = !this.quick_edit; + this.switcher = new openerp.instances.instance0.web.BooleanSwitchWidget( this.$checkbox, { + 'readonly': readonly, + 'disabled': disabled, onSwitchChange: _.bind(function(event, state) { this.internal_set_value(this.$checkbox.is(':checked')); event.preventDefault(); }, this) }); - - this.setupFocus(this.$checkbox); - //TODO: use initialize_content to change -// var check_readonly = function() { -// self.$checkbox.prop('disabled', self.get("effective_readonly")); -// }; -// this.on("change:effective_readonly", this, check_readonly); -// check_readonly.call(this); - this._super.apply(this, arguments); + this.on("change:effective_readonly", this, this.switcher_states); + this._super(); + }, + switcher_states: function () { + if (this.quick_edit) + return; + this.switcher.set_disabled(this.get('effective_readonly')) }, render_value: function() { - this.widget.set_value(this.get('value')); - //this.$checkbox.bootstrapSwitch('state', this.get('value'), true); + this.switcher.set_value(this.get('value')); }, - focus: function() { - var input = this.$checkbox && this.$checkbox[0]; - return input ? input.focus() : false; - } }); // List view From 11b544bb73e0e68dfeeec4f71f329bc98676f585 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Fri, 2 Oct 2015 00:31:51 +0200 Subject: [PATCH 06/31] lib: allow change value through js only in case skip is true as we won't fire event, we allow to change that value to display the switcher as it should --- .../static/lib/bootstrap-switch/README.md | 3 ++- .../static/lib/bootstrap-switch/bootstrap-switch.js | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/web_widget_boolean_switch/static/lib/bootstrap-switch/README.md b/web_widget_boolean_switch/static/lib/bootstrap-switch/README.md index 8cd08298..6a84a345 100644 --- a/web_widget_boolean_switch/static/lib/bootstrap-switch/README.md +++ b/web_widget_boolean_switch/static/lib/bootstrap-switch/README.md @@ -8,4 +8,5 @@ directories at this [revision](https://github.com/nostalgiaz/bootstrap-switch/ tree/a39a1e9d6059822235bf4a9c0e7700a7e6a5ad19/dist) the september 30th 2015. The default library doesn't allow to change value through javascript if -switcher is set `readonly` or `disabled`. +switcher is set `readonly` or `disabled`. We add a small change to +allow it when skip is true. diff --git a/web_widget_boolean_switch/static/lib/bootstrap-switch/bootstrap-switch.js b/web_widget_boolean_switch/static/lib/bootstrap-switch/bootstrap-switch.js index 82c904ea..804c586e 100644 --- a/web_widget_boolean_switch/static/lib/bootstrap-switch/bootstrap-switch.js +++ b/web_widget_boolean_switch/static/lib/bootstrap-switch/bootstrap-switch.js @@ -135,6 +135,9 @@ if (typeof value === "undefined") { return this.options.state; } + if (!skip && (this.options.disabled || this.options.readonly)) { + return this.$element; + } if (this.options.state && !this.options.radioAllOff && this.$element.is(":radio")) { return this.$element; } From e25f0ce0f03af6d595880cd045bae316f6ed9e6b Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Fri, 2 Oct 2015 00:32:41 +0200 Subject: [PATCH 07/31] format readme --- web_widget_boolean_switch/static/lib/bootstrap-switch/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_widget_boolean_switch/static/lib/bootstrap-switch/README.md b/web_widget_boolean_switch/static/lib/bootstrap-switch/README.md index 6a84a345..af265be5 100644 --- a/web_widget_boolean_switch/static/lib/bootstrap-switch/README.md +++ b/web_widget_boolean_switch/static/lib/bootstrap-switch/README.md @@ -9,4 +9,4 @@ tree/a39a1e9d6059822235bf4a9c0e7700a7e6a5ad19/dist) the september 30th 2015. The default library doesn't allow to change value through javascript if switcher is set `readonly` or `disabled`. We add a small change to -allow it when skip is true. +allow it when ``skip`` is ``true``. From 567d681766cc9c301a76a0785a0d0d4850d9c4aa Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Fri, 2 Oct 2015 00:34:10 +0200 Subject: [PATCH 08/31] manage states (readonly/disabled) on list view --- .../src/js/web_widget_boolean_switch.js | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index ee006860..67e2fff3 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -13,8 +13,10 @@ openerp.web_widget_boolean_switch = function(instance){ var options = options ? options : {}; this.checkboxes = checkboxes; var switchOptions = { - 'readonly': options.hasOwnProperty('readonly') ? options.readonly : false, - 'disabled': options.hasOwnProperty('disabled') ? options.disabled : false, + 'readonly': options.hasOwnProperty('readonly') ? + options.readonly : false, + 'disabled': options.hasOwnProperty('disabled') ? + options.disabled : false, }; if(options.hasOwnProperty('onSwitchChange')){ switchOptions.onSwitchChange = options.onSwitchChange @@ -50,11 +52,10 @@ openerp.web_widget_boolean_switch = function(instance){ this.quick_edit = this.options && this.options.hasOwnProperty('quick_edit') ? this.options.quick_edit : false; - var disabled = !this.quick_edit; this.switcher = new openerp.instances.instance0.web.BooleanSwitchWidget( this.$checkbox, { 'readonly': readonly, - 'disabled': disabled, + 'disabled': !this.quick_edit, onSwitchChange: _.bind(function(event, state) { this.internal_set_value(this.$checkbox.is(':checked')); event.preventDefault(); @@ -82,14 +83,24 @@ openerp.web_widget_boolean_switch = function(instance){ switch_fields.forEach(function(field){ if(view.grouped){ //Manage if it's grouped by boolean_switch widget field - var checkboxes = view.$el.find('th.oe_list_group_name input[type="checkbox"]'); - new openerp.instances.instance0.web.BooleanSwitchWidget(checkboxes, {'readonly': true}); + var checkboxes = view.$el.find( + 'th.oe_list_group_name input[type="checkbox"]'); + new openerp.instances.instance0.web.BooleanSwitchWidget( + checkboxes, {'readonly': true, 'disabled': true}); } - var quick_edit = false; - quick_edit = py.eval(field.options).quick_edit ? py.eval(field.options).quick_edit : false; - var checkboxes = view.$el.find( - 'td[data-field=' + field.name + '].oe_list_field_boolean_switch > input[type="checkbox"]'); - new openerp.instances.instance0.web.BooleanSwitchWidget(checkboxes, {'readonly': !quick_edit}); + + var readonly = field.modifiers && + field.modifiers.hasOwnProperty('readonly') ? + field.modifiers.readonly : false; + var options = py.eval(field.options) + var quick_edit = options && + options.hasOwnProperty('quick_edit') ? + options.quick_edit : false; + + var checkboxes = view.$el.find('td[data-field=' + field.name + + '].oe_list_field_boolean_switch > input[type="checkbox"]'); + new openerp.instances.instance0.web.BooleanSwitchWidget( + checkboxes, {'readonly': readonly, 'disabled': !quick_edit}); }); } From 562c20d624e3353ddd8272629266be2d68192f7e Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Fri, 2 Oct 2015 01:01:22 +0200 Subject: [PATCH 09/31] refactor init options switcher --- .../src/js/web_widget_boolean_switch.js | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index 67e2fff3..4e9818f5 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -12,11 +12,17 @@ openerp.web_widget_boolean_switch = function(instance){ init: function(checkboxes, options){ var options = options ? options : {}; this.checkboxes = checkboxes; + + this.quick_edit = options.hasOwnProperty('quick_edit') ? + options.quick_edit : false; + var readonly = options.hasOwnProperty('readonly') ? + options.readonly : false; + var switchOptions = { 'readonly': options.hasOwnProperty('readonly') ? - options.readonly : false, + options.readonly : readonly, 'disabled': options.hasOwnProperty('disabled') ? - options.disabled : false, + options.disabled : !this.quick_edit, }; if(options.hasOwnProperty('onSwitchChange')){ switchOptions.onSwitchChange = options.onSwitchChange @@ -46,26 +52,23 @@ openerp.web_widget_boolean_switch = function(instance){ }, start: function(){ this.$checkbox = $("input", this.$el); - var readonly = this.modifiers && - this.modifiers.hasOwnProperty('readonly') ? - this.modifiers.readonly : false; - this.quick_edit = this.options && - this.options.hasOwnProperty('quick_edit') ? - this.options.quick_edit : false; - this.switcher = new openerp.instances.instance0.web.BooleanSwitchWidget( - this.$checkbox, { - 'readonly': readonly, - 'disabled': !this.quick_edit, + + var options = { onSwitchChange: _.bind(function(event, state) { this.internal_set_value(this.$checkbox.is(':checked')); event.preventDefault(); - }, this) - }); + }, this), + } + _.extend(options, this.modifiers ? this.modifiers : {}); + _.extend(options, this.options ? this.options : {}); + + this.switcher = new openerp.instances.instance0.web.BooleanSwitchWidget( + this.$checkbox, options); this.on("change:effective_readonly", this, this.switcher_states); this._super(); }, switcher_states: function () { - if (this.quick_edit) + if (this.switcher.quick_edit) return; this.switcher.set_disabled(this.get('effective_readonly')) }, @@ -86,21 +89,16 @@ openerp.web_widget_boolean_switch = function(instance){ var checkboxes = view.$el.find( 'th.oe_list_group_name input[type="checkbox"]'); new openerp.instances.instance0.web.BooleanSwitchWidget( - checkboxes, {'readonly': true, 'disabled': true}); + checkboxes, {'readonly': true}); } - var readonly = field.modifiers && - field.modifiers.hasOwnProperty('readonly') ? - field.modifiers.readonly : false; var options = py.eval(field.options) - var quick_edit = options && - options.hasOwnProperty('quick_edit') ? - options.quick_edit : false; + _.extend(options, field.modifiers ? field.modifiers : {}); var checkboxes = view.$el.find('td[data-field=' + field.name + '].oe_list_field_boolean_switch > input[type="checkbox"]'); new openerp.instances.instance0.web.BooleanSwitchWidget( - checkboxes, {'readonly': readonly, 'disabled': !quick_edit}); + checkboxes, options); }); } From 87d958d38b827d72f859262ec504b7a799e113b5 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Fri, 2 Oct 2015 11:49:48 +0200 Subject: [PATCH 10/31] allow extra parameters + poc of quick editing --- web_widget_boolean_switch/README.rst | 50 ++++++++++++++++++- .../demo/res_users_view.xml | 9 ++-- .../src/js/web_widget_boolean_switch.js | 36 +++++++++++-- 3 files changed, 86 insertions(+), 9 deletions(-) diff --git a/web_widget_boolean_switch/README.rst b/web_widget_boolean_switch/README.rst index 5cc824ad..df31a543 100644 --- a/web_widget_boolean_switch/README.rst +++ b/web_widget_boolean_switch/README.rst @@ -18,9 +18,55 @@ To install this module, you need to: Configuration ============= -To configure this module, you need to: +Example +------- + +```xml + +``` + +Options +------- + + +quick_edit +~~~~~~~~~~ + +extra +~~~~~ +``extra`` is used to set +`bootstrap-switch `_ options. + +Available:: + + * **size**: - default: `null` + * **animate**: - default: `true` + * **indeterminate**: `false` + * **inverse**: `false` + * **radioAllOff**: `false` + * **onColor**: `"primary"` + * **offColor**: `default` + * **onText**: `"ON"`, + * **offText**: `"OFF"`, + * **labelText**: `" "`, + * **handleWidth**: `"auto"`, + * **labelWidth**: `"auto"`, + * **baseClass**: `"bootstrap-switch"`, + * **wrapperClass**: `"wrapper"`, + + +.. warning:: + + Those parameters are overwritten by this module or highly discourage:: + + * **state**: true, + * **disabled**: `false` + * **readonly**: `false` + * **onInit**: `function() {}`, + * **onSwitchChange**: `function() {}` -* go to ... Usage ===== diff --git a/web_widget_boolean_switch/demo/res_users_view.xml b/web_widget_boolean_switch/demo/res_users_view.xml index 1543c83a..ffe16e9c 100644 --- a/web_widget_boolean_switch/demo/res_users_view.xml +++ b/web_widget_boolean_switch/demo/res_users_view.xml @@ -19,7 +19,8 @@ 20 - + @@ -29,7 +30,8 @@ res.users - + @@ -43,7 +45,8 @@ - + diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index 4e9818f5..2f713a40 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -17,17 +17,37 @@ openerp.web_widget_boolean_switch = function(instance){ options.quick_edit : false; var readonly = options.hasOwnProperty('readonly') ? options.readonly : false; + var switchOptions = options.hasOwnProperty('extra') ? + options.extra : {}; - var switchOptions = { + + _.extend(switchOptions, { 'readonly': options.hasOwnProperty('readonly') ? options.readonly : readonly, 'disabled': options.hasOwnProperty('disabled') ? options.disabled : !this.quick_edit, - }; + }); if(options.hasOwnProperty('onSwitchChange')){ switchOptions.onSwitchChange = options.onSwitchChange } this.checkboxes.bootstrapSwitch(switchOptions); + if(this.quick_edit){ + this.checkboxes.on('switchChange.bootstrapSwitch', + function(event, state) { + var model_name = 'res.users'; + var id = 4; + var values = {}; + values['active'] = state; + var some_context = {}; + + var model = new openerp.instances.instance0.web.Model(model_name); + + model.call('write', [[id], values], + {context: some_context}).then(function (result) { + console.log('success'); + }); + }); + } }, set_value: function(value){ // the third parameter tell if we should skip to fire evnets @@ -55,8 +75,16 @@ openerp.web_widget_boolean_switch = function(instance){ var options = { onSwitchChange: _.bind(function(event, state) { - this.internal_set_value(this.$checkbox.is(':checked')); - event.preventDefault(); + // Test effective_readonly in case we are using quick_edit, + // and we are not in edit mode. + // We could use this.view.get('actual_mode') which sons + // semantically better, possible values are + // at least `view`, `edit`, `create`, ...? to avoid doupt + // using bool seems safer! + if(!this.get('effective_readonly')){ + this.internal_set_value(state); + event.preventDefault(); + } }, this), } _.extend(options, this.modifiers ? this.modifiers : {}); From e6215b0e3d4c63e53b6b817161b0aed34248591c Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Fri, 2 Oct 2015 16:25:10 +0200 Subject: [PATCH 11/31] finalize quick edit fixe context --- .../demo/res_users_view.xml | 9 ++- .../src/js/web_widget_boolean_switch.js | 76 ++++++++++++------- 2 files changed, 54 insertions(+), 31 deletions(-) diff --git a/web_widget_boolean_switch/demo/res_users_view.xml b/web_widget_boolean_switch/demo/res_users_view.xml index ffe16e9c..d61e1ac3 100644 --- a/web_widget_boolean_switch/demo/res_users_view.xml +++ b/web_widget_boolean_switch/demo/res_users_view.xml @@ -20,7 +20,8 @@ + options="{'quick_edit': True, 'extra': {'onText': 'Yes', 'offText': 'No'}}" + context="{'test': 'test value'}"/> @@ -31,7 +32,8 @@ + options="{'quick_edit': True, 'extra': {'onText': 'Yes', 'offText': 'No'}}" + context="{'test': 'test value'}"/> @@ -46,7 +48,8 @@ + options="{'quick_edit': True, 'extra': {'onText': 'Yes', 'offText': 'No'}}" + context="{'test': 'test value'}" /> diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index 2f713a40..e646976f 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -1,6 +1,7 @@ 'use strict'; openerp.web_widget_boolean_switch = function(instance){ + var instance = instance; instance.web.form.widgets.add('boolean_switch', 'instance.web.form.FieldBooleanSwitch'); @@ -9,7 +10,7 @@ openerp.web_widget_boolean_switch = function(instance){ instance.web.BooleanSwitchWidget = instance.web.Class.extend({ - init: function(checkboxes, options){ + init: function(checkboxes, options, quick_edit_callback){ var options = options ? options : {}; this.checkboxes = checkboxes; @@ -31,22 +32,9 @@ openerp.web_widget_boolean_switch = function(instance){ switchOptions.onSwitchChange = options.onSwitchChange } this.checkboxes.bootstrapSwitch(switchOptions); - if(this.quick_edit){ + if(this.quick_edit && quick_edit_callback){ this.checkboxes.on('switchChange.bootstrapSwitch', - function(event, state) { - var model_name = 'res.users'; - var id = 4; - var values = {}; - values['active'] = state; - var some_context = {}; - - var model = new openerp.instances.instance0.web.Model(model_name); - - model.call('write', [[id], values], - {context: some_context}).then(function (result) { - console.log('success'); - }); - }); + quick_edit_callback); } }, set_value: function(value){ @@ -67,12 +55,8 @@ openerp.web_widget_boolean_switch = function(instance){ template: 'FieldBooleanSwitch', - init: function(field_manager, node){ - this._super(field_manager, node); - }, start: function(){ this.$checkbox = $("input", this.$el); - var options = { onSwitchChange: _.bind(function(event, state) { // Test effective_readonly in case we are using quick_edit, @@ -91,10 +75,26 @@ openerp.web_widget_boolean_switch = function(instance){ _.extend(options, this.options ? this.options : {}); this.switcher = new openerp.instances.instance0.web.BooleanSwitchWidget( - this.$checkbox, options); + this.$checkbox, options, _.bind(function(event, state) { + var id = this.view.dataset.ids[this.view.dataset.index]; + var values = {}; + values[this.name] = state; + var context = openerp.instances.instance0.web.pyeval.eval( + 'contexts', this.build_context()) + var model = new openerp.instances.instance0.web.Model(this.view.model); + model.call('write', [[id], values], + {'context': this.build_context()}); + this.internal_set_value(state, {'silent': true}); + }, this)); this.on("change:effective_readonly", this, this.switcher_states); this._super(); }, + internal_set_value: function(value_, options) { + var tmp = this.no_rerender; + this.no_rerender = true; + this.set({'value': value_}, options); + this.no_rerender = tmp; + }, switcher_states: function () { if (this.switcher.quick_edit) return; @@ -105,9 +105,8 @@ openerp.web_widget_boolean_switch = function(instance){ }, }); - // List view - - function apply_helper(view, columns){ + // Helper methods + function apply_switcher(view, columns){ var switch_fields = columns.filter(function(c){ return c.widget === 'boolean_switch'; }); @@ -117,7 +116,7 @@ openerp.web_widget_boolean_switch = function(instance){ var checkboxes = view.$el.find( 'th.oe_list_group_name input[type="checkbox"]'); new openerp.instances.instance0.web.BooleanSwitchWidget( - checkboxes, {'readonly': true}); + checkboxes, {'readonly': true}, null); } var options = py.eval(field.options) @@ -126,15 +125,36 @@ openerp.web_widget_boolean_switch = function(instance){ var checkboxes = view.$el.find('td[data-field=' + field.name + '].oe_list_field_boolean_switch > input[type="checkbox"]'); new openerp.instances.instance0.web.BooleanSwitchWidget( - checkboxes, options); + checkboxes, options, _.bind(function(event, state) { + var id = $(event.target).data('rowid'); + var values = {}; + values[this.field.name] = state; + var context = py.eval(field.context); + var model = new openerp.instances.instance0.web.Model(this.view.model); + model.call('write', [[id], values], + {'context': context}); + }, {'view': view, 'field': field}) + ); }); } + // List view + instance.web.list.columns.add('field.boolean_switch', 'instance.web.list.FieldBooleanSwitch'); + + instance.web.list.FieldBooleanSwitch = instance.web.list.Column.extend({ + + _format: function (row_data, options) { + return _.str.sprintf('', + row_data[this.id].value ? 'checked="checked"' : '', + row_data.hasOwnProperty('id') ? row_data['id'].value : -1); + } + }); + instance.web.ListView.Groups.include({ render: function(post_render){ var self = this; var prender = function(){ - apply_helper(self.view, self.columns); + apply_switcher(self.view, self.columns); if (post_render) { post_render(); } }; return this._super(prender); @@ -147,7 +167,7 @@ openerp.web_widget_boolean_switch = function(instance){ // after edition var self = this; return this._super(record).then(function(){ - apply_helper(self, self.columns); + apply_switcher(self, self.columns); }); }, }); From 91cb0e0645025ba4483ac423f0cd21fd9ec91c72 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Fri, 2 Oct 2015 17:25:08 +0200 Subject: [PATCH 12/31] documentation --- web_widget_boolean_switch/README.rst | 77 ++++++++++++++-------------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/web_widget_boolean_switch/README.rst b/web_widget_boolean_switch/README.rst index df31a543..292dee45 100644 --- a/web_widget_boolean_switch/README.rst +++ b/web_widget_boolean_switch/README.rst @@ -6,27 +6,31 @@ Web widget boolean switch ========================= -This module add a widget to render boolean fields +This module add a widget ``boolean_switch`` to render boolean fields. One +of it's main features is to quick edit that field without enter in edit mode. -Installation -============ - -To install this module, you need to: - -* do this ... Configuration ============= +In the view (test on tree view and form view), you can declare any boolean +field using this widget. + Example ------- ```xml ``` +.. note:: + + ``context`` is sent to the ``write`` method of the field model in case of + special needs with the quick edition. + Options ------- @@ -41,31 +45,31 @@ extra Available:: - * **size**: - default: `null` - * **animate**: - default: `true` - * **indeterminate**: `false` - * **inverse**: `false` - * **radioAllOff**: `false` - * **onColor**: `"primary"` - * **offColor**: `default` - * **onText**: `"ON"`, - * **offText**: `"OFF"`, - * **labelText**: `" "`, - * **handleWidth**: `"auto"`, - * **labelWidth**: `"auto"`, - * **baseClass**: `"bootstrap-switch"`, - * **wrapperClass**: `"wrapper"`, + * **size**: The checkbox size - default: `null` - values: null, 'mini', 'small', 'normal', 'large' + * **animate**: Animate the switch - default: `true` + * **indeterminate**: Indeterminate state - default: `false` + * **inverse**: Inverse switch direction - default: `false` + * **onColor**: Color of the left side of the switch - default: `"primary"` - values: 'primary', 'info', 'success', 'warning', 'danger', 'default' + * **offColor**: Color of the right side of the switch - default: `default` - values: 'primary', 'info', 'success', 'warning', 'danger', 'default' + * **onText**: Text of the left side of the switch - default: `"ON"` + * **offText**: Text of the right side of the switch - default: `"OFF"`, + * **labelText**: Text of the center handle of the switch - default: `" "`, + * **handleWidth**: Width of the left and right sides in pixels - default: `"auto"`, + * **labelWidth**: Width of the center handle in pixels - default: `"auto"`, + * **baseClass**: Global class prefix - default: `"bootstrap-switch"`, + * **wrapperClass**: Container element class(es) - default: `"wrapper"`, .. warning:: - Those parameters are overwritten by this module or highly discourage:: + Those parameters are overwritten by this module or highly discouraged:: - * **state**: true, - * **disabled**: `false` - * **readonly**: `false` - * **onInit**: `function() {}`, - * **onSwitchChange**: `function() {}` + * **radioAllOff**: Allow this radio button to be unchecked by the user - default: `false` + * **state**: The checkbox state - default: `true` + * **disabled**: Disable state - default: `false` + * **readonly**: Readonly state - default: `false` + * **onInit**: Callback function to execute on initialization - default: `function() {}`, + * **onSwitchChange**: Callback function to execute on switch state change - default: `function() {}` Usage @@ -77,26 +81,23 @@ To use this module, you need to: .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/{repo_id}/{branch} - -.. repo_id is available in https://github.com/OCA/maintainer-tools/blob/master/tools/repos_with_ids.txt -.. branch is "8.0" for example + :target: https://runbot.odoo-community.org/runbot/162/7.0 Known issues / Roadmap ====================== -* ... +* Manage Null values +* Bug Tracker =========== -Bugs are tracked on `GitHub Issues `_. +Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. -If you spotted it first, help us smashing it by providing a detailed and welcomed feedback `here `_. +If you spotted it first, help us smashing it by providing a detailed and +welcomed feedback `here `_. Credits From 924756ba8a7da659699789d19d38b45aea3cf0e9 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Fri, 2 Oct 2015 17:27:55 +0200 Subject: [PATCH 13/31] avoid multi call to the server in case of view list editable + quick edition fix context on view list for quick edition --- .../src/js/web_widget_boolean_switch.js | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index e646976f..001d5d0b 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -63,7 +63,7 @@ openerp.web_widget_boolean_switch = function(instance){ // and we are not in edit mode. // We could use this.view.get('actual_mode') which sons // semantically better, possible values are - // at least `view`, `edit`, `create`, ...? to avoid doupt + // at least `view`, `edit`, `create`... ? to avoid doupt // using bool seems safer! if(!this.get('effective_readonly')){ this.internal_set_value(state); @@ -76,15 +76,19 @@ openerp.web_widget_boolean_switch = function(instance){ this.switcher = new openerp.instances.instance0.web.BooleanSwitchWidget( this.$checkbox, options, _.bind(function(event, state) { - var id = this.view.dataset.ids[this.view.dataset.index]; - var values = {}; - values[this.name] = state; - var context = openerp.instances.instance0.web.pyeval.eval( - 'contexts', this.build_context()) - var model = new openerp.instances.instance0.web.Model(this.view.model); - model.call('write', [[id], values], - {'context': this.build_context()}); - this.internal_set_value(state, {'silent': true}); + // get in mind that in case of view list editable + // actual_mode is undefined... + if(this.view.get('actual_mode') === 'view'){ + var id = this.view.dataset.ids[this.view.dataset.index]; + var values = {}; + values[this.name] = state; + var context = openerp.instances.instance0.web.pyeval.eval( + 'contexts', this.build_context()) + var model = new openerp.instances.instance0.web.Model(this.view.model); + model.call('write', [[id], values], + {'context': this.build_context()}); + this.internal_set_value(state, {'silent': true}); + } }, this)); this.on("change:effective_readonly", this, this.switcher_states); this._super(); @@ -130,6 +134,7 @@ openerp.web_widget_boolean_switch = function(instance){ var values = {}; values[this.field.name] = state; var context = py.eval(field.context); + _.extend(context, view.session.user_context) var model = new openerp.instances.instance0.web.Model(this.view.model); model.call('write', [[id], values], {'context': context}); From 77b12a283e79aa9beee014f19b053df6446b4bbf Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Fri, 2 Oct 2015 17:37:27 +0200 Subject: [PATCH 14/31] jshint --- .../src/js/web_widget_boolean_switch.js | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index 001d5d0b..7b4e4501 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -1,7 +1,6 @@ -'use strict'; openerp.web_widget_boolean_switch = function(instance){ + "use strict"; - var instance = instance; instance.web.form.widgets.add('boolean_switch', 'instance.web.form.FieldBooleanSwitch'); @@ -11,7 +10,7 @@ openerp.web_widget_boolean_switch = function(instance){ instance.web.BooleanSwitchWidget = instance.web.Class.extend({ init: function(checkboxes, options, quick_edit_callback){ - var options = options ? options : {}; + options = options ? options : {}; this.checkboxes = checkboxes; this.quick_edit = options.hasOwnProperty('quick_edit') ? @@ -21,7 +20,6 @@ openerp.web_widget_boolean_switch = function(instance){ var switchOptions = options.hasOwnProperty('extra') ? options.extra : {}; - _.extend(switchOptions, { 'readonly': options.hasOwnProperty('readonly') ? options.readonly : readonly, @@ -29,7 +27,7 @@ openerp.web_widget_boolean_switch = function(instance){ options.disabled : !this.quick_edit, }); if(options.hasOwnProperty('onSwitchChange')){ - switchOptions.onSwitchChange = options.onSwitchChange + switchOptions.onSwitchChange = options.onSwitchChange; } this.checkboxes.bootstrapSwitch(switchOptions); if(this.quick_edit && quick_edit_callback){ @@ -50,7 +48,6 @@ openerp.web_widget_boolean_switch = function(instance){ }); // Form view - instance.web.form.FieldBooleanSwitch = instance.web.form.AbstractField.extend({ template: 'FieldBooleanSwitch', @@ -70,7 +67,7 @@ openerp.web_widget_boolean_switch = function(instance){ event.preventDefault(); } }, this), - } + }; _.extend(options, this.modifiers ? this.modifiers : {}); _.extend(options, this.options ? this.options : {}); @@ -83,7 +80,7 @@ openerp.web_widget_boolean_switch = function(instance){ var values = {}; values[this.name] = state; var context = openerp.instances.instance0.web.pyeval.eval( - 'contexts', this.build_context()) + 'contexts', this.build_context()); var model = new openerp.instances.instance0.web.Model(this.view.model); model.call('write', [[id], values], {'context': this.build_context()}); @@ -102,7 +99,7 @@ openerp.web_widget_boolean_switch = function(instance){ switcher_states: function () { if (this.switcher.quick_edit) return; - this.switcher.set_disabled(this.get('effective_readonly')) + this.switcher.set_disabled(this.get('effective_readonly')); }, render_value: function() { this.switcher.set_value(this.get('value')); @@ -115,18 +112,19 @@ openerp.web_widget_boolean_switch = function(instance){ return c.widget === 'boolean_switch'; }); switch_fields.forEach(function(field){ + var checkboxes; if(view.grouped){ //Manage if it's grouped by boolean_switch widget field - var checkboxes = view.$el.find( + checkboxes = view.$el.find( 'th.oe_list_group_name input[type="checkbox"]'); new openerp.instances.instance0.web.BooleanSwitchWidget( checkboxes, {'readonly': true}, null); } - var options = py.eval(field.options) + var options = py.eval(field.options); _.extend(options, field.modifiers ? field.modifiers : {}); - var checkboxes = view.$el.find('td[data-field=' + field.name + + checkboxes = view.$el.find('td[data-field=' + field.name + '].oe_list_field_boolean_switch > input[type="checkbox"]'); new openerp.instances.instance0.web.BooleanSwitchWidget( checkboxes, options, _.bind(function(event, state) { @@ -134,7 +132,7 @@ openerp.web_widget_boolean_switch = function(instance){ var values = {}; values[this.field.name] = state; var context = py.eval(field.context); - _.extend(context, view.session.user_context) + _.extend(context, view.session.user_context); var model = new openerp.instances.instance0.web.Model(this.view.model); model.call('write', [[id], values], {'context': context}); @@ -151,7 +149,7 @@ openerp.web_widget_boolean_switch = function(instance){ _format: function (row_data, options) { return _.str.sprintf('', row_data[this.id].value ? 'checked="checked"' : '', - row_data.hasOwnProperty('id') ? row_data['id'].value : -1); + row_data.hasOwnProperty('id') ? row_data.id.value : -1); } }); From e8182de5d22a13f98f6156a2c2aa49612cc0054e Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Fri, 2 Oct 2015 18:19:25 +0200 Subject: [PATCH 15/31] when quick editing, set records data --- .../static/src/js/web_widget_boolean_switch.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index 7b4e4501..0a1fa7e2 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -135,7 +135,12 @@ openerp.web_widget_boolean_switch = function(instance){ _.extend(context, view.session.user_context); var model = new openerp.instances.instance0.web.Model(this.view.model); model.call('write', [[id], values], - {'context': context}); + {'context': context}).then(_.bind(function(){ + if(!this.view.grouped){ + this.view.records._byId[this.id].attributes[this.field.name] = this.state; + } + }, {'view': this.view, 'field': this.field, + 'id': id, 'state': state})); }, {'view': view, 'field': field}) ); }); From 3b56d9973667e0eb28c5db130e24c3e9b126b05f Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Fri, 2 Oct 2015 18:33:12 +0200 Subject: [PATCH 16/31] doc missing cote in example --- web_widget_boolean_switch/README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_widget_boolean_switch/README.rst b/web_widget_boolean_switch/README.rst index 292dee45..2d8c8493 100644 --- a/web_widget_boolean_switch/README.rst +++ b/web_widget_boolean_switch/README.rst @@ -23,7 +23,7 @@ Example + options="{'quick_edit': True, 'extra': {'onText': 'Yes', 'offText': 'No' }"/> ``` .. note:: From fd2cbe6078b4485981baf1f3278ac2d5bcca1a47 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Fri, 2 Oct 2015 22:31:33 +0200 Subject: [PATCH 17/31] RST format --- web_widget_boolean_switch/README.rst | 29 +++++++++++----------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/web_widget_boolean_switch/README.rst b/web_widget_boolean_switch/README.rst index 2d8c8493..be1cff95 100644 --- a/web_widget_boolean_switch/README.rst +++ b/web_widget_boolean_switch/README.rst @@ -19,11 +19,11 @@ field using this widget. Example ------- -```xml +``` + options="{'quick_edit': True, 'extra': {'onText': 'Yes', 'offText': 'No' }}"/> ``` .. note:: @@ -43,7 +43,7 @@ extra ``extra`` is used to set `bootstrap-switch `_ options. -Available:: +*Available options*: * **size**: The checkbox size - default: `null` - values: null, 'mini', 'small', 'normal', 'large' * **animate**: Animate the switch - default: `true` @@ -60,24 +60,17 @@ Available:: * **wrapperClass**: Container element class(es) - default: `"wrapper"`, -.. warning:: - - Those parameters are overwritten by this module or highly discouraged:: - - * **radioAllOff**: Allow this radio button to be unchecked by the user - default: `false` - * **state**: The checkbox state - default: `true` - * **disabled**: Disable state - default: `false` - * **readonly**: Readonly state - default: `false` - * **onInit**: Callback function to execute on initialization - default: `function() {}`, - * **onSwitchChange**: Callback function to execute on switch state change - default: `function() {}` - +..warning:: -Usage -===== + Those parameters are overwritten by this module or highly discouraged: -To use this module, you need to: + * **radioAllOff**: Allow this radio button to be unchecked by the user - default: `false` + * **state**: The checkbox state - default: `true` + * **disabled**: Disable state - default: `false` + * **readonly**: Readonly state - default: `false` + * **onInit**: Callback function to execute on initialization - default: `function() {}`, + * **onSwitchChange**: Callback function to execute on switch state change - default: `function() {}` -* go to ... .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot From b722d5299ec246d81d3530a65854568b92cffcd6 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Fri, 2 Oct 2015 22:32:34 +0200 Subject: [PATCH 18/31] foward options to grouped switcher --- .../static/src/js/web_widget_boolean_switch.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index 0a1fa7e2..c76d7c99 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -113,17 +113,21 @@ openerp.web_widget_boolean_switch = function(instance){ }); switch_fields.forEach(function(field){ var checkboxes; + + var options = py.eval(field.options); + if(view.grouped){ //Manage if it's grouped by boolean_switch widget field + var opt = {}; + _.extend(opt, options); + opt.readonly = true; checkboxes = view.$el.find( 'th.oe_list_group_name input[type="checkbox"]'); new openerp.instances.instance0.web.BooleanSwitchWidget( - checkboxes, {'readonly': true}, null); + checkboxes, opt, null); } - var options = py.eval(field.options); _.extend(options, field.modifiers ? field.modifiers : {}); - checkboxes = view.$el.find('td[data-field=' + field.name + '].oe_list_field_boolean_switch > input[type="checkbox"]'); new openerp.instances.instance0.web.BooleanSwitchWidget( From 0c41e40ec53e3b6b7f50a1896f054df4a1e59985 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Fri, 2 Oct 2015 22:34:35 +0200 Subject: [PATCH 19/31] code formatting --- .../static/src/js/web_widget_boolean_switch.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index c76d7c99..c5c06b51 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -139,12 +139,13 @@ openerp.web_widget_boolean_switch = function(instance){ _.extend(context, view.session.user_context); var model = new openerp.instances.instance0.web.Model(this.view.model); model.call('write', [[id], values], - {'context': context}).then(_.bind(function(){ - if(!this.view.grouped){ - this.view.records._byId[this.id].attributes[this.field.name] = this.state; - } - }, {'view': this.view, 'field': this.field, - 'id': id, 'state': state})); + {'context': context}).then(_.bind(function(){ + if(!this.view.grouped){ + this.view.records._byId[this.id].attributes[ + this.field.name] = this.state; + } + }, {'view': this.view, 'field': this.field, + 'id': id, 'state': state})); }, {'view': view, 'field': field}) ); }); From 858d554cfc1770aaffd44a579b492c4bfe71212e Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Sat, 3 Oct 2015 01:15:27 +0200 Subject: [PATCH 20/31] manage attrs attribute, espesialy for readonly --- web_widget_boolean_switch/README.rst | 20 +++++--- .../demo/res_users_view.xml | 5 +- .../src/js/web_widget_boolean_switch.js | 47 +++++++++++++++---- 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/web_widget_boolean_switch/README.rst b/web_widget_boolean_switch/README.rst index be1cff95..0bd24001 100644 --- a/web_widget_boolean_switch/README.rst +++ b/web_widget_boolean_switch/README.rst @@ -22,19 +22,14 @@ Example ``` ``` -.. note:: - - ``context`` is sent to the ``write`` method of the field model in case of - special needs with the quick edition. - Options ------- - quick_edit ~~~~~~~~~~ @@ -60,7 +55,7 @@ extra * **wrapperClass**: Container element class(es) - default: `"wrapper"`, -..warning:: +.. warning:: Those parameters are overwritten by this module or highly discouraged: @@ -71,6 +66,17 @@ extra * **onInit**: Callback function to execute on initialization - default: `function() {}`, * **onSwitchChange**: Callback function to execute on switch state change - default: `function() {}` +attrs +----- + +This attribute is supported as expected! + +context +------- + +``context`` is sent to the ``write`` method of the field model in case of +special needs with the quick edition. + .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot diff --git a/web_widget_boolean_switch/demo/res_users_view.xml b/web_widget_boolean_switch/demo/res_users_view.xml index d61e1ac3..1c9aca19 100644 --- a/web_widget_boolean_switch/demo/res_users_view.xml +++ b/web_widget_boolean_switch/demo/res_users_view.xml @@ -20,6 +20,7 @@ @@ -31,7 +32,8 @@ res.users - @@ -48,6 +50,7 @@ diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index c5c06b51..5c4407fb 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -9,8 +9,8 @@ openerp.web_widget_boolean_switch = function(instance){ instance.web.BooleanSwitchWidget = instance.web.Class.extend({ - init: function(checkboxes, options, quick_edit_callback){ - options = options ? options : {}; + init: function(checkboxes, opts, quick_edit_callback){ + var options = _.extend({}, opts ? opts : {}); this.checkboxes = checkboxes; this.quick_edit = options.hasOwnProperty('quick_edit') ? @@ -20,12 +20,23 @@ openerp.web_widget_boolean_switch = function(instance){ var switchOptions = options.hasOwnProperty('extra') ? options.extra : {}; + // in case of domain (using attrs={...}), readonly is set afterward + if(!_.isBoolean(options.readonly)){ + options.readonly = false; + } _.extend(switchOptions, { 'readonly': options.hasOwnProperty('readonly') ? options.readonly : readonly, 'disabled': options.hasOwnProperty('disabled') ? options.disabled : !this.quick_edit, }); + + //finnaly if readonly is false, we remove it to init widget + //with the value of its attributes well managed by qweb and + //FieldBooleanSwitch class + if(!switchOptions.readonly){ + delete switchOptions.readonly; + } if(options.hasOwnProperty('onSwitchChange')){ switchOptions.onSwitchChange = options.onSwitchChange; } @@ -73,7 +84,7 @@ openerp.web_widget_boolean_switch = function(instance){ this.switcher = new openerp.instances.instance0.web.BooleanSwitchWidget( this.$checkbox, options, _.bind(function(event, state) { - // get in mind that in case of view list editable + // keep in mind that in case of view list editable // actual_mode is undefined... if(this.view.get('actual_mode') === 'view'){ var id = this.view.dataset.ids[this.view.dataset.index]; @@ -87,8 +98,9 @@ openerp.web_widget_boolean_switch = function(instance){ this.internal_set_value(state, {'silent': true}); } }, this)); - this.on("change:effective_readonly", this, this.switcher_states); + this.on("change:readonly", this, this.switcher_states); this._super(); + this.switcher_states.call(this); }, internal_set_value: function(value_, options) { var tmp = this.no_rerender; @@ -97,9 +109,10 @@ openerp.web_widget_boolean_switch = function(instance){ this.no_rerender = tmp; }, switcher_states: function () { - if (this.switcher.quick_edit) - return; - this.switcher.set_disabled(this.get('effective_readonly')); + this.switcher.set_readonly(this.get('readonly')); + if (!this.switcher.quick_edit){ + this.switcher.set_disabled(this.get('effective_readonly')); + } }, render_value: function() { this.switcher.set_value(this.get('value')); @@ -155,10 +168,26 @@ openerp.web_widget_boolean_switch = function(instance){ instance.web.list.columns.add('field.boolean_switch', 'instance.web.list.FieldBooleanSwitch'); instance.web.list.FieldBooleanSwitch = instance.web.list.Column.extend({ + format: function (row_data, options) { + options = options || {}; + var attrs = {}; + if (options.process_modifiers !== false) { + attrs = this.modifiers_for(row_data); + } + if (attrs.invisible) { return ''; } + + if (!row_data[this.id]) { + return options.value_if_empty === undefined ? + '' : options.value_if_empty; + } + var readonly = attrs.hasOwnProperty('readonly') ? attrs.readonly : false; + return this._format(row_data, options, readonly); + }, - _format: function (row_data, options) { - return _.str.sprintf('', + _format: function (row_data, options, readonly) { + return _.str.sprintf('', row_data[this.id].value ? 'checked="checked"' : '', + readonly ? 'readonly' : '', row_data.hasOwnProperty('id') ? row_data.id.value : -1); } }); From 0fb54c760f1b83c5b5bafc44beb24bb8ba7cc578 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Sat, 3 Oct 2015 01:24:15 +0200 Subject: [PATCH 21/31] remove readonly managment initialization --- .../static/src/js/web_widget_boolean_switch.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index 5c4407fb..279e4de9 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -15,28 +15,14 @@ openerp.web_widget_boolean_switch = function(instance){ this.quick_edit = options.hasOwnProperty('quick_edit') ? options.quick_edit : false; - var readonly = options.hasOwnProperty('readonly') ? - options.readonly : false; var switchOptions = options.hasOwnProperty('extra') ? options.extra : {}; - // in case of domain (using attrs={...}), readonly is set afterward - if(!_.isBoolean(options.readonly)){ - options.readonly = false; - } _.extend(switchOptions, { - 'readonly': options.hasOwnProperty('readonly') ? - options.readonly : readonly, 'disabled': options.hasOwnProperty('disabled') ? options.disabled : !this.quick_edit, }); - //finnaly if readonly is false, we remove it to init widget - //with the value of its attributes well managed by qweb and - //FieldBooleanSwitch class - if(!switchOptions.readonly){ - delete switchOptions.readonly; - } if(options.hasOwnProperty('onSwitchChange')){ switchOptions.onSwitchChange = options.onSwitchChange; } @@ -133,7 +119,7 @@ openerp.web_widget_boolean_switch = function(instance){ //Manage if it's grouped by boolean_switch widget field var opt = {}; _.extend(opt, options); - opt.readonly = true; + opt.disabled = true; checkboxes = view.$el.find( 'th.oe_list_group_name input[type="checkbox"]'); new openerp.instances.instance0.web.BooleanSwitchWidget( From 6c80374aec5d5db78440ecf14f59b9bd6ae7a397 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Sat, 3 Oct 2015 01:28:36 +0200 Subject: [PATCH 22/31] fix issue on create new object on editable listview --- .../static/src/js/web_widget_boolean_switch.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index 279e4de9..8bab7979 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -172,9 +172,10 @@ openerp.web_widget_boolean_switch = function(instance){ _format: function (row_data, options, readonly) { return _.str.sprintf('', - row_data[this.id].value ? 'checked="checked"' : '', - readonly ? 'readonly' : '', - row_data.hasOwnProperty('id') ? row_data.id.value : -1); + row_data[this.id].value ? 'checked="checked"' : '', + readonly ? 'readonly' : '', + row_data.hasOwnProperty('id') && _.isNumber(row_data.id.value) ? + row_data.id.value : -1); } }); From e402b8a73f84031c7c61e5747b16da5ed5767038 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Sat, 3 Oct 2015 01:45:08 +0200 Subject: [PATCH 23/31] py.eval is not protect against undefined --- .../static/src/js/web_widget_boolean_switch.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index 8bab7979..fb47b9fd 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -113,7 +113,7 @@ openerp.web_widget_boolean_switch = function(instance){ switch_fields.forEach(function(field){ var checkboxes; - var options = py.eval(field.options); + var options = field.options ? py.eval(field.options) : {}; if(view.grouped){ //Manage if it's grouped by boolean_switch widget field @@ -134,7 +134,7 @@ openerp.web_widget_boolean_switch = function(instance){ var id = $(event.target).data('rowid'); var values = {}; values[this.field.name] = state; - var context = py.eval(field.context); + var context = field.context ? py.eval(field.context) : {}; _.extend(context, view.session.user_context); var model = new openerp.instances.instance0.web.Model(this.view.model); model.call('write', [[id], values], From 354324bbc21800eeb5fd5d54699140e6094be509 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Sat, 3 Oct 2015 15:54:15 +0200 Subject: [PATCH 24/31] remove test lib file --- .../static/lib/bootstrap-switch/index.html | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 web_widget_boolean_switch/static/lib/bootstrap-switch/index.html diff --git a/web_widget_boolean_switch/static/lib/bootstrap-switch/index.html b/web_widget_boolean_switch/static/lib/bootstrap-switch/index.html deleted file mode 100644 index 463bed49..00000000 --- a/web_widget_boolean_switch/static/lib/bootstrap-switch/index.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - Bootstrap switch: test - - -
- -
-
- -
- - - From bfb5a0686f5f59434fc9b2d26a321c1a93bc167c Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Sat, 3 Oct 2015 23:30:43 +0200 Subject: [PATCH 25/31] add unit test and got one fix + update doc --- web_widget_boolean_switch/README.rst | 37 +++-- web_widget_boolean_switch/__openerp__.py | 139 +++++++++++++++++- .../src/js/web_widget_boolean_switch.js | 9 +- .../static/test/web_widget_boolean_switch.js | 139 ++++++++++++++++++ 4 files changed, 304 insertions(+), 20 deletions(-) create mode 100644 web_widget_boolean_switch/static/test/web_widget_boolean_switch.js diff --git a/web_widget_boolean_switch/README.rst b/web_widget_boolean_switch/README.rst index 0bd24001..aee88be0 100644 --- a/web_widget_boolean_switch/README.rst +++ b/web_widget_boolean_switch/README.rst @@ -7,7 +7,8 @@ Web widget boolean switch ========================= This module add a widget ``boolean_switch`` to render boolean fields. One -of it's main features is to quick edit that field without enter in edit mode. +of it's main features is to quick edit that field without enter in edit mode +from list view or form view. Configuration @@ -24,7 +25,7 @@ Example widget="boolean_switch" attrs="{'readonly': [('login', '=', 'admin')]}" context="{'fake_parameter': 'foo'}" - options="{'quick_edit': True, 'extra': {'onText': 'Yes', 'offText': 'No' }}"/> + options="{'quick_edit': True, 'extra': {'onText': 'Yes', 'offText': 'No'}}"/> ``` Options @@ -40,31 +41,39 @@ extra *Available options*: - * **size**: The checkbox size - default: `null` - values: null, 'mini', 'small', 'normal', 'large' + * **size**: The checkbox size - default: `null` - values: null, 'mini', + 'small', 'normal', 'large' * **animate**: Animate the switch - default: `true` * **indeterminate**: Indeterminate state - default: `false` * **inverse**: Inverse switch direction - default: `false` - * **onColor**: Color of the left side of the switch - default: `"primary"` - values: 'primary', 'info', 'success', 'warning', 'danger', 'default' - * **offColor**: Color of the right side of the switch - default: `default` - values: 'primary', 'info', 'success', 'warning', 'danger', 'default' + * **onColor**: Color of the left side of the switch - default: `"primary"` - + values: 'primary', 'info', 'success', 'warning', 'danger', 'default' + * **offColor**: Color of the right side of the switch - default: `default` - + values: 'primary', 'info', 'success', 'warning', 'danger', 'default' * **onText**: Text of the left side of the switch - default: `"ON"` - * **offText**: Text of the right side of the switch - default: `"OFF"`, - * **labelText**: Text of the center handle of the switch - default: `" "`, - * **handleWidth**: Width of the left and right sides in pixels - default: `"auto"`, - * **labelWidth**: Width of the center handle in pixels - default: `"auto"`, - * **baseClass**: Global class prefix - default: `"bootstrap-switch"`, - * **wrapperClass**: Container element class(es) - default: `"wrapper"`, + * **offText**: Text of the right side of the switch - default: `"OFF"` + * **labelText**: Text of the center handle of the switch - default: + `" "`, + * **handleWidth**: Width of the left and right sides in pixels - default: + `"auto"`, + * **labelWidth**: Width of the center handle in pixels - default: `"auto"` + * **baseClass**: Global class prefix - default: `"bootstrap-switch"` + * **wrapperClass**: Container element class(es) - default: `"wrapper"` .. warning:: Those parameters are overwritten by this module or highly discouraged: - * **radioAllOff**: Allow this radio button to be unchecked by the user - default: `false` + * **radioAllOff**: Allow this radio button to be unchecked by the user - + default: `false` * **state**: The checkbox state - default: `true` * **disabled**: Disable state - default: `false` * **readonly**: Readonly state - default: `false` - * **onInit**: Callback function to execute on initialization - default: `function() {}`, - * **onSwitchChange**: Callback function to execute on switch state change - default: `function() {}` + * **onInit**: Callback function to execute on initialization - default: + `function() {}`, + * **onSwitchChange**: Callback function to execute on switch state change - + default: `function() {}` attrs ----- diff --git a/web_widget_boolean_switch/__openerp__.py b/web_widget_boolean_switch/__openerp__.py index a4c085df..5c1fe9b9 100644 --- a/web_widget_boolean_switch/__openerp__.py +++ b/web_widget_boolean_switch/__openerp__.py @@ -25,6 +25,9 @@ 'static/lib/bootstrap-switch/bootstrap-switch.js', 'static/src/js/web_widget_boolean_switch.js', ], + 'test': [ + 'static/test/web_widget_boolean_switch.js', + ], "css": [ 'static/lib/bootstrap-switch/bootstrap-switch.css', ], @@ -34,5 +37,139 @@ "demo": [ 'demo/res_users_view.xml', ], - 'description': """""", # TODO: copy README.rst + 'description': """ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +========================= +Web widget boolean switch +========================= + +This module add a widget ``boolean_switch`` to render boolean fields. One +of it's main features is to quick edit that field without enter in edit mode +from list view or form view. + + +Configuration +============= + +In the view (test on tree view and form view), you can declare any boolean +field using this widget. + +Example +------- + +``` + +``` + +Options +------- + +quick_edit +~~~~~~~~~~ + +extra +~~~~~ +``extra`` is used to set +`bootstrap-switch `_ options. + +*Available options*: + + * **size**: The checkbox size - default: `null` - values: null, 'mini', + 'small', 'normal', 'large' + * **animate**: Animate the switch - default: `true` + * **indeterminate**: Indeterminate state - default: `false` + * **inverse**: Inverse switch direction - default: `false` + * **onColor**: Color of the left side of the switch - default: `"primary"` - + values: 'primary', 'info', 'success', 'warning', 'danger', 'default' + * **offColor**: Color of the right side of the switch - default: `default` - + values: 'primary', 'info', 'success', 'warning', 'danger', 'default' + * **onText**: Text of the left side of the switch - default: `"ON"` + * **offText**: Text of the right side of the switch - default: `"OFF"` + * **labelText**: Text of the center handle of the switch - default: + `" "`, + * **handleWidth**: Width of the left and right sides in pixels - default: + `"auto"`, + * **labelWidth**: Width of the center handle in pixels - default: `"auto"` + * **baseClass**: Global class prefix - default: `"bootstrap-switch"` + * **wrapperClass**: Container element class(es) - default: `"wrapper"` + + +.. warning:: + + Those parameters are overwritten by this module or highly discouraged: + + * **radioAllOff**: Allow this radio button to be unchecked by the user - + default: `false` + * **state**: The checkbox state - default: `true` + * **disabled**: Disable state - default: `false` + * **readonly**: Readonly state - default: `false` + * **onInit**: Callback function to execute on initialization - default: + `function() {}`, + * **onSwitchChange**: Callback function to execute on switch state change - + default: `function() {}` + +attrs +----- + +This attribute is supported as expected! + +context +------- + +``context`` is sent to the ``write`` method of the field model in case of +special needs with the quick edition. + + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/162/7.0 + +Known issues / Roadmap +====================== + +* Manage Null values +* + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and +welcomed feedback `here `_. + + +Credits +======= + +Contributors +------------ + +* Pierre Verkest + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit http://odoo-community.org. + + """, } diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index fb47b9fd..a8eb54c6 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -18,22 +18,21 @@ openerp.web_widget_boolean_switch = function(instance){ var switchOptions = options.hasOwnProperty('extra') ? options.extra : {}; - _.extend(switchOptions, { - 'disabled': options.hasOwnProperty('disabled') ? - options.disabled : !this.quick_edit, - }); if(options.hasOwnProperty('onSwitchChange')){ switchOptions.onSwitchChange = options.onSwitchChange; } this.checkboxes.bootstrapSwitch(switchOptions); + this.set_disabled(options.hasOwnProperty('disabled') ? + options.disabled : !this.quick_edit); if(this.quick_edit && quick_edit_callback){ this.checkboxes.on('switchChange.bootstrapSwitch', quick_edit_callback); } }, set_value: function(value){ - // the third parameter tell if we should skip to fire evnets + // the third parameter tell if we should skip to fire events + // and force change the state whatever it's readonly or disabled this.checkboxes.bootstrapSwitch('state', value, true); }, set_readonly: function(value){ diff --git a/web_widget_boolean_switch/static/test/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/test/web_widget_boolean_switch.js new file mode 100644 index 00000000..fa7e9810 --- /dev/null +++ b/web_widget_boolean_switch/static/test/web_widget_boolean_switch.js @@ -0,0 +1,139 @@ +openerp.testing.section('web_widget_boolean_switch', + {'dependences': ['web.web_widget_boolean_switch'], + }, function(test){ + "use strict"; + var check_values = function (scratchpad, value, readonly, disabled, + message){ + var $container = scratchpad.children(); + var $input = $container.find('input'); + strictEqual($input[0].checked, value, message + " - Input value"); + strictEqual($input[0].readOnly && $input[0].readOnly ? true : false, + readonly, message + " - Input readonly"); + strictEqual($input[0].disabled && $input[0].disabled ? true : false, disabled, + message + " - Input disabled"); + + var prefix = 'bootstrap-switch-'; + ok($container[0].classList.contains(prefix + (value ? 'on' : 'off')), + message + " - Bootstrap-switch value class"); + strictEqual($container[0].classList.contains(prefix + "readonly"), + readonly, message + " - Bootstrap-switch readonly class"); + strictEqual($container[0].classList.contains(prefix + "disabled"), + disabled, message + " - Bootstrap-switch disabled class"); + + }; + + var init_check_values = function(instance, scratchpad, html, options, + checked, readonly, disabled, message){ + scratchpad.html(html); + var widget = new instance.web.BooleanSwitchWidget( + scratchpad.find('input'), options, null); + check_values(scratchpad, checked, readonly, disabled, message); + return widget; + }; + + test('BooleanSwitchWidget Class test method', function(instance, $scratchpad){ + + var numTest = 1; + var widget = init_check_values( + instance, $scratchpad, '', {}, + false, false, true, numTest++ + " - init values"); + + ok($scratchpad.children()[0].classList.contains('bootstrap-switch'), + "Basic bootstrap-switch init using BooleanSwitchWidget class"); + + widget.set_disabled(false); + check_values($scratchpad, false, false, false, + numTest++ + " - Enable"); + + widget.set_value(true); + check_values($scratchpad, true, false, false, + numTest++ + " - Set true"); + + widget.set_readonly(true); + check_values($scratchpad, true, true, false, + numTest++ + " - Set readonly"); + + widget.set_disabled(true); + check_values($scratchpad, true, true, true, + numTest++ + " - Disabled"); + + widget.set_value(false); + check_values($scratchpad, false, true, true, + numTest++ + " - set value whatever its Disabled and readonly"); + widget.set_readonly(false); + widget.set_value(true); + check_values($scratchpad, true, false, true, + numTest++ + " - set value whatever its Disabled"); + widget.set_disabled(false); + widget.set_readonly(true); + widget.set_value(false); + check_values($scratchpad, false, true, false, + numTest++ + " - set value whatever its readonly"); + }); + + test('BooleanSwitchWidget Class test init', function(instance, $scratchpad){ + var numTest = 1; + + init_check_values(instance, $scratchpad, + '', + {}, true, true, true, + numTest++ + " - init values disabled readonly checked"); + + init_check_values(instance, $scratchpad, + '', + {}, false, true, true, + numTest++ + " - init values disabled readonly"); + + init_check_values(instance, $scratchpad, + '', + {}, true, false, true, + numTest++ + " - init values disabled checked"); + + init_check_values(instance, $scratchpad, + '', + {'disabled': false}, true, true, false, + numTest++ + " - init values checked readonly"); + + init_check_values(instance, $scratchpad, + '', + {}, false, false, true, + numTest++ + " - By default input is disabled without any parameter"); + + init_check_values(instance, $scratchpad, + '', + {'disabled': false}, true, false, false, + numTest++ + " - init values checked"); + + init_check_values(instance, $scratchpad, + '', + {'disabled': false, 'quick_edit': true}, + false, true, false, + numTest++ + " - init values disabled readonly"); + + init_check_values(instance, $scratchpad, + '', + {'disabled': false}, false, false, false, + numTest++ + " - every thing is false"); + + init_check_values(instance, $scratchpad, + '', + {'quick_edit': true}, true, false, false, + numTest++ + " - quick edit enable widget"); + + init_check_values(instance, $scratchpad, + '', + {'quick_edit': true}, true, false, false, + numTest++ + " - quick edit enable widget case initial element is disabled"); + + init_check_values(instance, $scratchpad, + '', + {}, true, false, true, + numTest++ + " - By default widget is disabled test with checked"); + + init_check_values(instance, $scratchpad, + '', + {}, true, true, true, + numTest++ + " - By default widget is disabled test with checked and readonly"); + }); + +}); From a30452cdfbf83bd5d93ee19e9a850e85bb238d8c Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Tue, 6 Oct 2015 14:40:38 +0200 Subject: [PATCH 26/31] manage tabindex and autofocus + flake8 --- web_widget_boolean_switch/__openerp__.py | 6 ++++-- web_widget_boolean_switch/demo/res_users_view.xml | 3 ++- .../static/src/js/web_widget_boolean_switch.js | 10 ++++++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/web_widget_boolean_switch/__openerp__.py b/web_widget_boolean_switch/__openerp__.py index 5c1fe9b9..f4aeb8cb 100644 --- a/web_widget_boolean_switch/__openerp__.py +++ b/web_widget_boolean_switch/__openerp__.py @@ -65,7 +65,8 @@ Example widget="boolean_switch" attrs="{'readonly': [('login', '=', 'admin')]}" context="{'fake_parameter': 'foo'}" - options="{'quick_edit': True, 'extra': {'onText': 'Yes', 'offText': 'No'}}"/> + options="{'quick_edit': True, 'extra': {'onText': 'Yes', + 'offText': 'No'}}"/> ``` Options @@ -127,7 +128,8 @@ context special needs with the quick edition. -.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas +.. image:: https://odoo-community.org/website/image/ir.attachment/ + 5784_f2813bd/datas :alt: Try me on Runbot :target: https://runbot.odoo-community.org/runbot/162/7.0 diff --git a/web_widget_boolean_switch/demo/res_users_view.xml b/web_widget_boolean_switch/demo/res_users_view.xml index 1c9aca19..c1351c24 100644 --- a/web_widget_boolean_switch/demo/res_users_view.xml +++ b/web_widget_boolean_switch/demo/res_users_view.xml @@ -45,11 +45,12 @@ res.users.tree res.users - + diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index a8eb54c6..e5482202 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -170,11 +170,17 @@ openerp.web_widget_boolean_switch = function(instance){ }, _format: function (row_data, options, readonly) { - return _.str.sprintf('', + options = options ? options : {}; + var autofocus = this.hasOwnProperty('autofocus') ? true : false; + var tabindex = this.hasOwnProperty('tabindex') ? + parseInt(this.tabindex) : 0; + return _.str.sprintf('', row_data[this.id].value ? 'checked="checked"' : '', readonly ? 'readonly' : '', row_data.hasOwnProperty('id') && _.isNumber(row_data.id.value) ? - row_data.id.value : -1); + row_data.id.value : -1, + autofocus ? 'autofocus' : '', + 'tabindex="' + tabindex + '"'); } }); From 98e3ab1c4b88b0e3004d508f5f75f0bde6647062 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Tue, 6 Oct 2015 16:12:49 +0200 Subject: [PATCH 27/31] setup focus event + fix autofocus init --- .../static/src/js/web_widget_boolean_switch.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index e5482202..e2fefbf8 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -84,6 +84,7 @@ openerp.web_widget_boolean_switch = function(instance){ } }, this)); this.on("change:readonly", this, this.switcher_states); + this.setupFocus(this.$checkbox); this._super(); this.switcher_states.call(this); }, @@ -102,6 +103,10 @@ openerp.web_widget_boolean_switch = function(instance){ render_value: function() { this.switcher.set_value(this.get('value')); }, + focus: function() { + var input = this.$checkbox && this.$checkbox[0]; + return input ? input.focus() : false; + }, }); // Helper methods @@ -171,7 +176,8 @@ openerp.web_widget_boolean_switch = function(instance){ _format: function (row_data, options, readonly) { options = options ? options : {}; - var autofocus = this.hasOwnProperty('autofocus') ? true : false; + var autofocus = this.hasOwnProperty('autofocus') ? + this.autofocus : false; var tabindex = this.hasOwnProperty('tabindex') ? parseInt(this.tabindex) : 0; return _.str.sprintf('', From 30dfcbd216ea1119c87e3176992d2562fcee18f5 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Wed, 7 Oct 2015 15:37:23 +0200 Subject: [PATCH 28/31] Initialiaze widget when a row is redraw This appens when a field perform a name_get on each row each row are redraw independently --- .../src/js/web_widget_boolean_switch.js | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index e2fefbf8..d789adc4 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -201,6 +201,37 @@ openerp.web_widget_boolean_switch = function(instance){ }, }); + instance.web.ListView.List.include({ + init: function(){ + //This is the case when on each line, a request to name_get + //id done, this cause a record to be re-render though on change. + //So we have to overide the events as I haven't found any good hooks + this._super.apply(this, arguments); + var self = this; + this.records.unbind('change'); + this.record_callbacks.change = function (event, record, attribute, value, old_value) { + var $row; + if (attribute === 'id') { + if (old_value) { + throw new Error(_.str.sprintf( _t("Setting 'id' attribute on existing record %s"), + JSON.stringify(record.attributes) )); + } + self.dataset.add_ids([value], self.records.indexOf(record)); + // Set id on new record + $row = self.$current.children('[data-id=false]'); + } else { + $row = self.$current.children( + '[data-id=' + record.get('id') + ']'); + } + $row.replaceWith(self.render_record(record)); + self.afterRowChanged($row, record, attribute); + }; + this.records.bind('change', this.record_callbacks.change); + }, + afterRowChanged: function($row, record, attribute){ + apply_switcher(this.view, this.columns, $row); + }, + }); instance.web.ListView.include({ reload_record: function(record){ // in case of editable list, only update record is reloaded From 3068b3217a06d5d4c16f4da60bdafd1ad374aa31 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Mon, 19 Oct 2015 18:11:14 +0200 Subject: [PATCH 29/31] remove inexisted sequence value field in demo data on ir.ui.view --- web_widget_boolean_switch/demo/res_users_view.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/web_widget_boolean_switch/demo/res_users_view.xml b/web_widget_boolean_switch/demo/res_users_view.xml index c1351c24..d1c201e6 100644 --- a/web_widget_boolean_switch/demo/res_users_view.xml +++ b/web_widget_boolean_switch/demo/res_users_view.xml @@ -16,7 +16,6 @@ res.users.tree res.users - 20 Date: Mon, 14 Dec 2015 15:40:18 +0100 Subject: [PATCH 30/31] fix issue on form view when: quick edit the value, them move to edit mode the form, change the value then cancel the change, the value was keeping the initial values without taking account the quick edition. find by @JonathanNEMRY --- .../src/js/web_widget_boolean_switch.js | 1 + .../static/test/web_widget_boolean_switch.js | 106 ++++++++++++++---- 2 files changed, 87 insertions(+), 20 deletions(-) diff --git a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js index d789adc4..82191e25 100644 --- a/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/src/js/web_widget_boolean_switch.js @@ -81,6 +81,7 @@ openerp.web_widget_boolean_switch = function(instance){ model.call('write', [[id], values], {'context': this.build_context()}); this.internal_set_value(state, {'silent': true}); + this.getParent().datarecord[this.name] = state; } }, this)); this.on("change:readonly", this, this.switcher_states); diff --git a/web_widget_boolean_switch/static/test/web_widget_boolean_switch.js b/web_widget_boolean_switch/static/test/web_widget_boolean_switch.js index fa7e9810..645a597a 100644 --- a/web_widget_boolean_switch/static/test/web_widget_boolean_switch.js +++ b/web_widget_boolean_switch/static/test/web_widget_boolean_switch.js @@ -1,26 +1,92 @@ -openerp.testing.section('web_widget_boolean_switch', +openerp.testing.section('BooleanSwitchWidget.behaviors', + {dependences: ['web.web_widget_boolean_switch'], + rpc: 'mock', + templates: true, + }, function(test){ + test('BooleanSwitchWidget quick edit - enter in edit mode - cancel', + {asserts: 30}, function (instance, $fix, mock) { + + mock('demo:read', function () { + console.log("read data"); + return [{ id: 1, a: true, b: 'bar', c: 'baz' }]; + }); + mock('demo:fields_view_get', function () { + return { + type: 'form', + fields: { + a: {type: 'boolean', string: "A"}, + b: {type: 'char', string: "B"}, + c: {type: 'char', string: "C"} + }, + arch: '
' + + ' ' + + ' ' + + ' ' + + '', + }; + }); + var ds = new instance.web.DataSetStatic(null, 'demo', null, [1]); + ds.index = 0; + var form = new instance.web.FormView({}, ds, false, { + initial_mode: 'view', + disable_autofocus: false, + $buttons: $(), + $pager: $() + }); + var numTest = 1; + form.appendTo($fix); + var promise = form.do_show(); + check_values(form.$el.find(".oe_form_field_boolean_switch"), + true, false, false, + numTest++ + " - Init state: quick editable with true value"); + form.fields.a.switcher.checkboxes.click(); + check_values(form.$el.find('.oe_form_field_boolean_switch'), + false, false, false, + numTest++ + " - Quick edit to `false` value"); + form.to_edit_mode(); + check_values(form.$el.find('.oe_form_field_boolean_switch'), + false, false, false, + numTest++ + " - Move to edit mode value still false"); + form.fields.a.switcher.checkboxes.click(); + check_values(form.$el.find('.oe_form_field_boolean_switch'), + true, false, false, + numTest++ + " - edit to True"); + // remove class oe_form_dirty to avoid popup in unit test while canceling + form.$el.removeClass('oe_form_dirty'); + form.on_button_cancel.call(form); + check_values(form.$el.find('.oe_form_field_boolean_switch'), + false, false, false, + numTest++ + " - Cancel edit mode return still False"); + return promise; + + }); + +}); + +var check_values = function (scratchpad, value, readonly, disabled, + message){ + var $container = scratchpad.children(); + var $input = $container.find('input'); + strictEqual($input[0].checked, value, message + " - Input value"); + strictEqual($input[0].readOnly && $input[0].readOnly ? true : false, + readonly, message + " - Input readonly"); + strictEqual($input[0].disabled && $input[0].disabled ? true : false, disabled, + message + " - Input disabled"); + + var prefix = 'bootstrap-switch-'; + ok($container[0].classList.contains(prefix + (value ? 'on' : 'off')), + message + " - Bootstrap-switch value class"); + strictEqual($container[0].classList.contains(prefix + "readonly"), + readonly, message + " - Bootstrap-switch readonly class"); + strictEqual($container[0].classList.contains(prefix + "disabled"), + disabled, message + " - Bootstrap-switch disabled class"); + +}; + +openerp.testing.section('BooleanSwitchWidget.tests', {'dependences': ['web.web_widget_boolean_switch'], }, function(test){ "use strict"; - var check_values = function (scratchpad, value, readonly, disabled, - message){ - var $container = scratchpad.children(); - var $input = $container.find('input'); - strictEqual($input[0].checked, value, message + " - Input value"); - strictEqual($input[0].readOnly && $input[0].readOnly ? true : false, - readonly, message + " - Input readonly"); - strictEqual($input[0].disabled && $input[0].disabled ? true : false, disabled, - message + " - Input disabled"); - - var prefix = 'bootstrap-switch-'; - ok($container[0].classList.contains(prefix + (value ? 'on' : 'off')), - message + " - Bootstrap-switch value class"); - strictEqual($container[0].classList.contains(prefix + "readonly"), - readonly, message + " - Bootstrap-switch readonly class"); - strictEqual($container[0].classList.contains(prefix + "disabled"), - disabled, message + " - Bootstrap-switch disabled class"); - - }; var init_check_values = function(instance, scratchpad, html, options, checked, readonly, disabled, message){ From e751635e47cd1c93e3bb215d0c26512135edf2e0 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Wed, 13 Jan 2016 15:50:05 +0100 Subject: [PATCH 31/31] discourage indeterminate param as odoo do not manage Null value on boolean --- web_widget_boolean_switch/README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_widget_boolean_switch/README.rst b/web_widget_boolean_switch/README.rst index aee88be0..b9ddb18b 100644 --- a/web_widget_boolean_switch/README.rst +++ b/web_widget_boolean_switch/README.rst @@ -44,7 +44,6 @@ extra * **size**: The checkbox size - default: `null` - values: null, 'mini', 'small', 'normal', 'large' * **animate**: Animate the switch - default: `true` - * **indeterminate**: Indeterminate state - default: `false` * **inverse**: Inverse switch direction - default: `false` * **onColor**: Color of the left side of the switch - default: `"primary"` - values: 'primary', 'info', 'success', 'warning', 'danger', 'default' @@ -74,6 +73,7 @@ extra `function() {}`, * **onSwitchChange**: Callback function to execute on switch state change - default: `function() {}` + * **indeterminate**: Indeterminate state - default: `false` attrs -----