[MERGE] Merge from openerp-web.

bzr revid: jra@tinyerp.com-20120625050934-ybo2tq8n9eyc3s7f
This commit is contained in:
Jiten (OpenERP) 2012-06-25 10:39:34 +05:30
commit 7b8e81139d
25 changed files with 380 additions and 1934 deletions

View File

@ -21,8 +21,6 @@
"static/lib/jquery.validate/jquery.validate.js",
"static/lib/jquery.ba-bbq/jquery.ba-bbq.js",
"static/lib/jquery.blockUI/jquery.blockUI.js",
"static/lib/jquery.superfish/js/hoverIntent.js",
"static/lib/jquery.superfish/js/superfish.js",
"static/lib/jquery.ui/js/jquery-ui-1.8.17.custom.min.js",
"static/lib/jquery.ui.timepicker/js/jquery-ui-timepicker-addon.js",
"static/lib/jquery.ui.notify/js/jquery.notify.js",
@ -30,13 +28,11 @@
"static/lib/jquery.scrollTo/jquery.scrollTo-min.js",
"static/lib/jquery.tipsy/jquery.tipsy.js",
"static/lib/jquery.textext/jquery.textext.js",
"static/lib/json/json2.js",
"static/lib/jquery.timeago/jquery.timeago.js",
"static/lib/qweb/qweb2.js",
"static/lib/underscore/underscore.js",
"static/lib/underscore/underscore.string.js",
"static/lib/backbone/backbone.js",
"static/lib/labjs/LAB.src.js",
"static/lib/py.js/lib/py.js",
"static/src/js/boot.js",
"static/src/js/corelib.js",
@ -56,12 +52,10 @@
"static/src/js/view_editor.js"
],
'css' : [
"static/lib/jquery.superfish/css/superfish.css",
"static/lib/jquery.ui.bootstrap/css/custom-theme/jquery-ui-1.8.16.custom.css",
"static/lib/jquery.ui.timepicker/css/jquery-ui-timepicker-addon.css",
"static/lib/jquery.ui.notify/css/ui.notify.css",
"static/lib/jquery.tipsy/tipsy.css",
# "static/src/css/base_old.css",
"static/src/css/base.css",
"static/src/css/data_export.css",
"static/src/css/data_import.css",

View File

@ -1814,15 +1814,20 @@ class Reports(View):
report = zlib.decompress(report)
report_mimetype = self.TYPES_MAPPING.get(
report_struct['format'], 'octet-stream')
file_name = None
if 'name' not in action:
reports = req.session.model('ir.actions.report.xml')
res_id = reports.search([('report_name', '=',action['report_name']),],
res_id = reports.search([('report_name', '=', action['report_name']),],
0, False, False, context)
action['name'] = reports.read(res_id, ['name'], context)[0]['name']
if len(res_id) > 0:
file_name = reports.read(res_id[0], ['name'], context)['name']
else:
file_name = action['report_name']
return req.make_response(report,
headers=[
('Content-Disposition', 'attachment; filename="%s.%s"' % (action['name'], report_struct['format'])),
# maybe we should take of what characters can appear in a file name?
('Content-Disposition', 'attachment; filename="%s.%s"' % (file_name, report_struct['format'])),
('Content-Type', report_mimetype),
('Content-Length', len(report))],
cookies={'fileToken': int(token)})

View File

@ -1,74 +0,0 @@
Changelog for Superfish - a jQuery menu plugin
v1.2.1: altered 2nd July 07. added hide() before animate to make work for jQuery 1.1.3.
v1.2.2: altered 2nd August 07. changed over function .find('ul') to .find('>ul') for smoother animations
Also deleted the iframe removal lines - not necessary it turns out
v1.2.3: altered jquery 1.1.3.1 broke keyboard access - had to change quite a few things and set display:none on the
.superfish rule in CSS instead of top:-999em
v1.3: Pretty much a complete overhaul to make all original features work in 1.1.3.1 and above.
.superfish rule reverted back to top:-999em (which is better).
v1.3.1: altered 'li[ul]' to $('li:has(ul)') to work with jQuery 1.2
v1.3.2: added onshow callback option as requested - 'this' keyword refers to revealed ul.
fixed bug whereby multiple menus on a page shared options. Now each menu can have separate options.
fixed IE6 and IE7 bug whereby under certain circumstances => 3rd tier menus appear instantly with text missing when revisited
v1.3.3: altered event attachment selectors for performance increase on menu setup.
v1.3.4: fixed pathClass bug as current path was not being restored. Still doesn't if using keyboard nav (will work on that).
v1.4: store options objects in array $.superfish.o. Also provide public access to $.superfish.defaults
provided backward compat for jQuery versions less than 1.2 via oldJquery option - will use li[ul] or li:has(ul) as needed
added more callbacks, also added option to disable hoverIntent usage if that plugin is detected
v1.4.1: fixed current path not being restored when using keyboard to tab away from the menu completely
optimised code further - now less code
removed addself() in favour of backward compatible add(this)
also remove new mouseenter/mouseleave events on window.unload (due to paranoia)
v1.4.2: 3rd July 2008. added semi-colon at start of superfish.js file to avert script concatenation errors
added pathLevels option to limit the depth of submenus that get restored by pathClass
CSS of main example hugely simplified - other example CSS files less-so.
- top level menu items are not fixed width
- only need to set submenu widths in one place.
- various other improvements.
- class names used in all CSS files are changed to be less generic
released optional Supersubs plugin which dynamically adjusts submenu widths
attach everything to jQuery.fn.superfish to clean up jQuery namespace
removed the multi-tier-all-horizontal-example as it was never a great idea and doesn't seem to be in use
Update documentation text and remove certain caveats which were there to support users of much older versions of Superfish
Documentation now show how to apply bgIgrame 2.1 - it's much easier than before
Add all links and their focus and blur events to the onunload unbind - paranoid about memory leaks
v1.4.3 5th July 2008. documentation completely redone using Mike Alsup's templates.
CSS revised so that all types of menu use superfish.css as a base. Include additional CSS files to acheive alternate styles.
class="sf-menu sf-vertical" creates vertical menu, class="sf-menu sf-navbar" creates nav-bar style menu
v1.4.4 7th July 2008. arrows feature added. If option 'autoArrows' is true, auto-appends (spans) to anchors that have a ul submenu sibling,
and adds class 'sf-with-ul' to anchor.
CSS added to style new arrows, including an 8-bit alpha (NOT INDEXED!) transparent png of arrow - degrades to solid for IE6.
Manually add arrow mark-up to docs and disable autoArrows (via defaults option) to maintain decent performance (for docs page)
Update docs, including zip download, to suit.
Fix CSS bug that had the third tier of the navbar-style menu visible when JS not available.
v1.4.5 9 July 2008. decreased code weight
added drop shadows for capable browsers - added css and 8-bit alpha transparent png image for shadow
remove support for jQuery v<1.2
remove unload clean-up which was there to solve garbage collection problems in early jQuery versions
remove toggling 'visibility' on hide and show which as a fix for an IE bug that is no longer exhibited
removed need for getOpts, rewrote getMenu
use [].join('') instead of string concatenation for performance increase - probably very slight in this case
change selector in 'over' function from '.'+o.hoverClass to 'li.'+o.hoverClass
v1.4.6 added workaround for IE7 shadows. If animation alters opacity then shadow is hidden during the animation and appears after.
This required some JS and a line of CSS, so created shortcut references to lighten code further.
v1.4.7 added back in the visibility toggle that was removed in 1.4.5 as the bug is indeed still exhibited by IE6 & 7
tweaked the look of the shadow slightly and use nicer 32bit png as I now find they behave the same as 8bit png with regard to fades in IE7
v1.4.8 fix over-sight: using 32bit png meant that the shadow image did show in IE6. Rather than go back to 8bit, add code to exclude IE6 from getting shadow class.
use new folder structure recommended by Matt from TopicTrack, for easier updates.

View File

@ -1,93 +0,0 @@
/*** adding the class sf-navbar in addition to sf-menu creates an all-horizontal nav-bar menu ***/
.sf-navbar {
background: #BDD2FF;
height: 2.5em;
padding-bottom: 2.5em;
position: relative;
}
.sf-navbar li {
background: #AABDE6;
position: static;
}
.sf-navbar a {
border-top: none;
}
.sf-navbar li ul {
width: 44em; /*IE6 soils itself without this*/
}
.sf-navbar li li {
background: #BDD2FF;
position: relative;
}
.sf-navbar li li ul {
width: 13em;
}
.sf-navbar li li li {
width: 100%;
}
.sf-navbar ul li {
width: auto;
float: left;
}
.sf-navbar a, .sf-navbar a:visited {
border: none;
}
.sf-navbar li.current {
background: #BDD2FF;
}
.sf-navbar li:hover,
.sf-navbar li.sfHover,
.sf-navbar li li.current,
.sf-navbar a:focus, .sf-navbar a:hover, .sf-navbar a:active {
background: #BDD2FF;
}
.sf-navbar ul li:hover,
.sf-navbar ul li.sfHover,
ul.sf-navbar ul li:hover li,
ul.sf-navbar ul li.sfHover li,
.sf-navbar ul a:focus, .sf-navbar ul a:hover, .sf-navbar ul a:active {
background: #D1DFFF;
}
ul.sf-navbar li li li:hover,
ul.sf-navbar li li li.sfHover,
.sf-navbar li li.current li.current,
.sf-navbar ul li li a:focus, .sf-navbar ul li li a:hover, .sf-navbar ul li li a:active {
background: #E6EEFF;
}
ul.sf-navbar .current ul,
ul.sf-navbar ul li:hover ul,
ul.sf-navbar ul li.sfHover ul {
left: 0;
top: 2.5em; /* match top ul list item height */
}
ul.sf-navbar .current ul ul {
top: -999em;
}
.sf-navbar li li.current > a {
font-weight: bold;
}
/*** point all arrows down ***/
/* point right for anchors in subs */
.sf-navbar ul .sf-sub-indicator { background-position: -10px -100px; }
.sf-navbar ul a > .sf-sub-indicator { background-position: 0 -100px; }
/* apply hovers to modern browsers */
.sf-navbar ul a:focus > .sf-sub-indicator,
.sf-navbar ul a:hover > .sf-sub-indicator,
.sf-navbar ul a:active > .sf-sub-indicator,
.sf-navbar ul li:hover > a > .sf-sub-indicator,
.sf-navbar ul li.sfHover > a > .sf-sub-indicator {
background-position: -10px -100px; /* arrow hovers for modern browsers*/
}
/*** remove shadow on first submenu ***/
.sf-navbar > li > ul {
background: transparent;
padding: 0;
-moz-border-radius-bottomleft: 0;
-moz-border-radius-topright: 0;
-webkit-border-top-right-radius: 0;
-webkit-border-bottom-left-radius: 0;
}

View File

@ -1,23 +0,0 @@
/*** adding sf-vertical in addition to sf-menu creates a vertical menu ***/
.sf-vertical, .sf-vertical li {
width: 10em;
}
/* this lacks ul at the start of the selector, so the styles from the main CSS file override it where needed */
.sf-vertical li:hover ul,
.sf-vertical li.sfHover ul {
left: 10em; /* match ul width */
top: 0;
}
/*** alter arrow directions ***/
.sf-vertical .sf-sub-indicator { background-position: -10px 0; } /* IE6 gets solid image only */
.sf-vertical a > .sf-sub-indicator { background-position: 0 0; } /* use translucent arrow for modern browsers*/
/* hover arrow direction for modern browsers*/
.sf-vertical a:focus > .sf-sub-indicator,
.sf-vertical a:hover > .sf-sub-indicator,
.sf-vertical a:active > .sf-sub-indicator,
.sf-vertical li:hover > a > .sf-sub-indicator,
.sf-vertical li.sfHover > a > .sf-sub-indicator {
background-position: -10px 0; /* arrow hovers for modern browsers*/
}

View File

@ -1,136 +0,0 @@
/*** ESSENTIAL STYLES ***/
.sf-menu, .sf-menu * {
margin: 0;
padding: 0;
list-style: none;
}
.sf-menu {
line-height: 1.0;
}
.sf-menu ul {
position: absolute;
top: -999em;
width: 10em; /* left offset of submenus need to match (see below) */
}
.sf-menu ul li {
width: 100%;
}
.sf-menu li:hover {
visibility: inherit; /* fixes IE7 'sticky bug' */
}
.sf-menu li {
float: left;
position: relative;
}
.sf-menu a {
display: block;
position: relative;
}
.sf-menu li:hover ul,
.sf-menu li.sfHover ul {
left: 0;
top: 2.5em; /* match top ul list item height */
z-index: 99;
}
ul.sf-menu li:hover li ul,
ul.sf-menu li.sfHover li ul {
top: -999em;
}
ul.sf-menu li li:hover ul,
ul.sf-menu li li.sfHover ul {
left: 10em; /* match ul width */
top: 0;
}
ul.sf-menu li li:hover li ul,
ul.sf-menu li li.sfHover li ul {
top: -999em;
}
ul.sf-menu li li li:hover ul,
ul.sf-menu li li li.sfHover ul {
left: 10em; /* match ul width */
top: 0;
}
/*** DEMO SKIN ***/
.sf-menu {
float: left;
margin-bottom: 1em;
}
.sf-menu a {
border-left: 1px solid #fff;
border-top: 1px solid #CFDEFF;
padding: .75em 1em;
text-decoration:none;
}
.sf-menu a, .sf-menu a:visited { /* visited pseudo selector so IE6 applies text colour*/
color: #13a;
}
.sf-menu li {
background: #BDD2FF;
}
.sf-menu li li {
background: #AABDE6;
}
.sf-menu li li li {
background: #9AAEDB;
}
.sf-menu li:hover, .sf-menu li.sfHover,
.sf-menu a:focus, .sf-menu a:hover, .sf-menu a:active {
background: #CFDEFF;
outline: 0;
}
/*** arrows **/
.sf-menu a.sf-with-ul {
padding-right: 2.25em;
min-width: 1px; /* trigger IE7 hasLayout so spans position accurately */
}
.sf-sub-indicator {
position: absolute;
display: block;
right: .75em;
top: 1.05em; /* IE6 only */
width: 10px;
height: 10px;
text-indent: -999em;
overflow: hidden;
background: url('../images/arrows-ffffff.png') no-repeat -10px -100px; /* 8-bit indexed alpha png. IE6 gets solid image only */
}
a > .sf-sub-indicator { /* give all except IE6 the correct values */
top: .8em;
background-position: 0 -100px; /* use translucent arrow for modern browsers*/
}
/* apply hovers to modern browsers */
a:focus > .sf-sub-indicator,
a:hover > .sf-sub-indicator,
a:active > .sf-sub-indicator,
li:hover > a > .sf-sub-indicator,
li.sfHover > a > .sf-sub-indicator {
background-position: -10px -100px; /* arrow hovers for modern browsers*/
}
/* point right for anchors in subs */
.sf-menu ul .sf-sub-indicator { background-position: -10px 0; }
.sf-menu ul a > .sf-sub-indicator { background-position: 0 0; }
/* apply hovers to modern browsers */
.sf-menu ul a:focus > .sf-sub-indicator,
.sf-menu ul a:hover > .sf-sub-indicator,
.sf-menu ul a:active > .sf-sub-indicator,
.sf-menu ul li:hover > a > .sf-sub-indicator,
.sf-menu ul li.sfHover > a > .sf-sub-indicator {
background-position: -10px 0; /* arrow hovers for modern browsers*/
}
/*** shadows for all but IE6 ***/
.sf-shadow ul {
background: url('../images/shadow.png') no-repeat bottom right;
padding: 0 8px 9px 0;
-moz-border-radius-bottomleft: 17px;
-moz-border-radius-topright: 17px;
-webkit-border-top-right-radius: 17px;
-webkit-border-bottom-left-radius: 17px;
}
.sf-shadow ul.sf-shadow-off {
background: transparent;
}

View File

@ -1,123 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>A very basic Superfish menu example</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<link rel="stylesheet" type="text/css" href="css/superfish.css" media="screen">
<script type="text/javascript" src="js/jquery-1.2.6.min.js"></script>
<script type="text/javascript" src="js/hoverIntent.js"></script>
<script type="text/javascript" src="js/superfish.js"></script>
<script type="text/javascript">
// initialise plugins
jQuery(function(){
jQuery('ul.sf-menu').superfish();
});
</script>
</head>
<body>
<ul class="sf-menu">
<li class="current">
<a href="#a">menu item</a>
<ul>
<li>
<a href="#aa">menu item that is quite long</a>
</li>
<li class="current">
<a href="#ab">menu item</a>
<ul>
<li class="current"><a href="#">menu item</a></li>
<li><a href="#aba">menu item</a></li>
<li><a href="#abb">menu item</a></li>
<li><a href="#abc">menu item</a></li>
<li><a href="#abd">menu item</a></li>
</ul>
</li>
<li>
<a href="#">menu item</a>
<ul>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
</ul>
</li>
<li>
<a href="#">menu item</a>
<ul>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
</ul>
</li>
</ul>
</li>
<li>
<a href="#">menu item</a>
</li>
<li>
<a href="#">menu item</a>
<ul>
<li>
<a href="#">menu item</a>
<ul>
<li><a href="#">short</a></li>
<li><a href="#">short</a></li>
<li><a href="#">short</a></li>
<li><a href="#">short</a></li>
<li><a href="#">short</a></li>
</ul>
</li>
<li>
<a href="#">menu item</a>
<ul>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
</ul>
</li>
<li>
<a href="#">menu item</a>
<ul>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
</ul>
</li>
<li>
<a href="#">menu item</a>
<ul>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
</ul>
</li>
<li>
<a href="#">menu item</a>
<ul>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
<li><a href="#">menu item</a></li>
</ul>
</li>
</ul>
</li>
<li>
<a href="#">menu item</a>
</li>
</ul>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1,84 +0,0 @@
(function($){
/* hoverIntent by Brian Cherne */
$.fn.hoverIntent = function(f,g) {
// default configuration options
var cfg = {
sensitivity: 7,
interval: 100,
timeout: 0
};
// override configuration options with user supplied object
cfg = $.extend(cfg, g ? { over: f, out: g } : f );
// instantiate variables
// cX, cY = current X and Y position of mouse, updated by mousemove event
// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
var cX, cY, pX, pY;
// A private function for getting mouse position
var track = function(ev) {
cX = ev.pageX;
cY = ev.pageY;
};
// A private function for comparing current and previous mouse position
var compare = function(ev,ob) {
ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
// compare mouse positions to see if they've crossed the threshold
if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
$(ob).unbind("mousemove",track);
// set hoverIntent state to true (so mouseOut can be called)
ob.hoverIntent_s = 1;
return cfg.over.apply(ob,[ev]);
} else {
// set previous coordinates for next time
pX = cX; pY = cY;
// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
}
};
// A private function for delaying the mouseOut function
var delay = function(ev,ob) {
ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
ob.hoverIntent_s = 0;
return cfg.out.apply(ob,[ev]);
};
// A private function for handling mouse 'hovering'
var handleHover = function(e) {
// next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
if ( p == this ) { return false; }
// copy objects to be passed into t (required for event object to be passed in IE)
var ev = jQuery.extend({},e);
var ob = this;
// cancel hoverIntent timer if it exists
if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }
// else e.type == "onmouseover"
if (e.type == "mouseover") {
// set "previous" X and Y position based on initial entry point
pX = ev.pageX; pY = ev.pageY;
// update "current" X and Y position based on mousemove
$(ob).bind("mousemove",track);
// start polling interval (self-calling timeout) to compare mouse coordinates over time
if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}
// else e.type == "onmouseout"
} else {
// unbind expensive mousemove event
$(ob).unbind("mousemove",track);
// if hoverIntent state is true, then call the mouseOut function after the specified delay
if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
}
};
// bind the function to the two event listeners
return this.mouseover(handleHover).mouseout(handleHover);
};
})(jQuery);

