mirror of
https://github.com/OCA/web.git
synced 2025-02-22 13:21:25 +02:00
[MIG] web_widget_slick: Migrate to v10
* Add local slick files to use instead of CDN
* Override CSS to display widget correctly
* Adjust arrow button size/placement
* Bump version
* Rename __openerp__.py -> __manifest__.py
* Rename widget_slick.js -> web_widget_slick.js
* Update copyright, license (AGPL -> LGPL)
* Update readme
* Correct eslint errors
* Change module name in various places for consistency
* Improve styling of widget arrows, dots
* Change css -> less
* Remove unneeded slick files
* Copyright 2017 -> 2016-2017
* Add OCA to authors
* Use OCA icon
* Fix readme
* Clean up assets
* Fix file permissions
* Update readme with reference to example module
* Fix formatting error, incorrect link
* Add javascript tests
* Add note to readme about functional testing with example module
* Fix/cleanup javascript
* Fix destroy_content() method
* Move slide navigation out of slide addition loop
* Remove unused variables
* Remove unneeded DOM append
* Reorganize files/directories
* Adjust template tags (templates -> template)
* Add slick-field class to field template instead of using jQuery
* Misc cleanup
* Adjust breakpoint settings to show fewer images by default
* Enable adaptiveHeight by default
* Add .img and .img-responsive classes to images
* Fix dragging issues by preventing default mousedown and
touchstart event behavior
* Set swipeToSlide default to true
* Change how slick slides are populated to allow grid mode
* Fix issue causing carousel images to display improperly in some
situations
* Add better functional testing instructions to readme
* Add roadmap to readme
* Make minor styling changes
* Fix issue with template loading w/ PhantomJS
* Clean up template, use css class provided by widget
* Remove unneeded dependency from tests
* Break up render_value method
* Break up destroy_content method
* Add unslicking to destroy_content, add test
* Clean up qweb template formatting
* Fix indentation
* Change widget name
* Add Slick copyright information
* Add padding left/right, move arrows in to avoid clipping when
widget not in a sheet tag
* Apply dot and arrow styles only when needed
* Add _resizeCarousel() and related methods to ensure accurate
carousel sizing in various views
* Resize carousel on core.bus resize
* Account for differences in group layouts and labels,
sheet/no-sheet layouts
* Adjust, clean up less
* Clean up js
This commit is contained in:
committed by
Dave Lasley
parent
ec343b6ec8
commit
d59af25db3
@@ -1,8 +0,0 @@
|
||||
/* Copyright (C) 2016-TODAY LasLabs, Inc. [https://laslabs.com]
|
||||
* @author Dave Lasley <dave@laslabs.com>
|
||||
* @license AGPL-3
|
||||
**/
|
||||
|
||||
.slick-arrow{
|
||||
background-color: #4c4c4c !important;
|
||||
}
|
||||
172
web_widget_slick/static/src/js/web_widget_slick.js
Normal file
172
web_widget_slick/static/src/js/web_widget_slick.js
Normal file
@@ -0,0 +1,172 @@
|
||||
/* Copyright 2016-2017 LasLabs Inc.
|
||||
* License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). */
|
||||
|
||||
odoo.define('web_widget_slick', function(require) {
|
||||
"use strict";
|
||||
|
||||
var core = require('web.core');
|
||||
var AbstractManyField = require('web.form_relational').AbstractManyField;
|
||||
|
||||
var FieldSlickImages = AbstractManyField.extend({
|
||||
|
||||
widget_class: 'o_slick',
|
||||
template: 'FieldSlickImages',
|
||||
$slick: null,
|
||||
no_rerender: true,
|
||||
loading: [],
|
||||
loaded: 0,
|
||||
|
||||
events: {
|
||||
'mousedown img': function(ev) {
|
||||
ev.preventDefault();
|
||||
},
|
||||
'touchstart img': function(ev) {
|
||||
ev.preventDefault();
|
||||
},
|
||||
// Triggering a resize on the lazyLoaded event prevents the carousel
|
||||
// from appearing empty when page loads
|
||||
'lazyLoaded': function(ev) {
|
||||
$(ev.target).trigger('resize');
|
||||
}
|
||||
},
|
||||
|
||||
defaults: {
|
||||
lazyLoad: 'ondemand',
|
||||
fieldName: 'datas',
|
||||
modelName: 'ir.attachment',
|
||||
slidesToShow: 3,
|
||||
slidesToScroll: 1,
|
||||
swipeToSlide: true,
|
||||
dots: true,
|
||||
infinite: true,
|
||||
speed: 500,
|
||||
arrows: true,
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1024,
|
||||
settings: {
|
||||
slidesToShow: 2,
|
||||
slidesToScroll: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 600,
|
||||
settings: {
|
||||
slidesToShow: 1,
|
||||
slidesToScroll: 1
|
||||
}
|
||||
}
|
||||
// You can unslick at a given breakpoint now by adding:
|
||||
// settings: "unslick"
|
||||
// instead of a settings object
|
||||
]
|
||||
},
|
||||
|
||||
init: function(field_manager, node) {
|
||||
this._super(field_manager, node);
|
||||
this.options = _.defaults(this.options, this.defaults);
|
||||
},
|
||||
|
||||
destroy_content: function() {
|
||||
if (this.$slick) {
|
||||
var $imgs = this.$el.find('img');
|
||||
// Unslicking removes the carousel but re-appends any images,
|
||||
// so removal of images is also required
|
||||
$imgs.each($.proxy(this._slickRemove, this));
|
||||
this.$slick.slick('unslick');
|
||||
}
|
||||
},
|
||||
|
||||
render_value: function() {
|
||||
this._super();
|
||||
this.destroy_content();
|
||||
|
||||
this.$el.parent('td').addClass('o_slick_cell');
|
||||
this.$slick = $('<div class="slick-container"></div>');
|
||||
if (this.options.arrows) {
|
||||
this.$slick.addClass('slick-arrowed');
|
||||
}
|
||||
this.$el.append(this.$slick);
|
||||
|
||||
var baseUrl = '/web/image/' + this.options.modelName + '/';
|
||||
var value = this.get('value');
|
||||
this.loading.push.apply(value);
|
||||
_.each(value, $.proxy(this._slickRender, this, [baseUrl]));
|
||||
|
||||
this.$slick.slick(this.options);
|
||||
core.bus.on('resize', this, this._resizeCarousel);
|
||||
},
|
||||
|
||||
_resizeCarousel: function () {
|
||||
var maxWidth = this._resizeMaxWidth();
|
||||
var containerWidth = maxWidth;
|
||||
|
||||
var $parentCell = this.$el.parent('td');
|
||||
if ($parentCell.length) {
|
||||
var scaledWidth = this._resizeScaledWidth($parentCell, maxWidth);
|
||||
var labelWidth = this._resizeLabelWidth($parentCell);
|
||||
containerWidth = scaledWidth - labelWidth;
|
||||
}
|
||||
|
||||
var marginWidth = this._resizeMarginWidth(this.$slick);
|
||||
var carouselWidth = containerWidth - marginWidth;
|
||||
|
||||
// Set outerWidth of carousel, with minimum size. Minimum size can cause
|
||||
// overflow in some cases but prevents displaying with zero width
|
||||
this.$slick.outerWidth(Math.max(carouselWidth, 150));
|
||||
},
|
||||
|
||||
_resizeLabelWidth: function ($parentCell) {
|
||||
// If the widget has a label, subtract label cell's width, plus the extra
|
||||
// padding applied to the parent cell, from container width
|
||||
var $labelCell = $parentCell.prev('.o_td_label');
|
||||
if ($labelCell.length) {
|
||||
var parentPadding = $parentCell.outerWidth() - $parentCell.width();
|
||||
return $labelCell.outerWidth() + parentPadding;
|
||||
}
|
||||
|
||||
return 0;
|
||||
},
|
||||
|
||||
_resizeMarginWidth: function ($element) {
|
||||
// Subtract container's margins so outerWidth can be set properly
|
||||
return $element.outerWidth(true) - $element.outerWidth();
|
||||
},
|
||||
|
||||
_resizeMaxWidth: function () {
|
||||
// Determine the maximum possible width the widget container can occupy
|
||||
var parentSelectors = ['.o_form_sheet', '.o_form_nosheet'];
|
||||
var containerWidth = parentSelectors.map(function (selector) {
|
||||
return this.$el.closest(selector).width();
|
||||
}, this).filter(function (width) {
|
||||
return width !== null;
|
||||
})[0];
|
||||
|
||||
return containerWidth;
|
||||
},
|
||||
|
||||
_resizeScaledWidth: function ($parentCell, maxWidth) {
|
||||
// If the widget is inside a group tag, scale carousel size based on
|
||||
// intended % width of parent cell
|
||||
return maxWidth * parseInt($parentCell[0].style.width, 10) / 100;
|
||||
},
|
||||
|
||||
_slickRemove: function (idx, val) {
|
||||
this.$slick.slick('slickRemove', idx);
|
||||
},
|
||||
|
||||
_slickRender: function (baseUrl, id) {
|
||||
var $img = $('<img class="img img-responsive"></img>');
|
||||
var $div = $('<div></div>');
|
||||
$img.attr('data-lazy', baseUrl + id + '/' + this.options.fieldName);
|
||||
$div.append($img);
|
||||
this.$slick.append($div);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
core.form_widget_registry.add("one2many_slick_images", FieldSlickImages);
|
||||
|
||||
return {FieldSlickImages: FieldSlickImages};
|
||||
|
||||
});
|
||||
@@ -1,114 +0,0 @@
|
||||
/* © 2016-TODAY LasLabs Inc.
|
||||
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
*/
|
||||
|
||||
odoo.define('web_widget_slick.slick_widget', function(require){
|
||||
"use strict";
|
||||
|
||||
var core = require('web.core');
|
||||
var AbstractManyField = require('web.form_relational').AbstractManyField;
|
||||
|
||||
var QWeb = core.qweb;
|
||||
var _t = core._t;
|
||||
|
||||
var FieldSlickImages = AbstractManyField.extend({
|
||||
|
||||
className: 'o_slick',
|
||||
template: 'FieldSlickImages',
|
||||
$slick: null,
|
||||
no_rerender: true,
|
||||
loading: [],
|
||||
loaded: 0,
|
||||
|
||||
defaults: {
|
||||
lazyLoad: 'ondemand',
|
||||
fieldName: 'datas',
|
||||
modelName: 'ir.attachment',
|
||||
slidesToShow: 3,
|
||||
slidesToScroll: 1,
|
||||
dots: true,
|
||||
infinite: true,
|
||||
speed: 500,
|
||||
arrows: true,
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1024,
|
||||
settings: {
|
||||
slidesToShow: 3,
|
||||
slidesToScroll: 3,
|
||||
infinite: true,
|
||||
dots: true
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 600,
|
||||
settings: {
|
||||
slidesToShow: 2,
|
||||
slidesToScroll: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 480,
|
||||
settings: {
|
||||
slidesToShow: 1,
|
||||
slidesToScroll: 1
|
||||
}
|
||||
},
|
||||
// You can unslick at a given breakpoint now by adding:
|
||||
// settings: "unslick"
|
||||
// instead of a settings object
|
||||
],
|
||||
},
|
||||
|
||||
init: function(field_manager, node) {
|
||||
this._super(field_manager, node);
|
||||
this.options = _.defaults(this.options, this.defaults);
|
||||
},
|
||||
|
||||
destroy_content: function() {
|
||||
var self = this;
|
||||
if (this.$slick) {
|
||||
console.log('Destroying SlickJS');
|
||||
var $imgs = this.$el.find('img');
|
||||
$imgs.each(function(idx, val){
|
||||
console.log('Removing ' + $imgs[idx]);
|
||||
self.$slick.slick('slickRemove', $imgs[idx]);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
render_value: function() {
|
||||
var self = this;
|
||||
this._super();
|
||||
console.log('Rerendering SlickJS');
|
||||
this.destroy_content();
|
||||
|
||||
var baseUrl = '/web/image/' + this.options.modelName;
|
||||
|
||||
this.$slick = $('<div class="slick-container"></div>');
|
||||
this.$el.append(this.$slick);
|
||||
this.$slick.slick(this.options);
|
||||
|
||||
self.loading.push.apply(self.get('value'));
|
||||
|
||||
_.each(self.get('value'), function(id){
|
||||
var $img = $('<img></img>');
|
||||
var $div = $('<div></div>');
|
||||
$div.append($img);
|
||||
$img.attr('data-lazy', baseUrl + '/' + id + '/' + self.options.fieldName);
|
||||
self.$el.append($div);
|
||||
self.$slick.slick('slickAdd', $div);
|
||||
self.$slick.slick('slickGoTo', 0);
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
core.form_widget_registry.add("one2many_slick_images", FieldSlickImages);
|
||||
|
||||
return {
|
||||
FieldSlickImages: FieldSlickImages,
|
||||
}
|
||||
|
||||
});
|
||||
74
web_widget_slick/static/src/less/slick.less
Executable file
74
web_widget_slick/static/src/less/slick.less
Executable file
@@ -0,0 +1,74 @@
|
||||
/* Copyright 2016-2017 LasLabs Inc.
|
||||
* License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). */
|
||||
|
||||
@slick-arrow-margin: 40px;
|
||||
@slick-arrow-offset: calc(-(@slick-arrow-margin - 5px));
|
||||
@slick-font-family: "FontAwesome";
|
||||
@slick-dot-character: "\f10c";
|
||||
@slick-dot-character-active: "\f111";
|
||||
@slick-dot-color: @odoo-brand-primary;
|
||||
@slick-dot-offset: 35px;
|
||||
@slick-dot-size: 12px;
|
||||
@slick-next-character: "\f054";
|
||||
@slick-prev-character: "\f053";
|
||||
@slick-opacity-default: 1;
|
||||
@slick-opacity-not-active: 0.5;
|
||||
|
||||
/* Odoo field */
|
||||
|
||||
.o_slick {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
/* Container */
|
||||
|
||||
.slick-container {
|
||||
&.slick-dotted {
|
||||
margin-bottom: @slick-dot-offset;
|
||||
}
|
||||
&.slick-arrowed {
|
||||
margin-left: @slick-arrow-margin;
|
||||
margin-right: @slick-arrow-margin;
|
||||
.slick-prev {
|
||||
left: @slick-arrow-offset;
|
||||
}
|
||||
.slick-next {
|
||||
right: @slick-arrow-offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Images */
|
||||
|
||||
.slick-slide {
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
outline: none;
|
||||
img {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
|
||||
/* Arrows */
|
||||
|
||||
.slick-arrow {
|
||||
height: 35px;
|
||||
width: 30px;
|
||||
font-size: 0 !important;
|
||||
padding: 0 !important;
|
||||
.btn();
|
||||
.btn-sm();
|
||||
.btn-primary();
|
||||
}
|
||||
|
||||
/* Dots */
|
||||
|
||||
.slick-dots {
|
||||
bottom: calc(-(@slick-dot-offset));
|
||||
li {
|
||||
&.slick-active button:before {
|
||||
content: @slick-dot-character-active;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
© 2016-TODAY LasLabs Inc.
|
||||
@license AGPL-3 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
-->
|
||||
|
||||
<templates id="field_templates" xml:space="preserve">
|
||||
<t t-name="FieldSlickImages">
|
||||
<span t-att-style="widget.node.attrs.style">
|
||||
<t t-if="!widget.get('effective_readonly')">
|
||||
|
||||
</t>
|
||||
</span>
|
||||
</t>
|
||||
</templates>
|
||||
9
web_widget_slick/static/src/xml/web_widget_slick.xml
Normal file
9
web_widget_slick/static/src/xml/web_widget_slick.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright 2016-2017 LasLabs Inc.
|
||||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). -->
|
||||
|
||||
<template>
|
||||
<t t-name="FieldSlickImages">
|
||||
<div t-attf-class="o_form_field {{ widget.widget_class }}"></div>
|
||||
</t>
|
||||
</template>
|
||||
Reference in New Issue
Block a user