diff options
Diffstat (limited to 'addons/web/static/src')
| -rw-r--r-- | addons/web/static/src/js/widgets/colorpicker.js | 78 | ||||
| -rw-r--r-- | addons/web/static/src/scss/colorpicker.scss | 68 | ||||
| -rw-r--r-- | addons/web/static/src/xml/colorpicker.xml | 60 |
3 files changed, 123 insertions, 83 deletions
diff --git a/addons/web/static/src/js/widgets/colorpicker.js b/addons/web/static/src/js/widgets/colorpicker.js index 87a46e77a2f..6b17431259a 100644 --- a/addons/web/static/src/js/widgets/colorpicker.js +++ b/addons/web/static/src/js/widgets/colorpicker.js @@ -12,6 +12,8 @@ var ColorpickerWidget = Widget.extend({ xmlDependencies: ['/web/static/src/xml/colorpicker.xml'], template: 'Colorpicker', events: { + 'click': '_onClick', + 'keypress': '_onKeypress', 'mousedown .o_color_pick_area': '_onMouseDownPicker', 'mousedown .o_color_slider': '_onMouseDownSlider', 'mousedown .o_opacity_slider': '_onMouseDownOpacitySlider', @@ -39,18 +41,22 @@ var ColorpickerWidget = Widget.extend({ this.sliderFlag = false; this.opacitySliderFlag = false; this.colorComponents = {}; - - var self = this; - var $body = $(document.body); - $body.on('mousemove.colorpicker', _.throttle(function (ev) { - self._onMouseMovePicker(ev); - self._onMouseMoveSlider(ev); - self._onMouseMoveOpacitySlider(ev); - }, 10)); - $body.on('mouseup.colorpicker', _.throttle(function (ev) { - self.pickerFlag = false; - self.sliderFlag = false; - self.opacitySliderFlag = false; + this.uniqueId = _.uniqueId('colorpicker'); + + // Needs to be bound on document to work in all possible cases. + const $document = $(document); + $document.on(`mousemove.${this.uniqueId}`, _.throttle((ev) => { + this._onMouseMovePicker(ev); + this._onMouseMoveSlider(ev); + this._onMouseMoveOpacitySlider(ev); + }, 50)); + $document.on(`mouseup.${this.uniqueId}`, _.throttle((ev) => { + if (this.pickerFlag || this.sliderFlag || this.opacitySliderFlag) { + this._colorSelected(); + } + this.pickerFlag = false; + this.sliderFlag = false; + this.opacitySliderFlag = false; }, 10)); this.options = _.clone(options); @@ -66,12 +72,17 @@ var ColorpickerWidget = Widget.extend({ this.$opacitySlider = this.$('.o_opacity_slider'); this.$opacitySliderPointer = this.$('.o_opacity_pointer'); + const resizeObserver = new window.ResizeObserver(() => { + this._updateUI(); + }); + resizeObserver.observe(this.el); + var defaultColor = this.options.defaultColor || '#FF0000'; var rgba = ColorpickerWidget.convertCSSColorToRgba(defaultColor); if (rgba) { this._updateRgba(rgba.red, rgba.green, rgba.blue, rgba.opacity); } - this._updateUI(); + this.previewActive = true; return this._super.apply(this, arguments); }, /** @@ -79,7 +90,7 @@ var ColorpickerWidget = Widget.extend({ */ destroy: function () { this._super.apply(this, arguments); - $(document.body).off('.colorpicker'); + $(document).off(`.${this.uniqueId}`); }, //-------------------------------------------------------------------------- @@ -207,6 +218,14 @@ var ColorpickerWidget = Widget.extend({ this._updateCssColor(); }, /** + * Trigger an event to annonce that the widget value has changed + * + * @private + */ + _colorSelected: function () { + this.trigger_up('colorpicker_select', this.colorComponents); + }, + /** * Updates css color representation. * * @private @@ -219,6 +238,9 @@ var ColorpickerWidget = Widget.extend({ _.extend(this.colorComponents, {cssColor: ColorpickerWidget.convertRgbaToCSSColor(r, g, b, a)} ); + if (this.previewActive) { + this.trigger_up('colorpicker_preview', this.colorComponents); + } }, //-------------------------------------------------------------------------- @@ -226,6 +248,26 @@ var ColorpickerWidget = Widget.extend({ //-------------------------------------------------------------------------- /** + * @private + * @param {Event} ev + */ + _onKeypress: function (ev) { + if (ev.charCode === $.ui.keyCode.ENTER) { + if (ev.target.tagName === 'INPUT') { + this._onChangeInputs(ev); + } + ev.preventDefault(); + this.trigger_up('enter_key_color_colorpicker'); + } + }, + /** + * @param {Event} ev + */ + _onClick: function (ev) { + ev.originalEvent.__isColorpickerClick = true; + $(ev.target).find('> .o_opacity_pointer, > .o_slider_pointer, > .o_picker_pointer').addBack('.o_opacity_pointer, .o_slider_pointer, .o_picker_pointer').focus(); + }, + /** * Updates color when the user starts clicking on the picker. * * @private @@ -233,6 +275,7 @@ var ColorpickerWidget = Widget.extend({ */ _onMouseDownPicker: function (ev) { this.pickerFlag = true; + ev.preventDefault(); this._onMouseMovePicker(ev); }, /** @@ -265,6 +308,7 @@ var ColorpickerWidget = Widget.extend({ */ _onMouseDownSlider: function (ev) { this.sliderFlag = true; + ev.preventDefault(); this._onMouseMoveSlider(ev); }, /** @@ -293,6 +337,7 @@ var ColorpickerWidget = Widget.extend({ */ _onMouseDownOpacitySlider: function (ev) { this.opacitySliderFlag = true; + ev.preventDefault(); this._onMouseMoveOpacitySlider(ev); }, /** @@ -344,6 +389,7 @@ var ColorpickerWidget = Widget.extend({ break; } this._updateUI(); + this._colorSelected(); }, }); @@ -598,7 +644,9 @@ const ColorpickerDialog = Dialog.extend({ */ start: function () { const proms = [this._super(...arguments)]; - this.colorPicker = new ColorpickerWidget(this, this.options); + this.colorPicker = new ColorpickerWidget(this, _.extend({ + colorPreview: true, + }, this.options)); proms.push(this.colorPicker.appendTo(this.$el)); return Promise.all(proms); }, diff --git a/addons/web/static/src/scss/colorpicker.scss b/addons/web/static/src/scss/colorpicker.scss index ab8d2fb4a90..c53b31198d4 100644 --- a/addons/web/static/src/scss/colorpicker.scss +++ b/addons/web/static/src/scss/colorpicker.scss @@ -2,8 +2,8 @@ .o_colorpicker_widget { .o_color_pick_area { position: relative; - width: 200px; - height: 200px; + width: 79%; + height: 125px; background-image: linear-gradient(to bottom, hsl(0, 0%, 100%) 0%, hsla(0, 0%, 100%, 0) 50%, hsla(0, 0%, 0%, 0) 50%, hsl(0, 0%, 0%) 100%), linear-gradient(to right, hsl(0, 0%, 50%) 0%, hsla(0, 0%, 50%, 0) 100%); cursor: crosshair; @@ -18,14 +18,15 @@ } .o_color_slider { position: relative; - width: 18px; - height: 200px; + margin-left: 2.5%; + width: 4%; + height: 125px; background: linear-gradient(#F00 0%, #FF0 16.66%, #0F0 33.33%, #0FF 50%, #00F 66.66%, #F0F 83.33%, #F00 100%); cursor: pointer; .o_slider_pointer { - @include o-position-absolute($left: -4px); - width: 23px; + @include o-position-absolute($left: -100%); + width: 300%; height: 6px; border: 1px solid white; box-shadow: 0px 0px 2px 1px gray('600'); @@ -33,13 +34,14 @@ } .o_opacity_slider { position: relative; - width: 18px; - height: 200px; + margin-left: 5%; + width: 4%; + height: 125px; cursor: pointer; .o_opacity_pointer { - @include o-position-absolute($left: -4px); - width: 23px; + @include o-position-absolute($left: -100%); + width: 300%; height: 6px; border: 1px solid white; box-shadow: 0px 0px 2px 1px gray('600'); @@ -52,34 +54,38 @@ background-image: url('/web_editor/static/src/img/transparent.png'); } } + .o_color_picker_inputs { + padding-top: 3px; + font-size: 12px; display: flex; - flex-direction: column; - & > .form-row { - flex: 1; - .col { - display: flex; - flex-direction: column; - justify-content: space-around; - } - } + .o_color_preview_parent { + height: 20px; + width: 30px; background-image: url('/web_editor/static/src/img/transparent.png'); + .o_color_preview { + height: inherit; + display: block; + } } - .o_color_preview { - padding: 0.375rem 1.2rem; + .o_hex_div { + width: 38%; + display: flex; + border: 1px solid; + margin-right: 2%; } - .form-group { - margin-bottom: 0.3rem; - label { - margin-bottom: 0px; - font-size: 0.7rem; - font-weight: bold; - } + .o_rgba_div { + width: 60%; + border: 1px solid; + display: flex; } - .form-control { - height: 24px !important; - font-weight: bold; + input { + width: 100%; + border: none; + height: 18px; + background-color: inherit; + color: inherit; } } } diff --git a/addons/web/static/src/xml/colorpicker.xml b/addons/web/static/src/xml/colorpicker.xml index 957bef83146..7fb81da8711 100644 --- a/addons/web/static/src/xml/colorpicker.xml +++ b/addons/web/static/src/xml/colorpicker.xml @@ -3,44 +3,30 @@ <t t-name="Colorpicker"> <div class="o_colorpicker_widget"> - <div class="row"> - <div class="col-12"> - <div class="o_color_pick_area d-inline-block border"> - <div class="o_picker_pointer rounded-circle" /> - </div> - <div class="o_color_slider d-inline-block ml-2 border"> - <div class="o_slider_pointer" /> - </div> - <div class="o_opacity_slider d-inline-block ml-2 border" t-if="!widget.options.noTransparency"> - <div class="o_opacity_pointer" /> - </div> + <div class="o_color_pick_area d-inline-block border" t-att-style="widget.options.noTransparency ? 'width: 89%;' : None"> + <div class="o_picker_pointer rounded-circle" tabindex="-1"/> + </div> + <div class="o_color_slider d-inline-block border"> + <div class="o_slider_pointer" tabindex="-1"/> + </div> + <div class="o_opacity_slider d-inline-block border" t-if="!widget.options.noTransparency"> + <div class="o_opacity_pointer" tabindex="-1"/> + </div> + <div class="o_color_picker_inputs"> + <div t-if="widget.options.colorPreview" class="o_color_preview_parent"> + <span class="rounded-0 o_color_preview"/> + </div> + <div class="o_hex_div"><input type="text" class="o_hex_input" data-color-method="hex" size="1"/>hex</div> + <div class="o_rgba_div"> + <input type="text" class="o_red_input" data-color-method="rgb" size="1"/> + <input type="text" class="o_green_input" data-color-method="rgb" size="1"/> + <input type="text" class="o_blue_input" data-color-method="rgb" size="1"/> + <t t-if="!widget.options.noTransparency"> + <input type="text" class="o_opacity_input" data-color-method="opacity" size="1"/> + RGBA + </t> + <t t-else="">RGB</t> </div> - <form class="col-12 o_color_picker_inputs"> - <div class="input-group"> - <div class="input-group-prepend"> - <span class="input-group-text rounded-0 o_color_preview" /> - </div> - <input type="text" class="form-control o_hex_input" data-color-method="hex" /> - </div> - <div class="form-row mt-2"> - <div class="col form-group"> - <label for="red">Red</label> - <input type="text" class="form-control o_red_input" data-color-method="rgb" id="red" /> - </div> - <div class="col form-group"> - <label for="green">Green</label> - <input type="text" class="form-control o_green_input" data-color-method="rgb" id="green" /> - </div> - <div class="col form-group"> - <label for="blue">Blue</label> - <input type="text" class="form-control o_blue_input" data-color-method="rgb" id="blue" /> - </div> - <div class="col form-group" t-if="!widget.options.noTransparency"> - <label for="opacity">Opacity %</label> - <input type="text" class="form-control o_opacity_input" data-color-method="opacity" id="opacity" /> - </div> - </div> - </form> </div> </div> </t> |