File diff suppressed because one or more lines are too long

View File

@ -1,10 +0,0 @@
/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
*
* $LastChangedDate: 2007-06-19 20:25:28 -0500 (Tue, 19 Jun 2007) $
* $Rev: 2111 $
*
* Version 2.1
*/
(function($){$.fn.bgIframe=$.fn.bgiframe=function(s){if($.browser.msie&&parseInt($.browser.version)<=6){s=$.extend({top:'auto',left:'auto',width:'auto',height:'auto',opacity:true,src:'javascript:false;'},s||{});var prop=function(n){return n&&n.constructor==Number?n+'px':n;},html='<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+'style="display:block;position:absolute;z-index:-1;'+(s.opacity!==false?'filter:Alpha(Opacity=\'0\');':'')+'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+'"/>';return this.each(function(){if($('> iframe.bgiframe',this).length==0)this.insertBefore(document.createElement(html),this.firstChild);});}return this;};if(!$.browser.version)$.browser.version=navigator.userAgent.toLowerCase().match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)[1];})(jQuery);

View File

@ -1,121 +0,0 @@
/*
* Superfish v1.4.8 - jQuery menu widget
* Copyright (c) 2008 Joel Birch
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
* CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt
*/
;(function($){
$.fn.superfish = function(op){
var sf = $.fn.superfish,
c = sf.c,
$arrow = $(['<span class="',c.arrowClass,'"> &#187;</span>'].join('')),
over = function(){
var $$ = $(this), menu = getMenu($$);
clearTimeout(menu.sfTimer);
$$.showSuperfishUl().siblings().hideSuperfishUl();
},
out = function(){
var $$ = $(this), menu = getMenu($$), o = sf.op;
clearTimeout(menu.sfTimer);
menu.sfTimer=setTimeout(function(){
o.retainPath=($.inArray($$[0],o.$path)>-1);
$$.hideSuperfishUl();
if (o.$path.length && $$.parents(['li.',o.hoverClass].join('')).length<1){over.call(o.$path);}
},o.delay);
},
getMenu = function($menu){
var menu = $menu.parents(['ul.',c.menuClass,':first'].join(''))[0];
sf.op = sf.o[menu.serial];
return menu;
},
addArrow = function($a){ $a.addClass(c.anchorClass).append($arrow.clone()); };
return this.each(function() {
var s = this.serial = sf.o.length;
var o = $.extend({},sf.defaults,op);
o.$path = $('li.'+o.pathClass,this).slice(0,o.pathLevels).each(function(){
$(this).addClass([o.hoverClass,c.bcClass].join(' '))
.filter('li:has(ul)').removeClass(o.pathClass);
});
sf.o[s] = sf.op = o;
$('li:has(ul)',this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() {
if (o.autoArrows) addArrow( $('>a:first-child',this) );
})
.not('.'+c.bcClass)
.hideSuperfishUl();
var $a = $('a',this);
$a.each(function(i){
var $li = $a.eq(i).parents('li');
$a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);});
});
o.onInit.call(this);
}).each(function() {
var menuClasses = [c.menuClass];
if (sf.op.dropShadows && !($.browser.msie && $.browser.version < 7)) menuClasses.push(c.shadowClass);
$(this).addClass(menuClasses.join(' '));
});
};
var sf = $.fn.superfish;
sf.o = [];
sf.op = {};
sf.IE7fix = function(){
var o = sf.op;
if ($.browser.msie && $.browser.version > 6 && o.dropShadows && o.animation.opacity!=undefined)
this.toggleClass(sf.c.shadowClass+'-off');
};
sf.c = {
bcClass : 'sf-breadcrumb',
menuClass : 'sf-js-enabled',
anchorClass : 'sf-with-ul',
arrowClass : 'sf-sub-indicator',
shadowClass : 'sf-shadow'
};
sf.defaults = {
hoverClass : 'sfHover',
pathClass : 'overideThisToUse',
pathLevels : 1,
delay : 800,
animation : {opacity:'show'},
speed : 'normal',
autoArrows : true,
dropShadows : true,
disableHI : false, // true disables hoverIntent detection
onInit : function(){}, // callback functions
onBeforeShow: function(){},
onShow : function(){},
onHide : function(){}
};
$.fn.extend({
hideSuperfishUl : function(){
var o = sf.op,
not = (o.retainPath===true) ? o.$path : '';
o.retainPath = false;
var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass)
.find('>ul').hide().css('visibility','hidden');
o.onHide.call($ul);
return this;
},
showSuperfishUl : function(){
var o = sf.op,
sh = sf.c.shadowClass+'-off',
$ul = this.addClass(o.hoverClass)
.find('>ul:hidden').css('visibility','visible');
sf.IE7fix.call($ul);
o.onBeforeShow.call($ul);
$ul.animate(o.animation,o.speed,function(){ sf.IE7fix.call($ul); o.onShow.call($ul); });
return this;
}
});
})(jQuery);

