Commit f73ad782 authored by Rafael Monnerat's avatar Rafael Monnerat

Added Compression Libraries for Javascript and CSS.

Made by Lucas Carvalho.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@24715 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 3206e108
##############################################################################
#
# Copyright (c) 2008 Nexedi SA and Contributors. All Rights Reserved.
# Lucas Carvalho Teixeira <lucas@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import re
def compressCSS(css):
"""
CSS file compressor
This compressor remove the comments, eol
and all the possible tabs.
"""
white_space_regex = re.compile("[\n|\t|\r]")
commment_regex = re.compile("/\*.*?\*/")
class_regex = re.compile(r"([^{]*?){(.*?)}")
style = re.compile(r"([\w\s-]*):([^;]*);?")
css = commment_regex.sub('', white_space_regex.sub("", css))
return '\n'.join(["%s{%s}" % (x[0].strip(), \
''.join(["%s:%s;" % (y[0].strip(), y[1].strip()) \
for y in style.findall(x[1])])) for x in class_regex.findall(css)])
## ParseMaster, version 1.0 (pre-release) (2005/05/12) x6
## Copyright 2005, Dean Edwards
## Web: http://dean.edwards.name/
##
## This software is licensed under the CC-GNU LGPL
## Web: http://creativecommons.org/licenses/LGPL/2.1/
##
## Ported to Python by Florian Schulze
import os, re
# a multi-pattern parser
class Pattern:
def __init__(self, expression, replacement, length):
self.expression = expression
self.replacement = replacement
self.length = length
def __str__(self):
return "(" + self.expression + ")"
class Patterns(list):
def __str__(self):
return '|'.join([str(e) for e in self])
class ParseMaster:
# constants
EXPRESSION = 0
REPLACEMENT = 1
LENGTH = 2
GROUPS = re.compile(r"""\(""", re.M)#g
SUB_REPLACE = re.compile(r"""\$\d""", re.M)
INDEXED = re.compile(r"""^\$\d+$""", re.M)
TRIM = re.compile(r"""(['"])\1\+(.*)\+\1\1$""", re.M)
ESCAPE = re.compile(r"""\\.""", re.M)#g
#QUOTE = re.compile(r"""'""", re.M)
DELETED = re.compile("""\x01[^\x01]*\x01""", re.M)#g
def __init__(self):
# private
self._patterns = Patterns() # patterns stored by index
self._escaped = []
self.ignoreCase = False
self.escapeChar = None
def DELETE(self, match, offset):
return "\x01" + match.group(offset) + "\x01"
def _repl(self, a, o, r, i):
while (i):
m = a.group(o+i-1)
if m is None:
s = ""
else:
s = m
r = r.replace("$" + str(i), s)
i = i - 1
r = ParseMaster.TRIM.sub("$1", r)
return r
# public
def add(self, expression="^$", replacement=None):
if replacement is None:
replacement = self.DELETE
# count the number of sub-expressions
# - add one because each pattern is itself a sub-expression
length = len(ParseMaster.GROUPS.findall(self._internalEscape(str(expression)))) + 1
# does the pattern deal with sub-expressions?
if (isinstance(replacement, str) and ParseMaster.SUB_REPLACE.match(replacement)):
# a simple lookup? (e.g. "$2")
if (ParseMaster.INDEXED.match(replacement)):
# store the index (used for fast retrieval of matched strings)
replacement = int(replacement[1:]) - 1
else: # a complicated lookup (e.g. "Hello $2 $1")
# build a function to do the lookup
i = length
r = replacement
replacement = lambda a,o: self._repl(a,o,r,i)
# pass the modified arguments
self._patterns.append(Pattern(expression, replacement, length))
# execute the global replacement
def execute(self, string):
if self.ignoreCase:
r = re.compile(str(self._patterns), re.I | re.M)
else:
r = re.compile(str(self._patterns), re.M)
string = self._escape(string, self.escapeChar)
string = r.sub(self._replacement, string)
string = self._unescape(string, self.escapeChar)
string = ParseMaster.DELETED.sub("", string)
return string
# clear the patterns collections so that this object may be re-used
def reset(self):
self._patterns = Patterns()
# this is the global replace function (it's quite complicated)
def _replacement(self, match):
i = 1
# loop through the patterns
for pattern in self._patterns:
if match.group(i) is not None:
replacement = pattern.replacement
if callable(replacement):
return replacement(match, i)
elif isinstance(replacement, (int, long)):
return match.group(replacement+i)
else:
return replacement
else:
i = i+pattern.length
# encode escaped characters
def _escape(self, string, escapeChar=None):
def repl(match):
char = match.group(1)
self._escaped.append(char)
return escapeChar
if escapeChar is None:
return string
r = re.compile("\\"+escapeChar+"(.)", re.M)
result = r.sub(repl, string)
return result
# decode escaped characters
def _unescape(self, string, escapeChar=None):
def repl(match):
try:
#result = eval("'"+escapeChar + self._escaped.pop(0)+"'")
result = escapeChar + self._escaped.pop(0)
return result
except IndexError:
return escapeChar
if escapeChar is None:
return string
r = re.compile("\\"+escapeChar, re.M)
result = r.sub(repl, string)
return result
def _internalEscape(self, string):
return ParseMaster.ESCAPE.sub("", string)
## packer, version 2.0 (2005/04/20)
## Copyright 2004-2005, Dean Edwards
## License: http://creativecommons.org/licenses/LGPL/2.1/
## Ported to Python by Florian Schulze
## http://dean.edwards.name/packer/
class JavaScriptPacker:
def __init__(self):
self._basicCompressionParseMaster = self.getCompressionParseMaster(False)
self._specialCompressionParseMaster = self.getCompressionParseMaster(True)
def basicCompression(self, script):
return self._basicCompressionParseMaster.execute(script)
def specialCompression(self, script):
return self._specialCompressionParseMaster.execute(script)
def getCompressionParseMaster(self, specialChars):
IGNORE = "$1"
parser = ParseMaster()
parser.escapeChar = '\\'
# protect strings
parser.add(r"""'[^']*?'""", IGNORE)
parser.add(r'"[^"]*?"', IGNORE)
# remove comments
parser.add(r"""//[^\n\r]*?[\n\r]""")
parser.add(r"""/\*[^*]*?\*+([^/][^*]*?\*+)*?/""")
# protect regular expressions
parser.add(r"""\s+(\/[^\/\n\r\*][^\/\n\r]*\/g?i?)""", "$2")
parser.add(r"""[^\w\$\/'"*)\?:]\/[^\/\n\r\*][^\/\n\r]*\/g?i?""", IGNORE)
# remove: ;;; doSomething();
if specialChars:
parser.add(""";;;[^\n\r]+[\n\r]""")
# remove redundant semi-colons
parser.add(r""";+\s*([};])""", "$2")
# remove white-space
parser.add(r"""(\b|\$)\s+(\b|\$)""", "$2 $3")
parser.add(r"""([+\-])\s+([+\-])""", "$2 $3")
parser.add(r"""\s+""", "")
return parser
def getEncoder(self, ascii):
mapping = {}
base = ord('0')
mapping.update(dict([(i, chr(i+base)) for i in range(10)]))
base = ord('a')
mapping.update(dict([(i+10, chr(i+base)) for i in range(26)]))
base = ord('A')
mapping.update(dict([(i+36, chr(i+base)) for i in range(26)]))
base = 161
mapping.update(dict([(i+62, chr(i+base)) for i in range(95)]))
# zero encoding
# characters: 0123456789
def encode10(charCode):
return str(charCode)
# inherent base36 support
# characters: 0123456789abcdefghijklmnopqrstuvwxyz
def encode36(charCode):
l = []
remainder = charCode
while 1:
result, remainder = divmod(remainder, 36)
l.append(mapping[remainder])
if not result:
break
remainder = result
l.reverse()
return "".join(l)
# hitch a ride on base36 and add the upper case alpha characters
# characters: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
def encode62(charCode):
l = []
remainder = charCode
while 1:
result, remainder = divmod(remainder, 62)
l.append(mapping[remainder])
if not result:
break
remainder = result
l.reverse()
return "".join(l)
# use high-ascii values
def encode95(charCode):
l = []
remainder = charCode
while 1:
result, remainder = divmod(remainder, 95)
l.append(mapping[remainder+62])
if not result:
break
remainder = result
l.reverse()
return "".join(l)
if ascii <= 10:
return encode10
elif ascii <= 36:
return encode36
elif ascii <= 62:
return encode62
return encode95
def escape(self, script):
script = script.replace("\\","\\\\")
script = script.replace("'","\\'")
script = script.replace('\n','\\n')
#return re.sub(r"""([\\'](?!\n))""", "\\$1", script)
return script
def escape95(self, script):
result = []
for x in script:
if x>'\xa1':
x = "\\x%0x" % ord(x)
result.append(x)
return "".join(result)
def encodeKeywords(self, script, encoding, fastDecode):
# escape high-ascii values already in the script (i.e. in strings)
if (encoding > 62):
script = self.escape95(script)
# create the parser
parser = ParseMaster()
encode = self.getEncoder(encoding)
# for high-ascii, don't encode single character low-ascii
if encoding > 62:
regexp = r"""\w\w+"""
else:
regexp = r"""\w+"""
# build the word list
keywords = self.analyze(script, regexp, encode)
encoded = keywords['encoded']
# encode
def repl(match, offset):
return encoded.get(match.group(offset), "")
parser.add(regexp, repl)
# if encoded, wrap the script in a decoding function
script = parser.execute(script)
script = self.bootStrap(script, keywords, encoding, fastDecode)
return script
def analyze(self, script, regexp, encode):
# analyse
# retreive all words in the script
regexp = re.compile(regexp, re.M)
all = regexp.findall(script)
sorted = [] # list of words sorted by frequency
encoded = {} # dictionary of word->encoding
protected = {} # instances of "protected" words
if all:
unsorted = []
_protected = {}
values = {}
count = {}
all.reverse()
for word in all:
word = "$"+word
if word not in count:
count[word] = 0
j = len(unsorted)
unsorted.append(word)
# make a dictionary of all of the protected words in this script
# these are words that might be mistaken for encoding
values[j] = encode(j)
_protected["$"+values[j]] = j
count[word] = count[word] + 1
# prepare to sort the word list, first we must protect
# words that are also used as codes. we assign them a code
# equivalent to the word itself.
# e.g. if "do" falls within our encoding range
# then we store keywords["do"] = "do";
# this avoids problems when decoding
sorted = [None] * len(unsorted)
for word in unsorted:
if word in _protected and isinstance(_protected[word], int):
sorted[_protected[word]] = word[1:]
protected[_protected[word]] = True
count[word] = 0
unsorted.sort(lambda a,b: count[b]-count[a])
j = 0
for i in range(len(sorted)):
if sorted[i] is None:
sorted[i] = unsorted[j][1:]
j = j + 1
encoded[sorted[i]] = values[i]
return {'sorted': sorted, 'encoded': encoded, 'protected': protected}
def encodePrivate(self, charCode):
return "_"+str(charCode)
def encodeSpecialChars(self, script):
parser = ParseMaster()
# replace: $name -> n, $$name -> $$na
def repl(match, offset):
#print offset, match.groups()
length = len(match.group(offset + 2))
start = length - max(length - len(match.group(offset + 3)), 0)
return match.group(offset + 1)[start:start+length] + match.group(offset + 4)
parser.add(r"""((\$+)([a-zA-Z\$_]+))(\d*)""", repl)
# replace: _name -> _0, double-underscore (__name) is ignored
regexp = r"""\b_[A-Za-z\d]\w*"""
# build the word list
keywords = self.analyze(script, regexp, self.encodePrivate)
# quick ref
encoded = keywords['encoded']
def repl(match, offset):
return encoded.get(match.group(offset), "")
parser.add(regexp, repl)
return parser.execute(script)
# build the boot function used for loading and decoding
def bootStrap(self, packed, keywords, encoding, fastDecode):
ENCODE = re.compile(r"""\$encode\(\$count\)""")
# $packed: the packed script
#packed = self.escape(packed)
#packed = [packed[x*10000:(x+1)*10000] for x in range((len(packed)/10000)+1)]
#packed = "'" + "'+\n'".join(packed) + "'\n"
packed = "'" + self.escape(packed) + "'"
# $count: number of words contained in the script
count = len(keywords['sorted'])
# $ascii: base for encoding
ascii = min(count, encoding) or 1
# $keywords: list of words contained in the script
for i in keywords['protected']:
keywords['sorted'][i] = ""
# convert from a string to an array
keywords = "'" + "|".join(keywords['sorted']) + "'.split('|')"
encoding_functions = {
10: """ function($charCode) {
return $charCode;
}""",
36: """ function($charCode) {
return $charCode.toString(36);
}""",
62: """ function($charCode) {
return ($charCode < _encoding ? "" : arguments.callee(parseInt($charCode / _encoding))) +
(($charCode = $charCode % _encoding) > 35 ? String.fromCharCode($charCode + 29) : $charCode.toString(36));
}""",
95: """ function($charCode) {
return ($charCode < _encoding ? "" : arguments.callee($charCode / _encoding)) +
String.fromCharCode($charCode % _encoding + 161);
}"""
}
# $encode: encoding function (used for decoding the script)
encode = encoding_functions[encoding]
encode = encode.replace('_encoding',"$ascii")
encode = encode.replace('arguments.callee', "$encode")
if ascii > 10:
inline = "$count.toString($ascii)"
else:
inline = "$count"
# $decode: code snippet to speed up decoding
if fastDecode:
# create the decoder
decode = r"""// does the browser support String.replace where the
// replacement value is a function?
if (!''.replace(/^/, String)) {
// decode all the values we need
while ($count--) $decode[$encode($count)] = $keywords[$count] || $encode($count);
// global replacement function
$keywords = [function($encoded){return $decode[$encoded]}];
// generic match
$encode = function(){return'\\w+'};
// reset the loop counter - we are now doing a global replace
$count = 1;
}"""
if encoding > 62:
decode = decode.replace('\\\\w', "[\\xa1-\\xff]")
else:
# perform the encoding inline for lower ascii values
if ascii < 36:
decode = ENCODE.sub(inline, decode)
# special case: when $count==0 there ar no keywords. i want to keep
# the basic shape of the unpacking funcion so i'll frig the code...
if not count:
raise NotImplemented
#) $decode = $decode.replace(/(\$count)\s*=\s*1/, "$1=0");
# boot function
unpack = r"""function($packed, $ascii, $count, $keywords, $encode, $decode) {
while ($count--)
if ($keywords[$count])
$packed = $packed.replace(new RegExp("\\b" + $encode($count) + "\\b", "g"), $keywords[$count]);
return $packed;
}"""
if fastDecode:
# insert the decoder
#unpack = re.sub(r"""\{""", "{" + decode + ";", unpack)
unpack = unpack.replace('{', "{" + decode + ";", 1)
if encoding > 62: # high-ascii
# get rid of the word-boundaries for regexp matches
unpack = re.sub(r"""'\\\\b'\s*\+|\+\s*'\\\\b'""", "", unpack)
if ascii > 36 or encoding > 62 or fastDecode:
# insert the encode function
#unpack = re.sub(r"""\{""", "{$encode=" + encode + ";", unpack)
unpack = unpack.replace('{', "{$encode=" + encode + ";", 1)
else:
# perform the encoding inline
unpack = ENCODE.sub(inline, unpack)
# pack the boot function too
unpack = self.pack(unpack, 0, False, True)
# arguments
params = [packed, str(ascii), str(count), keywords]
if fastDecode:
# insert placeholders for the decoder
params.extend(['0', "{}"])
# the whole thing
return "eval(" + unpack + "(" + ",".join(params) + "))\n";
def pack(self, script, encoding=0, fastDecode=False, specialChars=False, compaction=True):
script = script+"\n"
self._encoding = encoding
self._fastDecode = fastDecode
if specialChars:
script = self.specialCompression(script)
script = self.encodeSpecialChars(script)
else:
if compaction:
script = self.basicCompression(script)
if encoding:
script = self.encodeKeywords(script, encoding, fastDecode)
return script
# The test methods (run and run1) have been moved to the unittest called
# testJSPacker.py, some tests have been improved as well.
# Method used to pack JavaScript
def compressJavaScript(js):
return JavaScriptPacker().pack(js, compaction=False, \
encoding=62, fastDecode=True)
/*
Copyright (c) 2007 Nexedi SA and Contributors. All Rights Reserved.
Vincent Pelletier <vincent@nexedi.com>
Christophe Dumez <christophe@nexedi.com>
Kazuhiko <kazuhiko@nexedi.com>
This program is Free Software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
input, textarea, select, button, body, div, span, fieldset {
font-family: Arial, Helvetica, sans-serif;
font-size: 12px;
margin: 0;
padding: 0;
}
div.input > select, div.input > input {
max-width:320px;
}
div.page > div.input {
width:100%;
}
option {
white-space: pre;
}
div.pre div {
background: #FFF;
}
span.pre {
font-family: monospace;
color: black;
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
button, select, input {
vertical-align: middle;
}
button span {
background-color: inherit;
color: #000;
}
button.sort_button {
background-color: inherit;
color: inherit;
border-width: 0;
cursor: pointer;
}
button.sort_button span {
color: inherit;
text-decoration: underline;
}
img {
border: 0;
}
body, div, span, fieldset {
color: #001730;
}
div, span, fieldset {
background-color: inherit;
}
body {
background-color: #DAE6F6;
}
#main_form {
background-color: inherit;
color: inherit;
}
input#hidden_button {
width: 0;
height: 0;
display: inline;
border-width: 0;
float: left;
}
a, a:visited, a:focus {
background-color: inherit;
color: #002e3f;
text-decoration: none;
}
a:hover {
background-color: inherit;
color: #3D6474;
text-decoration: underline;
}
p.clear {
height: 0;
margin: 0;
padding: 0;
clear: both;
}
div.index_html {
text-align: center;
}
div.index_html table {
margin: 0 auto;
text-align: left;
}
.ModuleShortcut div {
margin-left: 0.5em;
text-indent: -0.5em;
line-height: 1.1em;
margin-bottom: 0.5em;
}
#main_bar button .description,
#context_bar button .description,
.content .field .description,
.document .actions button.save .description,
#context_bar .tool_buttons a .description {
display: none;
}
/* The fields set for generated hidden fields */
#hidden_fieldset {
display: none;
}
/* Main bar */
#main_bar {
color: inherit;
background-color: #97B0D1;
padding-top: 2px;
padding-bottom: 2px;
vertical-align: middle;
}
#main_bar .first,
#context_bar .first {
float: left;
vertical-align: middle;
}
#context_bar #jump,
#main_bar .first{
margin-left: 10px;
}
.listbox_title_line select,
#context_bar select,
#main_bar select {
color: #596dab;
}
#main_bar .second,
#context_bar .second {
float: right;
vertical-align: middle;
}
#main_bar button,
#context_bar button,
.dialog_selector button,
.document .actions button.save {
border: 0;
margin-top: 1px;
margin-left: 0;
margin-right: 2px;
padding: 0;
position: relative;
cursor: pointer;
background-color: inherit;
color: inherit;
}
#context_bar .tool_buttons {
vertical-align: middle;
}
#context_bar .tool_buttons a {
margin-top: 2px;
margin-left: 2px;
margin-right: 2px;
padding: 0;
position: relative;
}
#context_bar .tool_buttons button {
float: left;
}
#main_bar button .image,
#context_bar button .image,
.dialog_selector button .image,
.document .actions button.save .image {
display: block;
width: 22px;
height: 22px;
background-repeat: no-repeat;
}
/* XXX: Bug fix when not logged
by <chritophe@nexedi.com> */
.document .actions {
min-height: 2.5em;
}
table.fake {
width: 100%;
}
table.fake tr td {
vertical-align: top;
width: 50%;
}
.content .field {
position: relative;
clear: left;
font-style: italic;
width: 100%;
}
.content .field .input {
font-style: normal;
}
.content .input .figure {
text-align: right;
}
.group_title {
display: none;
}
table.fake,
fieldset.left,
fieldset.center,
fieldset.bottom {
clear: both;
}
table.fake,
fieldset.left,
fieldset.right,
fieldset.center,
fieldset.bottom {
margin-bottom: 5px;
}
table.fake,
fieldset.left,
fieldset.right,
fieldset.center {
border-style: solid;
border-width: 1px;
border-color: #97B0D1;
padding-top: 5px;
padding-left: 5px;
padding-right: 5px;
}
fieldset.center {
padding-bottom: 5px;
}
.login fieldset {
width: 50%;
float: left;
}
fieldset.left {
width: 50%;
float: left;
margin-right: -12px; /* 5px margin *2 + 2px for left & right border width */
}
fieldset.right {
width: 50%;
float: left;
margin-left: -12px; /* 5px margin *2 + 2px for left & right border width */
}
table.fake fieldset {
border-width: 0;
padding: 0;
margin: 0;
width: 100%;
float: none;
}
fieldset.center,
fieldset.bottom {
clear: both;
}
fieldset.bottom {
border-width: 0;
}
fieldset.bottom .field label {
display: none;
}
.login fieldset,
.dialog_box table.fake,
.dialog_box .left,
.dialog_box .right,
.dialog_box .center {
border-width: 0;
}
.content .field {
padding-bottom: 3px;
}
.content .field label {
width: 30%;
}
.content .field label,
.content .field .input {
float: left;
}
/* Exception case of the previous generic rule
The CSS statement below fix bug #517: it doesn't make sense to have
floating div in bottom field since label are hidden. */
fieldset.bottom .field .input {
float: inherit;
}
.content .field .input a img {
vertical-align: middle;
}
.content .required label {
font-weight: bold;
}
.content .field .error {
background-color: inherit;
color: #f40;
}
.content .error .input {
border: 1px solid #f40;
}
.content .invisible > label {
display: None;
}
.content .invisible > .input {
float: None;
}
.listbox_domain_tree_table a.tree_open {
background: url('http://localhost:9004/erp5/images/tree_open.png') left no-repeat;
padding-left:15px;
}
.listbox_domain_tree_table a.tree_closed {
background: url('http://localhost:9004/erp5/images/tree_closed.png') left no-repeat;
padding-left:15px;
}
.login .submit {
margin-left: 15%;
}
#jump,
#action,
#favourites,
#modules,
#language,
#search {
float: left;
}
#favourites button .image {
background-image: url('http://localhost:9004/erp5/images/favourite.png');
}
#modules button .image {
background-image: url('http://localhost:9004/erp5/images/appearance.png');
}
#language button .image {
background-image: url('http://localhost:9004/erp5/images/language.png');
}
#search button .image {
background-image: url('http://localhost:9004/erp5/images/search.png');
}
#status,
#master {
padding-left: .5em;
padding-right: .5em;
}
#status {
padding-top: .3em;
padding-bottom: .4em;
}
/* Context bar */
#context_bar {
padding-top: 2px;
padding-bottom: 2px;
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #97B0D1;
background-color: #BDD0F0;
color: inherit;
vertical-align: middle;
}
#context_bar .tool_buttons a {
float: left;
margin-left: 2px;
margin-right: 2px;
}
.separator {
height: 24px;
width: 2px;
margin-left: 6px;
margin-right: 6px;
display: block;
float: left;
}
#main_bar .separator {
background-image: url('http://localhost:9004/erp5/images/sepafon.png');
}
#context_bar .separator {
background-image: url('http://localhost:9004/erp5/images/sepacla.png');
}
#context_bar .tool_buttons a .image,
#context_bar .tool_buttons button .image,
#context_bar .tool_buttons a img {
width: 22px;
height: 22px;
margin: 0;
padding: 0;
display: block;
background-repeat: no-repeat;
}
#context_bar #jump button .image {
background-image: url('http://localhost:9004/erp5/images/jump22.png');
}
#context_bar #action button .image {
background-image: url('http://localhost:9004/erp5/images/exec.png');
}
#context_bar .tool_buttons .list_mode .image {
background-image: url('http://localhost:9004/erp5/images/text_block.png');
}
#context_bar .tool_buttons .new .image {
background-image: url('http://localhost:9004/erp5/images/filenew.png');
}
#context_bar .tool_buttons .clone .image {
background-image: url('http://localhost:9004/erp5/images/fileclone.png');
}
#context_bar .tool_buttons .jump_first .image {
background-image: url('http://localhost:9004/erp5/images/2leftarrowb.png');
}
#context_bar .tool_buttons .jump_previous .image {
background-image: url('http://localhost:9004/erp5/images/1leftarrowb.png');
}
#context_bar .tool_buttons .jump_next .image {
background-image: url('http://localhost:9004/erp5/images/1rightarrowb.png');
}
#context_bar .tool_buttons .jump_last .image {
background-image: url('http://localhost:9004/erp5/images/2rightarrowb.png');
}
#context_bar .tool_buttons .import_export .image {
background-image: url('http://localhost:9004/erp5/images/imp-exp.png');
}
#context_bar .tool_buttons .jump_help .image {
background-image: url('http://localhost:9004/erp5/images/userhelp.png');
}
#context_bar .tool_buttons .find .image {
background-image: url('http://localhost:9004/erp5/images/find.png');
}
#context_bar .tool_buttons .print .image {
background-image: url('http://localhost:9004/erp5/images/print.png');
}
#context_bar .tool_buttons .report .image {
background-image: url('http://localhost:9004/erp5/images/report.png');
}
#context_bar .tool_buttons .fast_input .image {
background-image: url('http://localhost:9004/erp5/images/fast_input.png');
}
#context_bar .tool_buttons .cut .image {
background-image: url('http://localhost:9004/erp5/images/editcut.png');
}
#context_bar .tool_buttons .copy .image {
background-image: url('http://localhost:9004/erp5/images/editcopy.png');
}
#context_bar .tool_buttons .paste .image {
background-image: url('http://localhost:9004/erp5/images/editpaste.png');
}
#context_bar .tool_buttons .delete .image {
background-image: url('http://localhost:9004/erp5/images/editdelete.png');
}
#context_bar .tool_buttons .show_all .image {
background-image: url('http://localhost:9004/erp5/images/showall.png');
}
#context_bar .tool_buttons .filter .image {
background-image: url('http://localhost:9004/erp5/images/filter.png');
}
#context_bar .tool_buttons .filter_on .image {
background-image: url('http://localhost:9004/erp5/images/filter_on.png');
}
#context_bar .tool_buttons .sort .image {
background-image: url('http://localhost:9004/erp5/images/sort.png');
}
#context_bar .tool_buttons .configure .image {
background-image: url('http://localhost:9004/erp5/images/configure.png');
}
#context_bar .tool_buttons .activity_pending .image {
width: 26px;
background-image: url('http://localhost:9004/erp5/images/activity_busy.png');
}
#context_bar .tool_buttons .inspect_object .image {
background-image: url('http://localhost:9004/erp5/images/inspect.png');
}
/* Status */
#breadcrumb {
float: left;
/* font-size: 90%; */
margin-bottom: 5px;
}
#breadcrumb a {
color: #002e3f;
}
#logged_in_as {
float: right;
}
#logged_in_as .logged_txt{
color: #002e3f;
/* font-size: 90%; */
}
#transition_message {
margin-left: 1em;
color: #f40;
background-color: inherit;
font-weight: bold;
}
#information_area {
margin-top: 1em;
padding:0.5em 1em 0.5em 1em;
border-width: 1px;
border-style: solid;
border-color: #3D5474;
color: orange;
background-color: #E3EAFA;
font-weight: bold;
}
/* Content */
.dialog_box {
color: inherit;
background-color: #BDD0F0;
border-width: 1px;
border-style: solid;
border-color: #3D5474;
padding: .5em;
margin-bottom: 1em;
}
.list_dialog {
margin-bottom: .5em;
}
.dialog_selector button .description {
display: none;
}
.dialog_selector button .image {
background-image: url('http://localhost:9004/erp5/images/exec16.png');
}
.document .actions {
position: relative;
float: left;
width: 100%;
margin: 0;
padding: 0;
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #3D6474;
color: #002e3f;
}
.document .actions button.save {
float: right;
}
.document .actions button.save span.image {
width: 48px;
height: 50px;
background-image: url('http://localhost:9004/erp5/images/save2.png');
}
.document .actions ul {
float: left;
list-style: none;
padding: 0;
margin: 0;
position: absolute;
bottom: -1px;
}
.document .actions li {
float: left;
}
.document .actions li a {
display: block;
color: inherit;
background: url('http://localhost:9004/erp5/images/tab_left.png') top left no-repeat;
margin: 0;
padding: 0 0 0 10px;
}
.document .actions li.selected a {
background: url('http://localhost:9004/erp5/images/tab_left_selected.png') top left no-repeat;
}
.document .actions li a span {
display: block;
padding: 5px 15px 4px 5px;
color: inherit;
background-color: inherit;
background: url('http://localhost:9004/erp5/images/tab_right.png') top right no-repeat;
/* font-size: 90%; */
}
.document .actions li.selected a span {
font-weight: bold;
padding-bottom: 5px;
background: url('http://localhost:9004/erp5/images/tab_right_selected.png') top right no-repeat;
}
.document .actions li a:hover {
text-decoration: none;
}
.document .content {
clear: both;
border-width: 1px;
border-style: solid;
border-color: #3D6474;
border-top: 0 none;
color: inherit;
background-color: #E3EAFA;
padding: 5px;
}
/* LISTBOX */
/* FIXME:
- listbox uses lots of IDs, but there can be more than one listbox in a page !
- hardcoded images in html which are inly used for rendering style
*/
.ListSummary {
background: url('http://localhost:9004/erp5/images/tab_left_selected.png') top left no-repeat;
color: #000;
background-color: #E3EAFA;
padding-left: 10px;
}
.ListSummary .listbox_title,
.ListSummary .listbox_record_number,
.ListSummary .listbox_item_number {
/* font-size: 90%; */
}
.ListSummary table {
width: 100%;
border-color: #3D6474;
border-style: solid;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 0;
border-left-width: 0;
padding-right: 5px;
padding-bottom: 2px;
}
.ListSummary img {
display: none;
}
.ListSummary .listbox_next_page,
.ListSummary .listbox_previous_page {
display: block;
font-size: 0;
width: 22px;
height: 22px;
background-repeat: no-repeat;
}
.ListContent {
color: #000;
background-color: #E3EAFA;
padding-left: 1px;
}
.ListContent table {
width: 100%;
border-collapse: collapse;
border-color: #3D6474;
border-style: solid;
border-top-width: 0px;
border-bottom-width: 1px;
border-left-width: 1px;
border-right-width: 1px;
}
.ListContent .listbox_label_line td.Data {
border-top-width: 1px;
}
.ListContent .listbox_label_line {
color: #001730;
background-color: #C1DAEB;
/* font-size: 90%; */
}
.ListContent .listbox_stat_line {
color: inherit;
background-color: #C1DAEB;
}
.ListContent .listbox_stat_line td.Data {
border-top-width: 1px;
border-top-style: solid;
border-color: #3D6474;
}
.ListContent tr.DataA {
color: inherit;
background-color: #FFF;
}
.ListContent tr.DataB {
color: inherit;
background-color: #DAE6F6;
}
.ListSummary .listbox_title_line .listbox_title,
.ListSummary .listbox_title_line .listbox_item_number,
.ListSummary .listbox_title_line .listbox_record_number {
vertical-align: middle;
}
.ListContent tr.DataA:hover,
.ListContent tr.DataB:hover {
color: inherit;
background-color: #BDD0F0;
}
.ListContent td {
border-color: #3D6474;
border-style: solid;
border-top-width: 0;
border-bottom-width: 0;
border-left-width: 1px;
border-right-width: 1px;
padding-left: 1px;
padding-right: 1px;
}
.ListContent .error {
color: #F00;
}
td.AnchorColumn {
!important
border-style:none;
border-color:#3D6474;
background-color:#E3EAFA;
border-width:0;
}
/* MatrixBox */
.MatrixContent {
color: #000;
background-color: #E3EAFA;
padding-left: 1px;
}
.MatrixContent table {
width: 100%;
border-collapse: collapse;
border-color: #3D6474;
border-style: solid;
border-top-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-right-width: 1px;
}
.MatrixContent tr.matrixbox_label_line {
vertical-align: middle;
border-color: #3D6474;
border-style: solid;
border-bottom-width: 1px;
border-top-width: 0;
border-left-width: 0;
border-right-width: 0;
}
.MatrixContent td.matrixbox_label_column {
white-space: nowrap;
}
.MatrixContent tr.DataA {
color: inherit;
background-color: #FFF;
}
.MatrixContent tr.DataB {
color: inherit;
background-color: #DAE6F6;
}
.MatrixContent tr.DataA:hover,
.MatrixContent tr.DataB:hover {
color: inherit;
background-color: #BDD0F0;
}
.MatrixContent td {
border-color: #3D6474;
border-style: solid;
border-top-width: 0;
border-bottom-width: 0;
border-left-width: 1px;
border-right-width: 1px;
padding-left: 1px;
padding-right: 1px;
}
.MatrixContent .error {
color: #F00;
}
.MatrixContent td.footer {
width: 100pt;
}
/* Web Page White Background */
.document div.page {
background-color: white;
border-color: black;
border-width: 1px;
padding: 1em;
}
.document div.page div {
color: black;
}
/*
Copyright (c) 20xx-2006 Nexedi SARL and Contributors. All Rights Reserved.
This program is Free Software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
function submitAction(form, act) {
form.action = act;
form.submit();
}
// This function will be called when the user click the save button. As
// submitAction function may have changed the action before, it's better to
// reset the form action to it's original behaviour. This is actually
// usefull when the user click the back button.
function clickSaveButton(act) {
document.forms[0].action = act;
}
// The first input element with an "autofocus" class will get the focus,
// else if no element have autofocus class, the first element which is not the
// search field will get the focus. This is generally the title input text of
// a view
function autoFocus() {
var first_autofocus_expr = ".//input[@class='autofocus']"
var FIRST_RESULT = XPathResult.FIRST_ORDERED_NODE_TYPE
var input = document.evaluate(first_autofocus_expr, document, null, FIRST_RESULT, null).singleNodeValue;
if (input) {
input.focus();
}else{
// The following is disabled, because it is too annoying to have an auto focus at everywhere.
//var first_text_input_expr = ".//input[@type='text'][@name != 'field_your_search_text']"
//var first_text_input = document.evaluate(first_text_input_expr, document, null, FIRST_RESULT, null).singleNodeValue;
//if (first_text_input){
// first_text_input.focus();
//}
}
}
function buildTables(element_list, rowPredicate, columnPredicate,
tableClassName) {
/* Generic code to build a table from elements in element_list.
* rowPredicate(element) -> bool
* When it returns a true value, a new line is started with element.
* When is returns a false value, element is skipped.
* columnPredicate(element, initial_element) -> bitfield
* bit 3: end_table (if true, imlies end_row)
* End current table.
* bit 2: end_row
* End current row.
* bit 1: use_element
* Element passed to columnPredicate will be put in current row.
* Hardcoded:
* - items in a table line must be siblings in existing DOM
* - table is put in place of first element of the first row
*/
var element_index = 0;
while (element_index < element_list.length) {
var row_list = [];
var end_table = false;
while ((!end_table) && element_index < element_list.length) {
var row_begin = element_list[element_index];
if (rowPredicate(row_begin)) {
var item_list = [row_begin];
var row_item = row_begin;
var end_line = false;
while ((!end_line) && (row_item = row_item.nextSibling) != null) {
var predicate_result = columnPredicate(row_item, row_begin)
if ((predicate_result & 1) != 0)
item_list.push(row_item);
end_table = ((predicate_result & 4) != 0);
end_line = ((predicate_result & 6) != 0);
}
row_list.push(item_list);
}
element_index++;
}
/* Do not create a table with just one cell. */
if ((row_list.length > 1) ||
(row_list.length == 1 && row_list[0].length > 1)) {
var first_element = row_list[0][0];
var container = first_element.parentNode;
var fake_table = document.createElement("table");
var i;
var j;
fake_table.className = tableClassName;
container.insertBefore(fake_table, first_element);
for (i = 0; i < row_list.length; i++) {
var fake_row = document.createElement("tr");
var row_element_list = row_list[i];
for (j = 0; j < row_element_list.length; j++) {
var fake_cell = document.createElement("td");
fake_cell.appendChild(row_element_list[j]);
fake_row.appendChild(fake_cell);
}
fake_table.appendChild(fake_row);
}
}
}
}
function matchChunk(string, separator, chunk_value) {
if (string != null) {
var id_chunks = string.split(separator);
var i;
for (i = 0; i < id_chunks.length; i++) {
if (id_chunks[i] == chunk_value)
return true;
}
}
return false;
}
function matchLeftFieldset(element) {
return (element.tagName == "FIELDSET") &&
matchChunk(element.id, '_', "left");
}
function matchRightFieldset(element, ignored) {
if ((element.tagName == "FIELDSET") &&
matchChunk(element.id, '_', "right"))
return 7; /* End row, table and use element */
return 0;
}
function fixLeftRightHeightAndFocus(fix_height) {
if (fix_height == 1) {
buildTables(document.getElementsByTagName('fieldset'),
matchLeftFieldset, matchRightFieldset,
"fake");
}
autoFocus();
}
// This function can be used to catch ENTER pressed in an input
// and modify respective main form action
function submitFormOnEnter(event, main_form_id, method_name){
var key_code = event.keyCode;
if(key_code == 13){
var main_form = getElement(main_form_id)
main_form.action=method_name;};
}
var old_index=0;
function shiftCheck(evt) {
evt=(evt)?evt:event;
var target=(evt.target)?evt.target:evt.srcElement;
// remove "checkbox" part from ID
// This part can be reused easilly by usual left column
var target_index= target.id.substr(8);
if(!evt.shiftKey) {
old_index= target_index
check_option = target.checked;
return false;
}
target.checked=1;
var low=Math.min(target_index , old_index);
var high=Math.max(target_index , old_index);
for(var i=low;i<=high;i++) {
document.getElementById("checkbox" + i ).checked = check_option;
}
return true;
}
var indexAllCheckBoxesAtBTInstallationOnLoad = function() {
// This Part is used basically for Business Template Installation.
var inputs = window.getElementsByTagAndClassName("input", "shift_check_support");
for(i=0;i<=inputs.length-1;i++) { inputs[i].id = "checkbox" + i; }
}
addLoadEvent(indexAllCheckBoxesAtBTInstallationOnLoad)
input, textarea, select, button, body, div, span, fieldset{font-family:Arial, Helvetica, sans-serif;font-size:12px;margin:0;padding:0;}
div.input > select, div.input > input{max-width:320px;}
div.page > div.input{width:100%;}
option{white-space:pre;}
div.pre div{background:#FFF;}
span.pre{font-family:monospace;color:black;white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;}
button, select, input{vertical-align:middle;}
button span{background-color:inherit;color:#000;}
button.sort_button{background-color:inherit;color:inherit;border-width:0;cursor:pointer;}
button.sort_button span{color:inherit;text-decoration:underline;}
img{border:0;}
body, div, span, fieldset{color:#001730;}
div, span, fieldset{background-color:inherit;}
body{background-color:#DAE6F6;}
#main_form{background-color:inherit;color:inherit;}
input#hidden_button{width:0;height:0;display:inline;border-width:0;float:left;}
a, a:visited, a:focus{background-color:inherit;color:#002e3f;text-decoration:none;}
a:hover{background-color:inherit;color:#3D6474;text-decoration:underline;}
p.clear{height:0;margin:0;padding:0;clear:both;}
div.index_html{text-align:center;}
div.index_html table{margin:0 auto;text-align:left;}
.ModuleShortcut div{margin-left:0.5em;text-indent:-0.5em;line-height:1.1em;margin-bottom:0.5em;}
#main_bar button .description,#context_bar button .description,.content .field .description,.document .actions button.save .description,#context_bar .tool_buttons a .description{display:none;}
#hidden_fieldset{display:none;}
#main_bar{color:inherit;background-color:#97B0D1;padding-top:2px;padding-bottom:2px;vertical-align:middle;}
#main_bar .first,#context_bar .first{float:left;vertical-align:middle;}
#context_bar #jump,#main_bar .first{margin-left:10px;}
.listbox_title_line select,#context_bar select,#main_bar select{color:#596dab;}
#main_bar .second,#context_bar .second{float:right;vertical-align:middle;}
#main_bar button,#context_bar button,.dialog_selector button,.document .actions button.save{border:0;margin-top:1px;margin-left:0;margin-right:2px;padding:0;position:relative;cursor:pointer;background-color:inherit;color:inherit;}
#context_bar .tool_buttons{vertical-align:middle;}
#context_bar .tool_buttons a{margin-top:2px;margin-left:2px;margin-right:2px;padding:0;position:relative;}
#context_bar .tool_buttons button{float:left;}
#main_bar button .image,#context_bar button .image,.dialog_selector button .image,.document .actions button.save .image{display:block;width:22px;height:22px;background-repeat:no-repeat;}
.document .actions{min-height:2.5em;}
table.fake{width:100%;}
table.fake tr td{vertical-align:top;width:50%;}
.content .field{position:relative;clear:left;font-style:italic;width:100%;}
.content .field .input{font-style:normal;}
.content .input .figure{text-align:right;}
.group_title{display:none;}
table.fake,fieldset.left,fieldset.center,fieldset.bottom{clear:both;}
table.fake,fieldset.left,fieldset.right,fieldset.center,fieldset.bottom{margin-bottom:5px;}
table.fake,fieldset.left,fieldset.right,fieldset.center{border-style:solid;border-width:1px;border-color:#97B0D1;padding-top:5px;padding-left:5px;padding-right:5px;}
fieldset.center{padding-bottom:5px;}
.login fieldset{width:50%;float:left;}
fieldset.left{width:50%;float:left;margin-right:-12px;}
fieldset.right{width:50%;float:left;margin-left:-12px;}
table.fake fieldset{border-width:0;padding:0;margin:0;width:100%;float:none;}
fieldset.center,fieldset.bottom{clear:both;}
fieldset.bottom{border-width:0;}
fieldset.bottom .field label{display:none;}
.login fieldset,.dialog_box table.fake,.dialog_box .left,.dialog_box .right,.dialog_box .center{border-width:0;}
.content .field{padding-bottom:3px;}
.content .field label{width:30%;}
.content .field label,.content .field .input{float:left;}
fieldset.bottom .field .input{float:inherit;}
.content .field .input a img{vertical-align:middle;}
.content .required label{font-weight:bold;}
.content .field .error{background-color:inherit;color:#f40;}
.content .error .input{border:1px solid #f40;}
.content .invisible > label{display:None;}
.content .invisible > .input{float:None;}
.listbox_domain_tree_table a.tree_open{background:url('http://localhost:9004/erp5/images/tree_open.png') left no-repeat;padding-left:15px;}
.listbox_domain_tree_table a.tree_closed{background:url('http://localhost:9004/erp5/images/tree_closed.png') left no-repeat;padding-left:15px;}
.login .submit{margin-left:15%;}
#jump,#action,#favourites,#modules,#language,#search{float:left;}
#favourites button .image{background-image:url('http://localhost:9004/erp5/images/favourite.png');}
#modules button .image{background-image:url('http://localhost:9004/erp5/images/appearance.png');}
#language button .image{background-image:url('http://localhost:9004/erp5/images/language.png');}
#search button .image{background-image:url('http://localhost:9004/erp5/images/search.png');}
#status,#master{padding-left:.5em;padding-right:.5em;}
#status{padding-top:.3em;padding-bottom:.4em;}
#context_bar{padding-top:2px;padding-bottom:2px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:#97B0D1;background-color:#BDD0F0;color:inherit;vertical-align:middle;}
#context_bar .tool_buttons a{float:left;margin-left:2px;margin-right:2px;}
.separator{height:24px;width:2px;margin-left:6px;margin-right:6px;display:block;float:left;}
#main_bar .separator{background-image:url('http://localhost:9004/erp5/images/sepafon.png');}
#context_bar .separator{background-image:url('http://localhost:9004/erp5/images/sepacla.png');}
#context_bar .tool_buttons a .image,#context_bar .tool_buttons button .image,#context_bar .tool_buttons a img{width:22px;height:22px;margin:0;padding:0;display:block;background-repeat:no-repeat;}
#context_bar #jump button .image{background-image:url('http://localhost:9004/erp5/images/jump22.png');}
#context_bar #action button .image{background-image:url('http://localhost:9004/erp5/images/exec.png');}
#context_bar .tool_buttons .list_mode .image{background-image:url('http://localhost:9004/erp5/images/text_block.png');}
#context_bar .tool_buttons .new .image{background-image:url('http://localhost:9004/erp5/images/filenew.png');}
#context_bar .tool_buttons .clone .image{background-image:url('http://localhost:9004/erp5/images/fileclone.png');}
#context_bar .tool_buttons .jump_first .image{background-image:url('http://localhost:9004/erp5/images/2leftarrowb.png');}
#context_bar .tool_buttons .jump_previous .image{background-image:url('http://localhost:9004/erp5/images/1leftarrowb.png');}
#context_bar .tool_buttons .jump_next .image{background-image:url('http://localhost:9004/erp5/images/1rightarrowb.png');}
#context_bar .tool_buttons .jump_last .image{background-image:url('http://localhost:9004/erp5/images/2rightarrowb.png');}
#context_bar .tool_buttons .import_export .image{background-image:url('http://localhost:9004/erp5/images/imp-exp.png');}
#context_bar .tool_buttons .jump_help .image{background-image:url('http://localhost:9004/erp5/images/userhelp.png');}
#context_bar .tool_buttons .find .image{background-image:url('http://localhost:9004/erp5/images/find.png');}
#context_bar .tool_buttons .print .image{background-image:url('http://localhost:9004/erp5/images/print.png');}
#context_bar .tool_buttons .report .image{background-image:url('http://localhost:9004/erp5/images/report.png');}
#context_bar .tool_buttons .fast_input .image{background-image:url('http://localhost:9004/erp5/images/fast_input.png');}
#context_bar .tool_buttons .cut .image{background-image:url('http://localhost:9004/erp5/images/editcut.png');}
#context_bar .tool_buttons .copy .image{background-image:url('http://localhost:9004/erp5/images/editcopy.png');}
#context_bar .tool_buttons .paste .image{background-image:url('http://localhost:9004/erp5/images/editpaste.png');}
#context_bar .tool_buttons .delete .image{background-image:url('http://localhost:9004/erp5/images/editdelete.png');}
#context_bar .tool_buttons .show_all .image{background-image:url('http://localhost:9004/erp5/images/showall.png');}
#context_bar .tool_buttons .filter .image{background-image:url('http://localhost:9004/erp5/images/filter.png');}
#context_bar .tool_buttons .filter_on .image{background-image:url('http://localhost:9004/erp5/images/filter_on.png');}
#context_bar .tool_buttons .sort .image{background-image:url('http://localhost:9004/erp5/images/sort.png');}
#context_bar .tool_buttons .configure .image{background-image:url('http://localhost:9004/erp5/images/configure.png');}
#context_bar .tool_buttons .activity_pending .image{width:26px;background-image:url('http://localhost:9004/erp5/images/activity_busy.png');}
#context_bar .tool_buttons .inspect_object .image{background-image:url('http://localhost:9004/erp5/images/inspect.png');}
#breadcrumb{float:left;margin-bottom:5px;}
#breadcrumb a{color:#002e3f;}
#logged_in_as{float:right;}
#logged_in_as .logged_txt{color:#002e3f;}
#transition_message{margin-left:1em;color:#f40;background-color:inherit;font-weight:bold;}
#information_area{margin-top:1em;padding:0.5em 1em 0.5em 1em;border-width:1px;border-style:solid;border-color:#3D5474;color:orange;background-color:#E3EAFA;font-weight:bold;}
.dialog_box{color:inherit;background-color:#BDD0F0;border-width:1px;border-style:solid;border-color:#3D5474;padding:.5em;margin-bottom:1em;}
.list_dialog{margin-bottom:.5em;}
.dialog_selector button .description{display:none;}
.dialog_selector button .image{background-image:url('http://localhost:9004/erp5/images/exec16.png');}
.document .actions{position:relative;float:left;width:100%;margin:0;padding:0;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:#3D6474;color:#002e3f;}
.document .actions button.save{float:right;}
.document .actions button.save span.image{width:48px;height:50px;background-image:url('http://localhost:9004/erp5/images/save2.png');}
.document .actions ul{float:left;list-style:none;padding:0;margin:0;position:absolute;bottom:-1px;}
.document .actions li{float:left;}
.document .actions li a{display:block;color:inherit;background:url('http://localhost:9004/erp5/images/tab_left.png') top left no-repeat;margin:0;padding:0 0 0 10px;}
.document .actions li.selected a{background:url('http://localhost:9004/erp5/images/tab_left_selected.png') top left no-repeat;}
.document .actions li a span{display:block;padding:5px 15px 4px 5px;color:inherit;background-color:inherit;background:url('http://localhost:9004/erp5/images/tab_right.png') top right no-repeat;}
.document .actions li.selected a span{font-weight:bold;padding-bottom:5px;background:url('http://localhost:9004/erp5/images/tab_right_selected.png') top right no-repeat;}
.document .actions li a:hover{text-decoration:none;}
.document .content{clear:both;border-width:1px;border-style:solid;border-color:#3D6474;border-top:0 none;color:inherit;background-color:#E3EAFA;padding:5px;}
.ListSummary{background:url('http://localhost:9004/erp5/images/tab_left_selected.png') top left no-repeat;color:#000;background-color:#E3EAFA;padding-left:10px;}
.ListSummary .listbox_title,.ListSummary .listbox_record_number,.ListSummary .listbox_item_number{}
.ListSummary table{width:100%;border-color:#3D6474;border-style:solid;border-top-width:1px;border-right-width:1px;border-bottom-width:0;border-left-width:0;padding-right:5px;padding-bottom:2px;}
.ListSummary img{display:none;}
.ListSummary .listbox_next_page,.ListSummary .listbox_previous_page{display:block;font-size:0;width:22px;height:22px;background-repeat:no-repeat;}
.ListContent{color:#000;background-color:#E3EAFA;padding-left:1px;}
.ListContent table{width:100%;border-collapse:collapse;border-color:#3D6474;border-style:solid;border-top-width:0px;border-bottom-width:1px;border-left-width:1px;border-right-width:1px;}
.ListContent .listbox_label_line td.Data{border-top-width:1px;}
.ListContent .listbox_label_line{color:#001730;background-color:#C1DAEB;}
.ListContent .listbox_stat_line{color:inherit;background-color:#C1DAEB;}
.ListContent .listbox_stat_line td.Data{border-top-width:1px;border-top-style:solid;border-color:#3D6474;}
.ListContent tr.DataA{color:inherit;background-color:#FFF;}
.ListContent tr.DataB{color:inherit;background-color:#DAE6F6;}
.ListSummary .listbox_title_line .listbox_title,.ListSummary .listbox_title_line .listbox_item_number,.ListSummary .listbox_title_line .listbox_record_number{vertical-align:middle;}
.ListContent tr.DataA:hover,.ListContent tr.DataB:hover{color:inherit;background-color:#BDD0F0;}
.ListContent td{border-color:#3D6474;border-style:solid;border-top-width:0;border-bottom-width:0;border-left-width:1px;border-right-width:1px;padding-left:1px;padding-right:1px;}
.ListContent .error{color:#F00;}
td.AnchorColumn{important border-style:none;border-color:#3D6474;background-color:#E3EAFA;border-width:0;}
.MatrixContent{color:#000;background-color:#E3EAFA;padding-left:1px;}
.MatrixContent table{width:100%;border-collapse:collapse;border-color:#3D6474;border-style:solid;border-top-width:1px;border-bottom-width:1px;border-left-width:1px;border-right-width:1px;}
.MatrixContent tr.matrixbox_label_line{vertical-align:middle;border-color:#3D6474;border-style:solid;border-bottom-width:1px;border-top-width:0;border-left-width:0;border-right-width:0;}
.MatrixContent td.matrixbox_label_column{white-space:nowrap;}
.MatrixContent tr.DataA{color:inherit;background-color:#FFF;}
.MatrixContent tr.DataB{color:inherit;background-color:#DAE6F6;}
.MatrixContent tr.DataA:hover,.MatrixContent tr.DataB:hover{color:inherit;background-color:#BDD0F0;}
.MatrixContent td{border-color:#3D6474;border-style:solid;border-top-width:0;border-bottom-width:0;border-left-width:1px;border-right-width:1px;padding-left:1px;padding-right:1px;}
.MatrixContent .error{color:#F00;}
.MatrixContent td.footer{width:100pt;}
.document div.page{background-color:white;border-color:black;border-width:1px;padding:1em;}
.document div.page div{color:black;}
\ No newline at end of file
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp("\\b"+e(c)+"\\b","g"),k[c]);return p}('/*\n4X (c) 4W-4V 4U 4T N 4S. 4R 4Q 4P.\n\nl 1s f 1r 1q; 4O 11 4N v N/1w\n1L v 4M 9 4L u 9 1v 1u 1t X\n4K 4J 1E 9 1r 1q 2j; 4I 2k 2\nu 9 X, 1w (29 4H 4G) 4F 4E 2k.\n\nl 1s f 4D q 9 4C 4B v H x 4A,\n4z 4y 4x 4w; 4v 4u 9 4t 4s u\n4r 1w 4q 4p A 4o 4n. 4m 9\n1v 1u 1t X o 4l 4k.\n\n4j 4i V 4h a 4g u 9 1v 1u 1t X\n4f Q 4e 1s; e 1f, 4d r 9 1r 1q\n2j, 4c., 4b 4a 49 - 48 47, 46, 45 44-43, 42.\n*/\n\nd 2i(C, W) {\n C.y = W;\n C.41();\n}\n\n// l d H x 40 2h 9 2g 2f 9 3Z 2e. 3Y \n// 2i d 3X V 3W 9 y 3V, v\'s 3U r\n// 3T 9 C y r v\'s 3S 3R. l f 3Q\n// 3P 2h 9 2g 2f 9 3O 2e.\nd 3N(W) {\n g.3M[0].y = W;\n}\n\n\n// 2a U k b Q 14 "1o" 1p H 2d 9 I,\n// 2b e 3L b V 1o 1p, 9 U b 3K f 1f 9\n// 3J 3I H 2d 9 I. l f 3H 9 3G k 28 u\n// a 3F\nd 1M() {\n 5 2c = ".//k[@1p=\'1o\']"\n 5 1n = 3E.3D\n\n 5 k = g.27(2c, g, z, 1n, z).25;\n e (k) {\n k.I();\n }2b{\n // 2a 3C f 3B, 3A v f 3z 3y r V 14 3x I 29 3w.\n //5 26 = ".//k[@3v=\'28\'][@3u != \'3t\']"\n //5 1m = g.27(26, g, z, 1n, z).25;\n //e (1m){\n // 1m.I();\n //}\n }\n}\n\nd 1P(G, 1j, T,\n 1X) {\n /* 3s 3r r 3q a t 1G 3p q G.\n * 1j(b) -> 3o\n * 24 v 23 a K 22, a 3n 20 f 3m Q b.\n * 24 f 23 a B 22, b f 3l.\n * T(b, 3k) -> 3j\n * 1l 3: S (e K, 3i 21)\n * 15 1k t.\n * 1l 2: 21\n * 15 1k O.\n * 1l 1: 3h\n * 3g 3f r T H x 1Z q 1k O.\n * 3e:\n * - 3d q a t 20 3c x 3b q 3a 39\n * - t f 1Z q 38 u U b u 9 U O\n */\n 5 D = 0;\n 1i (D < G.h) {\n 5 n = [];\n 5 S = B;\n 1i ((!S) && D < G.h) {\n 5 F = G[D];\n e (1j(F)) {\n 5 1g = [F];\n 5 E = F;\n 5 1h = B;\n 1i ((!1h) && (E = E.37) != z) {\n 5 R = T(E, F)\n e ((R & 1) != 0)\n 1g.1Y(E);\n S = ((R & 4) != 0);\n 1h = ((R & 6) != 0);\n }\n n.1Y(1g);\n }\n D++;\n }\n /* 36 1f 35 a t Q 34 33 32. */\n e ((n.h > 1) ||\n (n.h == 1 && n[0].h > 1)) {\n 5 1e = n[0][0];\n 5 1W = 1e.31;\n 5 P = g.1d("t");\n 5 i;\n 5 j;\n P.30 = 1X;\n 1W.2Z(P, 1e);\n o (i = 0; i < n.h; i++) {\n 5 19 = g.1d("2Y");\n 5 1c = n[i];\n o (j = 0; j < 1c.h; j++) {\n 5 1b = g.1d("2X");\n 1b.1a(1c[j]);\n 19.1a(1b);\n }\n P.1a(19);\n }\n }\n }\n}\n\nd 16(18, 1V, 1U) {\n e (18 != z) {\n 5 17 = 18.2W(1V);\n 5 i;\n o (i = 0; i < 17.h; i++) {\n e (17[i] == 1U)\n p K;\n }\n }\n p B;\n}\n\nd 1O(b) {\n p (b.1T == "1S") &&\n 16(b.J, \'1R\', "1D");\n}\n\nd 1N(b, 2V) {\n e ((b.1T == "1S") &&\n 16(b.J, \'1R\', "2U"))\n p 7; /* 15 O, t N 2T b */\n p 0;\n}\n\nd 2S(1Q) {\n e (1Q == 1) {\n 1P(g.2R(\'2Q\'),\n 1O, 1N,\n "2P");\n }\n 1M();\n}\n\n// l d 11 x 1y r 2O 2N 2M q 14 k \n// N 1L 2L 2K C y\nd 2J(12, 1J, 1H){\n 5 1K = 12.2I;\n e(1K == 13){\n 5 1I = 2H(1J)\n 1I.y=1H;};\n}\n\n5 L=0;\nd 2G(m) {\n m=(m)?m:12;\n 5 w=(m.w)?m.w:m.2F;\n // 2E "Y" 1F 1G 2D\n // l 1F 11 x 2C 2B 1E 2A 1D 2z\n 5 M= w.J.2y(8);\n e(!m.2x) {\n L= M\n 1z = w.10;\n p B;\n }\n w.10=1;\n 5 1B=1C.2w(M , L);\n 5 1A=1C.2v(M , L);\n o(5 i=1B;i<=1A;i++) {\n g.2u("Y" + i ).10 = 1z;\n }\n p K;\n }\n\n5 1x = d() {\n // l 2t f 1y 2s o 2r 2q 2p.\n 5 Z = 2o.2n("k", "2m");\n o(i=0;i<=Z.h-1;i++) { Z[i].J = "Y" + i; }\n}\n\n2l(1x)\n\n\n',62,308,'|||||var||||the||element||function|if|is|document|length|||input|This|evt|row_list|for|return|in|to||table|of|it|target|be|action|null||false|form|element_index|row_item|row_begin|element_list|will|focus|id|true|old_index|target_index|and|row|fake_table|with|predicate_result|end_table|columnPredicate|first|have|act|License|checkbox|inputs|checked|can|event||an|End|matchChunk|id_chunks|string|fake_row|appendChild|fake_cell|row_element_list|createElement|first_element|not|item_list|end_line|while|rowPredicate|current|bit|first_text_input|FIRST_RESULT|autofocus|class|Software|Free|program|Public|General|GNU|or|indexAllCheckBoxesAtBTInstallationOnLoad|used|check_option|high|low|Math|left|by|part|from|method_name|main_form|main_form_id|key_code|modify|autoFocus|matchRightFieldset|matchLeftFieldset|buildTables|fix_height|_|FIELDSET|tagName|chunk_value|separator|container|tableClassName|push|put|line|end_row|value|returns|When|singleNodeValue|first_text_input_expr|evaluate|text|at|The|else|first_autofocus_expr|get|button|click|user|when|submitAction|Foundation|version|addLoadEvent|shift_check_support|getElementsByTagAndClassName|window|Installation|Template|Business|basically|Part|getElementById|max|min|shiftKey|substr|column|usual|easilly|reused|ID|remove|srcElement|shiftCheck|getElement|keyCode|submitFormOnEnter|main|respective|pressed|ENTER|catch|fake|fieldset|getElementsByTagName|fixLeftRightHeightAndFocus|use|right|ignored|split|td|tr|insertBefore|className|parentNode|cell|one|just|create|Do|nextSibling|place|DOM|existing|siblings|must|items|Hardcoded|passed|Element|use_element|imlies|bitfield|initial_element|skipped|started|new|bool|elements|build|code|Generic|field_your_search_text|name|type|everywhere|auto|annoying|too|because|disabled|following|FIRST_ORDERED_NODE_TYPE|XPathResult|view|title|generally|field|search|which|no|forms|clickSaveButton|back|usefull|actually|behaviour|original|reset|better|before|changed|may|As|save|called|submit|USA|1307|02111|MA|Boston|330|Suite|Place|Temple|59|Inc|write|this|along|copy|received|should|You|details|more|See|PURPOSE|PARTICULAR|FOR|FITNESS|MERCHANTABILITY|warranty|implied|even|without|WARRANTY|ANY|WITHOUT|but|useful|that|hope|distributed|later|any|option|your|either|published|as|terms|under|redistribute|you|Reserved|Rights|All|Contributors|SARL|Nexedi|2006|20xx|Copyright'.split('|'),0,{}))
##############################################################################
#
# Copyright (c) 2008 Nexedi SA and Contributors. All Rights Reserved.
# Lucas Carvalho <lucas@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import unittest
from Products.ERP5Type.CSSPacker import compressCSS
from os.path import abspath, join, dirname
PREFIX = abspath(dirname(__file__))
class TestCSSPacker(unittest.TestCase):
def test_compressCSS(self):
script = open(join(PREFIX, 'input/input_erp5.css')).read()
result = compressCSS(script)
output = open(join(PREFIX, 'output/output_erp5.css')).read()
self.assertEquals(result, output)
def test_CSSStyleWithoutSemicolon(self):
result = compressCSS('.something {color: #FFFFF}')
self.assertEquals('.something{color:#FFFFF;}', result)
def test_CSSStyleAndClassWithSpaces(self):
css = '.something {color: #FFFFFF; border: 0px; }'
result = compressCSS(css)
self.assertEquals('.something{color:#FFFFFF;border:0px;}', result)
def test_CSSClassWithSpecialCharacter(self):
css = 'div#main_content input.button, input[type="submit"] { \
/* XXX Is this case happend in current web implementation ? */ \
background: #fff url(erp5-website-button.png) bottom repeat-x; \
}'
result = compressCSS(css)
expected_result = 'div#main_content input.button, \
input[type="submit"]{background:#fff url(erp5-website-button.png) bottom \
repeat-x;}'
self.assertEquals(result, expected_result)
if __name__ == '__main__':
unittest.main()
##############################################################################
#
# Copyright (c) 2008 Nexedi SA and Contributors. All Rights Reserved.
# Lucas Carvalho <lucas@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import unittest
from Products.ERP5Type.JSPacker import compressJavaScript
from os.path import abspath, join, dirname
PREFIX = abspath(dirname(__file__))
class TestJSPacker(unittest.TestCase):
def test_compressJavaScript(self):
script = open(join(PREFIX, 'input/input_erp5.js')).read()
result = compressJavaScript(script)
output = open(join(PREFIX, 'output/output_erp5.js')).read()
self.assertEquals(result, output)
if __name__ == '__main__':
unittest.main()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment