mirror of
https://github.com/OCA/web.git
synced 2025-02-22 13:21:25 +02:00
[FIX] web_responsive: Other minor fixes
* Add Tecnativa as author * Remove untestable JS method * Rename to web_responsive
This commit is contained in:
committed by
Angel Moya Pardo
parent
19b5fc41e8
commit
6e4680f4a0
294
web_responsive/static/src/js/web_responsive.js
Executable file
294
web_responsive/static/src/js/web_responsive.js
Executable file
@@ -0,0 +1,294 @@
|
||||
/* Copyright 2016 LasLabs Inc.
|
||||
* License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). */
|
||||
|
||||
odoo.define('web_responsive', function(require) {
|
||||
'use strict';
|
||||
|
||||
var $ = require('$');
|
||||
var Menu = require('web.Menu');
|
||||
var Class = require('web.Class');
|
||||
var SearchView = require('web.SearchView');
|
||||
var core = require('web.core');
|
||||
|
||||
Menu.include({
|
||||
|
||||
// Force all_outside to prevent app icons from going into more menu
|
||||
reflow: function() {
|
||||
this._super('all_outside');
|
||||
},
|
||||
|
||||
/* Overload to collapse unwanted visible submenus
|
||||
* @param allow_open bool Switch to allow submenus to be opened
|
||||
*/
|
||||
open_menu: function(id, allowOpen) {
|
||||
this._super(id);
|
||||
if (allowOpen) return;
|
||||
var $clicked_menu = this.$secondary_menus.find('a[data-menu=' + id + ']');
|
||||
$clicked_menu.parents('.oe_secondary_submenu').css('display', '');
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
SearchView.include({
|
||||
|
||||
// Prevent focus of search field on mobile devices
|
||||
toggle_visibility: function (is_visible) {
|
||||
$('div.oe_searchview_input').last()
|
||||
.one('focus', $.proxy(this.preventMobileFocus, this));
|
||||
return this._super(is_visible);
|
||||
},
|
||||
|
||||
// It prevents focusing of search el on mobile
|
||||
preventMobileFocus: function(event) {
|
||||
if (this.isMobile()) {
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
// For lack of Modernizr, TouchEvent will do
|
||||
isMobile: function () {
|
||||
try{
|
||||
document.createEvent('TouchEvent');
|
||||
return true;
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
var AppDrawer = Class.extend({
|
||||
|
||||
LEFT: 'left',
|
||||
RIGHT: 'right',
|
||||
UP: 'up',
|
||||
DOWN: 'down',
|
||||
|
||||
isOpen: false,
|
||||
keyBuffer: '',
|
||||
keyBufferTime: 500,
|
||||
keyBufferTimeoutEvent: false,
|
||||
dropdownHeightFactor: 0.90,
|
||||
initialized: false,
|
||||
|
||||
init: function() {
|
||||
this.directionCodes = {
|
||||
'left': this.LEFT,
|
||||
'right': this.RIGHT,
|
||||
'up': this.UP,
|
||||
'pageup': this.UP,
|
||||
'down': this.DOWN,
|
||||
'pagedown': this.DOWN,
|
||||
'+': this.RIGHT,
|
||||
'-': this.LEFT,
|
||||
};
|
||||
this.initDrawer();
|
||||
var $clickZones = $('.openerp_webclient_container, ' +
|
||||
'a.oe_menu_leaf, ' +
|
||||
'a.oe_menu_toggler'
|
||||
);
|
||||
$clickZones.click($.proxy(this.handleClickZones, this));
|
||||
core.bus.on('resize', this, this.handleWindowResize);
|
||||
core.bus.on('keydown', this, this.handleNavKeys);
|
||||
},
|
||||
|
||||
// It provides initialization handlers for Drawer
|
||||
initDrawer: function() {
|
||||
this.$el = $('.drawer');
|
||||
this.$el.drawer();
|
||||
this.$el.one('drawer.opened', $.proxy(this.onDrawerOpen, this));
|
||||
this.$el.on('drawer.opened', function setIScrollProbes(){
|
||||
var onIScroll = function() {
|
||||
var transform = (this.iScroll.y) ? this.iScroll.y * -1 : 0;
|
||||
$(this).find('#appDrawerAppPanelHead').css(
|
||||
'transform', 'matrix(1, 0, 0, 1, 0, ' + transform + ')'
|
||||
);
|
||||
};
|
||||
this.iScroll.options.probeType = 2;
|
||||
this.iScroll.on('scroll', $.proxy(onIScroll, this));
|
||||
});
|
||||
this.initialized = true;
|
||||
},
|
||||
|
||||
// It provides handlers to hide drawer when "unfocused"
|
||||
handleClickZones: function() {
|
||||
this.$el.drawer('close');
|
||||
$('.oe_secondary_menus_container')
|
||||
.parent()
|
||||
.collapse('hide');
|
||||
},
|
||||
|
||||
// It resizes bootstrap dropdowns for screen
|
||||
handleWindowResize: function() {
|
||||
$('.dropdown-scrollable').css(
|
||||
'max-height', $(window).height() * this.dropdownHeightFactor
|
||||
);
|
||||
},
|
||||
|
||||
// It provides keyboard shortcuts for app drawer nav
|
||||
handleNavKeys: function(e) {
|
||||
if (!this.isOpen){
|
||||
return;
|
||||
}
|
||||
var directionCode = $.hotkeys.specialKeys[e.keyCode.toString()];
|
||||
if (Object.keys(this.directionCodes).indexOf(directionCode) !== -1) {
|
||||
var $link = this.findAdjacentAppLink(
|
||||
this.$el.find('a:first, a:focus').last(),
|
||||
this.directionCodes[directionCode]
|
||||
);
|
||||
this.selectAppLink($link);
|
||||
} else if ($.hotkeys.specialKeys[e.keyCode.toString()] == 'esc') {
|
||||
this.handleClickZones();
|
||||
} else {
|
||||
var buffer = this.handleKeyBuffer(e.keyCode);
|
||||
this.selectAppLink(this.searchAppLinks(buffer));
|
||||
}
|
||||
},
|
||||
|
||||
/* It adds to keybuffer, sets expire timer, and returns buffer
|
||||
* @returns str of current buffer
|
||||
*/
|
||||
handleKeyBuffer: function(keyCode) {
|
||||
this.keyBuffer += String.fromCharCode(keyCode);
|
||||
if (this.keyBufferTimeoutEvent) {
|
||||
clearTimeout(this.keyBufferTimeoutEvent);
|
||||
}
|
||||
this.keyBufferTimeoutEvent = setTimeout(
|
||||
$.proxy(this.clearKeyBuffer, this),
|
||||
this.keyBufferTime
|
||||
);
|
||||
return this.keyBuffer;
|
||||
},
|
||||
|
||||
clearKeyBuffer: function() {
|
||||
this.keyBuffer = '';
|
||||
},
|
||||
|
||||
/* It performs close actions
|
||||
* @fires ``drawer.closed`` to the ``core.bus``
|
||||
* @listens ``drawer.opened`` and sends to onDrawerOpen
|
||||
*/
|
||||
onDrawerClose: function() {
|
||||
core.bus.trigger('drawer.closed');
|
||||
this.$el.one('drawer.opened', $.proxy(this.onDrawerOpen, this));
|
||||
this.isOpen = false;
|
||||
// Remove inline style inserted by drawer.js
|
||||
this.$el.css("overflow", "");
|
||||
},
|
||||
|
||||
/* It finds app links and register event handlers
|
||||
* @fires ``drawer.opened`` to the ``core.bus``
|
||||
* @listens ``drawer.closed`` and sends to :meth:``onDrawerClose``
|
||||
*/
|
||||
onDrawerOpen: function() {
|
||||
this.$appLinks = $('.app-drawer-icon-app').parent();
|
||||
this.selectAppLink($(this.$appLinks[0]));
|
||||
this.$el.one('drawer.closed', $.proxy(this.onDrawerClose, this));
|
||||
core.bus.trigger('drawer.opened');
|
||||
this.isOpen = true;
|
||||
},
|
||||
|
||||
// It selects an app link visibly
|
||||
selectAppLink: function($appLink) {
|
||||
if ($appLink) {
|
||||
$appLink.focus();
|
||||
}
|
||||
},
|
||||
|
||||
/* It returns first App Link by its name according to query
|
||||
* @param query str to search
|
||||
* @return jQuery obj
|
||||
*/
|
||||
searchAppLinks: function(query) {
|
||||
return this.$appLinks.filter(function() {
|
||||
return $(this).data('menuName').toUpperCase().startsWith(query);
|
||||
}).first();
|
||||
},
|
||||
|
||||
/* It returns the link adjacent to $appLink in provided direction.
|
||||
* It also handles edge cases in the following ways:
|
||||
* * Moves to last link if LEFT on first
|
||||
* * Moves to first link if PREV on last
|
||||
* * Moves to first link of following row if RIGHT on last in row
|
||||
* * Moves to last link of previous row if LEFT on first in row
|
||||
* * Moves to top link in same column if DOWN on bottom row
|
||||
* * Moves to bottom link in same column if UP on top row
|
||||
* @param $appLink jQuery obj of App icon link
|
||||
* @param direction str of direction to go (constants LEFT, UP, etc.)
|
||||
* @return jQuery obj for adjacent applink
|
||||
*/
|
||||
findAdjacentAppLink: function($appLink, direction) {
|
||||
|
||||
var obj = [],
|
||||
$objs = this.$appLinks;
|
||||
|
||||
switch(direction){
|
||||
case this.LEFT:
|
||||
obj = $objs[$objs.index($appLink) - 1];
|
||||
if (!obj) {
|
||||
obj = $objs[$objs.length - 1];
|
||||
}
|
||||
break;
|
||||
case this.RIGHT:
|
||||
obj = $objs[$objs.index($appLink) + 1];
|
||||
if (!obj) {
|
||||
obj = $objs[0];
|
||||
}
|
||||
break;
|
||||
case this.UP:
|
||||
$objs = this.getRowObjs($appLink, this.$appLinks);
|
||||
obj = $objs[$objs.index($appLink) - 1];
|
||||
if (!obj) {
|
||||
obj = $objs[$objs.length - 1];
|
||||
}
|
||||
break;
|
||||
case this.DOWN:
|
||||
$objs = this.getRowObjs($appLink, this.$appLinks);
|
||||
obj = $objs[$objs.index($appLink) + 1];
|
||||
if (!obj) {
|
||||
obj = $objs[0];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (obj.length) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
return $(obj);
|
||||
|
||||
},
|
||||
|
||||
/* It returns els in the same row
|
||||
* @param @obj jQuery object to get row for
|
||||
* @param $grid jQuery objects representing grid
|
||||
* @return $objs jQuery objects of row
|
||||
*/
|
||||
getRowObjs: function($obj, $grid) {
|
||||
// Filter by object which middle lies within left/right bounds
|
||||
function filterWithin(left, right) {
|
||||
return function() {
|
||||
var $this = $(this),
|
||||
thisMiddle = $this.offset().left + ($this.width() / 2);
|
||||
return thisMiddle >= left && thisMiddle <= right;
|
||||
};
|
||||
}
|
||||
var left = $obj.offset().left,
|
||||
right = left + $obj.outerWidth();
|
||||
return $grid.filter(filterWithin(left, right));
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
// It inits a new AppDrawer when the web client is ready
|
||||
core.bus.on('web_client_ready', null, function () {
|
||||
new AppDrawer();
|
||||
});
|
||||
|
||||
return {
|
||||
'AppDrawer': AppDrawer,
|
||||
'SearchView': SearchView,
|
||||
'Menu': Menu,
|
||||
};
|
||||
|
||||
});
|
||||
86
web_responsive/static/src/less/app_drawer.less
Executable file
86
web_responsive/static/src/less/app_drawer.less
Executable file
@@ -0,0 +1,86 @@
|
||||
/* Copyright 2016 LasLabs Inc.
|
||||
* License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). */
|
||||
|
||||
.app-drawer-nav {
|
||||
border-color: @dropdown-border;
|
||||
background-color: @dropdown-bg;
|
||||
border: 1px solid @dropdown-fallback-border; // IE8 fallback
|
||||
border: 1px solid @dropdown-border;
|
||||
-webkit-border-radius: @border-radius-base;
|
||||
-moz-border-radius: @border-radius-base;
|
||||
border-radius: @border-radius-base;
|
||||
.box-shadow(0 6px 12px rgba(0, 0, 0, .175));
|
||||
background-clip: padding-box;
|
||||
|
||||
.navbar-left {
|
||||
width: 100%;
|
||||
|
||||
li {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.app-drawer-title {
|
||||
float: none;
|
||||
}
|
||||
|
||||
.app-drawer-panel-title {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.app-drawer-icon-app {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
max-width: @app-drawer-icon-size;
|
||||
max-height: @app-drawer-icon-size;
|
||||
object-fit: contain;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
.panel-body {
|
||||
padding-top: @app-drawer-title-height;
|
||||
}
|
||||
|
||||
#appDrawerAppPanelHead {
|
||||
position: absolute;
|
||||
height: @app-drawer-title-height;
|
||||
width: 100%;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.drawer-nav {
|
||||
width: @app-drawer-width;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.drawer--left .drawer-nav {
|
||||
left: -@app-drawer-width;
|
||||
}
|
||||
|
||||
.drawer--left.drawer-open .drawer-hamburger {
|
||||
left: @app-drawer-width;
|
||||
}
|
||||
|
||||
.drawer--right .drawer-nav {
|
||||
right: -@app-drawer-width;
|
||||
}
|
||||
|
||||
.drawer-open .oe-right-toolbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.drawer-closed .oe-right-toolbar {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* App Drawer Toggle */
|
||||
|
||||
.app-drawer-toggle {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.app-drawer-toggle.navbar-toggle {
|
||||
margin-left: 1em;
|
||||
}
|
||||
23
web_responsive/static/src/less/main.less
Executable file
23
web_responsive/static/src/less/main.less
Executable file
@@ -0,0 +1,23 @@
|
||||
/* Copyright 2016 LasLabs Inc.
|
||||
* License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). */
|
||||
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
// Do not fix the search part, it's too big for small screens
|
||||
@media (max-width: @screen-sm-max) {
|
||||
overflow: inherit;
|
||||
.openerp {
|
||||
.oe-view-manager {
|
||||
overflow: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
36
web_responsive/static/src/less/navbar.less
Executable file
36
web_responsive/static/src/less/navbar.less
Executable file
@@ -0,0 +1,36 @@
|
||||
/* Copyright 2016 LasLabs Inc.
|
||||
* License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). */
|
||||
|
||||
.main-nav {
|
||||
margin-bottom: 0;
|
||||
min-height: @app-drawer-navbar-height;
|
||||
}
|
||||
|
||||
.main-nav ul.nav > li > a {
|
||||
padding: @app-drawer-navbar-padding-vertical @app-drawer-padding-horizontal;
|
||||
}
|
||||
|
||||
.oe_topbar_avatar {
|
||||
margin-top: -@app-drawer-padding-horizontal;
|
||||
height: @app-drawer-navbar-height;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
a.navbar-collapse.collapse {
|
||||
@media (min-width: @screen-sm) {
|
||||
padding-bottom: @app-drawer-navbar-padding-vertical;
|
||||
padding-top: @app-drawer-navbar-padding-vertical;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-scrollable {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
@media (max-width: @screen-xs-max) {
|
||||
#odooMenuBarNav[aria-expanded="false"] {
|
||||
/* Hack to hide the visibly expanded mobile menu on load. */
|
||||
position: absolute;
|
||||
z-index: -9999;
|
||||
}
|
||||
}
|
||||
13
web_responsive/static/src/less/variables.less
Executable file
13
web_responsive/static/src/less/variables.less
Executable file
@@ -0,0 +1,13 @@
|
||||
/* Copyright 2016 LasLabs Inc.
|
||||
* License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). */
|
||||
|
||||
// App Drawer / Icons
|
||||
@app-drawer-icon-size: 6em;
|
||||
@app-drawer-icon-margin: 1em;
|
||||
@app-drawer-width: 80%;
|
||||
@app-drawer-title-height: @navbar-height;
|
||||
|
||||
// Navbar
|
||||
@app-drawer-navbar-height: @navbar-height / 2;
|
||||
@app-drawer-navbar-padding-vertical: @navbar-padding-vertical / 2;
|
||||
@app-drawer-padding-horizontal: @navbar-padding-horizontal / 2;
|
||||
Reference in New Issue
Block a user