View File

@ -1,90 +0,0 @@
/*
* Supersubs v0.2b - jQuery plugin
* Copyright (c) 2008 Joel Birch
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*
* This plugin automatically adjusts submenu widths of suckerfish-style menus to that of
* their longest list item children. If you use this, please expect bugs and report them
* to the jQuery Google Group with the word 'Superfish' in the subject line.
*
*/
;(function($){ // $ will refer to jQuery within this closure
$.fn.supersubs = function(options){
var opts = $.extend({}, $.fn.supersubs.defaults, options);
// return original object to support chaining
return this.each(function() {
// cache selections
var $$ = $(this);
// support metadata
var o = $.meta ? $.extend({}, opts, $$.data()) : opts;
// get the font size of menu.
// .css('fontSize') returns various results cross-browser, so measure an em dash instead
var fontsize = $('<li id="menu-fontsize">&#8212;</li>').css({
'padding' : 0,
'position' : 'absolute',
'top' : '-999em',
'width' : 'auto'
}).appendTo($$).width(); //clientWidth is faster, but was incorrect here
// remove em dash
$('#menu-fontsize').remove();
// cache all ul elements
$ULs = $$.find('ul');
// loop through each ul in menu
$ULs.each(function(i) {
// cache this ul
var $ul = $ULs.eq(i);
// get all (li) children of this ul
var $LIs = $ul.children();
// get all anchor grand-children
var $As = $LIs.children('a');
// force content to one line and save current float property
var liFloat = $LIs.css('white-space','nowrap').css('float');
// remove width restrictions and floats so elements remain vertically stacked
var emWidth = $ul.add($LIs).add($As).css({
'float' : 'none',
'width' : 'auto'
})
// this ul will now be shrink-wrapped to longest li due to position:absolute
// so save its width as ems. Clientwidth is 2 times faster than .width() - thanks Dan Switzer
.end().end()[0].clientWidth / fontsize;
// add more width to ensure lines don't turn over at certain sizes in various browsers
emWidth += o.extraWidth;
// restrict to at least minWidth and at most maxWidth
if (emWidth > o.maxWidth) { emWidth = o.maxWidth; }
else if (emWidth < o.minWidth) { emWidth = o.minWidth; }
emWidth += 'em';
// set ul to width in ems
$ul.css('width',emWidth);
// restore li floats to avoid IE bugs
// set li width to full width of this ul
// revert white-space to normal
$LIs.css({
'float' : liFloat,
'width' : '100%',
'white-space' : 'normal'
})
// update offset position of descendant ul to reflect new width of parent
.each(function(){
var $childUl = $('>ul',this);
var offsetDirection = $childUl.css('left')!==undefined ? 'left' : 'right';
$childUl.css(offsetDirection,emWidth);
});
});
});
};
// expose defaults
$.fn.supersubs.defaults = {
minWidth : 9, // requires em unit.
maxWidth : 25, // requires em unit.
extraWidth : 0 // extra width can ensure lines don't sometimes turn over due to slight browser differences in how they round-off values
};
})(jQuery); // plugin code ends

View File

@ -0,0 +1,152 @@
/**
* Timeago is a jQuery plugin that makes it easy to support automatically
* updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
*
* @name timeago
* @version 0.11.3
* @requires jQuery v1.2.3+
* @author Ryan McGeary
* @license MIT License - http://www.opensource.org/licenses/mit-license.php
*
* For usage and examples, visit:
* http://timeago.yarp.com/
*
* Copyright (c) 2008-2012, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)
*/
(function($) {
$.timeago = function(timestamp) {
if (timestamp instanceof Date) {
return inWords(timestamp);
} else if (typeof timestamp === "string") {
return inWords($.timeago.parse(timestamp));
} else if (typeof timestamp === "number") {
return inWords(new Date(timestamp));
} else {
return inWords($.timeago.datetime(timestamp));
}
};
var $t = $.timeago;
$.extend($.timeago, {
settings: {
refreshMillis: 60000,
allowFuture: false,
strings: {
prefixAgo: null,
prefixFromNow: null,
suffixAgo: "ago",
suffixFromNow: "from now",
seconds: "less than a minute",
minute: "about a minute",
minutes: "%d minutes",
hour: "about an hour",
hours: "about %d hours",
day: "a day",
days: "%d days",
month: "about a month",
months: "%d months",
year: "about a year",
years: "%d years",
wordSeparator: " ",
numbers: []
}
},
inWords: function(distanceMillis) {
var $l = this.settings.strings;
var prefix = $l.prefixAgo;
var suffix = $l.suffixAgo;
if (this.settings.allowFuture) {
if (distanceMillis < 0) {
prefix = $l.prefixFromNow;
suffix = $l.suffixFromNow;
}
}
var seconds = Math.abs(distanceMillis) / 1000;
var minutes = seconds / 60;
var hours = minutes / 60;
var days = hours / 24;
var years = days / 365;
function substitute(stringOrFunction, number) {
var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
var value = ($l.numbers && $l.numbers[number]) || number;
return string.replace(/%d/i, value);
}
var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
seconds < 90 && substitute($l.minute, 1) ||
minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
minutes < 90 && substitute($l.hour, 1) ||
hours < 24 && substitute($l.hours, Math.round(hours)) ||
hours < 42 && substitute($l.day, 1) ||
days < 30 && substitute($l.days, Math.round(days)) ||
days < 45 && substitute($l.month, 1) ||
days < 365 && substitute($l.months, Math.round(days / 30)) ||
years < 1.5 && substitute($l.year, 1) ||
substitute($l.years, Math.round(years));
var separator = $l.wordSeparator === undefined ? " " : $l.wordSeparator;
return $.trim([prefix, words, suffix].join(separator));
},
parse: function(iso8601) {
var s = $.trim(iso8601);
s = s.replace(/\.\d\d\d+/,""); // remove milliseconds
s = s.replace(/-/,"/").replace(/-/,"/");
s = s.replace(/T/," ").replace(/Z/," UTC");
s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
return new Date(s);
},
datetime: function(elem) {
var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title");
return $t.parse(iso8601);
},
isTime: function(elem) {
// jQuery's `is()` doesn't play well with HTML5 in IE
return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
}
});
$.fn.timeago = function() {
var self = this;
self.each(refresh);
var $s = $t.settings;
if ($s.refreshMillis > 0) {
setInterval(function() { self.each(refresh); }, $s.refreshMillis);
}
return self;
};
function refresh() {
var data = prepareData(this);
if (!isNaN(data.datetime)) {
$(this).text(inWords(data.datetime));
}
return this;
}
function prepareData(element) {
element = $(element);
if (!element.data("timeago")) {
element.data("timeago", { datetime: $t.datetime(element) });
var text = $.trim(element.text());
if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) {
element.attr("title", text);
}
}
return element.data("timeago");
}
function inWords(date) {
return $t.inWords(distance(date));
}
function distance(date) {
return (new Date().getTime() - date.getTime());
}
// fix for IE6 suckage
document.createElement("abbr");
document.createElement("time");
}(jQuery));

