diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..a163f89
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,104 @@
+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|
+
+
+Requirements
+============
+
+This module has been ported to 8.0
+
+
+Usage
+=====
+
+You need to declare a char field of at least size 7::
+
+ _columns = {
+ 'color': fields.char(
+ u"Couleur",
+ help=u"Toutes couleur valid css, exemple blue ou #f57900"
+ ),
+ }
+
+ OR
+
+ 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
+
+
+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
+------------
+
+* Adil Houmadi
+
+Maintainer
+----------
+
+.. image:: http://odoo-community.org/logo.png
+ :alt: Odoo Community Association
+ :target: http://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/__init__.py b/__init__.py
new file mode 100644
index 0000000..c18661e
--- /dev/null
+++ b/__init__.py
@@ -0,0 +1,25 @@
+# -*- encoding: utf-8 -*-
+############################################################################
+#
+# Odoo, Open Source Web Color
+# Copyright (C) 2012 Savoir-faire Linux ().
+# Copyright (C) 2014 Anybox
+# Copyright (C) 2015 Taktik SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# @author Étienne Beaudry Auger
+# @author Adil Houmadi
+#
+##############################################################################
diff --git a/__openerp__.py b/__openerp__.py
new file mode 100644
index 0000000..529c27d
--- /dev/null
+++ b/__openerp__.py
@@ -0,0 +1,45 @@
+# -*- encoding: utf-8 -*-
+############################################################################
+#
+# Odoo, Open Source Web Widget Color
+# Copyright (C) 2012 Savoir-faire Linux ().
+# Copyright (C) 2014 Anybox
+# Copyright (C) 2015 Taktik SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# @author Étienne Beaudry Auger
+# @author Adil Houmadi
+#
+##############################################################################
+{
+ 'name': "Web Widget Color",
+ 'category': "web",
+ 'version': "8.0.1.0.0",
+ "author": "Savoir-faire Linux, "
+ "Anybox, "
+ "Taktik SA, "
+ "Odoo Community Association (OCA)",
+ 'depends': ['base', 'web'],
+ 'data': [
+ 'view/web_widget_color_view.xml'
+ ],
+ 'qweb': [
+ 'static/src/xml/widget.xml',
+ ],
+ 'auto_install': False,
+ 'installable': True,
+ 'web_preload': True,
+ 'license': 'GPL-3 or any later version',
+}
diff --git a/i18n/web_widget_color.pot b/i18n/web_widget_color.pot
new file mode 100644
index 0000000..386b255
--- /dev/null
+++ b/i18n/web_widget_color.pot
@@ -0,0 +1,14 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 8.0\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
diff --git a/images/form_view.png b/images/form_view.png
new file mode 100644
index 0000000..db1026b
Binary files /dev/null and b/images/form_view.png differ
diff --git a/images/list_view.png b/images/list_view.png
new file mode 100644
index 0000000..f4965fd
Binary files /dev/null and b/images/list_view.png differ
diff --git a/images/picker.png b/images/picker.png
new file mode 100644
index 0000000..4c3f5e0
Binary files /dev/null and b/images/picker.png differ
diff --git a/static/description/icon.png b/static/description/icon.png
new file mode 100644
index 0000000..540f72d
Binary files /dev/null and b/static/description/icon.png differ
diff --git a/static/lib/jscolor/arrow.gif b/static/lib/jscolor/arrow.gif
new file mode 100644
index 0000000..246478a
Binary files /dev/null and b/static/lib/jscolor/arrow.gif differ
diff --git a/static/lib/jscolor/cross.gif b/static/lib/jscolor/cross.gif
new file mode 100644
index 0000000..0ee9c7a
Binary files /dev/null and b/static/lib/jscolor/cross.gif differ
diff --git a/static/lib/jscolor/demo.html b/static/lib/jscolor/demo.html
new file mode 100644
index 0000000..cb86066
--- /dev/null
+++ b/static/lib/jscolor/demo.html
@@ -0,0 +1,12 @@
+
+
+ jscolor demo
+
+
+
+
+
+ Click here:
+
+
+
diff --git a/static/lib/jscolor/hs.png b/static/lib/jscolor/hs.png
new file mode 100644
index 0000000..3d94486
Binary files /dev/null and b/static/lib/jscolor/hs.png differ
diff --git a/static/lib/jscolor/hv.png b/static/lib/jscolor/hv.png
new file mode 100644
index 0000000..1c5e01f
Binary files /dev/null and b/static/lib/jscolor/hv.png differ
diff --git a/static/lib/jscolor/jscolor.js b/static/lib/jscolor/jscolor.js
new file mode 100644
index 0000000..47c8961
--- /dev/null
+++ b/static/lib/jscolor/jscolor.js
@@ -0,0 +1,1010 @@
+/**
+ * jscolor, JavaScript Color Picker
+ *
+ * @version 1.4.4
+ * @license GNU Lesser General Public License, http://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 0 && $input.val()) {
+ var val = $input.val();
+ var isOk = /^#[0-9A-F]{6}$/i.test(val);
+ if (!isOk) {
+ return false;
+ }
+ try {
+ this.parse_value(this.$('input').val(), '');
+ return true;
+ } catch (e) {
+ return false;
+ }
+ }
+ return true;
+ },
+ render_value: function () {
+ var show_value = this.format_value(this.get('value'), '');
+ if (!this.get("effective_readonly")) {
+ var $input = this.$el.find('input');
+ $input.val(show_value);
+ $input.css("background-color", show_value)
+ jscolor.init(this.$el[0]);
+ } else {
+ this.$(".oe_form_char_content").text(show_value);
+ this.$('div').css("background-color", show_value)
+ }
+ }
+ });
+
+ /*
+ * Init jscolor for each editable mode on view form
+ */
+ instance.web.FormView.include({
+ to_edit_mode: function () {
+ this._super();
+ jscolor.init(this.$el[0]);
+ }
+ });
+};
diff --git a/static/src/xml/widget.xml b/static/src/xml/widget.xml
new file mode 100644
index 0000000..79c9ad7
--- /dev/null
+++ b/static/src/xml/widget.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/view/web_widget_color_view.xml b/view/web_widget_color_view.xml
new file mode 100644
index 0000000..7c2c8d0
--- /dev/null
+++ b/view/web_widget_color_view.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file