[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:
Brenton Hughes
2017-08-22 16:19:31 -07:00
committed by Dave Lasley
parent ec343b6ec8
commit d59af25db3
21 changed files with 3975 additions and 12944 deletions

View File

@@ -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;
}

View 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};
});

View File

@@ -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,
}
});

View 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;
}
}
}

View File

@@ -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>

View 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>