View File

@ -1,480 +0,0 @@
/*
http://www.JSON.org/json2.js
2011-02-23
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
See http://www.JSON.org/js.html
This code should be minified before deployment.
See http://javascript.crockford.com/jsmin.html
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
NOT CONTROL.
This file creates a global JSON object containing two methods: stringify
and parse.
JSON.stringify(value, replacer, space)
value any JavaScript value, usually an object or array.
replacer an optional parameter that determines how object
values are stringified for objects. It can be a
function or an array of strings.
space an optional parameter that specifies the indentation
of nested structures. If it is omitted, the text will
be packed without extra whitespace. If it is a number,
it will specify the number of spaces to indent at each
level. If it is a string (such as '\t' or '&nbsp;'),
it contains the characters used to indent at each level.
This method produces a JSON text from a JavaScript value.
When an object value is found, if the object contains a toJSON
method, its toJSON method will be called and the result will be
stringified. A toJSON method does not serialize: it returns the
value represented by the name/value pair that should be serialized,
or undefined if nothing should be serialized. The toJSON method
will be passed the key associated with the value, and this will be
bound to the value
For example, this would serialize Dates as ISO strings.
Date.prototype.toJSON = function (key) {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
return this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z';
};
You can provide an optional replacer method. It will be passed the
key and value of each member, with this bound to the containing
object. The value that is returned from your method will be
serialized. If your method returns undefined, then the member will
be excluded from the serialization.
If the replacer parameter is an array of strings, then it will be
used to select the members to be serialized. It filters the results
such that only members with keys listed in the replacer array are
stringified.
Values that do not have JSON representations, such as undefined or
functions, will not be serialized. Such values in objects will be
dropped; in arrays they will be replaced with null. You can use
a replacer function to replace those with JSON values.
JSON.stringify(undefined) returns undefined.
The optional space parameter produces a stringification of the
value that is filled with line breaks and indentation to make it
easier to read.
If the space parameter is a non-empty string, then that string will
be used for indentation. If the space parameter is a number, then
the indentation will be that many spaces.
Example:
text = JSON.stringify(['e', {pluribus: 'unum'}]);
// text is '["e",{"pluribus":"unum"}]'
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
text = JSON.stringify([new Date()], function (key, value) {
return this[key] instanceof Date ?
'Date(' + this[key] + ')' : value;
});
// text is '["Date(---current time---)"]'
JSON.parse(text, reviver)
This method parses a JSON text to produce an object or array.
It can throw a SyntaxError exception.
The optional reviver parameter is a function that can filter and
transform the results. It receives each of the keys and values,
and its return value is used instead of the original value.
If it returns what it received, then the structure is not modified.
If it returns undefined then the member is deleted.
Example:
// Parse the text. Values that look like ISO date strings will
// be converted to Date objects.
myData = JSON.parse(text, function (key, value) {
var a;
if (typeof value === 'string') {
a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
if (a) {
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+a[5], +a[6]));
}
}
return value;
});
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
var d;
if (typeof value === 'string' &&
value.slice(0, 5) === 'Date(' &&
value.slice(-1) === ')') {
d = new Date(value.slice(5, -1));
if (d) {
return d;
}
}
return value;
});
This is a reference implementation. You are free to copy, modify, or
redistribute.
*/
/*jslint evil: true, strict: false, regexp: false */
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
*/
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
var JSON;
if (!JSON) {
JSON = {};
}
(function () {
"use strict";
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
if (typeof Date.prototype.toJSON !== 'function') {
Date.prototype.toJSON = function (key) {
return isFinite(this.valueOf()) ?
this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z' : null;
};
String.prototype.toJSON =
Number.prototype.toJSON =
Boolean.prototype.toJSON = function (key) {
return this.valueOf();
};
}
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
gap,
indent,
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
},
rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string' ? c :
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' : '"' + string + '"';
}
function str(key, holder) {
// Produce a string from holder[key].
var i, // The loop counter.
k, // The member key.
v, // The member value.
length,
mind = gap,
partial,
value = holder[key];
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === 'function') {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// null.
case 'object':
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
if (!value) {
return 'null';
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === '[object Array]') {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0 ? '[]' : gap ?
'[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
'[' + partial.join(',') + ']';
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === 'object') {
length = rep.length;
for (i = 0; i < length; i += 1) {
if (typeof rep[i] === 'string') {
k = rep[i];
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0 ? '{}' : gap ?
'{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
'{' + partial.join(',') + '}';
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
JSON.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = '';
indent = '';
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === 'number') {
for (i = 0; i < space; i += 1) {
indent += ' ';
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === 'string') {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
}
// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.
return str('', {'': value});
};
}
// If the JSON object does not yet have a parse method, give it one.
if (typeof JSON.parse !== 'function') {
JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
var j;
function walk(holder, key) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
text = String(text);
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval('(' + text + ')');
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function' ?
walk({'': j}, '') : j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError('JSON.parse');
};
}
}());

View File

