Browse Source

[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
pull/706/head
Brenton Hughes 7 years ago
committed by Dave Lasley
parent
commit
d59af25db3
No known key found for this signature in database GPG Key ID: 7DDBA4BA81B934CF
  1. 76
      web_widget_slick/README.rst
  2. 4
      web_widget_slick/__init__.py
  3. 25
      web_widget_slick/__manifest__.py
  4. 25
      web_widget_slick/__openerp__.py
  5. BIN
      web_widget_slick/static/description/icon.png
  6. 12822
      web_widget_slick/static/description/icon.svg
  7. BIN
      web_widget_slick/static/lib/slick/ajax-loader.gif
  8. 172
      web_widget_slick/static/lib/slick/slick-theme.less
  9. 2996
      web_widget_slick/static/lib/slick/slick.js
  10. 104
      web_widget_slick/static/lib/slick/slick.less
  11. 8
      web_widget_slick/static/src/css/slick.css
  12. 172
      web_widget_slick/static/src/js/web_widget_slick.js
  13. 114
      web_widget_slick/static/src/js/widget_slick.js
  14. 74
      web_widget_slick/static/src/less/slick.less
  15. 16
      web_widget_slick/static/src/xml/field_templates.xml
  16. 9
      web_widget_slick/static/src/xml/web_widget_slick.xml
  17. 225
      web_widget_slick/static/tests/js/web_widget_slick.js
  18. 36
      web_widget_slick/templates/assets.xml
  19. 4
      web_widget_slick/tests/__init__.py
  20. 19
      web_widget_slick/tests/test_ui.py
  21. 18
      web_widget_slick/views/assets.xml

76
web_widget_slick/README.rst

@ -1,13 +1,12 @@
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. image:: https://img.shields.io/badge/license-LGPL--3-blue.svg
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
=================
Odoo Slick Widget
=================
This module provides a Slick Carousel widget for use in Odoo.
=====================
Slick Carousel Widget
=====================
This module provides a Slick Carousel widget for use in the Odoo backend web interface.
Usage
=====
@ -23,16 +22,14 @@ Default usage is on a One2many attachment field, as defined below::
inverse_name='res_id',
)
Assuming the above model, you would use add a Slick Carousel on the
Assuming the above model, you would add a Slick Carousel on the
``image_ids`` column by using the following field definition in the
model's form view::
<field name="image_ids" widget="one2many_slick_images" options="{}"/>
Example implementation - https://repo.laslabs.com/projects/ODOO/repos/web/browse/web_widget_slick_example
Options
=======
-------
The widget passes options directly through to Slick, so any `setting
available to Slick`_ is available to the widget. Additional options
@ -48,6 +45,42 @@ specific to Odoo are:
.. _setting available to Slick: http://kenwheeler.github.io/slick/#settings
Example Module
--------------
An example implementation, for instructional purposes as well as convenient
functional testing, is provided in the `web_widget_slick_example` module.
* Install `web_widget_slick_example`.
* Activate Developer Mode.
* Go to Settings / Technical / Slick, and open the record to view the widget.
To try out different Slick settings:
* Go to Settings/User Interface/Views and search for 'slick.example.view.form'.
* Open the form view record.
* Click the Edit button.
* In the Architecture editor, find `options="{'slidesToShow': 2}`, and add
any desired settings (separated by commas) inside the curly braces.
* Save the changes and browse to the widget, as described above, to see the
widget with the new settings in effect.
.. 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/10.0
Known issues / Roadmap
======================
* Adding / Deleting images from a carousel is not currently supported.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/web/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smash it by providing detailed and welcomed feedback.
Credits
=======
@ -55,18 +88,27 @@ Credits
Images
------
* LasLabs: `Icon <https://repo.laslabs.com/projects/TEM/repos/odoo-module_template/browse/module_name/static/description/icon.svg?raw>`_.
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
Contributors
------------
* Dave Lasley <dave@laslabs.com>
* Brent Hughes <brent.hughes@laslabs.com>
Do not contact contributors directly about support or help with technical issues.
Maintainer
----------
.. image:: https://laslabs.com/logo.png
:alt: LasLabs Inc.
:target: https://laslabs.com
.. 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.
This module is maintained by LasLabs Inc.
To contribute to this module, please visit https://odoo-community.org.

4
web_widget_slick/__init__.py

@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
# © 2016-TODAY LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# Copyright 2016-2017 LasLabs Inc.
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).

25
web_widget_slick/__manifest__.py

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Copyright 2016-2017 LasLabs Inc.
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
"name": "Slick Carousel Widget",
"summary": "Adds SlickJS slider widget for use as a carousel on Many2one"
" attachment fields in backend form views.",
"version": "10.0.1.0.0",
"category": "Web",
"website": "https://laslabs.com/",
"author": "LasLabs, Odoo Community Association (OCA)",
"license": "LGPL-3",
"application": False,
"installable": True,
"depends": [
"web",
],
"data": [
"templates/assets.xml",
],
"qweb": [
"static/src/xml/web_widget_slick.xml",
],
}

25
web_widget_slick/__openerp__.py

@ -1,25 +0,0 @@
# -*- coding: utf-8 -*-
# © 2016-TODAY LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
"name": "Web Slick Widget",
"summary": "Adds SlickJS slider widget for use as a carousel on Many2one"
" attachment fields in backend form views.",
"version": "9.0.1.0.1",
"category": "Web",
"website": "https://laslabs.com/",
"author": "LasLabs",
"license": "AGPL-3",
"application": False,
"installable": True,
"depends": [
"web",
],
"data": [
'views/assets.xml',
],
'qweb': [
"static/src/xml/*.xml",
],
}

BIN
web_widget_slick/static/description/icon.png

Before

Width: 600  |  Height: 518  |  Size: 10 KiB

After

Width: 128  |  Height: 128  |  Size: 9.2 KiB

12822
web_widget_slick/static/description/icon.svg
File diff suppressed because it is too large
View File

BIN
web_widget_slick/static/lib/slick/ajax-loader.gif

After

Width: 32  |  Height: 32  |  Size: 4.1 KiB

172
web_widget_slick/static/lib/slick/slick-theme.less

