[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 2017-08-22 16:19:31 -07:00 committed by Dave Lasley
parent ec343b6ec8
commit d59af25db3
No known key found for this signature in database
GPG Key ID: 7DDBA4BA81B934CF
21 changed files with 3975 additions and 12944 deletions

View File

@ -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 LasLabs Inc.
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 https://odoo-community.org.

4
web_widget_slick/__init__.py 100755 → 100644
View File

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

View File

@ -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",
],
}

View File

@ -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",
],
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 932 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

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

File diff suppressed because it is too large Load Diff

View File

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

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>

View File

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

View File

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

View File

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

View File

@ -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",
)

View File

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