diff --git a/web_widget_color/README.rst b/web_widget_color/README.rst
new file mode 100644
index 000000000..439c8fba0
--- /dev/null
+++ b/web_widget_color/README.rst
@@ -0,0 +1,100 @@
+Color widget for Odoo web client
+================================
+
+This module aims to add a color picker to Odoo.
+
+It's a `jsColor `_ lib integration.
+
+
+Features
+========
+
+* The picker allow the user to quickly select a color on edit mode
+
+ |picker|
+
+ .. note::
+
+ Notice how html code and the background color is updating when selecting a color.
+
+
+* Display the color on form view when you are not editing it
+
+ |formview|
+
+* Display the color on list view to quickly find what's wrong!
+
+ |listview|
+
+
+Usage
+=====
+
+You need to declare a char field::
+
+ color = fields.Char(
+ string="Color",
+ help="Choose your color"
+ )
+
+
+In the view declaration, put widget='color' attribute in the field tag::
+
+ ...
+
+
+ ...
+
+ ...
+
+
+ ...
+
+
+
+ ...
+
+.. |picker| image:: ./images/picker.png
+.. |formview| image:: ./images/form_view.png
+.. |listview| image:: ./images/list_view.png
+
+.. 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/11.0
+
+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.
+
+Credits
+=======
+
+Contributors
+------------
+
+* Adil Houmadi
+* Enric Tobella
+* Nicolas JEUDY (Sudokeys)
+
+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 https://odoo-community.org.
diff --git a/web_widget_color/__init__.py b/web_widget_color/__init__.py
new file mode 100644
index 000000000..ec51c5a2b
--- /dev/null
+++ b/web_widget_color/__init__.py
@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+#
diff --git a/web_widget_color/__manifest__.py b/web_widget_color/__manifest__.py
new file mode 100644
index 000000000..ebcd0f408
--- /dev/null
+++ b/web_widget_color/__manifest__.py
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+# Odoo, Open Source Web Widget Color
+# Copyright (C) 2012 Savoir-faire Linux ().
+# Copyright (C) 2014 Anybox
+# Copyright (C) 2015 Taktik SA
+#
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).#
+{
+ 'name': "Web Widget Color",
+ 'category': "web",
+ 'version': "11.0.1.0.0",
+ "author": "Savoir-faire Linux, "
+ "Anybox, "
+ "Taktik SA, "
+ "Sudokeys, "
+ "Odoo Community Association (OCA)",
+ 'depends': ['base', 'web'],
+ 'data': [
+ 'view/web_widget_color_view.xml'
+ ],
+ 'qweb': [
+ 'static/src/xml/widget.xml',
+ ],
+ 'license': 'AGPL-3',
+ 'auto_install': False,
+ 'installable': True,
+ 'web_preload': True,
+}
diff --git a/web_widget_color/images/form_view.png b/web_widget_color/images/form_view.png
new file mode 100644
index 000000000..db1026b94
Binary files /dev/null and b/web_widget_color/images/form_view.png differ
diff --git a/web_widget_color/images/list_view.png b/web_widget_color/images/list_view.png
new file mode 100644
index 000000000..f4965fd5e
Binary files /dev/null and b/web_widget_color/images/list_view.png differ
diff --git a/web_widget_color/images/picker.png b/web_widget_color/images/picker.png
new file mode 100644
index 000000000..4c3f5e079
Binary files /dev/null and b/web_widget_color/images/picker.png differ
diff --git a/web_widget_color/static/description/icon.png b/web_widget_color/static/description/icon.png
new file mode 100644
index 000000000..540f72db9
Binary files /dev/null and b/web_widget_color/static/description/icon.png differ
diff --git a/web_widget_color/static/lib/jscolor/arrow.gif b/web_widget_color/static/lib/jscolor/arrow.gif
new file mode 100644
index 000000000..246478a86
Binary files /dev/null and b/web_widget_color/static/lib/jscolor/arrow.gif differ
diff --git a/web_widget_color/static/lib/jscolor/cross.gif b/web_widget_color/static/lib/jscolor/cross.gif
new file mode 100644
index 000000000..0ee9c7ac5
Binary files /dev/null and b/web_widget_color/static/lib/jscolor/cross.gif differ
diff --git a/web_widget_color/static/lib/jscolor/demo.html b/web_widget_color/static/lib/jscolor/demo.html
new file mode 100644
index 000000000..cb8606649
--- /dev/null
+++ b/web_widget_color/static/lib/jscolor/demo.html
@@ -0,0 +1,12 @@
+
+
+ jscolor demo
+
+
+
+
+
+ Click here:
+
+
+
diff --git a/web_widget_color/static/lib/jscolor/hs.png b/web_widget_color/static/lib/jscolor/hs.png
new file mode 100644
index 000000000..3d94486ce
Binary files /dev/null and b/web_widget_color/static/lib/jscolor/hs.png differ
diff --git a/web_widget_color/static/lib/jscolor/hv.png b/web_widget_color/static/lib/jscolor/hv.png
new file mode 100644
index 000000000..1c5e01f8b
Binary files /dev/null and b/web_widget_color/static/lib/jscolor/hv.png differ
diff --git a/web_widget_color/static/lib/jscolor/jscolor.js b/web_widget_color/static/lib/jscolor/jscolor.js
new file mode 100644
index 000000000..659ab2080
--- /dev/null
+++ b/web_widget_color/static/lib/jscolor/jscolor.js
@@ -0,0 +1,1010 @@
+/**
+ * jscolor, JavaScript Color Picker
+ *
+ * @version 1.4.4
+ * @license GNU Lesser General Public License, https://www.gnu.org/copyleft/lesser.html
+ * @author Jan Odvarko, http://odvarko.cz
+ * @created 2008-06-15
+ * @updated 2014-12-09
+ * @link http://jscolor.com
+ */
+
+
+var jscolor = {
+
+
+ dir : '', // location of jscolor directory (leave empty to autodetect)
+ bindClass : 'color', // class name
+ binding : true, // automatic binding via
+ preloading : true, // use image preloading?
+
+
+ install : function() {
+ jscolor.addEvent(window, 'load', jscolor.init);
+ },
+
+
+ init : function() {
+ if(jscolor.binding) {
+ jscolor.bind();
+ }
+ if(jscolor.preloading) {
+ jscolor.preload();
+ }
+ },
+
+
+ getDir : function() {
+ if(!jscolor.dir) {
+ var detected = jscolor.detectDir();
+ jscolor.dir = detected!==false ? detected : 'jscolor/';
+ }
+ return jscolor.dir;
+ },
+
+
+ detectDir : function() {
+ var base = location.href;
+
+ var e = document.getElementsByTagName('base');
+ for(var i=0; i vs[a] ?
+ (-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) :
+ tp[a],
+ -vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ?
+ (-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) :
+ (tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c)
+ ];
+ }
+ drawPicker(pp[a], pp[b]);
+ }
+ };
+
+
+ this.importColor = function() {
+ if(!valueElement) {
+ this.exportColor();
+ } else {
+ if(!this.adjust) {
+ if(!this.fromString(valueElement.value, leaveValue)) {
+ styleElement.style.backgroundImage = styleElement.jscStyle.backgroundImage;
+ styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor;
+ styleElement.style.color = styleElement.jscStyle.color;
+ this.exportColor(leaveValue | leaveStyle);
+ }
+ } else if(!this.required && /^\s*$/.test(valueElement.value)) {
+ valueElement.value = '';
+ styleElement.style.backgroundImage = styleElement.jscStyle.backgroundImage;
+ styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor;
+ styleElement.style.color = styleElement.jscStyle.color;
+ this.exportColor(leaveValue | leaveStyle);
+
+ } else if(this.fromString(valueElement.value)) {
+ // OK
+ } else {
+ this.exportColor();
+ }
+ }
+ };
+
+
+ this.exportColor = function(flags) {
+ if(!(flags & leaveValue) && valueElement) {
+ var value = this.toString();
+ if(this.caps) { value = value.toUpperCase(); }
+ if(this.hash) { value = '#'+value; }
+ valueElement.value = value;
+ }
+ if(!(flags & leaveStyle) && styleElement) {
+ styleElement.style.backgroundImage = "none";
+ styleElement.style.backgroundColor =
+ '#'+this.toString();
+ styleElement.style.color =
+ 0.213 * this.rgb[0] +
+ 0.715 * this.rgb[1] +
+ 0.072 * this.rgb[2]
+ < 0.5 ? '#FFF' : '#000';
+ }
+ if(!(flags & leavePad) && isPickerOwner()) {
+ redrawPad();
+ }
+ if(!(flags & leaveSld) && isPickerOwner()) {
+ redrawSld();
+ }
+ };
+
+
+ this.fromHSV = function(h, s, v, flags) { // null = don't change
+ if(h !== null) { h = Math.max(0.0, this.minH, Math.min(6.0, this.maxH, h)); }
+ if(s !== null) { s = Math.max(0.0, this.minS, Math.min(1.0, this.maxS, s)); }
+ if(v !== null) { v = Math.max(0.0, this.minV, Math.min(1.0, this.maxV, v)); }
+
+ this.rgb = HSV_RGB(
+ h===null ? this.hsv[0] : (this.hsv[0]=h),
+ s===null ? this.hsv[1] : (this.hsv[1]=s),
+ v===null ? this.hsv[2] : (this.hsv[2]=v)
+ );
+
+ this.exportColor(flags);
+ };
+
+
+ this.fromRGB = function(r, g, b, flags) { // null = don't change
+ if(r !== null) { r = Math.max(0.0, Math.min(1.0, r)); }
+ if(g !== null) { g = Math.max(0.0, Math.min(1.0, g)); }
+ if(b !== null) { b = Math.max(0.0, Math.min(1.0, b)); }
+
+ var hsv = RGB_HSV(
+ r===null ? this.rgb[0] : r,
+ g===null ? this.rgb[1] : g,
+ b===null ? this.rgb[2] : b
+ );
+ if(hsv[0] !== null) {
+ this.hsv[0] = Math.max(0.0, this.minH, Math.min(6.0, this.maxH, hsv[0]));
+ }
+ if(hsv[2] !== 0) {
+ this.hsv[1] = hsv[1]===null ? null : Math.max(0.0, this.minS, Math.min(1.0, this.maxS, hsv[1]));
+ }
+ this.hsv[2] = hsv[2]===null ? null : Math.max(0.0, this.minV, Math.min(1.0, this.maxV, hsv[2]));
+
+ // update RGB according to final HSV, as some values might be trimmed
+ var rgb = HSV_RGB(this.hsv[0], this.hsv[1], this.hsv[2]);
+ this.rgb[0] = rgb[0];
+ this.rgb[1] = rgb[1];
+ this.rgb[2] = rgb[2];
+
+ this.exportColor(flags);
+ };
+
+
+ this.fromString = function(hex, flags) {
+ var m = hex.match(/^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i);
+ if(!m) {
+ return false;
+ } else {
+ if(m[1].length === 6) { // 6-char notation
+ this.fromRGB(
+ parseInt(m[1].substr(0,2),16) / 255,
+ parseInt(m[1].substr(2,2),16) / 255,
+ parseInt(m[1].substr(4,2),16) / 255,
+ flags
+ );
+ } else { // 3-char notation
+ this.fromRGB(
+ parseInt(m[1].charAt(0)+m[1].charAt(0),16) / 255,
+ parseInt(m[1].charAt(1)+m[1].charAt(1),16) / 255,
+ parseInt(m[1].charAt(2)+m[1].charAt(2),16) / 255,
+ flags
+ );
+ }
+ return true;
+ }
+ };
+
+
+ this.toString = function() {
+ return (
+ (0x100 | Math.round(255*this.rgb[0])).toString(16).substr(1) +
+ (0x100 | Math.round(255*this.rgb[1])).toString(16).substr(1) +
+ (0x100 | Math.round(255*this.rgb[2])).toString(16).substr(1)
+ );
+ };
+
+
+ function RGB_HSV(r, g, b) {
+ var n = Math.min(Math.min(r,g),b);
+ var v = Math.max(Math.max(r,g),b);
+ var m = v - n;
+ if(m === 0) { return [ null, 0, v ]; }
+ var h = r===n ? 3+(b-g)/m : (g===n ? 5+(r-b)/m : 1+(g-r)/m);
+ return [ h===6?0:h, m/v, v ];
+ }
+
+
+ function HSV_RGB(h, s, v) {
+ if(h === null) { return [ v, v, v ]; }
+ var i = Math.floor(h);
+ var f = i%2 ? h-i : 1-(h-i);
+ var m = v * (1 - s);
+ var n = v * (1 - s*f);
+ switch(i) {
+ case 6:
+ case 0: return [v,n,m];
+ case 1: return [n,v,m];
+ case 2: return [m,v,n];
+ case 3: return [m,n,v];
+ case 4: return [n,m,v];
+ case 5: return [v,m,n];
+ }
+ }
+
+
+ function removePicker() {
+ delete jscolor.picker.owner;
+ document.getElementsByTagName('body')[0].removeChild(jscolor.picker.boxB);
+ }
+
+
+ function drawPicker(x, y) {
+ if(!jscolor.picker) {
+ jscolor.picker = {
+ box : document.createElement('div'),
+ boxB : document.createElement('div'),
+ pad : document.createElement('div'),
+ padB : document.createElement('div'),
+ padM : document.createElement('div'),
+ sld : document.createElement('div'),
+ sldB : document.createElement('div'),
+ sldM : document.createElement('div'),
+ btn : document.createElement('div'),
+ btnS : document.createElement('span'),
+ btnT : document.createTextNode(THIS.pickerCloseText)
+ };
+ for(var i=0,segSize=4; i
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web_widget_color/view/web_widget_color_view.xml b/web_widget_color/view/web_widget_color_view.xml
new file mode 100644
index 000000000..82300a007
--- /dev/null
+++ b/web_widget_color/view/web_widget_color_view.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+