@ -1,514 +0,0 @@
/*! LAB.js (LABjs :: Loading And Blocking JavaScript)
v2.0.3 (c) Kyle Simpson
MIT License
*/
(function(global){
var _$LAB = global.$LAB,
// constants for the valid keys of the options object
_UseLocalXHR = "UseLocalXHR",
_AlwaysPreserveOrder = "AlwaysPreserveOrder",
_AllowDuplicates = "AllowDuplicates",
_CacheBust = "CacheBust",
/*!START_DEBUG*/_Debug = "Debug",/*!END_DEBUG*/
_BasePath = "BasePath",
// stateless variables used across all $LAB instances
root_page = /^[^?#]*\//.exec(location.href)[0],
root_domain = /^\w+\:\/\/\/?[^\/]+/.exec(root_page)[0],
append_to = document.head || document.getElementsByTagName("head"),
// inferences... ick, but still necessary
opera_or_gecko = (global.opera && Object.prototype.toString.call(global.opera) == "[object Opera]") || ("MozAppearance" in document.documentElement.style),
/*!START_DEBUG*/
// console.log() and console.error() wrappers
log_msg = function(){},
log_error = log_msg,
/*!END_DEBUG*/
// feature sniffs (yay!)
test_script_elem = document.createElement("script"),
explicit_preloading = typeof test_script_elem.preload == "boolean", // http://wiki.whatwg.org/wiki/Script_Execution_Control#Proposal_1_.28Nicholas_Zakas.29
real_preloading = explicit_preloading || (test_script_elem.readyState && test_script_elem.readyState == "uninitialized"), // will a script preload with `src` set before DOM append?
script_ordered_async = !real_preloading && test_script_elem.async === true, // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
// XHR preloading (same-domain) and cache-preloading (remote-domain) are the fallbacks (for some browsers)
xhr_or_cache_preloading = !real_preloading && !script_ordered_async && !opera_or_gecko
;
/*!START_DEBUG*/
// define console wrapper functions if applicable
if (global.console && global.console.log) {
if (!global.console.error) global.console.error = global.console.log;
log_msg = function(msg) { global.console.log(msg); };
log_error = function(msg,err) { global.console.error(msg,err); };
}
/*!END_DEBUG*/
// test for function
function is_func(func) { return Object.prototype.toString.call(func) == "[object Function]"; }
// test for array
function is_array(arr) { return Object.prototype.toString.call(arr) == "[object Array]"; }
// make script URL absolute/canonical
function canonical_uri(src,base_path) {
var absolute_regex = /^\w+\:\/\//;
// is `src` is protocol-relative (begins with // or ///), prepend protocol
if (/^\/\/\/?/.test(src)) {
src = location.protocol + src;
}
// is `src` page-relative? (not an absolute URL, and not a domain-relative path, beginning with /)
else if (!absolute_regex.test(src) && src.charAt(0) != "/") {
// prepend `base_path`, if any
src = (base_path || "") + src;
}
// make sure to return `src` as absolute
return absolute_regex.test(src) ? src : ((src.charAt(0) == "/" ? root_domain : root_page) + src);
}
// merge `source` into `target`
function merge_objs(source,target) {
for (var k in source) { if (source.hasOwnProperty(k)) {
target[k] = source[k]; // TODO: does this need to be recursive for our purposes?
}}
return target;
}
// does the chain group have any ready-to-execute scripts?
function check_chain_group_scripts_ready(chain_group) {
var any_scripts_ready = false;
for (var i=0; i<chain_group.scripts.length; i++) {
if (chain_group.scripts[i].ready && chain_group.scripts[i].exec_trigger) {
any_scripts_ready = true;
chain_group.scripts[i].exec_trigger();
chain_group.scripts[i].exec_trigger = null;
}
}
return any_scripts_ready;
}
// creates a script load listener
function create_script_load_listener(elem,registry_item,flag,onload) {
elem.onload = elem.onreadystatechange = function() {
if ((elem.readyState && elem.readyState != "complete" && elem.readyState != "loaded") || registry_item[flag]) return;
elem.onload = elem.onreadystatechange = null;
onload();
};
}
// script executed handler
function script_executed(registry_item) {
registry_item.ready = registry_item.finished = true;
for (var i=0; i<registry_item.finished_listeners.length; i++) {
registry_item.finished_listeners[i]();
}
registry_item.ready_listeners = [];
registry_item.finished_listeners = [];
}
// make the request for a scriptha
function request_script(chain_opts,script_obj,registry_item,onload,preload_this_script) {
// setTimeout() "yielding" prevents some weird race/crash conditions in older browsers
setTimeout(function(){
var script, src = script_obj.real_src, xhr;
// don't proceed until `append_to` is ready to append to
if ("item" in append_to) { // check if `append_to` ref is still a live node list
if (!append_to[0]) { // `append_to` node not yet ready
// try again in a little bit -- note: will re-call the anonymous function in the outer setTimeout, not the parent `request_script()`
setTimeout(arguments.callee,25);
return;
}
// reassign from live node list ref to pure node ref -- avoids nasty IE bug where changes to DOM invalidate live node lists
append_to = append_to[0];
}
script = document.createElement("script");
if (script_obj.type) script.type = script_obj.type;
if (script_obj.charset) script.charset = script_obj.charset;
// should preloading be used for this script?
if (preload_this_script) {
// real script preloading?
if (real_preloading) {
/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script preload: "+src);/*!END_DEBUG*/
registry_item.elem = script;
if (explicit_preloading) { // explicit preloading (aka, Zakas' proposal)
script.preload = true;
script.onpreload = onload;
}
else {
script.onreadystatechange = function(){
if (script.readyState == "loaded") onload();
};
}
script.src = src;
// NOTE: no append to DOM yet, appending will happen when ready to execute
}
// same-domain and XHR allowed? use XHR preloading
else if (preload_this_script && src.indexOf(root_domain) == 0 && chain_opts[_UseLocalXHR]) {
xhr = new XMLHttpRequest(); // note: IE never uses XHR (it supports true preloading), so no more need for ActiveXObject fallback for IE <= 7
/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script preload (xhr): "+src);/*!END_DEBUG*/
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
xhr.onreadystatechange = function(){}; // fix a memory leak in IE
registry_item.text = xhr.responseText + "\n//@ sourceURL=" + src; // http://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/
onload();
}
};
xhr.open("GET",src);
xhr.send();
}
// as a last resort, use cache-preloading
else {
/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script preload (cache): "+src);/*!END_DEBUG*/
script.type = "text/cache-script";
create_script_load_listener(script,registry_item,"ready",function() {
append_to.removeChild(script);
onload();
});
script.src = src;
append_to.insertBefore(script,append_to.firstChild);
}
}
// use async=false for ordered async? parallel-load-serial-execute http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
else if (script_ordered_async) {
/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script load (ordered async): "+src);/*!END_DEBUG*/
script.async = false;
create_script_load_listener(script,registry_item,"finished",onload);
script.src = src;
append_to.insertBefore(script,append_to.firstChild);
}
// otherwise, just a normal script element
else {
/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script load: "+src);/*!END_DEBUG*/
create_script_load_listener(script,registry_item,"finished",onload);
script.src = src;
append_to.insertBefore(script,append_to.firstChild);
}
},0);
}
// create a clean instance of $LAB
function create_sandbox() {
var global_defaults = {},
can_use_preloading = real_preloading || xhr_or_cache_preloading,
queue = [],
registry = {},
instanceAPI
;
// global defaults
global_defaults[_UseLocalXHR] = true;
global_defaults[_AlwaysPreserveOrder] = false;
global_defaults[_AllowDuplicates] = false;
global_defaults[_CacheBust] = false;
/*!START_DEBUG*/global_defaults[_Debug] = false;/*!END_DEBUG*/
global_defaults[_BasePath] = "";
// execute a script that has been preloaded already
function execute_preloaded_script(chain_opts,script_obj,registry_item) {
var script;
function preload_execute_finished() {
if (script != null) { // make sure this only ever fires once
script = null;
script_executed(registry_item);
}
}
if (registry[script_obj.src].finished) return;
if (!chain_opts[_AllowDuplicates]) registry[script_obj.src].finished = true;
script = registry_item.elem || document.createElement("script");
if (script_obj.type) script.type = script_obj.type;
if (script_obj.charset) script.charset = script_obj.charset;
create_script_load_listener(script,registry_item,"finished",preload_execute_finished);
// script elem was real-preloaded
if (registry_item.elem) {
registry_item.elem = null;
}
// script was XHR preloaded
else if (registry_item.text) {
script.onload = script.onreadystatechange = null; // script injection doesn't fire these events
script.text = registry_item.text;
}
// script was cache-preloaded
else {
script.src = script_obj.real_src;
}
append_to.insertBefore(script,append_to.firstChild);
// manually fire execution callback for injected scripts, since events don't fire
if (registry_item.text) {
preload_execute_finished();
}
}
// process the script request setup
function do_script(chain_opts,script_obj,chain_group,preload_this_script) {
var registry_item,
registry_items,
ready_cb = function(){ script_obj.ready_cb(script_obj,function(){ execute_preloaded_script(chain_opts,script_obj,registry_item); }); },
finished_cb = function(){ script_obj.finished_cb(script_obj,chain_group); }
;
script_obj.src = canonical_uri(script_obj.src,chain_opts[_BasePath]);
script_obj.real_src = script_obj.src +
// append cache-bust param to URL?
(chain_opts[_CacheBust] ? ((/\?.*$/.test(script_obj.src) ? "&_" : "?_") + ~~(Math.random()*1E9) + "=") : "")
;
if (!registry[script_obj.src]) registry[script_obj.src] = {items:[],finished:false};
registry_items = registry[script_obj.src].items;
// allowing duplicates, or is this the first recorded load of this script?
if (chain_opts[_AllowDuplicates] || registry_items.length == 0) {
registry_item = registry_items[registry_items.length] = {
ready:false,
finished:false,
ready_listeners:[ready_cb],
finished_listeners:[finished_cb]
};
request_script(chain_opts,script_obj,registry_item,
// which callback type to pass?
(
(preload_this_script) ? // depends on script-preloading
function(){
registry_item.ready = true;
for (var i=0; i<registry_item.ready_listeners.length; i++) {
registry_item.ready_listeners[i]();
}
registry_item.ready_listeners = [];
} :
function(){ script_executed(registry_item); }
),
// signal if script-preloading should be used or not
preload_this_script
);
}
else {
registry_item = registry_items[0];
if (registry_item.finished) {
finished_cb();
}
else {
registry_item.finished_listeners.push(finished_cb);
}
}
}
// creates a closure for each separate chain spawned from this $LAB instance, to keep state cleanly separated between chains
function create_chain() {
var chainedAPI,
chain_opts = merge_objs(global_defaults,{}),
chain = [],
exec_cursor = 0,
scripts_currently_loading = false,
group
;
// called when a script has finished preloading
function chain_script_ready(script_obj,exec_trigger) {
/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("script preload finished: "+script_obj.real_src);/*!END_DEBUG*/
script_obj.ready = true;
script_obj.exec_trigger = exec_trigger;
advance_exec_cursor(); // will only check for 'ready' scripts to be executed
}
// called when a script has finished executing
function chain_script_executed(script_obj,chain_group) {
/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("script execution finished: "+script_obj.real_src);/*!END_DEBUG*/
script_obj.ready = script_obj.finished = true;
script_obj.exec_trigger = null;
// check if chain group is all finished
for (var i=0; i<chain_group.scripts.length; i++) {
if (!chain_group.scripts[i].finished) return;
}
// chain_group is all finished if we get this far
chain_group.finished = true;
advance_exec_cursor();
}
// main driver for executing each part of the chain
function advance_exec_cursor() {
while (exec_cursor < chain.length) {
if (is_func(chain[exec_cursor])) {
/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("$LAB.wait() executing: "+chain[exec_cursor]);/*!END_DEBUG*/
try { chain[exec_cursor++](); } catch (err) {
/*!START_DEBUG*/if (chain_opts[_Debug]) log_error("$LAB.wait() error caught: ",err);/*!END_DEBUG*/
}
continue;
}
else if (!chain[exec_cursor].finished) {
if (check_chain_group_scripts_ready(chain[exec_cursor])) continue;
break;
}
exec_cursor++;
}
// we've reached the end of the chain (so far)
if (exec_cursor == chain.length) {
scripts_currently_loading = false;
group = false;
}
}
// setup next chain script group
function init_script_chain_group() {
if (!group || !group.scripts) {
chain.push(group = {scripts:[],finished:true});
}
}
// API for $LAB chains
chainedAPI = {
// start loading one or more scripts
script:function(){
for (var i=0; i<arguments.length; i++) {
(function(script_obj,script_list){
var splice_args;
if (!is_array(script_obj)) {
script_list = [script_obj];
}
for (var j=0; j<script_list.length; j++) {
init_script_chain_group();
script_obj = script_list[j];
if (is_func(script_obj)) script_obj = script_obj();
if (!script_obj) continue;
if (is_array(script_obj)) {
// set up an array of arguments to pass to splice()
splice_args = [].slice.call(script_obj); // first include the actual array elements we want to splice in
splice_args.unshift(j,1); // next, put the `index` and `howMany` parameters onto the beginning of the splice-arguments array
[].splice.apply(script_list,splice_args); // use the splice-arguments array as arguments for splice()
j--; // adjust `j` to account for the loop's subsequent `j++`, so that the next loop iteration uses the same `j` index value
continue;
}
if (typeof script_obj == "string") script_obj = {src:script_obj};
script_obj = merge_objs(script_obj,{
ready:false,
ready_cb:chain_script_ready,
finished:false,
finished_cb:chain_script_executed
});
group.finished = false;
group.scripts.push(script_obj);
do_script(chain_opts,script_obj,group,(can_use_preloading && scripts_currently_loading));
scripts_currently_loading = true;
if (chain_opts[_AlwaysPreserveOrder]) chainedAPI.wait();
}
})(arguments[i],arguments[i]);
}
return chainedAPI;
},
// force LABjs to pause in execution at this point in the chain, until the execution thus far finishes, before proceeding
wait:function(){
if (arguments.length > 0) {
for (var i=0; i<arguments.length; i++) {
chain.push(arguments[i]);
}
group = chain[chain.length-1];
}
else group = false;
advance_exec_cursor();
return chainedAPI;
}
};
// the first chain link API (includes `setOptions` only this first time)
return {
script:chainedAPI.script,
wait:chainedAPI.wait,
setOptions:function(opts){
merge_objs(opts,chain_opts);
return chainedAPI;
}
};
}
// API for each initial $LAB instance (before chaining starts)
instanceAPI = {
// main API functions
setGlobalDefaults:function(opts){
merge_objs(opts,global_defaults);
return instanceAPI;
},
setOptions:function(){
return create_chain().setOptions.apply(null,arguments);
},
script:function(){
return create_chain().script.apply(null,arguments);
},
wait:function(){
return create_chain().wait.apply(null,arguments);
},
// built-in queuing for $LAB `script()` and `wait()` calls
// useful for building up a chain programmatically across various script locations, and simulating
// execution of the chain
queueScript:function(){
queue[queue.length] = {type:"script", args:[].slice.call(arguments)};
return instanceAPI;
},
queueWait:function(){
queue[queue.length] = {type:"wait", args:[].slice.call(arguments)};
return instanceAPI;
},
runQueue:function(){
var $L = instanceAPI, len=queue.length, i=len, val;
for (;--i>=0;) {
val = queue.shift();
$L = $L[val.type].apply(null,val.args);
}
return $L;
},
// rollback `[global].$LAB` to what it was before this file was loaded, the return this current instance of $LAB
noConflict:function(){
global.$LAB = _$LAB;
return instanceAPI;
},
// create another clean instance of $LAB
sandbox:function(){
return create_sandbox();
}
};
return instanceAPI;
}
// create the main instance of $LAB
global.$LAB = create_sandbox();
/* The following "hack" was suggested by Andrea Giammarchi and adapted from: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html
NOTE: this hack only operates in FF and then only in versions where document.readyState is not present (FF < 3.6?).
The hack essentially "patches" the **page** that LABjs is loaded onto so that it has a proper conforming document.readyState, so that if a script which does
proper and safe dom-ready detection is loaded onto a page, after dom-ready has passed, it will still be able to detect this state, by inspecting the now hacked
document.readyState property. The loaded script in question can then immediately trigger any queued code executions that were waiting for the DOM to be ready.
For instance, jQuery 1.4+ has been patched to take advantage of document.readyState, which is enabled by this hack. But 1.3.2 and before are **not** safe or
fixed by this hack, and should therefore **not** be lazy-loaded by script loader tools such as LABjs.
*/
(function(addEvent,domLoaded,handler){
if (document.readyState == null && document[addEvent]){
document.readyState = "loading";
document[addEvent](domLoaded,handler = function(){
document.removeEventListener(domLoaded,handler,false);
document.readyState = "complete";
},false);
}
})("addEventListener","DOMContentLoaded");
})(this);