@ -0,0 +1,172 @@
/* Copyright 2013-2016 Ken Wheeler
* Version 1.7.1
* License MIT (https://opensource.org/licenses/MIT) */
@charset "UTF-8";
// Default Variables
@slick-font-path: "./fonts/";
@slick-font-family: "slick";
@slick-loader-path: "./";
@slick-arrow-color: white;
@slick-dot-color: black;
@slick-dot-color-active: @slick-dot-color;
@slick-prev-character: "←";
@slick-next-character: "→";
@slick-dot-character: "•";
@slick-dot-size: 6px;
@slick-opacity-default: 0.75;
@slick-opacity-on-hover: 1;
@slick-opacity-not-active: 0.25;
/* Slider */
.slick-loading .slick-list{
background: #fff url('@{slick-loader-path}ajax-loader.gif') center center no-repeat;
}
/* Arrows */
.slick-prev,
.slick-next {
position: absolute;
display: block;
height: 20px;
width: 20px;
line-height: 0px;
font-size: 0px;
cursor: pointer;
background: transparent;
color: transparent;
top: 50%;
-webkit-transform: translate(0, -50%);
-ms-transform: translate(0, -50%);
transform: translate(0, -50%);
padding: 0;
border: none;
outline: none;
&:hover, &:focus {
outline: none;
background: transparent;
color: transparent;
&:before {
opacity: @slick-opacity-on-hover;
}
}
&.slick-disabled:before {
opacity: @slick-opacity-not-active;
}
}
.slick-prev:before, .slick-next:before {
font-family: @slick-font-family;
font-size: 20px;
line-height: 1;
color: @slick-arrow-color;
opacity: @slick-opacity-default;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
& when ( @slick-font-family = 'slick' ) {
/* Icons */
@font-face {
font-family: 'slick';
font-weight: normal;
font-style: normal;
src: url('@{slick-font-path}slick.eot');
src: url('@{slick-font-path}slick.eot?#iefix') format('embedded-opentype'), url('@{slick-font-path}slick.woff') format('woff'), url('@{slick-font-path}slick.ttf') format('truetype'), url('@{slick-font-path}slick.svg#slick') format('svg');
}
}
}
.slick-prev {
left: -25px;
[dir="rtl"] & {
left: auto;
right: -25px;
}
&:before {
content: @slick-prev-character;
[dir="rtl"] & {
content: @slick-next-character;
}
}
}
.slick-next {
right: -25px;
[dir="rtl"] & {
left: -25px;
right: auto;
}
&:before {
content: @slick-next-character;
[dir="rtl"] & {
content: @slick-prev-character;
}
}
}
/* Dots */
.slick-dotted .slick-slider {
margin-bottom: 30px;
}
.slick-dots {
position: absolute;
bottom: -25px;
list-style: none;
display: block;
text-align: center;
padding: 0;
margin: 0;
width: 100%;
li {
position: relative;
display: inline-block;
height: 20px;
width: 20px;
margin: 0 5px;
padding: 0;
cursor: pointer;
button {
border: 0;
background: transparent;
display: block;
height: 20px;
width: 20px;
outline: none;
line-height: 0px;
font-size: 0px;
color: transparent;
padding: 5px;
cursor: pointer;
&:hover, &:focus {
outline: none;
&:before {
opacity: @slick-opacity-on-hover;
}
}
&:before {
position: absolute;
top: 0;
left: 0;
content: @slick-dot-character;
width: 20px;
height: 20px;
font-family: @slick-font-family;
font-size: @slick-dot-size;
line-height: 20px;
text-align: center;
color: @slick-dot-color;
opacity: @slick-opacity-not-active;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
}
&.slick-active button:before {
color: @slick-dot-color-active;
opacity: @slick-opacity-default;
}
}
}

2996
web_widget_slick/static/lib/slick/slick.js
File diff suppressed because it is too large
View File

104
web_widget_slick/static/lib/slick/slick.less

@ -0,0 +1,104 @@
/* Copyright 2013-2016 Ken Wheeler
* Version 1.7.1
* License MIT (https://opensource.org/licenses/MIT) */
/* Slider */
.slick-slider {
position: relative;
display: block;
box-sizing: border-box;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-ms-touch-action: pan-y;
touch-action: pan-y;
-webkit-tap-highlight-color: transparent;
}
.slick-list {
position: relative;
overflow: hidden;
display: block;
margin: 0;
padding: 0;
&:focus {
outline: none;
}
&.dragging {
cursor: pointer;
cursor: hand;
}
}
.slick-slider .slick-track,
.slick-slider .slick-list {
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.slick-track {
position: relative;
left: 0;
top: 0;
display: block;
margin-left: auto;
margin-right: auto;
&:before,
&:after {
content: "";
display: table;
}
&:after {
clear: both;
}
.slick-loading & {
visibility: hidden;
}
}
.slick-slide {
float: left;
height: 100%;
min-height: 1px;
[dir="rtl"] & {
float: right;
}
img {
display: block;
}
&.slick-loading img {
display: none;
}
display: none;
&.dragging img {
pointer-events: none;
}
.slick-initialized & {
display: block;
}
.slick-loading & {
visibility: hidden;
}
.slick-vertical & {
display: block;
height: auto;
border: 1px solid transparent;
}
}
.slick-arrow.slick-hidden {
display: none;
}

8
web_widget_slick/static/src/css/slick.css

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

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

114
web_widget_slick/static/src/js/widget_slick.js

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

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

16
web_widget_slick/static/src/xml/field_templates.xml

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

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

225
web_widget_slick/static/tests/js/web_widget_slick.js

@ -0,0 +1,225 @@
/* Copyright 2017 LasLabs Inc.
* License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). */
odoo.define_section('web_widget_slick', ['web.core', 'web.form_common'], function(test) {
"use strict";
function appendWidget (core, formCommon, $fix) {
var fieldManager = new formCommon.DefaultFieldManager(null, {});
var node = {'attrs': {}};
var FieldSlickImages = core.form_widget_registry.get('one2many_slick_images');
var widget = new FieldSlickImages(fieldManager, node);
widget.appendTo($fix);
return widget;
}
function imageUrl (modelName, fieldName, id) {
return '/web/image/' + modelName + '/' + id + '/' + fieldName;
}
test('It should add a slick widget',
function(assert, core, formCommon) {
var $fix = $('#qunit-fixture');
var widget = appendWidget(core, formCommon, $fix);
var slickContainerCount = $fix.find('.slick-container').length;
assert.strictEqual(slickContainerCount, 1);
}
);
test('.init() should add defaults to options',
function(assert, core, formCommon) {
var $fix = $('#qunit-fixture');
var fieldManager = new formCommon.DefaultFieldManager(null, {});
var node = {'attrs': {}};
var FieldSlickImages = core.form_widget_registry.get('one2many_slick_images');
var widget = new FieldSlickImages(fieldManager, node);
widget.appendTo($fix);
widget.defaults.testing = 'tested';
widget.init(fieldManager, node);
assert.strictEqual(widget.options.testing, 'tested');
}
);
test('.destroy_content() should remove images',
function(assert, core, formCommon) {
var $fix = $('#qunit-fixture');
var widget = appendWidget(core, formCommon, $fix);
var $slickImage = $('<div><img></div>');
widget.$slick.slick('slickAdd', $slickImage);
widget.destroy_content();
var slickImageCount = widget.$slick.find('img').length;
assert.strictEqual(slickImageCount, 0);
}
);
test('.destroy_content() should remove carousel',
function (assert, core, formCommon) {
var $fix = $('#qunit-fixture');
var widget = appendWidget(core, formCommon, $fix);
widget.destroy_content();
var slickChildren = widget.$slick.children().length;
assert.strictEqual(slickChildren, 0);
}
);
test('.render_value() should add images corresponding to field value',
function(assert, core, formCommon) {
var $fix = $('#qunit-fixture');
var widget = appendWidget(core, formCommon, $fix);
var fieldValues = [1, 2];
widget.set({'value': fieldValues});
widget.render_value();
var slickImages = widget.$slick.find('img');
var slickImageUrls = slickImages.map(function() {
return $(this).data('lazy');
}).get();
var modelName = widget.options.modelName;
var fieldName = widget.options.fieldName;
var expectedUrls = fieldValues.map(function(id) {
return '/web/image/' + modelName + '/' + id + '/' + fieldName;
});
assert.deepEqual(slickImageUrls, expectedUrls);
}
);
test('._resizeCarousel() should resize the widget',
function (assert, core, formCommon) {
var $fix = $('#qunit-fixture');
var $nosheet = $('<div class="o_form_nosheet"></div>');
$fix.append($nosheet);
var widget = appendWidget(core, formCommon, $nosheet);
var setWidth = 50;
widget.$slick.outerWidth(setWidth);
widget._resizeCarousel();
assert.notStrictEqual(widget.$slick.outerWidth(), setWidth);
}
);
test('._resizeCarousel() should be called when container is resized',
function (assert, core, formCommon) {
var $fix = $('#qunit-fixture');
var $nosheet = $('<div class="o_form_nosheet"></div>');
$fix.append($nosheet);
var widget = appendWidget(core, formCommon, $nosheet);
var setWidth = 50;
widget.$slick.outerWidth(setWidth);
core.bus.trigger('resize');
assert.notStrictEqual(widget.$slick.outerWidth(), setWidth);
}
);
test('._resizeLabelWidth() should return the width of the preceding ' +
'sibling label cell if it exists',
function (assert, core, formCommon) {
var $fix = $('#qunit-fixture');
var widget = appendWidget(core, formCommon, $fix);
var width = 100;
var $cell = $('<td style="width:10px;"></td>');
var $labelCell = $('<td class="o_td_label"></td>');
$labelCell.outerWidth(width);
widget.$slick.append($labelCell);
widget.$slick.append($cell);
assert.strictEqual(widget._resizeLabelWidth($cell), width);
}
);
test('._resizeLabelWidth() should return 0 if the previous sibling cell ' +
' of the provided element is not a label cell',
function (assert, core, formCommon) {
var $fix = $('#qunit-fixture');
var widget = appendWidget(core, formCommon, $fix);
var width = '100px';
var $cell = $('<td></td>');
widget.$slick.append($('<td style="width:' + width + ';"></td>'));
widget.$slick.append($cell);
assert.strictEqual(widget._resizeLabelWidth($cell), 0);
}
);
test('._resizeMarginWidth() should return the total left and right ' +
' margins of the provided element',
function (assert, core, formCommon) {
var $fix = $('#qunit-fixture');
var widget = appendWidget(core, formCommon, $fix);
var elementStyle = 'margin-left: 12px; margin-right: 7px;';
var marginTotal = 19;
var $element = $('<div style="' + elementStyle + '"></div>');
widget.$slick.append($element);
assert.strictEqual(widget._resizeMarginWidth($element), marginTotal);
}
);
test('._resizeMaxWidth() should return the width of the closest sheet element',
function (assert, core, formCommon) {
var $fix = $('#qunit-fixture');
var $sheet1 = $('<div class="o_form_sheet"></div>');
var $sheet2 = $('<div class="o_form_sheet"></div>');
var expectedWidth = 266;
$sheet1.width(700);
$sheet2.width(expectedWidth);
$sheet1.append($sheet2);
$fix.append($sheet1);
var widget = appendWidget(core, formCommon, $sheet2);
assert.strictEqual(widget._resizeMaxWidth(), expectedWidth);
}
);
test('._resizeMaxWidth() should return the width of the closest nosheet element',
function (assert, core, formCommon) {
var $fix = $('#qunit-fixture');
var $nosheet1 = $('<div class="o_form_nosheet"></div>');
var $nosheet2 = $('<div class="o_form_nosheet"></div>');
var expectedWidth = 266;
$nosheet1.width(700);
$nosheet2.width(expectedWidth);
$nosheet1.append($nosheet2);
$fix.append($nosheet1);
var widget = appendWidget(core, formCommon, $nosheet2);
assert.strictEqual(widget._resizeMaxWidth(), expectedWidth);
}
);
test('._resizeScaledWidth() should return the provided integer, scaled' +
'to the % width in the provided element style attribute',
function (assert, core, formCommon) {
var $fix = $('#qunit-fixture');
var widget = appendWidget(core, formCommon, $fix);
var givenWidth = 100;
var widthPercent = 54;
var expectedWidth = widthPercent;
var $cell = $('<td style="width:' + widthPercent + '%;"></td>');
assert.strictEqual(widget._resizeScaledWidth($cell, givenWidth), expectedWidth);
}
);
});

36
web_widget_slick/templates/assets.xml

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2016-2017 LasLabs Inc.
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
<odoo>
<template id="assets_slick" inherit_id="web.assets_backend">
<xpath expr="//script[last()]" position="after">
<link rel="stylesheet"
type="text/less"
href="/web_widget_slick/static/lib/slick/slick.less"
/>
<link rel="stylesheet"
type="text/less"
href="/web_widget_slick/static/lib/slick/slick-theme.less"
/>
<link rel="stylesheet"
type="text/less"
href="/web_widget_slick/static/src/less/slick.less"
/>
<script type="application/javascript"
src="/web_widget_slick/static/lib/slick/slick.js"
/>
<script type="application/javascript"
src="/web_widget_slick/static/src/js/web_widget_slick.js"
/>
</xpath>
</template>
<template id="qunit_suite" inherit_id="web.qunit_suite">
<xpath expr="//t[@t-set='head']" position="inside">
<script type="application/javascript"
src="/web_widget_slick/static/tests/js/web_widget_slick.js"
/>
</xpath>
</template>
</odoo>

4
web_widget_slick/tests/__init__.py

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import test_ui

19
web_widget_slick/tests/test_ui.py

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Copyright 2017 LasLabs Inc.
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from odoo.tests.common import HttpCase
class UICase(HttpCase):
post_install = True
at_install = False
def test_ui_web(self):
"""Test backend tests."""
self.phantom_js(
"/web/tests?debug=assets&module=web_widget_slick",
"",
login="admin",
)

18
web_widget_slick/views/assets.xml

@ -1,18 +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).
-->
<odoo>
<template id="assets_slick" name="web_widget_slick Assets" inherit_id="web.assets_backend">
<xpath expr="//script[last()]" position="after">
<link href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.5.9/slick.min.css" rel="stylesheet" type="text/css" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.5.9/slick-theme.min.css" rel="stylesheet" type="text/css" />
<link href="/web_widget_slick/static/src/css/slick.css" rel="stylesheet" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.5.9/slick.min.js" />
<script src="/web_widget_slick/static/src/js/widget_slick.js" />
</xpath>
</template>
</odoo>
Loading…
Cancel
Save