View File

@ -152,10 +152,13 @@
box-shadow: 0 0 3px #80bfff, 0 1px 1px rgba(255, 255, 255, 0.8) inset;
}
.openerp a.button:active, .openerp a.button.active, .openerp button:active, .openerp button.active, .openerp input[type='submit']:active, .openerp input[type='submit'].active {
background: #e3e3e3;
background: -moz-linear-gradient(top, #e3e3e3, #f6f6f6) #1b468f;
background: -webkit-gradient(linear, left top, left bottom, from(#e3e3e3), to(#f6f6f6)) #1b468f;
background: linear-gradient(top, #e3e3e3, #f6f6f6) #1b468f;
background-color: #e3e3e3;
background-image: -webkit-gradient(linear, left top, left bottom, from(#e3e3e3), to(#f6f6f6));
background-image: -webkit-linear-gradient(top, #e3e3e3, #f6f6f6);
background-image: -moz-linear-gradient(top, #e3e3e3, #f6f6f6);
background-image: -ms-linear-gradient(top, #e3e3e3, #f6f6f6);
background-image: -o-linear-gradient(top, #e3e3e3, #f6f6f6);
background-image: linear-gradient(to bottom, #e3e3e3, #f6f6f6);
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
@ -215,8 +218,8 @@
.openerp .oe_bold {
font-weight: bold;
}
.openerp .oe_inline  {
width: auto;
.openerp .oe_inline {
width: auto !important;
}
.openerp .oe_highlight {
color: white;
@ -1523,10 +1526,47 @@
.openerp .oe_form_button_save_dirty:hover {
background: #ed6f6a;
}
.openerp .oe_form_invisible {
display: none !important;
.openerp .oe_form_editable .oe_highlight {
color: #404040;
background: none;
}
.openerp .oe_form_editable .oe_edit_only {
.openerp .oe_form_editable button.oe_highlight {
background-color: #efefef;
background-image: -webkit-gradient(linear, left top, left bottom, from(#efefef), to(#d8d8d8));
background-image: -webkit-linear-gradient(top, #efefef, #d8d8d8);
background-image: -moz-linear-gradient(top, #efefef, #d8d8d8);
background-image: -ms-linear-gradient(top, #efefef, #d8d8d8);
background-image: -o-linear-gradient(top, #efefef, #d8d8d8);
background-image: linear-gradient(to bottom, #efefef, #d8d8d8);
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
}
.openerp .oe_form_editable button.oe_highlight:active {
background-color: #e3e3e3;
background-image: -webkit-gradient(linear, left top, left bottom, from(#e3e3e3), to(#f6f6f6));
background-image: -webkit-linear-gradient(top, #e3e3e3, #f6f6f6);
background-image: -moz-linear-gradient(top, #e3e3e3, #f6f6f6);
background-image: -ms-linear-gradient(top, #e3e3e3, #f6f6f6);
background-image: -o-linear-gradient(top, #e3e3e3, #f6f6f6);
background-image: linear-gradient(to bottom, #e3e3e3, #f6f6f6);
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
}
.openerp .oe_form_editable button.oe_highlight:hover {
background-color: #f6f6f6;
background-image: -webkit-gradient(linear, left top, left bottom, from(#f6f6f6), to(#e3e3e3));
background-image: -webkit-linear-gradient(top, #f6f6f6, #e3e3e3);
background-image: -moz-linear-gradient(top, #f6f6f6, #e3e3e3);
background-image: -ms-linear-gradient(top, #f6f6f6, #e3e3e3);
background-image: -o-linear-gradient(top, #f6f6f6, #e3e3e3);
background-image: linear-gradient(to bottom, #f6f6f6, #e3e3e3);
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
}
.openerp .oe_form_invisible {
display: none !important;
}
.openerp .oe_form_readonly .oe_edit_only, .openerp .oe_form_readonly .oe_form_field:empty {
@ -1595,26 +1635,25 @@
font-weight: bold;
color: #b33630;
}
.openerp .oe_form_subtotal_footer {
width: auto;
float: right;
.openerp .oe_form .oe_subtotal_footer {
width: 1% !important;
}
.openerp .oe_form_subtotal_footer td.oe_form_group_cell {
.openerp .oe_form .oe_subtotal_footer td.oe_form_group_cell {
text-align: right;
padding: 0;
padding: 0 !important;
}
.openerp .oe_form_subtotal_footer td.oe_form_group_cell_label {
border: none;
.openerp .oe_form .oe_subtotal_footer td.oe_form_group_cell_label {
border-right: none;
}
.openerp .oe_form_subtotal_footer .oe_form_field {
.openerp .oe_form .oe_subtotal_footer .oe_form_field {
width: auto !important;
}
.openerp .oe_form_subtotal_footer .oe_form_subtotal_footer_separator {
.openerp .oe_form .oe_subtotal_footer .oe_subtotal_footer_separator {
border-top: 1px solid #cacaca;
font-size: 120%;
font-sie: 120%;
font-weight: bold;
}
.openerp .oe_form_subtotal_footer label.oe_form_subtotal_footer_separator {
.openerp .oe_form .oe_subtotal_footer label.oe_subtotal_footer_separator {
font-weight: bold !important;
padding: 2px 8px 2px 0px !important;
}
@ -1723,7 +1762,7 @@
.openerp .oe_form .oe_form_field_selection select {
width: inherit;
}
.openerp .oe_form .oe_form_sheet textarea {
.openerp .oe_form .oe_form_field_text.oe_inline, .openerp .oe_form .oe_form_field_text.oe_inline > textarea {
width: 500px;
}
.openerp .oe_form .oe_form_field_float input {
@ -1809,6 +1848,7 @@
}
.openerp .oe_form .oe_form_field_boolean {
padding-top: 4px;
width: auto;
}
.openerp .oe_form .oe_form_field_many2manytags .text-wrap {
width: 100% !important;

View File

@ -169,10 +169,7 @@ $colour4: #8a89ba
@include box-shadow((0 0 3px #80bfff, 0 1px 1px rgba(255, 255, 255, .8) inset))
a.button:active, a.button.active, button:active, button.active, input[type='submit']:active, input[type='submit'].active
background: #e3e3e3
background: -moz-linear-gradient(top, #e3e3e3, #f6f6f6) #1b468f
background: -webkit-gradient(linear, left top, left bottom, from(#e3e3e3), to(#f6f6f6)) #1b468f
background: linear-gradient(top, #e3e3e3, #f6f6f6) #1b468f
@include vertical-gradient(#e3e3e3, #f6f6f6)
@include box-shadow(none)
a.button.disabled, button:disabled, input[type='submit']:disabled
@ -220,8 +217,8 @@ $colour4: #8a89ba
color: #888
.oe_bold
font-weight: bold
.oe_inline 
width: auto
.oe_inline
width: auto !important
.oe_highlight
color: white
background: #DC5F59
@ -1216,10 +1213,21 @@ $colour4: #8a89ba
font-weight: bold
&:hover
background: #ED6F6A
.oe_form_editable
.oe_highlight
color: #404040
background: none
button.oe_highlight
@include vertical-gradient(#efefef, #d8d8d8)
@include box-shadow((0 1px 2px rgba(0, 0, 0, .1), 0 1px 1px rgba(255, 255, 255, .8) inset))
button.oe_highlight:active
@include vertical-gradient(#e3e3e3, #f6f6f6)
@include box-shadow(none)
button.oe_highlight:hover
@include vertical-gradient(#f6f6f6, #e3e3e3)
@include box-shadow((0 1px 2px rgba(0, 0, 0, .1), 0 1px 1px rgba(255, 255, 255, .8) inset))
.oe_form_invisible
display: none !important
.oe_form_editable .oe_edit_only
display: none !important
.oe_form_readonly
.oe_edit_only, .oe_form_field:empty
display: none !important
@ -1271,21 +1279,20 @@ $colour4: #8a89ba
.oe_form_steps_active
font-weight: bold
color: #b33630
.oe_form_subtotal_footer
width: auto
float: right
.oe_form .oe_subtotal_footer
width: 1% !important
td.oe_form_group_cell
text-align: right
padding: 0
padding: 0 !important
td.oe_form_group_cell_label
border: none
border-right: none
.oe_form_field
width: auto !important
.oe_form_subtotal_footer_separator
.oe_subtotal_footer_separator
border-top: 1px solid #cacaca
font-size: 120%
font-sie: 120%
font-weight: bold
label.oe_form_subtotal_footer_separator
label.oe_subtotal_footer_separator
font-weight: bold !important
padding: 2px 8px 2px 0px !important
// no sheet in popups
@ -1380,7 +1387,7 @@ $colour4: #8a89ba
.oe_form_field_text textarea,
.oe_form_field_selection select
width: inherit
.oe_form_sheet textarea
.oe_form_field_text.oe_inline, .oe_form_field_text.oe_inline > textarea
width: 500px
.oe_form_field_float input
width: 100px
@ -1440,6 +1447,7 @@ $colour4: #8a89ba
white-space: nowrap
.oe_form_field_boolean
padding-top: 4px
width: auto
.oe_form_field_many2manytags
.text-wrap
width: 100% !important

View File

@ -224,6 +224,7 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
}
return loaded.then(function() {
self.on_modules_loaded();
self.trigger('module_loaded');
if (!no_session_valid_signal) {
self.on_session_valid();
}
@ -477,64 +478,6 @@ instance.web.TranslationDataBase = instance.web.Class.extend(/** @lends instance
}
});
/** Configure default qweb */
instance.web._t = new instance.web.TranslationDataBase().build_translation_function();
/**
* Lazy translation function, only performs the translation when actually
* printed (e.g. inserted into a template)
*
* Useful when defining translatable strings in code evaluated before the
* translation database is loaded, as class attributes or at the top-level of
* an OpenERP Web module
*
* @param {String} s string to translate
* @returns {Object} lazy translation object
*/
instance.web._lt = function (s) {
return {toString: function () { return instance.web._t(s); }}
};
instance.web.qweb = new QWeb2.Engine();
instance.web.qweb.debug = ($.deparam($.param.querystring()).debug != undefined);
instance.web.qweb.default_dict = {
'_' : _,
'_t' : instance.web._t
};
instance.web.qweb.preprocess_node = function() {
// Note that 'this' is the Qweb Node
switch (this.node.nodeType) {
case 3:
case 4:
// Text and CDATAs
var translation = this.node.parentNode.attributes['t-translation'];
if (translation && translation.value === 'off') {
return;
}
var ts = _.str.trim(this.node.data);
if (ts.length === 0) {
return;
}
var tr = instance.web._t(ts);
if (tr !== ts) {
this.node.data = tr;
}
break;
case 1:
// Element
var attr, attrs = ['label', 'title', 'alt'];
while (attr = attrs.pop()) {
if (this.attributes[attr]) {
this.attributes[attr] = instance.web._t(this.attributes[attr]);
}
}
}
};
/** Configure blockui */
if ($.blockUI) {
$.blockUI.defaults.baseZ = 1100;
$.blockUI.defaults.message = '<img src="/web/static/src/img/throbber2.gif">';
}
/** Custom jQuery plugins */
$.fn.getAttributes = function() {
var o = {};
@ -564,10 +507,6 @@ $.Mutex = (function() {
return Mutex;
})();
/** Setup default session */
instance.connection = new instance.web.Session();
instance.web.qweb.default_dict['__debug__'] = instance.connection.debug;
$.async_when = function() {
var async = false;
var def = $.Deferred();
@ -603,6 +542,79 @@ $.async_when = function() {
return old_async_when.apply(this, arguments);
};
/** Setup blockui */
if ($.blockUI) {
$.blockUI.defaults.baseZ = 1100;
$.blockUI.defaults.message = '<img src="/web/static/src/img/throbber2.gif">';
}
/** Setup default session */
instance.connection = new instance.web.Session();
/** Configure default qweb */
instance.web._t = new instance.web.TranslationDataBase().build_translation_function();
/**
* Lazy translation function, only performs the translation when actually
* printed (e.g. inserted into a template)
*
* Useful when defining translatable strings in code evaluated before the
* translation database is loaded, as class attributes or at the top-level of
* an OpenERP Web module
*
* @param {String} s string to translate
* @returns {Object} lazy translation object
*/
instance.web._lt = function (s) {
return {toString: function () { return instance.web._t(s); }}
};
instance.web.qweb = new QWeb2.Engine();
instance.web.qweb.default_dict['__debug__'] = instance.connection.debug; // Which one ?
instance.web.qweb.debug = instance.connection.debug;
instance.web.qweb.default_dict = {
'_' : _,
'_t' : instance.web._t
};
instance.web.qweb.preprocess_node = function() {
// Note that 'this' is the Qweb Node
switch (this.node.nodeType) {
case 3:
case 4:
// Text and CDATAs
var translation = this.node.parentNode.attributes['t-translation'];
if (translation && translation.value === 'off') {
return;
}
var ts = _.str.trim(this.node.data);
if (ts.length === 0) {
return;
}
var tr = instance.web._t(ts);
if (tr !== ts) {
this.node.data = tr;
}
break;
case 1:
// Element
var attr, attrs = ['label', 'title', 'alt'];
while (attr = attrs.pop()) {
if (this.attributes[attr]) {
this.attributes[attr] = instance.web._t(this.attributes[attr]);
}
}
}
};
/** Setup jQuery timeago */
var timeago_setup = function () {
var s = $.timeago.settings.strings;
_.each(s, function(v,k) {
if(_.isString(v)) {
s[k] = instance.web._t(v);
}
});
}
instance.connection.on('module_loaded', this, timeago_setup);
/**
* Registry for all the client actions key: tag value: widget
*/
@ -612,8 +624,6 @@ instance.web.client_actions = new instance.web.Registry();
* Client action to reload the whole interface.
* If params has an entry 'menu_id', it opens the given menu entry.
*/
instance.web.client_actions.add("reload", "instance.web.Reload");
instance.web.Reload = instance.web.Widget.extend({
init: function(parent, params) {
this._super(parent);
@ -634,6 +644,7 @@ instance.web.Reload = instance.web.Widget.extend({
window.location = url;
}
});
instance.web.client_actions.add("reload", "instance.web.Reload");
};

View File

@ -118,7 +118,9 @@ instance.web.format_value = function (value, descriptor, value_if_empty) {
return instance.web.insert_thousand_seps(
_.str.sprintf('%d', value));
case 'float':
var precision = descriptor.digits ? descriptor.digits[1] : 2;
var digits = descriptor.digits ? descriptor.digits : [69,2];
digits = typeof digits === "string" ? py.eval(digits) : digits;
var precision = digits[1];
var formatted = _.str.sprintf('%.' + precision + 'f', value).split('.');
formatted[0] = instance.web.insert_thousand_seps(formatted[0]);
return formatted.join(l10n.decimal_point);

View File

@ -33,7 +33,7 @@ instance.web.form.FieldManagerMixin = {
};
instance.web.views.add('form', 'instance.web.FormView');
instance.web.FormView = instance.web.View.extend(_.extend({}, instance.web.form.FieldManagerMixin, {
instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerMixin, {
/**
* Indicates that this view is not searchable, and thus that no search
* view should be displayed (if there is one active).
@ -472,6 +472,7 @@ instance.web.FormView = instance.web.View.extend(_.extend({}, instance.web.form.
return self.on_processed_onchange(response, processed);
} catch(e) {
console.error(e);
instance.webclient.crashmanager.on_javascript_exception(e);
return $.Deferred().reject();
}
@ -509,6 +510,9 @@ instance.web.FormView = instance.web.View.extend(_.extend({}, instance.web.form.
}
if (result.domain) {
function edit_domain(node) {
if (typeof node !== "object") {
return;
}
var new_domain = result.domain[node.attrs.name];
if (new_domain) {
node.attrs.domain = new_domain;
@ -520,6 +524,7 @@ instance.web.FormView = instance.web.View.extend(_.extend({}, instance.web.form.
return $.Deferred().resolve();
} catch(e) {
console.error(e);
instance.webclient.crashmanager.on_javascript_exception(e);
return $.Deferred().reject();
}
},
@ -552,6 +557,7 @@ instance.web.FormView = instance.web.View.extend(_.extend({}, instance.web.form.
on_button_cancel: function(event) {
if (this.can_be_discarded()) {
this.set({mode: "view"});
this.on_record_loaded(this.datarecord);
}
return false;
},
@ -891,7 +897,7 @@ instance.web.FormView = instance.web.View.extend(_.extend({}, instance.web.form.
is_create_mode: function() {
return !this.datarecord.id;
},
}));
});
/**
* Interface to be implemented by rendering engines for the form view.
@ -1438,7 +1444,7 @@ instance.web.form.InvisibilityChangerMixin = {
},
};
instance.web.form.InvisibilityChanger = instance.web.Class.extend(_.extend({}, instance.web.PropertiesMixin, instance.web.form.InvisibilityChangerMixin, {
instance.web.form.InvisibilityChanger = instance.web.Class.extend(instance.web.PropertiesMixin, instance.web.form.InvisibilityChangerMixin, {
init: function(parent, field_manager, invisible_domain, $element) {
this.setParent(parent);
instance.web.PropertiesMixin.init.call(this);
@ -1446,9 +1452,9 @@ instance.web.form.InvisibilityChanger = instance.web.Class.extend(_.extend({}, i
this.$element = $element;
this.start();
},
}));
});
instance.web.form.FormWidget = instance.web.Widget.extend(_.extend({}, instance.web.form.InvisibilityChangerMixin, {
instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.InvisibilityChangerMixin, {
/**
* @constructs instance.web.form.FormWidget
* @extends instance.web.Widget
@ -1554,7 +1560,7 @@ instance.web.form.FormWidget = instance.web.Widget.extend(_.extend({}, instance.
}
return final_domain;
}
}));
});
instance.web.form.WidgetButton = instance.web.form.FormWidget.extend({
template: 'WidgetButton',
@ -1652,7 +1658,7 @@ instance.web.form.WidgetButton = instance.web.form.FormWidget.extend({
* - changed_value: triggered to inform the view to check on_changes
*
*/
instance.web.form.FieldMixin = {
instance.web.form.FieldInterface = {
/**
* Constructor takes 2 arguments:
* - field_manager: Implements FieldManagerMixin
@ -1716,7 +1722,7 @@ instance.web.form.FieldMixin = {
};
/**
* Abstract class for classes implementing FieldMixin.
* Abstract class for classes implementing FieldInterface.
*
* Properties:
* - effective_readonly: when it is true, the widget is displayed as readonly. Vary depending
@ -1726,7 +1732,7 @@ instance.web.form.FieldMixin = {
* a 'changed_value' event that inform the view to trigger on_changes.
*
*/
instance.web.form.AbstractField = instance.web.form.FormWidget.extend(_.extend({}, instance.web.form.FieldMixin, {
instance.web.form.AbstractField = instance.web.form.FormWidget.extend(instance.web.form.FieldInterface, {
/**
* @constructs instance.web.form.AbstractField
* @extends instance.web.form.FormWidget
@ -1844,7 +1850,7 @@ instance.web.form.AbstractField = instance.web.form.FormWidget.extend(_.extend({
set_input_id: function(id) {
this.id_for_label = id;
},
}));
});
/**
* A mixin to apply on any field that has to completely re-render when its readonly state
@ -1883,7 +1889,7 @@ instance.web.form.ReinitializeFieldMixin = {
render_value: function() {},
};
instance.web.form.FieldChar = instance.web.form.AbstractField.extend(_.extend({}, instance.web.form.ReinitializeFieldMixin, {
instance.web.form.FieldChar = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin, {
template: 'FieldChar',
widget_class: 'oe_form_field_char',
init: function (field_manager, node) {
@ -1928,7 +1934,7 @@ instance.web.form.FieldChar = instance.web.form.AbstractField.extend(_.extend({}
focus: function() {
this.delay_focus(this.$element.find('input:first'));
}
}));
});
instance.web.form.FieldID = instance.web.form.FieldChar.extend({
@ -1995,7 +2001,7 @@ instance.web.form.FieldFloat = instance.web.form.FieldChar.extend({
this._super(field_manager, node);
this.set({'value': 0});
if (this.node.attrs.digits) {
this.digits = py.eval(node.attrs.digits);
this.digits = this.node.attrs.digits;
} else {
this.digits = this.field.digits;
}
@ -2023,6 +2029,7 @@ instance.web.DateTimeWidget = instance.web.OldWidget.extend({
this.$input_picker = this.$element.find('input.oe_datepicker_container');
this.$input.change(this.on_change);
this.picker({
onClose: this.on_picker_select,
onSelect: this.on_picker_select,
changeMonth: true,
changeYear: true,
@ -2094,7 +2101,7 @@ instance.web.DateWidget = instance.web.DateTimeWidget.extend({
type_of_date: "date"
});
instance.web.form.FieldDatetime = instance.web.form.AbstractField.extend(_.extend({}, instance.web.form.ReinitializeFieldMixin, {
instance.web.form.FieldDatetime = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin, {
template: "FieldDatetime",
build_widget: function() {
return new instance.web.DateTimeWidget(this);
@ -2138,7 +2145,7 @@ instance.web.form.FieldDatetime = instance.web.form.AbstractField.extend(_.exten
if (this.datewidget && this.datewidget.$input)
this.delay_focus(this.datewidget.$input);
}
}));
});
instance.web.form.FieldDate = instance.web.form.FieldDatetime.extend({
template: "FieldDate",
@ -2147,7 +2154,7 @@ instance.web.form.FieldDate = instance.web.form.FieldDatetime.extend({
}
});
instance.web.form.FieldText = instance.web.form.AbstractField.extend(_.extend({}, instance.web.form.ReinitializeFieldMixin, {
instance.web.form.FieldText = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin, {
template: 'FieldText',
initialize_content: function() {
this.$textarea = this.$element.find('textarea');
@ -2207,7 +2214,7 @@ instance.web.form.FieldText = instance.web.form.AbstractField.extend(_.extend({}
$div.remove();
$input.height(new_height);
},
}));
});
instance.web.form.FieldBoolean = instance.web.form.AbstractField.extend({
template: 'FieldBoolean',
@ -2256,7 +2263,7 @@ instance.web.form.FieldTextXml = instance.web.form.AbstractField.extend({
// to replace view editor
});
instance.web.form.FieldSelection = instance.web.form.AbstractField.extend(_.extend({}, instance.web.form.ReinitializeFieldMixin, {
instance.web.form.FieldSelection = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin, {
template: 'FieldSelection',
init: function(field_manager, node) {
var self = this;
@ -2324,7 +2331,7 @@ instance.web.form.FieldSelection = instance.web.form.AbstractField.extend(_.exte
focus: function() {
this.delay_focus(this.$element.find('select:first'));
}
}));
});
// jquery autocomplete tweak to allow html
(function() {
@ -2409,7 +2416,7 @@ instance.web.form.CompletionFieldMixin = {
}
// create...
values.push({label: _t("<em>   Create and Edit...</em>"), action: function() {
self._search_create_popup("form", undefined, {"default_name": search_val});
self._search_create_popup("form", undefined, {});
}});
return values;
@ -2459,8 +2466,7 @@ instance.web.form.CompletionFieldMixin = {
add_id: function(id) {},
};
instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(_.extend({}, instance.web.form.ReinitializeFieldMixin,
instance.web.form.CompletionFieldMixin, {
instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instance.web.form.CompletionFieldMixin, instance.web.form.ReinitializeFieldMixin, {
template: "FieldMany2One",
init: function(field_manager, node) {
this._super(field_manager, node);
@ -2686,7 +2692,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(_.exten
focus: function () {
this.delay_focus(this.$input);
}
}));
});
/*
# Values: (0, 0, { fields }) create
@ -3152,8 +3158,7 @@ instance.web.form.One2ManyKanbanView = instance.web_kanban.KanbanView.extend({
});
}
instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(_.extend({}, instance.web.form.CompletionFieldMixin,
instance.web.form.ReinitializeFieldMixin, {
instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(instance.web.form.CompletionFieldMixin, instance.web.form.ReinitializeFieldMixin, {
template: "FieldMany2ManyTags",
init: function() {
this._super.apply(this, arguments);
@ -3277,7 +3282,7 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(_.
add_id: function(id) {
this.set({'value': _.uniq(this.get('value').concat([id]))});
},
}));
});
/*
* TODO niv: clean those deferred stuff, it could be better
@ -3412,7 +3417,7 @@ instance.web.form.Many2ManyListView = instance.web.ListView.extend(/** @lends in
}
});
instance.web.form.FieldMany2ManyKanban = instance.web.form.AbstractField.extend(_.extend({}, instance.web.form.CompletionFieldMixin, {
instance.web.form.FieldMany2ManyKanban = instance.web.form.AbstractField.extend(instance.web.form.CompletionFieldMixin, {
disable_utility_classes: true,
init: function(field_manager, node) {
this._super(field_manager, node);
@ -3535,7 +3540,7 @@ instance.web.form.FieldMany2ManyKanban = instance.web.form.AbstractField.extend(
add_id: function(id) {
this.quick_create.add_id(id);
},
}));
});
function m2m_kanban_lazy_init() {
if (instance.web.form.Many2ManyKanbanView)
@ -3888,7 +3893,7 @@ instance.web.form.SelectCreateListView = instance.web.ListView.extend({
}
});
instance.web.form.FieldReference = instance.web.form.AbstractField.extend(_.extend({}, instance.web.form.ReinitializeFieldMixin, {
instance.web.form.FieldReference = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin, {
template: 'FieldReference',
init: function(field_manager, node) {
this._super(field_manager, node);
@ -3980,9 +3985,9 @@ instance.web.form.FieldReference = instance.web.form.AbstractField.extend(_.exte
}
throw Exception("Should not happen");
},
}));
});
instance.web.form.FieldBinary = instance.web.form.AbstractField.extend(_.extend({}, instance.web.form.ReinitializeFieldMixin, {
instance.web.form.FieldBinary = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin, {
init: function(field_manager, node) {
var self = this;
this._super(field_manager, node);
@ -4072,7 +4077,7 @@ instance.web.form.FieldBinary = instance.web.form.AbstractField.extend(_.extend(
}
return false;
}
}));
});
instance.web.form.FieldBinaryFile = instance.web.form.FieldBinary.extend({
template: 'FieldBinaryFile',
@ -4285,7 +4290,7 @@ instance.web.form.FieldStatus = instance.web.form.AbstractField.extend({
/**
* Registry of form fields, called by :js:`instance.web.FormView`.
*
* All referenced classes must implement FieldMixin. Those represent the classes whose instances
* All referenced classes must implement FieldInterface. Those represent the classes whose instances
* will substitute to the <field> tags as defined in OpenERP's views.
*/
instance.web.form.widgets = new instance.web.Registry({

View File

@ -37,14 +37,6 @@
-moz-user-select:-moz-none;
}
.openerp .dhx_cal_navline{
height:20px;
position:absolute;
z-index:1;
width:750px;
color:#2F3A48;
background-color:#eee;
}
.openerp .dhx_cal_navline div{
top:2px;
white-space:nowrap;

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -231,6 +231,14 @@ instance.web.form.DashBoard = instance.web.form.FormWidget.extend({
}
},
renderElement: function() {
var check = _.detect(this.node.children, function(column, column_index) {
return _.detect(column.children,function(element){
return element.tag === "action"? element: false;
});
});
if (!check) {
return this.no_result();
}
// We should start with three columns available
for (var i = this.node.children.length; i < 3; i++) {
this.node.children.push({
@ -242,6 +250,15 @@ instance.web.form.DashBoard = instance.web.form.FormWidget.extend({
var rendered = QWeb.render(this.form_template, this);
this.$element.html(rendered);
},
no_result: function() {
if (this.view.options.action.help) {
this.$element.append(
$('<div class="oe_view_nocontent">')
.append($('<img>', { src: '/web_dashboard/static/src/img/view_todo_arrow.png' }))
.append($('<div>').html(this.view.options.action.help || " "))
);
}
},
do_reload: function() {
var view_manager = this.view.getParent(),
action_manager = view_manager.getParent();