bzr revid: nicolas.vanhoren@openerp.com-20120217101731-3g9hrhs65qb32pkv
This commit is contained in:
niv-openerp 2012-02-17 11:17:31 +01:00
commit 1e9380b8fa
247 changed files with 26138 additions and 13811 deletions

View File

@ -1,7 +1,8 @@
import common
import controllers
import logging
from . import common
from . import controllers
_logger = logging.getLogger(__name__)
class Options(object):

View File

@ -25,7 +25,7 @@
"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/js/jquery-ui-timepicker-addon.js",
"static/lib/jquery.ui.timepicker/js/jquery-ui-timepicker-addon.js",
"static/lib/jquery.ui.notify/js/jquery.notify.js",
"static/lib/jquery.deferred-queue/jquery.deferred-queue.js",
"static/lib/jquery.scrollTo/jquery.scrollTo-min.js",
@ -56,6 +56,7 @@
'css' : [
"static/lib/jquery.superfish/css/superfish.css",
"static/lib/jquery.ui/css/smoothness/jquery-ui-1.8.17.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.css",

View File

@ -1,6 +1,6 @@
#!/usr/bin/python
import http
import nonliterals
import release
import session
import xml2json
from . import http
from . import nonliterals
from . import release
from . import session
from . import xml2json

View File

@ -25,9 +25,9 @@ import werkzeug.utils
import werkzeug.wrappers
import werkzeug.wsgi
import nonliterals
import session
import openerplib
from . import nonliterals
from . import session
from . import openerplib
__all__ = ['Root', 'jsonrequest', 'httprequest', 'Controller',
'WebRequest', 'JsonRequest', 'HttpRequest']
@ -357,11 +357,13 @@ def session_context(request, storage_path, session_cookie='sessionid'):
# session id, and are generally noise
removed_sessions = set()
for key, value in request.session.items():
if (isinstance(value, session.OpenERPSession)
and not value._uid
and not value.jsonp_requests
and value._creation_time + (60*5) < time.time() # FIXME do not use a fixed value
):
if not isinstance(value, session.OpenERPSession):
continue
if getattr(value, '_suicide', False) or (
not value._uid
and not value.jsonp_requests
# FIXME do not use a fixed value
and value._creation_time + (60*5) < time.time()):
_logger.debug('remove session %s', key)
removed_sessions.add(key)
del request.session[key]

View File

@ -28,5 +28,5 @@
#
##############################################################################
from main import *
from .main import *

View File

@ -6,7 +6,7 @@ import logging
import time
import openerplib
import nonliterals
from . import nonliterals
_logger = logging.getLogger(__name__)
#----------------------------------------------------------
@ -36,6 +36,7 @@ class OpenERPSession(object):
self._uid = False
self._login = False
self._password = False
self._suicide = False
self.context = {}
self.contexts_store = {}
self.domains_store = {}

View File

@ -1 +1 @@
import main
from . import main

View File

@ -5,8 +5,10 @@ import base64
import csv
import glob
import itertools
import logging
import operator
import datetime
import hashlib
import os
import re
import simplejson
@ -19,6 +21,7 @@ from cStringIO import StringIO
import babel.messages.pofile
import werkzeug.utils
import werkzeug.wrappers
try:
import xlwt
except ImportError:
@ -34,21 +37,22 @@ openerpweb = common.http
def concat_xml(file_list):
"""Concatenate xml files
return (concat,timestamp)
concat: concatenation of file content
timestamp: max(os.path.getmtime of file_list)
:param list(str) file_list: list of files to check
:returns: (concatenation_result, checksum)
:rtype: (str, str)
"""
checksum = hashlib.new('sha1')
if not file_list:
return '', None
return '', checksum.hexdigest()
root = None
files_timestamp = 0
for fname in file_list:
ftime = os.path.getmtime(fname)
if ftime > files_timestamp:
files_timestamp = ftime
xml = ElementTree.parse(fname).getroot()
with open(fname, 'rb') as fp:
contents = fp.read()
checksum.update(contents)
fp.seek(0)
xml = ElementTree.parse(fp).getroot()
if root is None:
root = ElementTree.Element(xml.tag)
@ -57,17 +61,21 @@ def concat_xml(file_list):
for child in xml.getchildren():
root.append(child)
return ElementTree.tostring(root, 'utf-8'), files_timestamp
return ElementTree.tostring(root, 'utf-8'), checksum.hexdigest()
def concat_files(file_list, reader=None, intersperse=""):
""" Concatenate file content
return (concat,timestamp)
concat: concatenation of file content, read by `reader`
timestamp: max(os.path.getmtime of file_list)
""" Concatenates contents of all provided files
:param list(str) file_list: list of files to check
:param function reader: reading procedure for each file
:param str intersperse: string to intersperse between file contents
:returns: (concatenation_result, checksum)
:rtype: (str, str)
"""
checksum = hashlib.new('sha1')
if not file_list:
return '', None
return '', checksum.hexdigest()
if reader is None:
def reader(f):
@ -75,19 +83,18 @@ def concat_files(file_list, reader=None, intersperse=""):
return fp.read()
files_content = []
files_timestamp = 0
for fname in file_list:
ftime = os.path.getmtime(fname)
if ftime > files_timestamp:
files_timestamp = ftime
contents = reader(fname)
checksum.update(contents)
files_content.append(contents)
files_content.append(reader(fname))
files_concat = intersperse.join(files_content)
return files_concat,files_timestamp
return files_concat, checksum.hexdigest()
html_template = """<!DOCTYPE html>
<html style="height: 100%%">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>OpenERP</title>
<link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon"/>
@ -149,10 +156,51 @@ class WebClient(openerpweb.Controller):
def qweblist(self, req, mods=None):
return self.manifest_list(req, mods, 'qweb')
def get_last_modified(self, files):
""" Returns the modification time of the most recently modified
file provided
:param list(str) files: names of files to check
:return: most recent modification time amongst the fileset
:rtype: datetime.datetime
"""
files = list(files)
if files:
return max(datetime.datetime.fromtimestamp(os.path.getmtime(f))
for f in files)
return datetime.datetime(1970, 1, 1)
def make_conditional(self, req, response, last_modified=None, etag=None):
""" Makes the provided response conditional based upon the request,
and mandates revalidation from clients
Uses Werkzeug's own :meth:`ETagResponseMixin.make_conditional`, after
setting ``last_modified`` and ``etag`` correctly on the response object
:param req: OpenERP request
:type req: web.common.http.WebRequest
:param response: Werkzeug response
:type response: werkzeug.wrappers.Response
:param datetime.datetime last_modified: last modification date of the response content
:param str etag: some sort of checksum of the content (deep etag)
:return: the response object provided
:rtype: werkzeug.wrappers.Response
"""
response.cache_control.must_revalidate = True
response.cache_control.max_age = 0
if last_modified:
response.last_modified = last_modified
if etag:
response.set_etag(etag)
return response.make_conditional(req.httprequest)
@openerpweb.httprequest
def css(self, req, mods=None):
files = list(self.manifest_glob(req, mods, 'css'))
last_modified = self.get_last_modified(f[0] for f in files)
if req.httprequest.if_modified_since and req.httprequest.if_modified_since >= last_modified:
return werkzeug.wrappers.Response(status=304)
file_map = dict(files)
rx_import = re.compile(r"""@import\s+('|")(?!'|"|/|https?://)""", re.U)
@ -181,24 +229,37 @@ class WebClient(openerpweb.Controller):
)
return data
content,timestamp = concat_files((f[0] for f in files), reader)
# TODO use timestamp to set Last mofified date and E-tag
return req.make_response(content, [('Content-Type', 'text/css')])
content, checksum = concat_files((f[0] for f in files), reader)
return self.make_conditional(
req, req.make_response(content, [('Content-Type', 'text/css')]),
last_modified, checksum)
@openerpweb.httprequest
def js(self, req, mods=None):
files = [f[0] for f in self.manifest_glob(req, mods, 'js')]
content, timestamp = concat_files(files, intersperse=';')
# TODO use timestamp to set Last mofified date and E-tag
return req.make_response(content, [('Content-Type', 'application/javascript')])
last_modified = self.get_last_modified(files)
if req.httprequest.if_modified_since and req.httprequest.if_modified_since >= last_modified:
return werkzeug.wrappers.Response(status=304)
content, checksum = concat_files(files, intersperse=';')
return self.make_conditional(
req, req.make_response(content, [('Content-Type', 'application/javascript')]),
last_modified, checksum)
@openerpweb.httprequest
def qweb(self, req, mods=None):
files = [f[0] for f in self.manifest_glob(req, mods, 'qweb')]
content,timestamp = concat_xml(files)
# TODO use timestamp to set Last mofified date and E-tag
return req.make_response(content, [('Content-Type', 'text/xml')])
last_modified = self.get_last_modified(files)
if req.httprequest.if_modified_since and req.httprequest.if_modified_since >= last_modified:
return werkzeug.wrappers.Response(status=304)
content,checksum = concat_xml(files)
return self.make_conditional(
req, req.make_response(content, [('Content-Type', 'text/xml')]),
last_modified, checksum)
@openerpweb.httprequest
def home(self, req, s_action=None, **kw):
@ -554,6 +615,10 @@ class Session(openerpweb.Controller):
req.session.assert_valid()
return None
@openerpweb.jsonrequest
def destroy(self, req):
req.session._suicide = True
def eval_context_and_domain(session, context, domain=None):
e_context = session.eval_context(context)
# should we give the evaluated context as an evaluation context to the domain?
@ -676,15 +741,33 @@ def fix_view_modes(action):
class Menu(openerpweb.Controller):
_cp_path = "/web/menu"
@openerpweb.jsonrequest
def load(self, req):
return {'data': self.do_load(req)}
def do_load_level(self, req, parent_id=False):
Menus = req.session.model('ir.ui.menu')
context = req.session.eval_context(req.context)
menu_ids = Menus.search([('parent_id','=',parent_id)], 0, False, False, context)
menu_items = Menus.read(menu_ids, ['name', 'sequence', 'parent_id'], context)
for menu in menu_items:
menu['children'] = self.do_load_level(req, parent_id = menu['id'])
return menu_items
@openerpweb.jsonrequest
def get_user_roots(self, req):
return self.do_get_user_roots(req)
def do_get_user_roots(self, req):
""" Return all root menu ids visible for the session user.
:param req: A request object, with an OpenERP session attribute
:type req: < session -> OpenERPSession >
:return: the root menu ids
:rtype: list(int)
"""
s = req.session
context = s.eval_context(req.context)
Menus = s.model('ir.ui.menu')
# If a menu action is defined use its domain to get the root menu items
user_menu_id = s.model('res.users').read([s._uid], ['menu_id'], context)[0]['menu_id']
if user_menu_id:
menu_domain = s.model('ir.actions.act_window').read([user_menu_id[0]], ['domain'], context)[0]['domain']
menu_domain = ast.literal_eval(menu_domain)
else:
menu_domain = [('parent_id', '=', False)]
return Menus.search(menu_domain, 0, False, False, context)
def do_load(self, req):
""" Loads all menu items (all applications and their sub-menus).
@ -694,13 +777,38 @@ class Menu(openerpweb.Controller):
:return: the menu root
:rtype: dict('children': menu_nodes)
"""
root_children = self.do_load_level(req)
root_menu = {'id': False, 'name': 'root', 'parent_id': [-1, ''], 'children': root_children}
return root_menu
context = req.session.eval_context(req.context)
Menus = req.session.model('ir.ui.menu')
@openerpweb.jsonrequest
def load(self, req):
return {'data': self.do_load(req)}
menu_roots = Menus.read(self.do_get_user_roots(req), ['name', 'sequence', 'parent_id'], context)
menu_root = {'id': False, 'name': 'root', 'parent_id': [-1, ''], 'children' : menu_roots}
# menus are loaded fully unlike a regular tree view, cause there are a
# limited number of items (752 when all 6.1 addons are installed)
menu_ids = Menus.search([], 0, False, False, context)
menu_items = Menus.read(menu_ids, ['name', 'sequence', 'parent_id'], context)
# adds roots at the end of the sequence, so that they will overwrite
# equivalent menu items from full menu read when put into id:item
# mapping, resulting in children being correctly set on the roots.
menu_items.extend(menu_roots)
# make a tree using parent_id
menu_items_map = dict((menu_item["id"], menu_item) for menu_item in menu_items)
for menu_item in menu_items:
if menu_item['parent_id']:
parent = menu_item['parent_id'][0]
else:
parent = False
if parent in menu_items_map:
menu_items_map[parent].setdefault(
'children', []).append(menu_item)
# sort by sequence a tree using parent_id
for menu_item in menu_items:
menu_item.setdefault('children', []).sort(
key=operator.itemgetter('sequence'))
return menu_root
@openerpweb.jsonrequest
def action(self, req, menu_id):
@ -743,21 +851,24 @@ class DataSet(openerpweb.Controller):
context, domain = eval_context_and_domain(
req.session, req.context, domain)
ids = Model.search(domain, 0, False, sort or False, context)
# need to fill the dataset with all ids for the (domain, context) pair,
# so search un-paginated and paginate manually before reading
paginated_ids = ids[offset:(offset + limit if limit else None)]
ids = Model.search(domain, offset or 0, limit or False, sort or False, context)
if limit and len(ids) == limit:
length = Model.search_count(domain, context)
else:
length = len(ids) + (offset or 0)
if fields and fields == ['id']:
# shortcut read if we only want the ids
return {
'ids': ids,
'records': [{'id': id} for id in paginated_ids]
'length': length,
'records': [{'id': id} for id in ids]
}
records = Model.read(paginated_ids, fields or False, context)
records = Model.read(ids, fields or False, context)
records.sort(key=lambda obj: ids.index(obj['id']))
return {
'ids': ids,
'length': length,
'records': records
}
@ -1134,11 +1245,21 @@ class SearchView(View):
@openerpweb.jsonrequest
def get_filters(self, req, model):
logger = logging.getLogger(__name__ + '.SearchView.get_filters')
Model = req.session.model("ir.filters")
filters = Model.get_filters(model)
for filter in filters:
filter["context"] = req.session.eval_context(parse_context(filter["context"], req.session))
filter["domain"] = req.session.eval_domain(parse_domain(filter["domain"], req.session))
try:
filter["context"] = req.session.eval_context(
parse_context(filter["context"], req.session))
filter["domain"] = req.session.eval_domain(
parse_domain(filter["domain"], req.session))
except Exception:
logger.exception("Failed to parse custom filter %s in %s",
filter['name'], model)
filter['disabled'] = True
del filter['context']
del filter['domain']
return filters
@openerpweb.jsonrequest
@ -1406,8 +1527,6 @@ class Export(View):
if import_compat:
if exclude and field_name in exclude:
continue
if 'function' in field:
continue
if field.get('readonly'):
# If none of the field's states unsets readonly, skip the field
if all(dict(attrs).get('readonly', True)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1465
addons/web/i18n/en_GB.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1472
addons/web/i18n/es_CR.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1456
addons/web/i18n/eu.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1456
addons/web/i18n/id.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1456
addons/web/i18n/ja.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1467
addons/web/i18n/sr@latin.po Normal file

File diff suppressed because it is too large Load Diff

1456
addons/web/i18n/sv.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,10 @@
Tipsy.prototype = {
show: function() {
$.fn.tipsy.clear();
if (!this.$element.parent().length) {
return;
}
var title = this.getTitle();
if (title && this.enabled) {
var $tip = this.tip();
@ -175,6 +179,10 @@
return this;
};
$.fn.tipsy.clear = function() {
$('div.tipsy').stop().remove();
}
$.fn.tipsy.defaults = {
className: null,

View File

@ -0,0 +1,6 @@
.ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }
.ui-timepicker-div dl { text-align: left; }
.ui-timepicker-div dl dt { height: 25px; margin-bottom: -25px; }
.ui-timepicker-div dl dd { margin: 0 10px 10px 65px; }
.ui-timepicker-div td { font-size: 90%; }
.ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; }

View File

@ -241,8 +241,8 @@ QWeb2.Engine = (function() {
return true;
},
load_xml : function(s) {
s = s.replace(/^\s*|\s*$/g, '');
if (this.tools.trim(s)[0] === '<') {
s = this.tools.trim(s);
if (s.charAt(0) === '<') {
return this.load_xml_string(s);
} else {
var req = this.get_xhr();
@ -256,6 +256,9 @@ QWeb2.Engine = (function() {
req.send(null);
var xDoc = req.responseXML;
if (xDoc) {
if (!xDoc.documentElement) {
throw new Error("QWeb2: This xml document has no root document : " + xDoc.responseText);
}
if (xDoc.documentElement.nodeName == "parsererror") {
return this.tools.exception(xDoc.documentElement.childNodes[0].nodeValue);
}

View File

@ -1,9 +1,12 @@
body { padding: 0; margin: 0; }
body.openerp {
padding: 0;
margin: 0;
overflow-y: scroll;
}
.openerp {
padding: 0;
margin: 0;
height: 100%;
overflow-y: scroll;
font-size: 80%;
font-family: Ubuntu, Helvetica, sans-serif;
}
@ -382,6 +385,14 @@ label.error {
height: 100%;
}
/* IE Hack - for IE < 9
* Avoids footer to be placed statically at 100% cutting the middle of the views
* */
.openerp .oe-application-container {
height: auto\9;
min-height: 100%\9;
}
/* Menu */
.openerp .menu {
height: 34px;
@ -747,6 +758,7 @@ label.error {
}
.openerp .filter_label.enabled, .openerp .filter_icon.enabled {
background: #aaa;
filter: none;
-moz-box-shadow: none;
-webkit-box-shadow: none;
-o-box-shadow: none;
@ -1172,7 +1184,20 @@ label.error {
/* Form */
.openerp .oe_form_button_save_dirty {
display: none;
}
.openerp .oe_form_dirty > .oe_form_header > .oe_form_buttons > .oe_form_button_save {
color: white;
background: #dc5f59;
background: -moz-linear-gradient(#dc5f59, #b33630);
background: -webkit-gradient(linear, left top, left bottom, from(#dc5f59), to(#b33630));
background: -webkit-linear-gradient(#dc5f59, #b33630);
-moz-box-shadow: none;
-webkit-box-shadow: none;
-box-shadow: none;
font-weight: bold;
}
.openerp .oe_form_frame_cell input[type="checkbox"] {
margin-top: 3px;
vertical-align: middle;
@ -1208,6 +1233,11 @@ label.error {
.openerp td.oe_form_frame_cell {
padding: 2px;
position: relative;
}
.openerp td.oe_form_field_translatable,
.openerp td.oe_form_field_many2one,
.openerp td.oe_form_field_date,
.openerp td.oe_form_field_datetime {
white-space: nowrap;
}
.openerp td.oe_form_field_boolean {
@ -1307,6 +1337,10 @@ label.error {
white-space: normal;
}
.openerp .oe_forms .oe_form_paragraph.oe_multilines {
white-space: pre;
}
.openerp .oe_form_field_one2many .oe-actions h3.oe_view_title,
.openerp .oe_form_field_one2many_list .oe-actions h3.oe_view_title{
display: inline;
@ -1319,6 +1353,9 @@ label.error {
margin-top: -9px;
}
.openerp table.oe_frame .oe-listview-content td {
color: inherit;
}
/* Uneditable Form View */
.openerp .oe_form_readonly {
@ -1421,10 +1458,14 @@ label.error {
.openerp .oe_forms select{
padding-top: 2px;
}
.openerp .oe_forms input[readonly],
.openerp .oe_forms select[readonly],
.openerp .oe_forms textarea[readonly],
.openerp .oe_forms input[disabled],
.openerp .oe_forms select[disabled],
.openerp .oe_forms textarea[disabled]{
background: #E0E0E0;
background: #E5E5E5 !important;
color: #666;
}
.openerp .oe_forms textarea {
resize:vertical;
@ -1446,15 +1487,21 @@ label.error {
min-width: 100%;
width: 100%;
}
.openerp .oe_forms .button {
height: 22px;
}
@-moz-document url-prefix() {
/* Strange firefox behaviour on width: 100% + white-space: nowrap */
.openerp .oe_forms .oe_form_button .oe_button {
width: auto;
}
}
/* IE Hack - for IE < 9
* Avoids buttons overflow
* */
.openerp .oe_forms .oe_form_button .oe_button {
min-width: auto\9;
}
.openerp .oe_forms .button {
height: 22px;
}
.openerp .oe_forms .oe_button span {
position: relative;
vertical-align: top;
@ -1888,6 +1935,7 @@ label.error {
width: 100%;
background-color : #FFFFFF;
border-spacing: 0;
}
.openerp .oe-treeview-table tr:hover{
color: blue;
@ -1908,14 +1956,14 @@ label.error {
white-space: nowrap;
display: block;
}
.treeview-tr:first-of-type {
.treeview-tr.oe-treeview-first {
background: transparent url(/web/static/src/img/expand.gif) 0 50% no-repeat;
}
.oe-open .treeview-tr:first-of-type {
.oe-open .treeview-tr.oe-treeview-first {
background-image: url(/web/static/src/img/collapse.gif);
}
.treeview-tr:first-of-type span,
.treeview-td:first-of-type span {
.treeview-tr.oe-treeview-first span,
.treeview-td.oe-treeview-first span {
margin-left: 16px;
}
@ -2031,34 +2079,31 @@ ul.oe-arrow-list li.oe-arrow-list-selected .oe-arrow-list-after {
border-bottom-right-radius: 3px;
}
.openerp .oe_view_editor {
border-collapse: collapse;
padding: 0;
align: left;
width:100%;
border-collapse : collapse;
margin-left: -12px;
width: 100%;
background-color : white;
border-spacing: 0;
}
.openerp .oe_view_editor_colum{
.openerp .oe_view_editor td{
text-align: center;
white-space: nowrap;
border: 1px solid #D8D8D8;
cursor: pointer;
font-size: 90%;
font-weight: normal;
padding: 0;
border-bottom: 1px solid #CFCCCC;
}
.openerp .oe_view_editor_row:hover {
background-color: #F3F3F3;
.openerp .oe_view_editor_field td{
border: 0px !important;
}
.openerp .oe_view_editor_tree_grid{
text-align: left;
white-space: nowrap;
border-collapse: collapse;
width: 100%;
}
.openerp .oe_view_editor_tree_grid a:hover {
color: blue;
}
.openerp .oe_view_editor_tree_grid a {
display: block;
.openerp .oe_view_editor tr:hover {
background-color: #ecebf2;
}
/* Dialog traceback cases */
.openerp .oe_error_detail{
display: block;

View File

@ -20,17 +20,27 @@ openerp.web.Notification = openerp.web.OldWidget.extend(/** @lends openerp.web.
expires: 2500
});
},
notify: function(title, text) {
notify: function(title, text, sticky) {
sticky = !!sticky;
var opts = {};
if (sticky) {
opts.expires = false;
}
this.$element.notify('create', {
title: title,
text: text
});
}, opts);
},
warn: function(title, text) {
warn: function(title, text, sticky) {
sticky = !!sticky;
var opts = {};
if (sticky) {
opts.expires = false;
}
this.$element.notify('create', 'oe_notification_alert', {
title: title,
text: text
});
}, opts);
}
});
@ -606,6 +616,10 @@ openerp.web.Login = openerp.web.OldWidget.extend(/** @lends openerp.web.Login#
}
var $e = this.$element;
var db = $e.find("form [name=db]").val();
if (!db) {
this.do_warn("Login", "No database selected !");
return false;
}
var login = $e.find("form input[name=login]").val();
var password = $e.find("form input[name=password]").val();
@ -945,7 +959,8 @@ openerp.web.Menu = openerp.web.OldWidget.extend(/** @lends openerp.web.Menu# */
do_menu_click: function($clicked_menu, manual) {
var $sub_menu, $main_menu,
active = $clicked_menu.is('.active'),
sub_menu_visible = false;
sub_menu_visible = false,
has_submenu_items = false;
if (this.$secondary_menu.has($clicked_menu).length) {
$sub_menu = $clicked_menu.parents('.oe_secondary_menu');
@ -956,15 +971,18 @@ openerp.web.Menu = openerp.web.OldWidget.extend(/** @lends openerp.web.Menu# */
}
sub_menu_visible = $sub_menu.is(':visible');
has_submenu_items = !!$sub_menu.children().length;
this.$secondary_menu.find('.oe_secondary_menu').hide();
$('.active', this.$element.add(this.$secondary_menu)).removeClass('active');
$main_menu.add($clicked_menu).add($sub_menu).addClass('active');
if (!(this.folded && manual)) {
this.do_show_secondary($sub_menu, $main_menu);
} else {
this.do_show_secondary();
if (has_submenu_items) {
if (!(this.folded && manual)) {
this.do_show_secondary($sub_menu, $main_menu);
} else {
this.do_show_secondary();
}
}
if ($main_menu != $clicked_menu) {
@ -980,7 +998,7 @@ openerp.web.Menu = openerp.web.OldWidget.extend(/** @lends openerp.web.Menu# */
return true;
}
} else if (this.folded) {
if (active && sub_menu_visible) {
if ((active && sub_menu_visible) || !has_submenu_items) {
$sub_menu.hide();
return true;
}
@ -1147,12 +1165,14 @@ openerp.web.WebClient = openerp.web.OldWidget.extend(/** @lends openerp.web.WebC
n.warn.apply(n, arguments);
},
on_logout: function() {
this.session.session_logout();
$(window).unbind('hashchange', this.on_hashchange);
this.do_push_state({});
//would be cool to be able to do this, but I think it will make addons do strange things
//this.show_login();
window.location.reload();
var self = this;
this.session.session_logout().then(function () {
$(window).unbind('hashchange', self.on_hashchange);
self.do_push_state({});
//would be cool to be able to do this, but I think it will make addons do strange things
//this.show_login();
window.location.reload();
});
},
bind_hashchange: function() {
$(window).bind('hashchange', this.on_hashchange);

View File

@ -254,6 +254,7 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry
* @param {Object} mapping a mapping of keys to object-paths
*/
init: function (mapping) {
this.parent = null;
this.map = mapping || {};
},
/**
@ -269,6 +270,9 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry
get_object: function (key, silent_error) {
var path_string = this.map[key];
if (path_string === undefined) {
if (this.parent) {
return this.parent.get_object(key, silent_error);
}
if (silent_error) { return void 'nooo'; }
throw new openerp.web.KeyNotFound(key);
}
@ -286,6 +290,21 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry
}
return object_match;
},
/**
* Checks if the registry contains an object mapping for this key.
*
* @param {String} key key to look for
*/
contains: function (key) {
if (key === undefined) { return false; }
if (key in this.map) {
return true
}
if (this.parent) {
return this.parent.contains(key);
}
return false;
},
/**
* Tries a number of keys, and returns the first object matching one of
* the keys.
@ -299,7 +318,7 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry
get_any: function (keys) {
for (var i=0; i<keys.length; ++i) {
var key = keys[i];
if (key === undefined || !(key in this.map)) {
if (!this.contains(key)) {
continue;
}
@ -324,11 +343,22 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry
* Creates and returns a copy of the current mapping, with the provided
* mapping argument added in (replacing existing keys if needed)
*
* Parent and child remain linked, a new key in the parent (which is not
* overwritten by the child) will appear in the child.
*
* @param {Object} [mapping={}] a mapping of keys to object-paths
*/
extend: function (mapping) {
var child = new openerp.web.Registry(mapping);
child.parent = this;
return child;
},
/**
* @deprecated use Registry#extend
*/
clone: function (mapping) {
return new openerp.web.Registry(
_.extend({}, this.map, mapping || {}));
console.warn('Registry#clone is deprecated, use Registry#extend');
return this.extend(mapping);
}
});
@ -644,6 +674,7 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
},
session_logout: function() {
this.set_cookie('session_id', '');
return this.rpc("/web/session/destroy", {});
},
on_session_valid: function() {
},
@ -702,17 +733,21 @@ openerp.web.Connection = openerp.web.CallbackEnabled.extend( /** @lends openerp.
var params = { mods: all_modules, lang: lang};
var to_load = _.difference(result, self.module_list).join(',');
self.module_list = all_modules;
return $.when(
self.rpc('/web/webclient/csslist', {mods: to_load}, self.do_load_css),
self.rpc('/web/webclient/qweblist', {mods: to_load}).pipe(self.do_load_qweb),
self.rpc('/web/webclient/translations', params).pipe(function(trans) {
openerp.web._t.database.set_bundle(trans);
var file_list = ["/web/static/lib/datejs/globalization/" + lang.replace("_", "-") + ".js"];
return self.rpc('/web/webclient/jslist', {mods: to_load}).pipe(function(files) {
return self.do_load_js(file_list.concat(files));
});
})
).then(function() {
var loaded = $.Deferred().resolve().promise();
if (to_load.length) {
loaded = $.when(
self.rpc('/web/webclient/csslist', {mods: to_load}, self.do_load_css),
self.rpc('/web/webclient/qweblist', {mods: to_load}).pipe(self.do_load_qweb),
self.rpc('/web/webclient/translations', params).pipe(function(trans) {
openerp.web._t.database.set_bundle(trans);
var file_list = ["/web/static/lib/datejs/globalization/" + lang.replace("_", "-") + ".js"];
return self.rpc('/web/webclient/jslist', {mods: to_load}).pipe(function(files) {
return self.do_load_js(file_list.concat(files));
});
}))
}
return loaded.then(function() {
self.on_modules_loaded();
if (!no_session_valid_signal) {
self.on_session_valid();
@ -1184,9 +1219,7 @@ openerp.web.TranslationDataBase = openerp.web.Class.extend(/** @lends openerp.we
add_module_translation: function(mod) {
var self = this;
_.each(mod.messages, function(message) {
if (self.db[message.id] === undefined) {
self.db[message.id] = message.string;
}
self.db[message.id] = message.string;
});
},
build_translation_function: function() {

View File

@ -469,13 +469,13 @@ openerp.web.DataSet = openerp.web.OldWidget.extend( /** @lends openerp.web.Data
* @param {String} name name to perform a search for/on
* @param {Array} [domain=[]] filters for the objects returned, OpenERP domain
* @param {String} [operator='ilike'] matching operator to use with the provided name value
* @param {Number} [limit=100] maximum number of matches to return
* @param {Number} [limit=0] maximum number of matches to return
* @param {Function} callback function to call with name_search result
* @returns {$.Deferred}
*/
name_search: function (name, domain, operator, limit, callback) {
return this.call_and_eval('name_search',
[name || '', domain || false, operator || 'ilike', this.get_context(), limit || 100],
[name || '', domain || false, operator || 'ilike', this.get_context(), limit || 0],
1, 3, callback);
},
/**
@ -522,7 +522,13 @@ openerp.web.DataSet = openerp.web.OldWidget.extend( /** @lends openerp.web.Data
this._sort.unshift((reverse ? '-' : '') + field);
return undefined;
}
},
size: function () {
return this.ids.length;
},
alter_ids: function(n_ids) {
this.ids = n_ids;
},
});
openerp.web.DataSetStatic = openerp.web.DataSet.extend({
init: function(parent, model, context, ids) {
@ -568,6 +574,7 @@ openerp.web.DataSetSearch = openerp.web.DataSet.extend(/** @lends openerp.web.D
this._super(parent, model, context);
this.domain = domain || [];
this.offset = 0;
this._length;
// subset records[offset:offset+limit]
// is it necessary ?
this.ids = [];
@ -599,6 +606,7 @@ openerp.web.DataSetSearch = openerp.web.DataSet.extend(/** @lends openerp.web.D
}).pipe(function (result) {
self.ids = result.ids;
self.offset = offset;
self._length = result.length;
return result.records;
});
},
@ -619,6 +627,12 @@ openerp.web.DataSetSearch = openerp.web.DataSet.extend(/** @lends openerp.web.D
if (callback)
callback(result);
}, error_callback);
},
size: function () {
if (this._length !== undefined) {
return this._length;
}
return this._super();
}
});
openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({
@ -640,7 +654,6 @@ openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({
defaults: this.last_default_get};
this.to_create.push(_.extend(_.clone(cached), {values: _.clone(cached.values)}));
this.cache.push(cached);
this.on_change();
var prom = $.Deferred().then(callback);
prom.resolve({result: cached.id});
return prom.promise();
@ -751,7 +764,7 @@ openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({
self.cache.push({id: id, values: record});
} else {
// I assume cache value is prioritary
_.defaults(cached.values, record);
cached.values = _.defaults(_.clone(cached.values), record);
}
});
return_records();
@ -774,7 +787,11 @@ openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({
}
}
return this._super(method, args, callback, error_callback);
}
},
alter_ids: function(n_ids) {
this._super(n_ids);
this.on_change();
},
});
openerp.web.BufferedDataSet.virtual_id_regex = /^one2many_v_id_.*$/;

View File

@ -109,9 +109,20 @@ openerp.web.DataImport = openerp.web.Dialog.extend({
_(fields).each(function (field, field_name) {
// Ignore spec for id field
// Don't import function fields (function and related)
if (field_name === 'id' || 'function' in field) {
if (field_name === 'id') {
return;
}
// Skip if there's no state which could disable @readonly,
// if a field is ever always readonly we can't import it
if (field.readonly) {
// no states at all
if (_.isEmpty(field.states)) { return; }
// no state altering @readonly
if (!_.any(field.states, function (modifiers) {
return _(modifiers).chain().pluck(0).contains('readonly').value();
})) { return; }
}
var f = {
id: field_name,
name: field_name,

View File

@ -61,6 +61,28 @@ openerp.web.insert_thousand_seps = function (num) {
return (negative ? '-' : '') + openerp.web.intersperse(
num, _t.database.parameters.grouping, _t.database.parameters.thousands_sep);
};
/**
* removes literal (non-format) text from a date or time pattern, as datejs can
* not deal with literal text in format strings (whatever the format), whereas
* strftime allows for literal characters
*
* @param {String} value original format
*/
openerp.web.strip_raw_chars = function (value) {
var isletter = /[a-zA-Z]/, output = [];
for(var index=0; index < value.length; ++index) {
var character = value[index];
if(isletter.test(character) && (index === 0 || value[index-1] !== '%')) {
continue;
}
output.push(character);
}
return output.join('');
};
var normalize_format = function (format) {
return Date.normalizeFormat(openerp.web.strip_raw_chars(format));
};
/**
* Formats a single atomic value based on a field descriptor
*
@ -101,7 +123,12 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) {
formatted[0] = openerp.web.insert_thousand_seps(formatted[0]);
return formatted.join(l10n.decimal_point);
case 'float_time':
return _.str.sprintf("%02d:%02d",
var pattern = '%02d:%02d';
if (value < 0) {
value = Math.abs(value);
pattern = '-' + pattern;
}
return _.str.sprintf(pattern,
Math.floor(value),
Math.round((value % 1) * 60));
case 'many2one':
@ -111,16 +138,16 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) {
if (typeof(value) == "string")
value = openerp.web.auto_str_to_date(value);
return value.format(l10n.date_format
+ ' ' + l10n.time_format);
return value.toString(normalize_format(l10n.date_format)
+ ' ' + normalize_format(l10n.time_format));
case 'date':
if (typeof(value) == "string")
value = openerp.web.auto_str_to_date(value);
return value.format(l10n.date_format);
return value.toString(normalize_format(l10n.date_format));
case 'time':
if (typeof(value) == "string")
value = openerp.web.auto_str_to_date(value);
return value.format(l10n.time_format);
return value.toString(normalize_format(l10n.time_format));
case 'selection':
// Each choice is [value, label]
if(_.isArray(value)) {
@ -137,8 +164,8 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) {
};
openerp.web.parse_value = function (value, descriptor, value_if_empty) {
var date_pattern = Date.normalizeFormat(_t.database.parameters.date_format),
time_pattern = Date.normalizeFormat(_t.database.parameters.time_format);
var date_pattern = normalize_format(_t.database.parameters.date_format),
time_pattern = normalize_format(_t.database.parameters.time_format);
switch (value) {
case false:
case "":
@ -171,12 +198,17 @@ openerp.web.parse_value = function (value, descriptor, value_if_empty) {
throw new Error(value + " is not a correct float");
return parsed;
case 'float_time':
var factor = 1;
if (value[0] === '-') {
value = value.slice(1);
factor = -1;
}
var float_time_pair = value.split(":");
if (float_time_pair.length != 2)
return openerp.web.parse_value(value, {type: "float"});
return factor * openerp.web.parse_value(value, {type: "float"});
var hours = openerp.web.parse_value(float_time_pair[0], {type: "integer"});
var minutes = openerp.web.parse_value(float_time_pair[1], {type: "integer"});
return hours + (minutes / 60);
return factor * (hours + (minutes / 60));
case 'progressbar':
return openerp.web.parse_value(value, {type: "float"});
case 'datetime':

View File

@ -154,7 +154,6 @@ openerp.web.SearchView = openerp.web.OldWidget.extend(/** @lends openerp.web.Sea
// for extended search view
var ext = new openerp.web.search.ExtendedSearch(this, this.model);
lines.push([ext]);
this.inputs.push(ext);
this.extended_search = ext;
var render = QWeb.render("SearchView", {
@ -187,7 +186,10 @@ openerp.web.SearchView = openerp.web.OldWidget.extend(/** @lends openerp.web.Sea
}).then(function(result) {
self.managed_filters = result;
var filters = self.$element.find(".oe_search-view-filters-management");
filters.html(QWeb.render("SearchView.managed-filters", {filters: result}));
filters.html(QWeb.render("SearchView.managed-filters", {
filters: result,
disabled_filter_message: _t('Filter disabled due to invalid syntax')
}));
filters.change(self.on_filters_management);
});
},
@ -425,13 +427,9 @@ openerp.web.SearchView = openerp.web.OldWidget.extend(/** @lends openerp.web.Sea
this.$element.find('table:last').hide();
$('.searchview_extended_groups_list').empty();
_.each(this.inputs, function (input) {
if(input.datewidget && input.datewidget.value) {
input.datewidget.set_value(false);
}
});
return $.async_when().pipe(
reload_view !== false ? this.on_clear : null);
return $.async_when.apply(
null, _(this.inputs).invoke('clear')).pipe(
reload_view !== false ? this.on_clear : null);
},
/**
* Triggered when the search view gets cleared
@ -618,7 +616,11 @@ openerp.web.search.Input = openerp.web.search.Widget.extend( /** @lends openerp.
}
}
this.attrs = attrs;
}
},
/**
* Specific clearing operations, if any
*/
clear: function () {}
});
openerp.web.search.FilterGroup = openerp.web.search.Input.extend(/** @lends openerp.web.search.FilterGroup# */{
template: 'SearchView.filters',
@ -900,6 +902,22 @@ openerp.web.search.SelectionField = openerp.web.search.Field.extend(/** @lends o
defaults[this.attrs.name] = false;
}
return this._super(defaults);
},
clear: function () {
var self = this, d = $.Deferred(), selection = this.attrs.selection;
for(var index=0; index<selection.length; ++index) {
var item = selection[index];
if (!item[1]) {
setTimeout(function () {
// won't override mutable, because we immediately bail out
//noinspection JSReferencingMutableVariableFromClosure
self.$element.val(index);
d.resolve();
}, 0);
return d.promise();
}
}
return d.resolve().promise();
}
});
openerp.web.search.BooleanField = openerp.web.search.SelectionField.extend(/** @lends openerp.web.search.BooleanField# */{
@ -947,15 +965,20 @@ openerp.web.search.DateField = openerp.web.search.Field.extend(/** @lends opener
template: "SearchView.date",
start: function () {
this._super();
// FIXME: this insanity puts a div inside a span
this.datewidget = new openerp.web.DateWidget(this);
this.datewidget.prependTo(this.$element);
this.datewidget.$element.find("input").attr("size", 15);
this.datewidget.$element.find("input").attr("autofocus",
this.attrs.default_focus === '1' ? 'autofocus' : undefined);
this.datewidget.$element.find("input")
.attr("size", 15)
.attr("autofocus", this.attrs.default_focus === '1' ? 'autofocus' : null)
.removeAttr('style');
this.datewidget.set_value(this.defaults[this.attrs.name] || false);
},
get_value: function () {
return this.datewidget.get_value() || null;
},
clear: function () {
this.datewidget.set_value(false);
}
});
/**
@ -1051,7 +1074,7 @@ openerp.web.search.ManyToOneField = openerp.web.search.CharField.extend({
}
});
openerp.web.search.ExtendedSearch = openerp.web.search.Widget.extend({
openerp.web.search.ExtendedSearch = openerp.web.search.Input.extend({
template: 'SearchView.extended_search',
init: function (parent, model) {
this._super(parent);

View File

@ -27,6 +27,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
type: 'ir.actions.act_window',
target: "current",
limit: this.dataset.limit || 80,
auto_search : true,
flags: {
sidebar: false,
deletable: false,
@ -45,9 +46,10 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
{text: _t("Create"), click: function() { self.on_create_view(); }},
{text: _t("Edit"), click: function() { self.xml_element_id = 0; self.get_arch(); }},
{text: _t("Remove"), click: function() { self.do_delete_view(); }},
{text: _t("Close"), click: function() { self.view_edit_dialog.close(); }}
{text: _t("Close"), click: function() { self.view_edit_dialog.close(); window.location.reload(); }}
]
}).open();
this.view_edit_dialog.on_close.add_last(function(){window.location.reload();});
this.main_view_id = this.parent.fields_view.view_id;
this.action_manager = new openerp.web.ActionManager(this);
this.action_manager.appendTo(this.view_edit_dialog);
@ -162,11 +164,12 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
}
},
do_delete_view: function() {
var self = this;
if (confirm(_t("Do you really want to remove this view?"))) {
var controller = this.action_manager.inner_viewmanager.views[this.action_manager.inner_viewmanager.active_view].controller;
this.dataset.unlink([this.main_view_id]).then(function() {
controller.reload_content();
this.main_view_id = self.parent.fields_view.view_id;
self.main_view_id = self.parent.fields_view.view_id;
});
}
},
@ -227,14 +230,14 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
get_arch: function() {
var self = this;
var view_arch_list = [];
this.dataset.read_ids([parseInt(self.main_view_id)], ['arch', 'type']).then(function(arch) {
this.dataset.read_ids([parseInt(self.main_view_id)], ['arch', 'type','priority']).then(function(arch) {
if (arch.length) {
var arch_object = self.parse_xml(arch[0].arch, self.main_view_id);
self.main_view_type = arch[0].type == 'tree'? 'list': arch[0].type;
view_arch_list.push({"view_id": self.main_view_id, "arch": arch[0].arch});
view_arch_list.push({"view_id": self.main_view_id, "arch": arch[0].arch,"priority":arch[0].priority});
self.dataset.read_slice([], {domain: [['inherit_id','=', parseInt(self.main_view_id)]]}).then(function(result) {
_.each(result, function(res) {
view_arch_list.push({"view_id": res.id, "arch": res.arch});
view_arch_list.push({"view_id": res.id, "arch": res.arch,"priority":res.priority});
self.inherit_view(arch_object, res);
});
return self.edit_view({"main_object": arch_object,
@ -303,7 +306,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
case 3:
//for field[@name='type']
obj = _.detect(arch_object, function(element){
if ((_.intersection(_.flatten(element.att_list), _.uniq(check))).length == check.length) {
if ((_.intersection(_.flatten(element.att_list), _.uniq(check))).length == _.uniq(check).length) {
return element;
}
});
@ -361,6 +364,20 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
title: _.str.sprintf(_t("View Editor %d - %s"), self.main_view_id, self.model),
height: '90%',
buttons: [
{text: _t("Inherited View"), click: function(){
var selected_row = self.edit_xml_dialog.$element.find('.ui-selected');
if (selected_row.length) {
if(selected_row.find('a').text().search("field") != -1){
if (confirm(_t("Do you really wants to create an inherited view here?"))) {
self.inherited_view(selected_row);
}
}else{
alert("Can't Update View");
}
}else{
alert("Select an element");
}
}},
{text: _t("Preview"), click: function() {
var action = {
context: self.session.user_context,
@ -368,6 +385,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
views: [[self.main_view_id, self.main_view_type]],
type: 'ir.actions.act_window',
target: "new",
auto_search: true,
flags: {
sidebar: false,
views_switcher: false,
@ -378,6 +396,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
action_manager.do_action(action);
}},
{text: _t("Close"), click: function(){
self.action_manager.inner_viewmanager.views[self.action_manager.inner_viewmanager.active_view].controller.reload_content();
self.edit_xml_dialog.close();
}}
]
@ -397,6 +416,53 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
self.on_select_img(this);
});
},
inherited_view: function(selected_row){
var self = this;
var row_id = parseInt((selected_row.attr('id')).split('-')[1]);
var obj = self.get_object_by_id(row_id,self.one_object['main_object'], [])[0];
var view_name = this.model + '.inherit_' + Math.round(Math.random() * 1000);
var view_find = selected_row;
var view_id;
var min_level = parseInt(selected_row.attr('level'));
while (1) {
view_find = view_find.prev();
if (view_find.length == 0 ||
self.edit_xml_dialog.$element.find(view_find).find('a').text().search("view_id") != -1 &&
parseInt(view_find.attr('level')) < min_level ) {
view_id = parseInt($(view_find).find('a').text().replace(/[^0-9]+/g, ''));
break;
}
if (view_find.attr('level') < min_level) {
min_level = parseInt(view_find.attr('level'));
}
}
var val = _.detect(obj.att_list, function(val) {return val[0] == "name";});
var priority = _.detect(self.one_object['arch'], function(val) {return val.view_id == view_id;});
var arch = _.str.sprintf("<?xml version='1.0'?>\n\t <field name='%s' position='after'> </field>", val[1]);
var vals = {'model': self.model, 'name': view_name, 'priority': priority.priority + 1, 'type': "form", 'arch': arch,'inherit_id':self.main_view_id};
this.dataset.create(vals, function(suc) {
var arch_to_obj = self.parse_xml(arch,suc.result);
obj.child_id.push(arch_to_obj[0]);
self.one_object['parent_child_id'] = self.parent_child_list(self.one_object['main_object'],[]);
self.one_object['arch'].push({'view_id':suc.result,"arch":arch,'priority': priority.priority + 1});
self.increase_level(arch_to_obj[0],obj.level+1);
self.render_inherited_view(selected_row,arch_to_obj[0]);
});
},
render_inherited_view: function(selected_row,obj){
var self = this,row_id = parseInt((selected_row.attr('id')).split('-')[1]);
var clone = this.create_clone(selected_row.clone(),obj);
if (selected_row.find("img[id^='parentimg-']").length == 0) {
($(selected_row.find('a').parent()).siblings('td'))
.append($('<img width="16" height="16"></img>').attr('src', '/web/static/src/img/collapse.gif').
attr('id','parentimg-'+ row_id).click(function(){
self.do_parent_img_hide_show(this);
}));
}
self.edit_xml_dialog.$element.
find("tr[id='viewedit-"+row_id+"']").after(clone.removeClass('ui-selected'));
_.each(obj.child_id,function(obj){self.render_inherited_view(clone,obj);});
},
on_select_img: function(element_img) {
var self = this;
var side = $(element_img).closest("tr[id^='viewedit-']");
@ -449,7 +515,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
},
do_node_add: function(side){
var self = this;
var tr = $(side).find('a').text();
var tr = self.get_object_by_id(this.one_object.clicked_tr_id, this.one_object['main_object'], [])[0].att_list[0];
var parent_tr = ($(side).prevAll("tr[level=" + String(this.one_object.clicked_tr_level - 1) + "]"))[0];
var field_dataset = new openerp.web.DataSetSearch(this, this.model, null, null);
parent_tr = $(parent_tr).find('a').text();
@ -562,13 +628,13 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
arch.arch = _.detect(children, function(xml_child) {
var temp_obj = self.create_View_Node(xml_child),
insert = _.intersection(_.flatten(temp_obj.att_list),_.uniq(check_list));
if (insert.length == check_list.length ) {return xml_child;}
if (insert.length == _.uniq(check_list).length ) {return xml_child;}
});
}
arch_to_pass = _.filter($(arch.arch), function (child) {
return child.nodeType == 1;
});
return self.do_save_xml(arch_to_pass[0], obj[0].child_id[0],[], move_direct, update_values,arch);
return self.do_save_xml(arch_to_pass[0], obj[0].child_id[0],obj[0].child_id, move_direct, update_values,arch);
},
get_object_by_id: function(id, one_object, result) {
var self = this;
@ -583,7 +649,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
}
return result;
},
create_clone: function(clone, new_node_obj, position){
create_clone: function(clone, new_node_obj){
var self = this;
clone.find('a').text(new_node_obj.name);
($(clone.find('a').parent()).siblings('td')).css( "padding-left", 20 * new_node_obj.level);
@ -599,7 +665,8 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
return clone;
},
do_save_xml: function(arch1, obj, child_list, move_direct, update_values, arch){
var self = this, children_list = $(arch1).children(), list_obj_xml = _.zip(children_list, obj.child_id);
var self = this, children_list = $(arch1).children(),list_obj_xml;
try{list_obj_xml = _.zip(children_list, obj.child_id);}catch(err){return;}
if (this.one_object.clicked_tr_id) {
if (obj.id == this.one_object.clicked_tr_id) {
var parent = false, index = _.indexOf(child_list, obj);
@ -823,6 +890,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
var value = _.detect(arch_val[0]['att_list'],function(res) {
return res instanceof Array? _.include(res, widget.name): false;
});
value = value instanceof Array ? value[1] : value;
self.edit_node_dialog.$element.find('table[id=rec_table]').append('<tr><td align="right">' + widget.string + ':</td>' + type_widget.render() + '</tr>');
type_widget.start();
@ -845,7 +913,7 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
res_groups.read_slice([], {}).done(function (res_grp) {
_.each(res_grp, function (res) {
var key = res.id;
group_names[key] = res.name;
group_names[key]=res.full_name;
group_ids.push(res.id);
});
model_data.read_slice([], {domain: [
@ -933,16 +1001,16 @@ openerp.web.ViewEditor = openerp.web.OldWidget.extend({
var action_manager = new openerp.web.ActionManager(self);
$.when(action_manager.do_action(action)).then(function() {
var controller = action_manager.dialog_viewmanager.views['form'].controller;
// TODO NIV: use page view
controller.do_set_readonly.add_last(function(){
controller.on_button_cancel.add_last(function(){
action_manager.stop()
});
controller.do_save.add_last(function(){
action_manager.stop();
new_fields_name = new openerp.web.DataSetSearch(self,'ir.model.fields', null, null);
new_fields_name.read_ids([controller.datarecord.id], ['name']).then(function(result) {
self.add_node_dialog.$element.find('select[id=field_value]').append($("<option selected></option>").attr("value", result[0].name).text(result[0].name));
var value =controller.fields.name.value;
self.add_node_dialog.$element.find('select[id=field_value]').append($("<option selected></option>").attr("value",value).text(value));
_.detect(self.add_widget,function(widget){
widget.name == "field_value"? widget.selection.push(result[0].name): false;
widget.name == "field_value"? widget.selection.push(value): false;
});
});
});
});
}
@ -1039,7 +1107,7 @@ openerp.web.ViewEditor.FieldSelect = openerp.web.ViewEditor.Field.extend({
var index = 0;
value = value === null? false: value;
for (var i = 0, ii = this.selection.length; i < ii; i++) {
if ((this.selection[i] instanceof Array && this.selection[i][1] === value) || this.selection[i] === value) index = i;
if ((this.selection[i] instanceof Array && this.selection[i][0] === value) || this.selection[i] === value) index = i;
}
this.$element.find("select[id=" + this.name + "]")[0].selectedIndex = index;
},
@ -1092,10 +1160,10 @@ var _CHILDREN = {
'calendar': ['field'],
'notebook': ['page'],
'page': ['notebook', 'group', 'field', 'label', 'button', 'newline', 'separator'],
'group': ['field', 'label', 'button', 'separator', 'newline'],
'group': ['field', 'label', 'button', 'separator', 'newline','group'],
'board': ['column'],
'action': [],
'field': ['form', 'tree', 'graph'],
'field': ['form', 'tree', 'graph','field'],
'label': [],
'button' : [],
'newline': [],

View File

@ -121,6 +121,15 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
this.sidebar.attachments = new openerp.web.form.SidebarAttachments(this.sidebar, this);
this.sidebar.add_toolbar(this.fields_view.toolbar);
this.set_common_sidebar_sections(this.sidebar);
this.sidebar.add_section(_t('Customize'), 'customize');
this.sidebar.add_items('customize', [{
label: _t('Set Default'),
form: this,
callback: function (item) {
item.form.open_defaults_dialog();
}
}]);
}
this.has_been_loaded.resolve();
},
@ -140,6 +149,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
do_show: function () {
var self = this;
this.$element.show().css('visibility', 'hidden');
this.$element.removeClass('oe_form_dirty');
return this.has_been_loaded.pipe(function() {
var result;
if (self.dataset.index === null) {
@ -168,7 +178,8 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
on_record_loaded: function(record) {
var self = this, set_values = [];
if (!record) {
throw new Error("Form: No record received");
this.do_warn("Form", "The record could not be found in the database.", true);
return $.Deferred().reject();
}
this.datarecord = record;
@ -204,6 +215,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
if (record.id) {
self.do_push_state({id:record.id});
}
self.$element.removeClass('oe_form_dirty');
});
},
on_form_changed: function() {
@ -216,6 +228,9 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
w.update_dom();
}
},
do_notify_change: function() {
this.$element.addClass('oe_form_dirty');
},
on_pager_action: function(action) {
if (this.can_be_discarded()) {
switch (action) {
@ -437,7 +452,9 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
});
},
on_button_cancel: function() {
return this.do_prev_view({'default': 'page'});
if (this.can_be_discarded()) {
return this.do_prev_view({'default': 'page'});
}
},
on_button_new: function() {
var self = this;
@ -459,8 +476,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
return def.promise();
},
can_be_discarded: function() {
return true; // FIXME: Disabled until the page view and button refactoring is done
return !this.is_dirty() || confirm(_t("Warning, the record has been modified, your changes will be discarded."));
return !this.$element.is('.oe_form_dirty') || confirm(_t("Warning, the record has been modified, your changes will be discarded."));
},
/**
* Triggers saving the form's record. Chooses between creating a new
@ -559,10 +575,10 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
} else {
this.datarecord.id = r.result;
if (!prepend_on_create) {
this.dataset.ids.push(this.datarecord.id);
this.dataset.alter_ids(this.dataset.ids.concat([this.datarecord.id]));
this.dataset.index = this.dataset.ids.length - 1;
} else {
this.dataset.ids.unshift(this.datarecord.id);
this.dataset.alter_ids([this.datarecord.id].concat(this.dataset.ids));
this.dataset.index = 0;
}
this.do_update_pager();
@ -631,6 +647,82 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
},
sidebar_context: function () {
return this.do_save().pipe(_.bind(function() {return this.get_fields_values();}, this));
},
open_defaults_dialog: function () {
var self = this;
var fields = _.chain(this.fields)
.map(function (field, name) {
var value = field.get_value();
// ignore fields which are empty, invisible, readonly, o2m
// or m2m
if (!value
|| field.invisible
|| field.readonly
|| field.field.type === 'one2many'
|| field.field.type === 'many2many') {
return false;
}
var displayed;
switch(field.field.type) {
case 'selection':
displayed = _(field.values).find(function (option) {
return option[0] === value;
})[1];
break;
case 'many2one':
displayed = field.value[1] || value;
break;
default:
displayed = value;
}
return {
name: name,
string: field.string,
value: value,
displayed: displayed,
// convert undefined to false
change_default: !!field.field.change_default
}
})
.compact()
.sortBy(function (field) { return field.string; })
.value();
var conditions = _.chain(fields)
.filter(function (field) { return field.change_default; })
.value();
var d = new openerp.web.Dialog(this, {
title: _t("Set Default"),
args: {
fields: fields,
conditions: conditions
},
buttons: [
{text: _t("Close"), click: function () { d.close(); }},
{text: _t("Save default"), click: function () {
var $defaults = d.$element.find('#formview_default_fields');
var field_to_set = $defaults.val();
if (!field_to_set) {
$defaults.parent().addClass('invalid');
return;
}
var condition = d.$element.find('#formview_default_conditions').val(),
all_users = d.$element.find('#formview_default_all').is(':checked');
new openerp.web.DataSet(self, 'ir.values').call(
'set_default', [
self.dataset.model,
field_to_set,
self.fields[field_to_set].get_value(),
all_users,
false,
condition || false
]).then(function () { d.close(); });
}}
]
});
d.template = 'FormView.set_default';
d.open();
}
});
openerp.web.FormDialog = openerp.web.Dialog.extend({
@ -831,7 +923,7 @@ openerp.web.form.Widget = openerp.web.OldWidget.extend(/** @lends openerp.web.fo
},
stop: function() {
this._super.apply(this, arguments);
$('div.tipsy').stop().remove();
$.fn.tipsy.clear();
},
process_modifiers: function() {
var compute_domain = openerp.web.form.compute_domain;
@ -861,7 +953,7 @@ openerp.web.form.Widget = openerp.web.OldWidget.extend(/** @lends openerp.web.fo
debug: openerp.connection.debug,
widget: widget
})},
gravity: $.fn.tipsy.autoBounds(50, 'n'),
gravity: $.fn.tipsy.autoBounds(50, 'nw'),
html: true,
opacity: 0.85,
trigger: 'hover'
@ -1219,6 +1311,11 @@ openerp.web.form.WidgetLabel = openerp.web.form.Widget.extend({
this._super(view, node);
if (this.node.tag == 'label' && !this.string && this.node.children.length) {
this.string = this.node.children[0];
this.align = 'left';
}
if (this.node.tag == 'label' && (this.align === 'left' || this.node.attrs.colspan || (this.string && this.string.length > 32))) {
this.form_template = "WidgetParagraph";
this.colspan = parseInt(this.node.attrs.colspan || 1, 10);
@ -1227,6 +1324,8 @@ openerp.web.form.WidgetLabel = openerp.web.form.Widget.extend({
if (isNaN(parseFloat(this.node.attrs.align))) {
this.align = 'left';
}
this.multilines = this.string && _.str.lines(this.string).length > 1;
} else {
this.colspan = 1;
this.width = '1%';
@ -1293,6 +1392,7 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f
this._super.apply(this, arguments);
if (this.field.translate) {
this.view.translatable_fields.push(this);
this.$element.addClass('oe_form_field_translatable');
this.$element.find('.oe_field_translate').click(this.on_translate);
}
if (this.nolabel && openerp.connection.debug) {
@ -1344,7 +1444,8 @@ openerp.web.form.Field = openerp.web.form.Widget.extend(/** @lends openerp.web.f
if (this.is_valid()) {
this.set_value_from_ui();
this.view.do_onchange(this);
this.view.on_form_changed();
this.view.on_form_changed(true);
this.view.do_notify_change();
} else {
this.update_dom(true);
}
@ -1389,7 +1490,7 @@ openerp.web.form.FieldChar = openerp.web.form.Field.extend({
},
update_dom: function() {
this._super.apply(this, arguments);
this.$element.find('input').prop('disabled', this.readonly);
this.$element.find('input').prop('readonly', this.readonly);
},
set_value_from_ui: function() {
this.value = openerp.web.parse_value(this.$element.find('input').val(), this);
@ -1412,7 +1513,7 @@ openerp.web.form.FieldChar = openerp.web.form.Field.extend({
openerp.web.form.FieldID = openerp.web.form.FieldChar.extend({
update_dom: function() {
this._super.apply(this, arguments);
this.$element.find('input').prop('disabled', true);
this.$element.find('input').prop('readonly', true);
}
});
@ -1490,7 +1591,7 @@ openerp.web.DateTimeWidget = openerp.web.OldWidget.extend({
showButtonPanel: true
});
this.$element.find('img.oe_datepicker_trigger').click(function() {
if (!self.readonly) {
if (!self.readonly && !self.picker('widget').is(':visible')) {
self.picker('setDate', self.value ? openerp.web.auto_str_to_date(self.value) : new Date());
self.$input_picker.show();
self.picker('show');
@ -1520,7 +1621,7 @@ openerp.web.DateTimeWidget = openerp.web.OldWidget.extend({
},
set_readonly: function(readonly) {
this.readonly = readonly;
this.$input.prop('disabled', this.readonly);
this.$input.prop('readonly', this.readonly);
this.$element.find('img.oe_datepicker_trigger').toggleClass('oe_input_icon_disabled', readonly);
},
is_valid: function(required) {
@ -1609,7 +1710,7 @@ openerp.web.form.FieldText = openerp.web.form.Field.extend({
},
update_dom: function() {
this._super.apply(this, arguments);
this.$element.find('textarea').prop('disabled', this.readonly);
this.$element.find('textarea').prop('readonly', this.readonly);
},
set_value_from_ui: function() {
this.value = openerp.web.parse_value(this.$element.find('textarea').val(), this);
@ -2126,7 +2227,7 @@ openerp.web.form.FieldMany2One = openerp.web.form.Field.extend({
},
update_dom: function() {
this._super.apply(this, arguments);
this.$input.prop('disabled', this.readonly);
this.$input.prop('readonly', this.readonly);
}
});
@ -2248,7 +2349,7 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({
this.viewmanager = new openerp.web.ViewManager(this, this.dataset, views, {});
this.viewmanager.template = 'One2Many.viewmanager';
this.viewmanager.registry = openerp.web.views.clone({
this.viewmanager.registry = openerp.web.views.extend({
list: 'openerp.web.form.One2ManyListView',
form: 'openerp.web.form.One2ManyFormView',
page: 'openerp.web.PageView'
@ -2326,13 +2427,13 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({
obj['id'] = _.uniqueId(self.dataset.virtual_id_prefix);
obj.defaults = {};
self.dataset.to_create.push(obj);
self.dataset.cache.push(_.clone(obj));
self.dataset.cache.push(_.extend(_.clone(obj), {values: _.clone(command[2])}));
ids.push(obj.id);
return;
case commands.UPDATE:
obj['id'] = command[1];
self.dataset.to_write.push(obj);
self.dataset.cache.push(_.clone(obj));
self.dataset.cache.push(_.extend(_.clone(obj), {values: _.clone(command[2])}));
ids.push(obj.id);
return;
case commands.DELETE:
@ -2539,6 +2640,13 @@ openerp.web.form.One2ManyFormView = openerp.web.FormView.extend({
this.$form_header.find('button.oe_form_button_create').click(function() {
self.do_save().then(self.on_button_new);
});
},
do_notify_change: function() {
if (this.dataset.parent_view) {
this.dataset.parent_view.do_notify_change();
} else {
this._super.apply(this, arguments);
}
}
});
@ -3151,7 +3259,7 @@ openerp.web.form.FieldBinaryFile = openerp.web.form.FieldBinary.extend({
update_dom: function() {
this._super.apply(this, arguments);
this.$element.find('.oe-binary-file-set, .oe-binary-file-clear').toggle(!this.readonly);
this.$element.find('input[type=text]').prop('disabled', this.readonly);
this.$element.find('input[type=text]').prop('readonly', this.readonly);
},
set_value: function(value) {
this._super.apply(this, arguments);

View File

@ -246,7 +246,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
self.page = 0; break;
case 'last':
self.page = Math.floor(
self.dataset.ids.length / self.limit());
self.dataset.size() / self.limit());
break;
case 'next':
self.page += 1; break;
@ -293,7 +293,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
this.dataset.ids = dataset.ids;
var limit = this.limit(),
total = dataset.ids.length,
total = dataset.size(),
first = (this.page * limit),
last;
if (!limit || (total - first) < limit) {
@ -1317,11 +1317,11 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L
if (!self.datagroup.openable) {
view.configure_pager(dataset);
} else {
if (dataset.ids.length == records.length) {
if (dataset.size() == records.length) {
// only one page
self.$row.find('td.oe-group-pagination').empty();
} else {
var pages = Math.ceil(dataset.ids.length / limit);
var pages = Math.ceil(dataset.size() / limit);
self.$row
.find('.oe-pager-state')
.text(_.str.sprintf(_t("%(page)d/%(page_count)d"), {

View File

@ -386,7 +386,7 @@ openerp.web.list_editable = function (openerp) {
template: 'ListView.row.frame'
});
var form_widgets = openerp.web.form.widgets;
openerp.web.list.form.widgets = form_widgets.clone({
openerp.web.list.form.widgets = form_widgets.extend({
'frame': 'openerp.web.list.form.WidgetFrame'
});
// All form widgets inherit a problematic behavior from
@ -395,7 +395,7 @@ openerp.web.list_editable = function (openerp) {
// former should completely remove the cell. We need to override update_dom
// on all widgets since we can't just hit on widget itself (I think)
var list_form_widgets = openerp.web.list.form.widgets;
_(list_form_widgets.map).each(function (widget_path, key) {
_(form_widgets.map).each(function (widget_path, key) {
if (key === 'frame') { return; }
var new_path = 'openerp.web.list.form.' + key;

View File

@ -92,11 +92,13 @@ openerp.web.page = function (openerp) {
openerp.web.page.FieldURIReadonly = openerp.web.page.FieldCharReadonly.extend({
form_template: 'FieldURI.readonly',
scheme: null,
format_value: function (value) {
return value;
},
set_value: function (value) {
var displayed = this._super.apply(this, arguments);
this.$element.find('a')
.attr('href', this.scheme + ':' + displayed)
.text(displayed);
.attr('href', this.scheme + ':' + value)
.text(this.format_value(value));
}
});
openerp.web.page.FieldEmailReadonly = openerp.web.page.FieldURIReadonly.extend({
@ -105,9 +107,10 @@ openerp.web.page = function (openerp) {
openerp.web.page.FieldUrlReadonly = openerp.web.page.FieldURIReadonly.extend({
set_value: function (value) {
var s = /(\w+):(.+)/.exec(value);
if (!s || !(s[1] === 'http' || s[1] === 'https')) { return; }
this.scheme = s[1];
this._super(s[2]);
if (!s) {
value = "http://" + value;
}
this.$element.find('a').attr('href', value).text(value);
}
});
openerp.web.page.FieldBooleanReadonly = openerp.web.form.FieldBoolean.extend({
@ -242,7 +245,7 @@ openerp.web.page = function (openerp) {
}
}
});
openerp.web.page.readonly = openerp.web.form.widgets.clone({
openerp.web.page.readonly = openerp.web.form.widgets.extend({
'frame': 'openerp.web.page.WidgetFrameReadonly',
'char': 'openerp.web.page.FieldCharReadonly',
'id': 'openerp.web.page.FieldCharReadonly',

View File

@ -602,16 +602,6 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner
width: '95%'}, $root).open();
});
break;
case 'customize_object':
this.rpc('/web/dataset/search_read', {
model: 'ir.model',
fields: ['id'],
domain: [['model', '=', this.dataset.model]]
}, function (result) {
self.do_edit_resource('ir.model', result.ids[0], {
name : _t("Customize Object") });
});
break;
case 'manage_views':
if (current_view.fields_view && current_view.fields_view.arch) {
var view_editor = new session.web.ViewEditor(current_view, current_view.$element, this.dataset, current_view.fields_view.arch);
@ -765,16 +755,21 @@ session.web.ViewManagerAction = session.web.ViewManager.extend(/** @lends oepner
var $logs_list = $logs.find('ul').empty();
$logs.toggleClass('oe-has-more', log_records.length > cutoff);
_(log_records.reverse()).each(function (record) {
var context = {};
if (record.context) {
try { context = py.eval(record.context).toJSON(); }
catch (e) { /* TODO: what do I do now? */ }
}
$(_.str.sprintf('<li><a href="#">%s</a></li>', record.name))
.appendTo($logs_list)
.delegate('a', 'click', function (e) {
.delegate('a', 'click', function () {
self.do_action({
type: 'ir.actions.act_window',
res_model: record.res_model,
res_id: record.res_id,
// TODO: need to have an evaluated context here somehow
//context: record.context,
views: [[false, 'form']]
context: context,
views: [[context.view_id || false, 'form']]
});
return false;
});
@ -821,10 +816,6 @@ session.web.Sidebar = session.web.OldWidget.extend({
}, {
label: _t("Export"),
callback: view.on_sidebar_export
}, {
label: _t("View Log"),
callback: view.on_sidebar_view_log,
classname: 'oe_hide oe_sidebar_view_log'
}
]);
},
@ -863,18 +854,32 @@ session.web.Sidebar = session.web.OldWidget.extend({
}
return $section;
},
/**
* For each item added to the section:
*
* ``label``
* will be used as the item's name in the sidebar
*
* ``action``
* descriptor for the action which will be executed, ``action`` and
* ``callback`` should be exclusive
*
* ``callback``
* function to call when the item is clicked in the sidebar, called
* with the item descriptor as its first argument (so information
* can be stored as additional keys on the object passed to
* ``add_items``)
*
* ``classname`` (optional)
* ``@class`` set on the sidebar serialization of the item
*
* ``title`` (optional)
* will be set as the item's ``@title`` (tooltip)
*
* @param {String} section_code
* @param {Array<{label, action | callback[, classname][, title]}>} items
*/
add_items: function(section_code, items) {
// An item is a dictonary : {
// label: label to be displayed for the link,
// action: action to be launch when the link is clicked,
// callback: a function to be executed when the link is clicked,
// classname: optional dom class name for the line,
// title: optional title for the link
// }
// Note: The item should have one action or/and a callback
//
var self = this,
$section = this.add_section(_.str.titleize(section_code.replace('_', ' ')), section_code),
section_id = $section.attr('id');
@ -1038,7 +1043,8 @@ session.web.TranslateDialog = session.web.Dialog.extend({
},
on_button_Save: function() {
var trads = {},
self = this;
self = this,
trads_mutex = new $.Mutex();
self.$fields_form.find('.oe_trad_field.touched').each(function() {
var field = $(this).attr('name').split('-');
if (!trads[field[0]]) {
@ -1051,9 +1057,10 @@ session.web.TranslateDialog = session.web.Dialog.extend({
_.each(data, function(value, field) {
self.view.fields[field].set_value(value);
});
} else {
self.view.dataset.write(self.view.datarecord.id, data, { 'lang': code });
}
trads_mutex.exec(function() {
return self.view.dataset.write(self.view.datarecord.id, data, { context : { 'lang': code } });
});
});
this.close();
},
@ -1222,8 +1229,6 @@ session.web.View = session.web.Widget.extend(/** @lends session.web.View# */{
view_mode : "list"
});
},
on_sidebar_view_log: function() {
},
sidebar_context: function () {
return $.when();
},

View File

@ -484,7 +484,6 @@
<option t-if="view_manager.searchview" value="edit" data-model="ir.ui.view" t-att-data-id="view_manager.searchview.view_id">Edit SearchView</option>
<option t-if="view_manager.action" value="edit" t-att-data-model="view_manager.action.type" t-att-data-id="view_manager.action.id">Edit Action</option>
<option value="edit_workflow">Edit Workflow</option>
<option value="customize_object">Customize Object</option>
</t>
</t>
<t t-name="ViewManagerDebugViewLog">
@ -529,11 +528,11 @@
</div>
</t>
<t t-name="Sidebar.section.items">
<li t-foreach="items" t-as="item" t-att-class="item.classname">
<a class="oe_sidebar_action_a" t-att-id="item.element_id" t-att-title="item.title" href="#">
<t t-esc="item.label"/>
</a>
</li>
<li t-foreach="items" t-as="item" t-att-class="item.classname">
<a class="oe_sidebar_action_a" t-att-id="item.element_id" t-att-title="item.title" href="#">
<t t-esc="item.label"/>
</a>
</li>
</t>
<t t-name="TranslateDialog">
@ -580,20 +579,21 @@
t-att-data-id="record.id" t-att-data-level="level + 1">
<t t-set="children" t-value="record[children_field]"/>
<t t-set="class" t-value="children and children.length ? 'treeview-tr' : 'treeview-td'"/>
<t t-set="rank" t-value="'oe-treeview-first'"/>
<t t-set="style" t-value="'background-position: ' + 19*level + 'px; padding-left: ' + 19*level + 'px;'"/>
<td t-foreach="fields_view" t-as="field"
t-if="!field.attrs.modifiers.tree_invisible"
t-att-data-id="record.id"
t-att-style="color_for(record) + style "
t-att-class="(fields[field.attrs.name].type === 'float') or (fields[field.attrs.name].type === 'integer')
? (class +' ' +'oe-number') : class">
t-attf-class="#{class} #{rank} #{(fields[field.attrs.name].type === 'float') or (fields[field.attrs.name].type === 'integer') ? 'oe-number' : ''}">
<span t-if="!field.attrs.modifiers.invisible" >
<t t-esc="render(record[field.attrs.name], fields[field.attrs.name])" />
</span>
<t t-set="class" t-value="'treeview-td'"/>
<t t-set="rank" t-value="''"/>
<t t-set="style" t-value="''"/>
</td>
</tr>
@ -791,6 +791,62 @@
</li>
</ul>
</t>
<form t-name="FormView.set_default" class="oe_forms oe_frame">
<t t-set="args" t-value="widget.dialog_options.args"/>
<table style="width: 100%">
<tr>
<td>
<label for="formview_default_fields"
class="oe_label oe_align_right">
Default:
</label>
</td>
<td class="required">
<select id="formview_default_fields">
<option value=""/>
<option t-foreach="args.fields" t-as="field"
t-att-value="field.name">
<t t-esc="field.string"/> = <t t-esc="field.displayed"/>
</option>
</select>
</td>
</tr>
<tr t-if="args.conditions.length">
<td>
<label for="formview_default_conditions"
class="oe_label oe_align_right">
Condition:
</label>
</td>
<td>
<select id="formview_default_conditions">
<option value=""/>
<option t-foreach="args.conditions" t-as="cond"
t-att-value="cond.name + '=' + cond.value">
<t t-esc="cond.string"/>=<t t-esc="cond.displayed"/>
</option>
</select>
</td>
</tr>
<tr>
<td colspan="2">
<input type="radio" id="formview_default_self"
value="self" name="scope" checked="checked"/>
<label for="formview_default_self" class="oe_label"
style="display: inline;">
Only you
</label>
<br/>
<input type="radio" id="formview_default_all"
value="all" name="scope"/>
<label for="formview_default_all" class="oe_label"
style="display: inline;">
All users
</label>
</td>
</tr>
</table>
</form>
<t t-name="Widget">
Unhandled widget
<t t-js="dict">console.warn('Unhandled widget', dict.widget);</t>
@ -906,6 +962,10 @@
<span class="oe_tooltip_technical_title">Modifiers:</span>
<t t-esc="widget.node.attrs.modifiers"/>
</li>
<li t-if="widget.field and widget.field.change_default" data-item="change_default">
<span class="oe_tooltip_technical_title">Change default:</span>
Yes
</li>
<li t-if="widget.node.attrs.on_change" data-item="on_change">
<span class="oe_tooltip_technical_title">On change:</span>
<t t-esc="widget.node.attrs.on_change"/>
@ -927,7 +987,7 @@
</ul>
</t>
<t t-name="WidgetParagraph">
<p t-attf-class="oe_form_paragraph oe_align_#{widget.align}"><t t-esc="widget.string"/></p>
<p t-attf-class="oe_form_paragraph oe_align_#{widget.align} #{widget.multilines ? 'oe_multilines' : ''}"><t t-esc="widget.string"/></p>
</t>
<t t-name="FieldChar">
<input t-att-type="widget.password ? 'password' : 'text'" size="1"
@ -945,7 +1005,7 @@
</t>
<t t-name="FieldURI.readonly">
<div>
<a href="#" class="oe_form_uri">#</a>
<a href="#" class="oe_form_uri"/>
</div>
</t>
<t t-name="FieldEmail">
@ -1217,7 +1277,11 @@
<option class="oe-filters-title" value="">Filters</option>
<optgroup label="-- Filters --">
<t t-foreach="filters" t-as="filter">
<option t-attf-value="get:#{filter_index}"><t t-esc="filter.name"/></option>
<option t-attf-value="get:#{filter_index}"
t-att-disabled="filter.disabled and 'disabled'"
t-att-title="filter.disabled and disabled_filter_message">
<t t-esc="filter.name"/>
</option>
</t>
</optgroup>
<optgroup label="-- Actions --">
@ -1293,7 +1357,7 @@
<span t-if="attrs.help">?</span>
</label>
<div t-att-style="style">
<span t-att-id="element_id"></span>
<span t-att-id="element_id"/>
<t t-if="filters.length" t-raw="filters.render(defaults)"/>
</div>
</t>
@ -1479,9 +1543,9 @@
</table>
</t>
<t t-name="view_editor.row">
<tr class="oe_view_editor_row" t-att-id="'viewedit-' + rec.id" t-att-level="rec.level" t-foreach="data" t-as="rec">
<td class="oe_view_editor_colum" width="85%">
<table class="oe_view_editor_tree_grid">
<tr t-att-id="'viewedit-' + rec.id" t-att-level="rec.level" t-foreach="data" t-as="rec">
<td width="90%">
<table class="oe_view_editor_field">
<tr>
<td width="16px" t-att-style="'background-position: ' + 20*rec.level + 'px; padding-left: ' + 20*rec.level + 'px'">
<img t-if="rec.child_id.length" t-att-id="'parentimg-' + rec.id"
@ -1495,30 +1559,24 @@
</tr>
</table>
</td>
<td align="left" class="oe_view_editor_colum" width="15%">
<table width="100%">
<tr>
<td width="20%">
<img t-if="rec.att_list.length"
id="side-add" src="/web/static/src/img/icons/gtk-add.png" style="cursor: pointer;"/>
</td>
<td width="20%">
<img id="side-remove" src="/web/static/src/img/icons/gtk-remove.png" style="cursor: pointer;"/>
</td>
<td width="20%">
<img t-if="rec.att_list.length and !_.include(no_properties, rec.att_list[0])"
id="side-edit" src="/web/static/src/img/icons/gtk-edit.png" style="cursor: pointer;"/>
</td>
<td width="20%">
<img t-if="rec.att_list.length"
id="side-up" src="/web/static/src/img/icons/gtk-go-up.png" style="cursor: pointer;"/>
</td>
<td width="20%">
<img t-if="rec.att_list.length"
id="side-down" src="/web/static/src/img/icons/gtk-go-down.png" style="cursor: pointer;"/>
</td>
</tr>
</table>
<td width="2%">
<img t-if="rec.att_list.length"
id="side-add" src="/web/static/src/img/icons/gtk-add.png" style="cursor: pointer;"/>
</td>
<td width="2%">
<img id="side-remove" src="/web/static/src/img/icons/gtk-remove.png" style="cursor: pointer;"/>
</td>
<td width="2%">
<img t-if="rec.att_list.length and !_.include(no_properties, rec.att_list[0])"
id="side-edit" src="/web/static/src/img/icons/gtk-edit.png" style="cursor: pointer;"/>
</td>
<td width="2%">
<img t-if="rec.att_list.length"
id="side-up" src="/web/static/src/img/icons/gtk-go-up.png" style="cursor: pointer;"/>
</td>
<td width="2%">
<img t-if="rec.att_list.length"
id="side-down" src="/web/static/src/img/icons/gtk-go-down.png" style="cursor: pointer;"/>
</td>
<t t-if="rec.child_id.length">
<t t-set="data" t-value="rec.child_id"/>

View File

@ -71,6 +71,15 @@ $(document).ready(function () {
strictEqual(
openerp.web.format_value(0.0085, {type:'float', widget:'float_time'}),
'00:01');
strictEqual(
openerp.web.format_value(-1.0, {type:'float', widget:'float_time'}),
'-01:00');
strictEqual(
openerp.web.format_value(-0.9853, {type:'float', widget:'float_time'}),
'-00:59');
strictEqual(
openerp.web.format_value(-0.0085, {type:'float', widget:'float_time'}),
'-00:01');
});
test("format_float", function () {
var fl = 12.1234;
@ -195,4 +204,29 @@ $(document).ready(function () {
equal(openerp.web.format_value(6000, {type: 'float'}),
'6.000,00');
});
module('custom-date-formats', {
setup: function () {
openerp = window.openerp.init();
window.openerp.web.core(openerp);
window.openerp.web.dates(openerp);
window.openerp.web.formats(openerp);
}
});
test('format stripper', function () {
strictEqual(openerp.web.strip_raw_chars('%a, %Y %b %d'), '%a, %Y %b %d');
strictEqual(openerp.web.strip_raw_chars('%a, %Y.eko %bren %da'), '%a, %Y. %b %d');
});
test('ES date format', function () {
openerp.web._t.database.parameters.date_format = '%a, %Y %b %d';
var date = openerp.web.str_to_date("2009-05-04");
strictEqual(openerp.web.format_value(date, {type:"date"}), 'Mon, 2009 May 04');
strictEqual(openerp.web.parse_value('Mon, 2009 May 04', {type: 'date'}), '2009-05-04');
});
test('extended ES date format', function () {
openerp.web._t.database.parameters.date_format = '%a, %Y.eko %bren %da';
var date = openerp.web.str_to_date("2009-05-04");
strictEqual(openerp.web.format_value(date, {type:"date"}), 'Mon, 2009. May 04');
strictEqual(openerp.web.parse_value('Mon, 2009. May 04', {type: 'date'}), '2009-05-04');
});
});

View File

@ -6,6 +6,7 @@ $(document).ready(function () {
window.openerp.web.core(openerp);
openerp.web.Foo = {};
openerp.web.Bar = {};
openerp.web.Foo2 = {};
}
});
test('key fetch', function () {
@ -30,4 +31,43 @@ $(document).ready(function () {
.add('bar', 'openerp.web.Bar');
strictEqual(reg.get_object('bar'), openerp.web.Bar);
});
test('extension', function () {
var reg = new openerp.web.Registry({
foo: 'openerp.web.Foo',
bar: 'openerp.web.Bar'
});
var reg2 = reg.extend({ 'foo': 'openerp.web.Foo2' });
strictEqual(reg.get_object('foo'), openerp.web.Foo);
strictEqual(reg2.get_object('foo'), openerp.web.Foo2);
});
test('remain-linked', function () {
var reg = new openerp.web.Registry({
foo: 'openerp.web.Foo',
bar: 'openerp.web.Bar'
});
var reg2 = reg.extend();
reg.add('foo2', 'openerp.web.Foo2');
strictEqual(reg.get_object('foo2'), openerp.web.Foo2);
strictEqual(reg2.get_object('foo2'), openerp.web.Foo2);
});
test('multiget', function () {
var reg = new openerp.web.Registry({
foo: 'openerp.web.Foo',
bar: 'openerp.web.Bar'
});
strictEqual(reg.get_any(['qux', 'grault', 'bar', 'foo']),
openerp.web.Bar);
});
test('extended-multiget', function () {
var reg = new openerp.web.Registry({
foo: 'openerp.web.Foo',
bar: 'openerp.web.Bar'
});
var reg2 = reg.extend();
strictEqual(reg2.get_any(['qux', 'grault', 'bar', 'foo']),
openerp.web.Bar);
});
});

View File

@ -13,7 +13,7 @@
<!-- jquery -->
<script src="/web/static/lib/jquery/jquery-1.6.4.js"></script>
<script src="/web/static/lib/jquery.ui/js/jquery-ui-1.8.9.custom.min.js"></script>
<script src="/web/static/lib/jquery.ui/js/jquery-ui-1.8.17.custom.min.js"></script>
<script src="/web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js"></script>
<script src="/web/static/lib/datejs/globalization/en-US.js"></script>

View File

@ -0,0 +1,39 @@
# English (United Kingdom) translation for openerp-web
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-06 17:33+0100\n"
"PO-Revision-Date: 2012-02-09 11:36+0000\n"
"Last-Translator: John Bradshaw <Unknown>\n"
"Language-Team: English (United Kingdom) <en_GB@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-02-10 05:09+0000\n"
"X-Generator: Launchpad (build 14771)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Calendar"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:466
msgid "Responsible"
msgstr "Responsible"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:504
msgid "Navigator"
msgstr "Navigator"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"

View File

@ -8,29 +8,29 @@ msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-06 17:33+0100\n"
"PO-Revision-Date: 2011-10-18 10:41+0000\n"
"Last-Translator: Amós Oviedo <Unknown>\n"
"PO-Revision-Date: 2012-02-13 12:43+0000\n"
"Last-Translator: luis tobar <Unknown>\n"
"Language-Team: Spanish <es@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-02-07 04:59+0000\n"
"X-Generator: Launchpad (build 14747)\n"
"X-Launchpad-Export-Date: 2012-02-14 06:19+0000\n"
"X-Generator: Launchpad (build 14781)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr ""
msgstr "Calendario"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:466
msgid "Responsible"
msgstr ""
msgstr "Responsable"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:504
msgid "Navigator"
msgstr ""
msgstr "Navegador"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:5

View File

@ -0,0 +1,41 @@
# Spanish translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2012-02-06 17:33+0100\n"
"PO-Revision-Date: 2012-02-16 21:34+0000\n"
"Last-Translator: Carlos Vásquez (CLEARCORP) "
"<carlos.vasquez@clearcorp.co.cr>\n"
"Language-Team: Spanish <es@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-02-17 05:13+0000\n"
"X-Generator: Launchpad (build 14814)\n"
"Language: es\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Calendario"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:466
msgid "Responsible"
msgstr "Responsable"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:504
msgid "Navigator"
msgstr "Navegador"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"

View File

@ -0,0 +1,39 @@
# Basque translation for openerp-web
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-06 17:33+0100\n"
"PO-Revision-Date: 2012-02-08 07:27+0000\n"
"Last-Translator: Daniel Campos <Unknown>\n"
"Language-Team: Basque <eu@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-02-09 07:27+0000\n"
"X-Generator: Launchpad (build 14763)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Egutegia"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:466
msgid "Responsible"
msgstr "Arduraduna"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:504
msgid "Navigator"
msgstr "Nabigatzailea"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"

View File

@ -8,29 +8,29 @@ msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-06 17:33+0100\n"
"PO-Revision-Date: 2011-10-23 12:12+0000\n"
"PO-Revision-Date: 2012-02-15 10:37+0000\n"
"Last-Translator: Fabrice (OpenERP) <Unknown>\n"
"Language-Team: French <fr@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-02-07 04:59+0000\n"
"X-Generator: Launchpad (build 14747)\n"
"X-Launchpad-Export-Date: 2012-02-16 05:21+0000\n"
"X-Generator: Launchpad (build 14781)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr ""
msgstr "Calendrier"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:466
msgid "Responsible"
msgstr ""
msgstr "Responsable"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:504
msgid "Navigator"
msgstr ""
msgstr "Navigateur"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:5

View File

@ -8,29 +8,29 @@ msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-06 17:33+0100\n"
"PO-Revision-Date: 2011-10-19 10:25+0000\n"
"Last-Translator: Amós Oviedo <Unknown>\n"
"PO-Revision-Date: 2012-02-09 14:24+0000\n"
"Last-Translator: Vicente <jviares@gmail.com>\n"
"Language-Team: Galician <gl@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-02-07 04:59+0000\n"
"X-Generator: Launchpad (build 14747)\n"
"X-Launchpad-Export-Date: 2012-02-10 05:09+0000\n"
"X-Generator: Launchpad (build 14771)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr ""
msgstr "Calendario"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:466
msgid "Responsible"
msgstr ""
msgstr "Responsable"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:504
msgid "Navigator"
msgstr ""
msgstr "Navegador"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:5

View File

@ -0,0 +1,39 @@
# Indonesian translation for openerp-web
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-06 17:33+0100\n"
"PO-Revision-Date: 2012-02-08 14:59+0000\n"
"Last-Translator: Budi Iskandar <Unknown>\n"
"Language-Team: Indonesian <id@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-02-09 07:27+0000\n"
"X-Generator: Launchpad (build 14763)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Kalender"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:466
msgid "Responsible"
msgstr "Yang Bertanggung Jawab"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:504
msgid "Navigator"
msgstr "Pengarah"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp"

View File

@ -8,29 +8,29 @@ msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-06 17:33+0100\n"
"PO-Revision-Date: 2011-10-08 13:39+0000\n"
"Last-Translator: Nicola Riolini - Micronaet <Unknown>\n"
"PO-Revision-Date: 2012-02-16 21:55+0000\n"
"Last-Translator: Davide Corio - agilebg.com <davide.corio@agilebg.com>\n"
"Language-Team: Italian <it@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-02-07 04:59+0000\n"
"X-Generator: Launchpad (build 14747)\n"
"X-Launchpad-Export-Date: 2012-02-17 05:13+0000\n"
"X-Generator: Launchpad (build 14814)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr ""
msgstr "Calendario"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:466
msgid "Responsible"
msgstr ""
msgstr "Responsabile"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:504
msgid "Navigator"
msgstr ""
msgstr "Navigatore"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:5

View File

@ -0,0 +1,39 @@
# Macedonian translation for openerp-web
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-06 17:33+0100\n"
"PO-Revision-Date: 2012-02-08 11:05+0000\n"
"Last-Translator: Nikola Stojanoski <nstojanoski@vion.mk>\n"
"Language-Team: Macedonian <mk@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-02-09 07:27+0000\n"
"X-Generator: Launchpad (build 14763)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Календар"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:466
msgid "Responsible"
msgstr "Одговорен"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:504
msgid "Navigator"
msgstr "Навигатор"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"

View File

@ -8,19 +8,19 @@ msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-06 17:33+0100\n"
"PO-Revision-Date: 2011-12-06 11:46+0000\n"
"Last-Translator: Douwe Wullink (Dypalio) <Unknown>\n"
"PO-Revision-Date: 2012-02-16 14:02+0000\n"
"Last-Translator: Erwin <Unknown>\n"
"Language-Team: Dutch <nl@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-02-07 04:59+0000\n"
"X-Generator: Launchpad (build 14747)\n"
"X-Launchpad-Export-Date: 2012-02-17 05:13+0000\n"
"X-Generator: Launchpad (build 14814)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr ""
msgstr "Agenda"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:466

View File

@ -8,29 +8,29 @@ msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-06 17:33+0100\n"
"PO-Revision-Date: 2011-10-07 09:05+0000\n"
"Last-Translator: Niels Huylebroeck <Unknown>\n"
"PO-Revision-Date: 2012-02-08 16:46+0000\n"
"Last-Translator: Els Van Vossel (Agaplan) <Unknown>\n"
"Language-Team: Dutch (Belgium) <nl_BE@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-02-07 04:59+0000\n"
"X-Generator: Launchpad (build 14747)\n"
"X-Launchpad-Export-Date: 2012-02-09 07:27+0000\n"
"X-Generator: Launchpad (build 14763)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr ""
msgstr "Kalender"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:466
msgid "Responsible"
msgstr ""
msgstr "Verantwoordelijke"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:504
msgid "Navigator"
msgstr ""
msgstr "Navigator"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:5

View File

@ -0,0 +1,39 @@
# Polish translation for openerp-web
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-06 17:33+0100\n"
"PO-Revision-Date: 2012-02-08 11:19+0000\n"
"Last-Translator: drygal <Unknown>\n"
"Language-Team: Polish <pl@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-02-09 07:27+0000\n"
"X-Generator: Launchpad (build 14763)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Kalendarz"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:466
msgid "Responsible"
msgstr "Odpowiedzialny"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:504
msgid "Navigator"
msgstr "Nawigator"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"

View File

@ -0,0 +1,39 @@
# Serbian Latin translation for openerp-web
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-06 17:33+0100\n"
"PO-Revision-Date: 2012-02-09 20:58+0000\n"
"Last-Translator: zmmaj <Unknown>\n"
"Language-Team: Serbian Latin <sr@latin@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-02-10 05:09+0000\n"
"X-Generator: Launchpad (build 14771)\n"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:11
msgid "Calendar"
msgstr "Kalendar"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:466
msgid "Responsible"
msgstr "Odgovorni"
#. openerp-web
#: addons/web_calendar/static/src/js/calendar.js:504
msgid "Navigator"
msgstr "Navigator"
#. openerp-web
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
msgid "&nbsp;"
msgstr "&nbsp;"

View File

@ -214,7 +214,7 @@
background-color:white;
}
.openerp .oe_cal_month .dhx_cal_data {
overflow-y: hidden;
overflow-y: auto;
}

View File

@ -350,7 +350,8 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({
event_obj['end_date'] = new Date(event_obj['start_date']);
event_obj['end_date'].addHours(1);
} else {
event_obj['end_date'].addSeconds(-1);
event_obj['start_date'].addHours(8);
event_obj['end_date'].addHours(-4);
}
this.do_create_event_with_formdialog(event_id, event_obj);
// return false;

View File

@ -1 +0,0 @@
import controllers

View File

@ -1,20 +0,0 @@
{
"name": "Web Chat",
"category": "Hidden",
"description":
"""
OpenERP Web chat module.
""",
"version": "2.0",
"depends": ['web'],
"js": [
'static/lib/AjaxIM/js/jquery.jsonp-1.1.0.js',
'static/lib/AjaxIM/js/jquery.jstore-all-min.js',
'static/lib/AjaxIM/js/jquery.md5.js',
'static/lib/AjaxIM/js/im.js',
'static/src/js/web_chat.js'
],
"css": [],
'active': False,
'installable': False,
}

View File

@ -1 +0,0 @@
import main

View File

@ -1,215 +0,0 @@
# -*- coding: utf-8 -*-
import time
import simplejson
import web.common.http as openerpweb
import logging
_logger = logging.getLogger(__name__)
#----------------------------------------------------------
# OpenERP Web ajaxim Controllers
#----------------------------------------------------------
class PollServerMessageQueue(object):
def __init__(self):
# message queue
self.messages = []
# online users
self.users = {}
# should contains: {
# 'user1234' : { s:1, m:"status message", timestamp: last_contact_timestamp }
# }
def userlist(self, req):
userlist = [users for users in req.applicationsession['users']]
# userlist = [
# {"u": "Guest130205108745.47", "s": {"s": 1, "m": ""}, "g": "Users"},
# {"u": "Guest130209838956.76", "s": {"s": 1, "m": ""}, "g": "Users"},
# ]
return userlist
def write(self, m_type, m_from, m_to, m_message, m_group):
self.messages.append({'type': m_type, 'from': m_from, 'to': m_to, 'message': m_message, 'group': m_group})
# when status message update users
pass
def read(self, recipient, timestamp):
for msg in self.messages:
if msg['to'] == recipient:
return self.messages
def gc(self):
# remove message older than 300s from self.l
# remove dead users from self.users
pass
class PollServer(openerpweb.Controller):
_cp_path = "/web_chat/pollserver"
@openerpweb.httprequest
def login(self, req, **kw):
"""
--> POST http://ajaxim.com/wp-content/plugins/im/ajaxim.php/login
Form Data
username:""
password:"d41d8cd98f00b204e9800998ecf8427e"
<-- 200 OK
Content-Type:text/html
{
"r":"logged in",
"u":"Guest130213866190.85",
"s":"f9e1811536f19ad5b9e00376f9ff1532",
"f":[
{"u":"Guest130205108745.47","s":{"s":1,"m":""},"g":"Users"},
{"u":"Guest130209838956.76","s":{"s":1,"m":""},"g":"Users"},
]
}
"""
mq = req.applicationsession.setdefault("web_chat", PollServerMessageQueue())
mq.messages = []
#r = 'logged in'
#u = generate random.randint(0,2**32)
#f = mq.userlist()
# username = 'Guest'+ str(random.randint(0, 2**32))
#
# if not req.applicationsession.get('users'):
# req.applicationsession['users'] = [{'u': username, 's':{'s':1, 'm':''}, 'g':'Users'}]
# else:
# req.applicationsession['users'].append({'u': username, 's':{'s':1, 'm':''}, 'g':'Users'})
req.applicationsession['users'] = [{'u': 'Guest1', 's':{'s':1, 'm':'111'}, 'g':'Users'},
{'u': 'Guest2', 's':{'s':1, 'm':'222'}, 'g':'Users'},
{'u': 'Guest3', 's':{'s':1, 'm':'333'}, 'g':'Users'}]
# Temporary Guest1 is my current user
req.applicationsession['current_user'] = 'Guest1'
return simplejson.dumps({'r': 'logged in', 'u': 'Guest1', 's': 'f9e1811536f19ad5b9e00376f9ff1532',
'f': [{'u': 'Guest1', 's':{'s':1, 'm':'111'}, 'g':'Users'},
{'u': 'Guest2', 's':{'s':1, 'm':'222'}, 'g':'Users'},
{'u': 'Guest3', 's':{'s':1, 'm':'333'}, 'g':'Users'}]})
@openerpweb.httprequest
def logout(self, req):
"""
--> GET http://im.ajaxim.com/logout
{ "r":"logged out" }
"""
@openerpweb.httprequest
def poll(self, req, **kw):
"""
--> GET http://im.ajaxim.com/poll?callback=jsonp1302138663582&_1302138663582=
<-- 200 OK
Content-Type:text/html
noop:
jsonp1302138663582([]);
roster user online:
jsonp1302140366243([{"t":"s","s":"Guest130214038974.31","r":"all","m":"1:","g":"Users"}]);
roster user left:
jsonp1302140441577([{"t":"s","s":"Guest130214038974.31","r":"","m":"0:"}]);
receive message:
jsonp1302140191599([{"t":"m","s":"Guest130214008855.5","r":"Guest130214013134.26","m":"xxxxxx"}]);
('t' => $msg->type, 's' => $msg->from, 'r' => $msg->to, 'm' => $msg->message )
mag type s or m
echo '<script type="text/javascript">parent.AjaxIM.incoming('. json_encode($this->_pollParseMessages($messages)) . ');</script>'
"""
mq = req.applicationsession.setdefault("web_chat", PollServerMessageQueue())
# Method: Long Poll
msg = '[]'
for i in range(5):
received_msg = mq.read('Guest1', i)
if received_msg:
msg = self._pollParseMessages(received_msg)
mq.messages = []
return '%s'%kw.get('callback', '') + '(' + str(msg) + ');'
else:
msg = '[]'
time.sleep(2)
return '%s'%kw.get('callback', '') + '(' + str(msg) + ');'
@openerpweb.httprequest
def send(self, req, **kw):
"""
--> GET http://im.ajaxim.com/send?callback=jsonp1302139980022&to=Guest130205108745.47&message=test&_1302139980022=
callback: jsonp1302139980022
to: Guest130205108745.47
message: test
_1302139980022:
<-- 200 OK
Content-Type:text/html
return array('r' => 'sent');
return array('r' => 'error', 'e' => 'no session found');
return array('r' => 'error', 'e' => 'no_recipient');
return array('r' => 'error', 'e' => 'send error');
"""
to = kw.get('to')
message = kw.get('message')
mq = req.applicationsession.setdefault("web_chat", PollServerMessageQueue())
if not req.applicationsession['current_user']:
return dict(r='error', e='no session found')
if not to:
return dict(r='error', e='no_recipient')
if message:
mq.write(m_type="m", m_from=req.applicationsession['current_user'], m_to=to, m_message=message, m_group="Users")
return '%s'%kw.get('callback', '') + '(' + simplejson.dumps({'r': 'sent'}) + ')'
else:
return {'r': 'error', 'e': 'send error'}
@openerpweb.httprequest
def status(self, req, **kw):
"""
--> GET status call
const Offline = 0;
const Available = 1;
const Away = 2;
const Invisible = 3;
<-- 200 OK
Content-Type:text/html
return array('r' => 'status set');
return array('r' => 'error', 'e' => 'no session found');
return array('r' => 'error', 'e' => 'status error');
"""
mq = req.applicationsession.setdefault("web_chat", PollServerMessageQueue())
_logger.debug("======== chat status ======== %s", kw)
# mq.write()
return {"action": ""}
def _pollParseMessages(self, messages):
msg_arr = []
for msg in messages:
msg_arr.append({"t": str(msg['type']), "s": str(msg['from']), "r": str(msg['to']), "m": str(msg['message'])})
return msg_arr
def _sanitize(self, message):
return message.replace('>', '&gt;').replace('<', '&lt;').replace('&', '&amp;');

View File

@ -1,19 +0,0 @@
# Translations template for PROJECT.
# Copyright (C) 2012 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2012-02-06 17:33+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.6\n"

View File

@ -1,19 +0,0 @@
Copyright (c) 2005 - 2010 Joshua Gross, http://ajaxim.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

File diff suppressed because it is too large Load Diff

View File

@ -1,79 +0,0 @@
// Automatically load dependencies, in order, if they aren't already loaded.
// Each array is: [filename, deptest] where deptest is the function to
// test for the dependency.
var AjaxIM, AjaxIMLoadedFunction;
(function() {
AjaxIM = {};
AjaxIM.loaded = function(f) {
AjaxIMLoadedFunction = f;
};
var tagsrc =
(thistag = document.getElementsByTagName('script'))[thistag.length-1].src;
var jsfolder = tagsrc.replace(/im.load.js([?].+)?/, '');
var imfolder = jsfolder.replace(/js\/$/, '');
var nodehost = '';
var dependencies = [
['jquery-1.3.2.js', function() { return (typeof window['jQuery'] != 'undefined'); }],
['jquery.jsonp-1.1.0.js', function() { return (typeof jQuery['jsonp'] != 'undefined'); }],
['jquery.jstore-all-min.js', function() { return (typeof jQuery['jstore'] != 'undefined'); }],
['jquery.md5.js', function() { return (typeof jQuery['md5'] != 'undefined'); }],
['im.js', function() { return (typeof window['AjaxIM'] != 'object'); }]
];
var head = document.getElementsByTagName('head')[0];
(loadDep = function(depPos) {
if(depPos >= dependencies.length) { init(); return; }
var dep = dependencies[depPos];
if(!dep[1]()) {
var newdep = document.createElement('script');
newdep.type = 'text/javascript';
newdep.src = jsfolder + dep[0];
var nextdep = function() { loadDep(depPos + 1); };
newdep.onload = nextdep;
newdep.onreadystatechange = nextdep;
head.appendChild(newdep);
} else loadDep(depPos + 1);
})(0);
var init = function() {
if(tagsrc.match(/[?]php$/)) {
AjaxIM.init({
pollServer: imfolder + 'ajaxim.php',
theme: imfolder + 'themes/default',
flashStorage: jsfolder + 'jStore.Flash.html'
});
} else if(tagsrc.match(/[?]node$/)) {
AjaxIM.init({
pollServer: imfolder + 'ajaxim.php',
theme: imfolder + 'themes/default',
flashStorage: jsfolder + 'jStore.Flash.html'
}, {
poll: 'http://' + nodehost + '/poll',
send: 'http://' + nodehost + '/send',
status: 'http://' + nodehost + '/status',
resume: 'http://' + nodehost + '/resume'
});
} else if(tagsrc.match(/[?]guest$/)) {
AjaxIM.init({
pollServer: imfolder + 'ajaxim.php',
theme: imfolder + 'themes/default',
flashStorage: jsfolder + 'jStore.Flash.html'
}, {
poll: 'http://' + nodehost + '/poll',
send: 'http://' + nodehost + '/send',
status: 'http://' + nodehost + '/status',
resume: 'http://' + nodehost + '/resume'
});
AjaxIM.client.login();
}
AjaxIM.loaded();
};
})();

View File

@ -1,19 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Flash External Object</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
/**
* This function captures the flash_ready event. We need to relay this
* back to the parent so it knows flash is ready.
*/
function flash_ready(){
parent.flash_ready();
}
</script>
</head>
<body>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width="1" height="1" id="jStoreFlash"><param name="allowScriptAccess" value="always" /><param name="movie" value="jStore.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffcc00" /><embed src="jStore.swf" quality="high" bgcolor="#ffcc00" width="1" height="1" name="jStoreFlash" align="middle" allowScriptAccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" /></object>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@ -1,269 +0,0 @@
/*
* jQuery JSONP Core Plugin 1.1.0 (2009-10-06)
*
* http://code.google.com/p/jquery-jsonp/
*
* Copyright (c) 2009 Julian Aubourg
*
* This document is licensed as free software under the terms of the
* MIT License: http://www.opensource.org/licenses/mit-license.php
*/
(function($){
// ###################### UTILITIES ##
// Test a value is neither undefined nor null
var defined = function(v) {
return v!==undefined && v!==null;
},
// Call if defined
callIfDefined = function(method,object,parameters) {
defined(method) && method.apply(object,parameters);
},
// Let the current thread running
later = function(functor) {
setTimeout(functor,0);
},
// String constants (for better minification)
empty="",
amp="&",
qMark="?",
success = "success",
error = "error",
// Head element (for faster use)
head = $("head"),
// Page cache
pageCache = {},
// ###################### DEFAULT OPTIONS ##
xOptionsDefaults = {
//beforeSend: undefined,
//cache: false,
callback: "C",
//callbackParameter: undefined,
//complete: undefined,
//data: ""
//dataFilter: undefined,
//error: undefined,
//pageCache: false,
//success: undefined,
//timeout: 0,
url: location.href
},
// ###################### MAIN FUNCTION ##
jsonp = function(xOptions) {
// Build data with default
xOptions = $.extend({},xOptionsDefaults,xOptions);
// References to beforeSend (for better minification)
var beforeSendCallback = xOptions.beforeSend,
// Abort/done flag
done = 0;
// Put a temporary abort
xOptions.abort = function() { done = 1; };
// Call beforeSend if provided (early abort if false returned)
if (defined(beforeSendCallback) && (beforeSendCallback(xOptions,xOptions)===false || done))
return xOptions;
// References to xOptions members (for better minification)
var successCallback = xOptions.success,
completeCallback = xOptions.complete,
errorCallback = xOptions.error,
dataFilter = xOptions.dataFilter,
callbackParameter = xOptions.callbackParameter,
successCallbackName = xOptions.callback,
cacheFlag = xOptions.cache,
pageCacheFlag = xOptions.pageCache,
url = xOptions.url,
data = xOptions.data,
timeout = xOptions.timeout,
// Misc variables
splitUrl,splitData,i,j;
// Control entries
url = defined(url)?url:empty;
data = defined(data)?((typeof data)=="string"?data:$.param(data)):empty;
// Add callback parameter if provided as option
defined(callbackParameter)
&& (data += (data==empty?empty:amp)+escape(callbackParameter)+"=?");
// Add anticache parameter if needed
!cacheFlag && !pageCacheFlag
&& (data += (data==empty?empty:amp)+"_"+(new Date()).getTime()+"=");
// Search for ? in url
splitUrl = url.split(qMark);
// Also in parameters if provided
// (and merge arrays)
if (data!=empty) {
splitData = data.split(qMark);
j = splitUrl.length-1;
j && (splitUrl[j] += amp + splitData.shift());
splitUrl = splitUrl.concat(splitData);
}
// If more than 2 ? replace the last one by the callback
i = splitUrl.length-2;
i && (splitUrl[i] += successCallbackName + splitUrl.pop());
// Build the final url
var finalUrl = splitUrl.join(qMark),
// Utility function
notifySuccess = function(json) {
// Apply the data filter if provided
defined(dataFilter) && (json = dataFilter.apply(xOptions,[json]));
// Call success then complete
callIfDefined(successCallback,xOptions,[json,success]);
callIfDefined(completeCallback,xOptions,[xOptions,success]);
},
notifyError = function(type) {
// Call error then complete
callIfDefined(errorCallback,xOptions,[xOptions,type]);
callIfDefined(completeCallback,xOptions,[xOptions,type]);
},
// Get from pageCache
pageCached = pageCache[finalUrl];
// Check page cache
if (pageCacheFlag && defined(pageCached)) {
later(function() {
// If an error was cached
defined(pageCached.s)
? notifySuccess(pageCached.s)
: notifyError(error);
});
return xOptions;
}
// Create & write to the iframe (sends the request)
// We let the hand to current code to avoid
// pre-emptive callbacks
// We also install the timeout here to avoid
// timeout before the code has been dumped to the frame
// (in case of insanely short timeout values)
later(function() {
// If it has been aborted, do nothing
if (done) return;
// Create an iframe & add it to the document
var frame = $("<iframe />").appendTo(head),
// Get the iframe's window and document objects
tmp = frame[0],
window = tmp.contentWindow || tmp.contentDocument,
document = window.document,
// Declaration of cleanup function
cleanUp,
// Declaration of timer for timeout (so we can clear it eventually)
timeoutTimer,
// Error function
errorFunction = function (_,type) {
// If pure error (not timeout), cache if needed
pageCacheFlag && !defined(type) && (pageCache[finalUrl] = empty);
// Cleanup
cleanUp();
// Call error then complete
notifyError(defined(type)?type:error);
},
// Iframe variable cleaning function
removeVariable = function(varName) {
window[varName] = undefined;
try { delete window[varName]; } catch(_) {}
},
// Error callback name
errorCallbackName = successCallbackName=="E"?"X":"E";
// Control if we actually retrieved the document
if(!defined(document)) {
document = window;
window = document.getParentNode();
}
// We have to open the document before
// declaring variables in the iframe's window
// Don't ask me why, I have no clue
document.open();
// Install callbacks
window[successCallbackName] = function(json) {
// Set as treated
done = 1;
// Pagecache is needed
pageCacheFlag && (pageCache[finalUrl] = {s: json});
// Give hand back to frame
// To finish gracefully
later(function(){
// Cleanup
cleanUp();
// Call success then complete
notifySuccess(json);
});
};
window[errorCallbackName] = function(state) {
// If not treated, mark
// then give hand back to iframe
// for it to finish gracefully
(!state || state=="complete") && !done++ && later(errorFunction);
};
// Clean up function (declaration)
xOptions.abort = cleanUp = function() {
// Clear the timeout (is it exists)
clearTimeout(timeoutTimer);
// Open the iframes document & clean
document.open();
removeVariable(errorCallbackName);
removeVariable(successCallbackName);
document.write(empty);
document.close();
frame.remove();
};
// Write to the document
document.write([
'<html><head><script src="',
finalUrl,'" onload="',
errorCallbackName,'()" onreadystatechange="',
errorCallbackName,'(this.readyState)"></script></head><body onload="',
errorCallbackName,'()"></body></html>'
].join(empty)
);
// Close (makes some browsers happier)
document.close();
// If a timeout is needed, install it
timeout>0 && (timeoutTimer = setTimeout(function(){
!done && errorFunction(empty,"timeout");
},timeout));
});
return xOptions;
}
// ###################### SETUP FUNCTION ##
jsonp.setup = function(xOptions) {
$.extend(xOptionsDefaults,xOptions);
};
// ###################### INSTALL in jQuery ##
$.jsonp = jsonp;
})(jQuery);

View File

@ -1,56 +0,0 @@
/*
* jStore - Persistent Client-Side Storage
*
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*
* Dual licensed under:
* MIT: http://www.opensource.org/licenses/mit-license.php
* GPLv3: http://www.opensource.org/licenses/gpl-3.0.html
*/
/*
* jQuery JSON Plugin
* version: 1.0 (2008-04-17)
*
* This document is licensed as free software under the terms of the
* MIT License: http://www.opensource.org/licenses/mit-license.php
*
* Brantley Harris technically wrote this plugin, but it is based somewhat
* on the JSON.org website's http://www.json.org/json2.js, which proclaims:
* "NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.", a sentiment that
* I uphold. I really just cleaned it up.
*
* It is also based heavily on MochiKit's serializeJSON, which is
* copywrited 2005 by Bob Ippolito.
*/
(function($){function toIntegersAtLease(n){return n<10?"0"+n:n}Date.prototype.toJSON=function(date){return this.getUTCFullYear()+"-"+toIntegersAtLease(this.getUTCMonth())+"-"+toIntegersAtLease(this.getUTCDate())};var escapeable=/["\\\x00-\x1f\x7f-\x9f]/g;var meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};$.quoteString=function(string){if(escapeable.test(string)){return'"'+string.replace(escapeable,function(a){var c=meta[a];if(typeof c==="string"){return c}c=a.charCodeAt();return"\\u00"+Math.floor(c/16).toString(16)+(c%16).toString(16)})+'"'}return'"'+string+'"'};$.toJSON=function(o,compact){var type=typeof(o);if(type=="undefined"){return"undefined"}else{if(type=="number"||type=="boolean"){return o+""}else{if(o===null){return"null"}}}if(type=="string"){return $.quoteString(o)}if(type=="object"&&typeof o.toJSON=="function"){return o.toJSON(compact)}if(type!="function"&&typeof(o.length)=="number"){var ret=[];for(var i=0;i<o.length;i++){ret.push($.toJSON(o[i],compact))}if(compact){return"["+ret.join(",")+"]"}else{return"["+ret.join(", ")+"]"}}if(type=="function"){throw new TypeError("Unable to convert object of type 'function' to json.")}var ret=[];for(var k in o){var name;type=typeof(k);if(type=="number"){name='"'+k+'"'}else{if(type=="string"){name=$.quoteString(k)}else{continue}}var val=$.toJSON(o[k],compact);if(typeof(val)!="string"){continue}if(compact){ret.push(name+":"+val)}else{ret.push(name+": "+val)}}return"{"+ret.join(", ")+"}"};$.compactJSON=function(o){return $.toJSON(o,true)};$.evalJSON=function(src){return eval("("+src+")")};$.secureEvalJSON=function(src){var filtered=src;filtered=filtered.replace(/\\["\\\/bfnrtu]/g,"@");filtered=filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]");filtered=filtered.replace(/(?:^|:|,)(?:\s*\[)+/g,"");if(/^[\],:{}\s]*$/.test(filtered)){return eval("("+src+")")}else{throw new SyntaxError("Error parsing JSON, source is not valid.")}}})(jQuery);(function(){var a=false,b=/xyz/.test(function(){xyz})?/\b_super\b/:/.*/;this.Class=function(){};Class.extend=function(g){var f=this.prototype;a=true;var e=new this();a=false;for(var d in g){e[d]=typeof g[d]=="function"&&typeof f[d]=="function"&&b.test(g[d])?(function(h,i){return function(){var k=this._super;this._super=f[h];var j=i.apply(this,arguments);this._super=k;return j}})(d,g[d]):g[d]}function c(){if(!a&&this.init){this.init.apply(this,arguments)}}c.prototype=e;c.constructor=c;c.extend=arguments.callee;return c}})();
/*
* jStore Delegate Framework
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
(function(a){this.jStoreDelegate=Class.extend({init:function(b){this.parent=b;this.callbacks={}},bind:function(b,c){if(!a.isFunction(c)){return this}if(!this.callbacks[b]){this.callbacks[b]=[]}this.callbacks[b].push(c);return this},trigger:function(){var d=this.parent,c=[].slice.call(arguments),e=c.shift(),b=this.callbacks[e];if(!b){return false}a.each(b,function(){this.apply(d,c)});return this}})})(jQuery);(function(b){var a;try{a=new RegExp('^("(\\\\.|[^"\\\\\\n\\r])*?"|[,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t])+?$')}catch(c){a=/^(true|false|null|\[.*\]|\{.*\}|".*"|\d+|\d+\.\d+)$/}b.jStore={};b.extend(b.jStore,{EngineOrder:[],Availability:{},Engines:{},Instances:{},CurrentEngine:null,defaults:{project:null,engine:null,autoload:true,flash:"jStore.Flash.html"},isReady:false,isFlashReady:false,delegate:new jStoreDelegate(b.jStore).bind("jStore-ready",function(d){b.jStore.isReady=true;if(b.jStore.defaults.autoload){d.connect()}}).bind("flash-ready",function(){b.jStore.isFlashReady=true}),ready:function(d){if(b.jStore.isReady){d.apply(b.jStore,[b.jStore.CurrentEngine])}else{b.jStore.delegate.bind("jStore-ready",d)}},fail:function(d){b.jStore.delegate.bind("jStore-failure",d)},flashReady:function(d){if(b.jStore.isFlashReady){d.apply(b.jStore,[b.jStore.CurrentEngine])}else{b.jStore.delegate.bind("flash-ready",d)}},use:function(g,i,f){i=i||b.jStore.defaults.project||location.hostname.replace(/\./g,"-")||"unknown";var h=b.jStore.Engines[g.toLowerCase()]||null,d=(f?f+".":"")+i+"."+g;if(!h){throw"JSTORE_ENGINE_UNDEFINED"}h=new h(i,d);if(b.jStore.Instances[d]){throw"JSTORE_JRI_CONFLICT"}if(h.isAvailable()){b.jStore.Instances[d]=h;if(!b.jStore.CurrentEngine){b.jStore.CurrentEngine=h}b.jStore.delegate.trigger("jStore-ready",h)}else{if(!h.autoload){throw"JSTORE_ENGINE_UNAVILABLE"}else{h.included(function(){if(this.isAvailable()){b.jStore.Instances[d]=this;if(!b.jStore.CurrentEngine){b.jStore.CurrentEngine=this}b.jStore.delegate.trigger("jStore-ready",this)}else{b.jStore.delegate.trigger("jStore-failure",this)}}).include()}}},setCurrentEngine:function(d){if(!b.jStore.Instances.length){return b.jStore.FindEngine()}if(!d&&b.jStore.Instances.length>=1){b.jStore.delegate.trigger("jStore-ready",b.jStore.Instances[0]);return b.jStore.CurrentEngine=b.jStore.Instances[0]}if(d&&b.jStore.Instances[d]){b.jStore.delegate.trigger("jStore-ready",b.jStore.Instances[d]);return b.jStore.CurrentEngine=b.jStore.Instances[d]}throw"JSTORE_JRI_NO_MATCH"},FindEngine:function(){b.each(b.jStore.EngineOrder,function(d){if(b.jStore.Availability[this]()){b.jStore.use(this,b.jStore.defaults.project,"default");return false}})},load:function(){if(b.jStore.defaults.engine){return b.jStore.use(b.jStore.defaults.engine,b.jStore.defaults.project,"default")}try{b.jStore.FindEngine()}catch(d){}},safeStore:function(d){switch(typeof d){case"object":case"function":return b.compactJSON(d);case"number":case"boolean":case"string":case"xml":return d;case"undefined":default:return""}},safeResurrect:function(d){return a.test(d)?b.evalJSON(d):d},store:function(d,e){if(!b.jStore.CurrentEngine){return false}if(!e){return b.jStore.CurrentEngine.get(d)}return b.jStore.CurrentEngine.set(d,e)},remove:function(d){if(!b.jStore.CurrentEngine){return false}return b.jStore.CurrentEngine.rem(d)},get:function(d){return b.jStore.store(d)},set:function(d,e){return b.jStore.store(d,e)}});b.extend(b.fn,{store:function(e,f){if(!b.jStore.CurrentEngine){return this}var d=b.jStore.store(e,f);return !f?d:this},removeStore:function(d){b.jStore.remove(d);return this},getStore:function(d){return b.jStore.store(d)},setStore:function(d,e){b.jStore.store(d,e);return this}})})(jQuery);(function(a){this.StorageEngine=Class.extend({init:function(c,b){this.project=c;this.jri=b;this.data={};this.limit=-1;this.includes=[];this.delegate=new jStoreDelegate(this).bind("engine-ready",function(){this.isReady=true}).bind("engine-included",function(){this.hasIncluded=true});this.autoload=false;this.isReady=false;this.hasIncluded=false},include:function(){var b=this,d=this.includes.length,c=0;a.each(this.includes,function(){a.ajax({type:"get",url:this,dataType:"script",cache:true,success:function(){c++;if(c==d){b.delegate.trigger("engine-included")}}})})},isAvailable:function(){return false},interruptAccess:function(){if(!this.isReady){throw"JSTORE_ENGINE_NOT_READY"}},ready:function(b){if(this.isReady){b.apply(this)}else{this.delegate.bind("engine-ready",b)}return this},included:function(b){if(this.hasIncluded){b.apply(this)}else{this.delegate.bind("engine-included",b)}return this},get:function(b){this.interruptAccess();return this.data[b]||null},set:function(b,c){this.interruptAccess();this.data[b]=c;return c},rem:function(b){this.interruptAccess();var c=this.data[b];this.data[b]=null;return c}})})(jQuery);
/*
* jStore DOM Storage Engine
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
(function(c){var b=c.jStore.Availability.session=function(){return !!window.sessionStorage},a=c.jStore.Availability.local=function(){return !!(window.localStorage||window.globalStorage)};this.jStoreDom=StorageEngine.extend({init:function(e,d){this._super(e,d);this.type="DOM";this.limit=5*1024*1024},connect:function(){this.delegate.trigger("engine-ready")},get:function(e){this.interruptAccess();var d=this.db.getItem(e);return c.jStore.safeResurrect((d&&d.value?d.value:d))},set:function(d,e){this.interruptAccess();this.db.setItem(d,c.jStore.safeStore(e));return e},rem:function(e){this.interruptAccess();var d=this.get(e);this.db.removeItem(e);return d}});this.jStoreLocal=jStoreDom.extend({connect:function(){this.db=!window.globalStorage?window.localStorage:window.globalStorage[location.hostname];this._super()},isAvailable:a});this.jStoreSession=jStoreDom.extend({connect:function(){this.db=sessionStorage;this._super()},isAvailable:b});c.jStore.Engines.local=jStoreLocal;c.jStore.Engines.session=jStoreSession;c.jStore.EngineOrder[1]="local"})(jQuery);
/*
* jStore Flash Storage Engine
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
* jStore.swf Copyright (c) 2008 Daniel Bulli (http://www.nuff-respec.com)
*/
(function(b){var a=b.jStore.Availability.flash=function(){return !!(b.jStore.hasFlash("8.0.0"))};this.jStoreFlash=StorageEngine.extend({init:function(e,d){this._super(e,d);this.type="Flash";var c=this;b.jStore.flashReady(function(){c.flashReady()})},connect:function(){var c="jstore-flash-embed-"+this.project;b(document.body).append('<iframe style="height:1px;width:1px;position:absolute;left:0;top:0;margin-left:-100px;" id="jStoreFlashFrame" src="'+b.jStore.defaults.flash+'"></iframe>')},flashReady:function(f){var c=b("#jStoreFlashFrame")[0];if(c.Document&&b.isFunction(c.Document.jStoreFlash.f_get_cookie)){this.db=c.Document.jStoreFlash}else{if(c.contentWindow&&c.contentWindow.document){var d=c.contentWindow.document;if(b.isFunction(b("object",b(d))[0].f_get_cookie)){this.db=b("object",b(d))[0]}else{if(b.isFunction(b("embed",b(d))[0].f_get_cookie)){this.db=b("embed",b(d))[0]}}}}if(this.db){this.delegate.trigger("engine-ready")}},isAvailable:a,get:function(d){this.interruptAccess();var c=this.db.f_get_cookie(d);return c=="null"?null:b.jStore.safeResurrect(c)},set:function(c,d){this.interruptAccess();this.db.f_set_cookie(c,b.jStore.safeStore(d));return d},rem:function(c){this.interruptAccess();var d=this.get(c);this.db.f_delete_cookie(c);return d}});b.jStore.Engines.flash=jStoreFlash;b.jStore.EngineOrder[2]="flash";b.jStore.hasFlash=function(c){var e=b.jStore.flashVersion().match(/\d+/g),f=c.match(/\d+/g);for(var d=0;d<3;d++){e[d]=parseInt(e[d]||0);f[d]=parseInt(f[d]||0);if(e[d]<f[d]){return false}if(e[d]>f[d]){return true}}return true};b.jStore.flashVersion=function(){try{try{var c=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");try{c.AllowScriptAccess="always"}catch(d){return"6,0,0"}}catch(d){}return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version").replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}catch(d){try{if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){return(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}}catch(d){}}return"0,0,0"}})(jQuery);function flash_ready(){$.jStore.delegate.trigger("flash-ready")}
/*
* jStore Google Gears Storage Engine
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
(function(b){var a=b.jStore.Availability.gears=function(){return !!(window.google&&window.google.gears)};this.jStoreGears=StorageEngine.extend({init:function(d,c){this._super(d,c);this.type="Google Gears";this.includes.push("http://code.google.com/apis/gears/gears_init.js");this.autoload=true},connect:function(){var c=this.db=google.gears.factory.create("beta.database");c.open("jstore-"+this.project);c.execute("CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)");this.updateCache()},updateCache:function(){var c=this.db.execute("SELECT k,v FROM jstore");while(c.isValidRow()){this.data[c.field(0)]=b.jStore.safeResurrect(c.field(1));c.next()}c.close();this.delegate.trigger("engine-ready")},isAvailable:a,set:function(d,e){this.interruptAccess();var c=this.db;c.execute("BEGIN");c.execute("INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)",[d,b.jStore.safeStore(e)]);c.execute("COMMIT");return this._super(d,e)},rem:function(d){this.interruptAccess();var c=this.db;c.execute("BEGIN");c.execute("DELETE FROM jstore WHERE k = ?",[d]);c.execute("COMMIT");return this._super(d)}});b.jStore.Engines.gears=jStoreGears;b.jStore.EngineOrder[3]="gears"})(jQuery);
/*
* jStore HTML5 Specification Storage Engine
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
(function(b){var a=b.jStore.Availability.html5=function(){return !!window.openDatabase};this.jStoreHtml5=StorageEngine.extend({init:function(d,c){this._super(d,c);this.type="HTML5";this.limit=1024*200},connect:function(){var c=this.db=openDatabase("jstore-"+this.project,"1.0",this.project,this.limit);if(!c){throw"JSTORE_ENGINE_HTML5_NODB"}c.transaction(function(d){d.executeSql("CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)")});this.updateCache()},updateCache:function(){var c=this;this.db.transaction(function(d){d.executeSql("SELECT k,v FROM jstore",[],function(f,e){var h=e.rows,g=0,j;for(;g<h.length;++g){j=h.item(g);c.data[j.k]=b.jStore.safeResurrect(j.v)}c.delegate.trigger("engine-ready")})})},isAvailable:a,set:function(c,d){this.interruptAccess();this.db.transaction(function(e){e.executeSql("INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)",[c,b.jStore.safeStore(d)])});return this._super(c,d)},rem:function(c){this.interruptAccess();this.db.transaction(function(d){d.executeSql("DELETE FROM jstore WHERE k = ?",[c])});return this._super(c)}});b.jStore.Engines.html5=jStoreHtml5;b.jStore.EngineOrder[0]="html5"})(jQuery);
/**
* jStore IE Storage Engine
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
(function(b){var a=b.jStore.Availability.ie=function(){return !!window.ActiveXObject};this.jStoreIE=StorageEngine.extend({init:function(d,c){this._super(d,c);this.type="IE";this.limit=64*1024},connect:function(){this.db=b('<div style="display:none;behavior:url(\'#default#userData\')" id="jstore-'+this.project+'"></div>').appendTo(document.body).get(0);this.delegate.trigger("engine-ready")},isAvailable:a,get:function(c){this.interruptAccess();this.db.load(this.project);return b.jStore.safeResurrect(this.db.getAttribute(c))},set:function(c,d){this.interruptAccess();this.db.setAttribute(c,b.jStore.safeStore(d));this.db.save(this.project);return d},rem:function(c){this.interruptAccess();var d=this.get(c);this.db.removeAttribute(c);this.db.save(this.project);return d}});b.jStore.Engines.ie=jStoreIE;b.jStore.EngineOrder[4]="ie"})(jQuery);

View File

@ -1,963 +0,0 @@
/*!
* jStore - Persistent Client-Side Storage
*
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*
* Dual licensed under:
* MIT: http://www.opensource.org/licenses/mit-license.php
* GPLv3: http://www.opensource.org/licenses/gpl-3.0.html
*/
/*!
* jQuery JSON Plugin
* version: 1.0 (2008-04-17)
*
* This document is licensed as free software under the terms of the
* MIT License: http://www.opensource.org/licenses/mit-license.php
*
* Brantley Harris technically wrote this plugin, but it is based somewhat
* on the JSON.org website's http://www.json.org/json2.js, which proclaims:
* "NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.", a sentiment that
* I uphold. I really just cleaned it up.
*
* It is also based heavily on MochiKit's serializeJSON, which is
* copywrited 2005 by Bob Ippolito.
*/
(function($) {
function toIntegersAtLease(n)
// Format integers to have at least two digits.
{
return n < 10 ? '0' + n : n;
}
Date.prototype.toJSON = function(date)
// Yes, it polutes the Date namespace, but we'll allow it here, as
// it's damned usefull.
{
return this.getUTCFullYear() + '-' +
toIntegersAtLease(this.getUTCMonth()) + '-' +
toIntegersAtLease(this.getUTCDate());
};
var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g;
var meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
};
$.quoteString = function(string)
// Places quotes around a string, inteligently.
// 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.
{
if (escapeable.test(string))
{
return '"' + string.replace(escapeable, function (a)
{
var c = meta[a];
if (typeof c === 'string') {
return c;
}
c = a.charCodeAt();
return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
}) + '"';
}
return '"' + string + '"';
};
$.toJSON = function(o, compact)
{
var type = typeof(o);
if (type == "undefined")
return "undefined";
else if (type == "number" || type == "boolean")
return o + "";
else if (o === null)
return "null";
// Is it a string?
if (type == "string")
{
return $.quoteString(o);
}
// Does it have a .toJSON function?
if (type == "object" && typeof o.toJSON == "function")
return o.toJSON(compact);
// Is it an array?
if (type != "function" && typeof(o.length) == "number")
{
var ret = [];
for (var i = 0; i < o.length; i++) {
ret.push( $.toJSON(o[i], compact) );
}
if (compact)
return "[" + ret.join(",") + "]";
else
return "[" + ret.join(", ") + "]";
}
// If it's a function, we have to warn somebody!
if (type == "function") {
throw new TypeError("Unable to convert object of type 'function' to json.");
}
// It's probably an object, then.
var ret = [];
for (var k in o) {
var name;
type = typeof(k);
if (type == "number")
name = '"' + k + '"';
else if (type == "string")
name = $.quoteString(k);
else
continue; //skip non-string or number keys
var val = $.toJSON(o[k], compact);
if (typeof(val) != "string") {
// skip non-serializable values
continue;
}
if (compact)
ret.push(name + ":" + val);
else
ret.push(name + ": " + val);
}
return "{" + ret.join(", ") + "}";
};
$.compactJSON = function(o)
{
return $.toJSON(o, true);
};
$.evalJSON = function(src)
// Evals JSON that we know to be safe.
{
try {
return eval("(" + src + ")");
} catch(e) {
return src;
}
};
$.secureEvalJSON = function(src)
// Evals JSON in a way that is *more* secure.
{
var filtered = src;
filtered = filtered.replace(/\\["\\\/bfnrtu]/g, '@');
filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
if (/^[\],:{}\s]*$/.test(filtered))
return eval("(" + src + ")");
else
throw new SyntaxError("Error parsing JSON, source is not valid.");
};
})(jQuery);
/**
* Javascript Class Framework
*
* Copyright (c) 2008 John Resig (http://ejohn.org/blog/simple-javascript-inheritance/)
* Inspired by base2 and Prototype
*/
(function(){
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
// The base Class implementation (does nothing)
this.Class = function(){};
// Create a new Class that inherits from this class
Class.extend = function(prop) {
var _super = this.prototype;
// Instantiate a base class (but only create the instance,
// don't run the init constructor)
initializing = true;
var prototype = new this();
initializing = false;
// Copy the properties over onto the new prototype
for (var name in prop) {
// Check if we're overwriting an existing function
prototype[name] = typeof prop[name] == "function" &&
typeof _super[name] == "function" && fnTest.test(prop[name]) ?
(function(name, fn){
return function() {
var tmp = this._super;
// Add a new ._super() method that is the same method
// but on the super-class
this._super = _super[name];
// The method only need to be bound temporarily, so we
// remove it when we're done executing
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, prop[name]) :
prop[name];
}
// The dummy class constructor
function Class() {
// All construction is actually done in the init method
if ( !initializing && this.init )
this.init.apply(this, arguments);
}
// Populate our constructed prototype object
Class.prototype = prototype;
// Enforce the constructor to be what we expect
Class.constructor = Class;
// And make this class extendable
Class.extend = arguments.callee;
return Class;
};
})();
/*!
* jStore Delegate Framework
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
(function($){
this.jStoreDelegate = Class.extend({
init: function(parent){
// The Object this delgate operates for
this.parent = parent;
// Container for callbacks to dispatch.
// eventType => [ callback, callback, ... ]
this.callbacks = {};
},
bind: function(event, callback){
if ( !$.isFunction(callback) ) return this;
if ( !this.callbacks[ event ] ) this.callbacks[ event ] = [];
this.callbacks[ event ].push(callback);
return this;
},
trigger: function(){
var parent = this.parent,
args = [].slice.call(arguments),
event = args.shift(),
handlers = this.callbacks[ event ];
if ( !handlers ) return false;
$.each(handlers, function(){ this.apply(parent, args) });
return this;
}
});
})(jQuery);
/**
* jStore-jQuery Interface
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
(function($){
var rxJson;
try {
rxJson = new RegExp('^("(\\\\.|[^"\\\\\\n\\r])*?"|[,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t])+?$')
} catch (e) {
rxJson = /^(true|false|null|\[.*\]|\{.*\}|".*"|\d+|\d+\.\d+)$/
}
// Setup the jStore namespace in jQuery for options storage
$.jStore = {};
// Seed the object
$.extend($.jStore, {
EngineOrder: [],
// Engines should put their availability tests within jStore.Availability
Availability: {},
// Defined engines should enter themselves into the jStore.Engines
Engines: {},
// Instanciated engines should exist within jStore.Instances
Instances: {},
// The current engine to use for storage
CurrentEngine: null,
// Provide global settings for overwriting
defaults: {
project: null,
engine: null,
autoload: true,
flash: 'jStore.Flash.html'
},
// Boolean for ready state handling
isReady: false,
// Boolean for flash ready state handling
isFlashReady: false,
// An event delegate
delegate: new jStoreDelegate($.jStore)
.bind('jStore-ready', function(engine){
$.jStore.isReady = true;
if ($.jStore.defaults.autoload) engine.connect();
})
.bind('flash-ready', function(){
$.jStore.isFlashReady = true;
}),
// Enable ready callback for jStore
ready: function(callback){
if ($.jStore.isReady) callback.apply($.jStore, [$.jStore.CurrentEngine]);
else $.jStore.delegate.bind('jStore-ready', callback);
},
// Enable failure callback registration for jStore
fail: function(callback){
$.jStore.delegate.bind('jStore-failure', callback);
},
// Enable ready callback for Flash
flashReady: function(callback){
if ($.jStore.isFlashReady) callback.apply($.jStore, [$.jStore.CurrentEngine]);
else $.jStore.delegate.bind('flash-ready', callback);
},
// Enable and test an engine
use: function(engine, project, identifier){
project = project || $.jStore.defaults.project || location.hostname.replace(/\./g, '-') || 'unknown';
var e = $.jStore.Engines[engine.toLowerCase()] || null,
name = (identifier ? identifier + '.' : '') + project + '.' + engine;
if ( !e ) throw 'JSTORE_ENGINE_UNDEFINED';
// Instanciate the engine
e = new e(project, name);
// Prevent against naming conflicts
if ($.jStore.Instances[name]) throw 'JSTORE_JRI_CONFLICT';
// Test the engine
if (e.isAvailable()){
$.jStore.Instances[name] = e; // The Easy Way
if (!$.jStore.CurrentEngine){
$.jStore.CurrentEngine = e;
}
$.jStore.delegate.trigger('jStore-ready', e);
} else {
if (!e.autoload) // Not available
throw 'JSTORE_ENGINE_UNAVILABLE';
else { // The hard way
e.included(function(){
if (this.isAvailable()) { // Worked out
$.jStore.Instances[name] = this;
// If there is no current engine, use this one
if (!$.jStore.CurrentEngine){
$.jStore.CurrentEngine = this;
}
$.jStore.delegate.trigger('jStore-ready', this);
}
else $.jStore.delegate.trigger('jStore-failure', this);
}).include();
}
}
},
// Set the current storage engine
setCurrentEngine: function(name){
if (!$.jStore.Instances.length ) // If no instances exist, attempt to load one
return $.jStore.FindEngine();
if (!name && $.jStore.Instances.length >= 1) { // If no name is specified, use the first engine
$.jStore.delegate.trigger('jStore-ready', $.jStore.Instances[0]);
return $.jStore.CurrentEngine = $.jStore.Instances[0];
}
if (name && $.jStore.Instances[name]) { // If a name is specified and exists, use it
$.jStore.delegate.trigger('jStore-ready', $.jStore.Instances[name]);
return $.jStore.CurrentEngine = $.jStore.Instances[name];
}
throw 'JSTORE_JRI_NO_MATCH';
},
// Test all possible engines for straightforward useability
FindEngine: function(){
$.each($.jStore.EngineOrder, function(k){
if ($.jStore.Availability[this]()){ // Find the first, easiest option and use it.
$.jStore.use(this, $.jStore.defaults.project, 'default');
return false;
}
})
},
// Provide a way for users to call for auto-loading
load: function(){
if ($.jStore.defaults.engine)
return $.jStore.use($.jStore.defaults.engine, $.jStore.defaults.project, 'default');
// Attempt to find a valid engine, and catch any exceptions if we can't
try {
$.jStore.FindEngine();
} catch (e) {}
},
// Parse a value as JSON before its stored.
safeStore: function(value){
switch (typeof value){
case 'object': case 'function': return $.compactJSON(value);
case 'number': case 'boolean': case 'string': case 'xml': return value;
case 'undefined': default: return '';
}
},
// Restores JSON'd values before returning
safeResurrect: function(value){
return rxJson.test(value) ? $.evalJSON(value) : value;
},
// Provide a simple interface for storing/getting values
store: function(key, value){
if (!$.jStore.CurrentEngine) return false;
if ( !value ) // Executing a get command
return $.jStore.CurrentEngine.get(key);
// Executing a set command
return $.jStore.CurrentEngine.set(key, value);
},
// Provide a simple interface for removing values
remove: function(key){
if (!$.jStore.CurrentEngine) return false;
return $.jStore.CurrentEngine.rem(key);
},
// Alias access for reading
get: function(key){
return $.jStore.store(key);
},
// Alias access for setting
set: function(key, value){
return $.jStore.store(key, value);
}
})
// Extend the jQuery funcitonal object
$.extend($.fn, {
// Provide a chainable interface for storing values/getting a value at the end of a chain
store: function(key, value){
if (!$.jStore.CurrentEngine) return this;
var result = $.jStore.store(key, value);
return !value ? result : this;
},
// Provide a chainable interface for removing values
removeStore: function(key){
$.jStore.remove(key);
return this;
},
// Alias access for reading at the end of a chain.
getStore: function(key){
return $.jStore.store(key);
},
// Alias access for setting on a chanin.
setStore: function(key, value){
$.jStore.store(key, value);
return this;
}
})
})(jQuery);
/**
* jStore Engine Core
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
(function($){
this.StorageEngine = Class.extend({
init: function(project, name){
// Configure the project name
this.project = project;
// The JRI name given by the manager
this.jri = name;
// Cache the data so we can work synchronously
this.data = {};
// The maximum limit of the storage engine
this.limit = -1;
// Third party script includes
this.includes = [];
// Create an event delegate for users to subscribe to event triggers
this.delegate = new jStoreDelegate(this)
.bind('engine-ready', function(){
this.isReady = true;
})
.bind('engine-included', function(){
this.hasIncluded = true;
});
// If enabled, the manager will check availability, then run include(), then check again
this.autoload = false; // This should be changed by the engines, if they have required includes
// When set, we're ready to transact data
this.isReady = false;
// When the includer is finished, it will set this to true
this.hasIncluded = false;
},
// Performs all necessary script includes
include: function(){
var self = this,
total = this.includes.length,
count = 0;
$.each(this.includes, function(){
$.ajax({type: 'get', url: this, dataType: 'script', cache: true,
success: function(){
count++;
if (count == total) self.delegate.trigger('engine-included');
}
})
});
},
// This should be overloaded with an actual functionality presence check
isAvailable: function(){
return false;
},
// All get/set/rem functions across the engines should add this to the
// first line of those functions to prevent accessing the engine while unstable.
interruptAccess: function(){
if (!this.isReady) throw 'JSTORE_ENGINE_NOT_READY';
},
/** Event Subscription Shortcuts **/
ready: function(callback){
if (this.isReady) callback.apply(this);
else this.delegate.bind('engine-ready', callback);
return this;
},
included: function(callback){
if (this.hasIncluded) callback.apply(this);
else this.delegate.bind('engine-included', callback);
return this;
},
/** Cache Data Access **/
get: function(key){
this.interruptAccess();
return this.data[key] || null;
},
set: function(key, value){
this.interruptAccess();
this.data[key] = value;
return value;
},
rem: function(key){
this.interruptAccess();
var beforeDelete = this.data[key];
this.data[key] = null;
return beforeDelete;
}
});
})(jQuery);
/*!
* jStore DOM Storage Engine
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
(function($){
// Set up a static test function for this instance
var sessionAvailability = $.jStore.Availability.session = function(){
return !!window.sessionStorage;
},
localAvailability = $.jStore.Availability.local = function(){
return !!(window.localStorage || window.globalStorage);
};
this.jStoreDom = StorageEngine.extend({
init: function(project, name){
// Call the parental init object
this._super(project, name);
// The type of storage engine
this.type = 'DOM';
// Set the Database limit
this.limit = 5 * 1024 * 1024;
},
connect: function(){
// Fire our delegate to indicate we're ready for data transactions
this.delegate.trigger('engine-ready');
},
get: function(key){
this.interruptAccess();
var out = this.db.getItem(key);
// Gecko's getItem returns {value: 'the value'}, WebKit returns 'the value'
return $.jStore.safeResurrect( (out && out.value ? out.value : out) );
},
set: function(key, value){
this.interruptAccess();
this.db.setItem(key,$.jStore.safeStore(value));
return value;
},
rem: function(key){
this.interruptAccess();
var out = this.get(key);
this.db.removeItem(key);
return out
}
})
this.jStoreLocal = jStoreDom.extend({
connect: function(){
// Gecko uses a non-standard globalStorage[ www.example.com ] DOM access object for persistant storage.
this.db = !window.globalStorage ? window.localStorage : window.globalStorage[location.hostname];
this._super();
},
isAvailable: localAvailability
})
this.jStoreSession = jStoreDom.extend({
connect: function(){
this.db = sessionStorage;
this._super();
},
isAvailable: sessionAvailability
})
$.jStore.Engines.local = jStoreLocal;
$.jStore.Engines.session = jStoreSession;
// Store the ordering preference
$.jStore.EngineOrder[ 1 ] = 'local';
})(jQuery);
/*!
* jStore Flash Storage Engine
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
* jStore.swf Copyright (c) 2008 Daniel Bulli (http://www.nuff-respec.com)
*/
(function($){
// Set up a static test function for this instance
var avilability = $.jStore.Availability.flash = function(){
return !!($.jStore.hasFlash('8.0.0'));
}
this.jStoreFlash = StorageEngine.extend({
init: function(project, name){
// Call the parental init object
this._super(project, name);
// The type of storage engine
this.type = 'Flash';
// Bind our flashReady function to the jStore Delegate
var self = this;
$.jStore.flashReady(function(){ self.flashReady() });
},
connect: function(){
var name = 'jstore-flash-embed-' + this.project;
// To make Flash Storage work on IE, we have to load up an iFrame
// which contains an HTML page that embeds the object using an
// object tag wrapping an embed tag. Of course, this is unnecessary for
// all browsers except for IE, which, to my knowledge, is the only browser
// in existance where you need to complicate your code to fix bugs. Goddamnit. :(
$(document.body)
.append('<iframe style="height:1px;width:1px;position:absolute;left:0;top:0;margin-left:-100px;" ' +
'id="jStoreFlashFrame" src="' +$.jStore.defaults.flash + '"></iframe>');
},
flashReady: function(e){
var iFrame = $('#jStoreFlashFrame')[0];
// IE
if (iFrame.Document && $.isFunction(iFrame.Document['jStoreFlash'].f_get_cookie)) this.db = iFrame.Document['jStoreFlash'];
// Safari && Firefox
else if (iFrame.contentWindow && iFrame.contentWindow.document){
var doc = iFrame.contentWindow.document;
// Safari
if ($.isFunction($('object', $(doc))[0].f_get_cookie)) this.db = $('object', $(doc))[0];
// Firefox
else if ($.isFunction($('embed', $(doc))[0].f_get_cookie)) this.db = $('embed', $(doc))[0];
}
// We're ready to process data
if (this.db) this.delegate.trigger('engine-ready');
},
isAvailable: avilability,
get: function(key){
this.interruptAccess();
var out = this.db.f_get_cookie(key);
return out == 'null' ? null : $.jStore.safeResurrect(out);
},
set: function(key, value){
this.interruptAccess();
this.db.f_set_cookie(key, $.jStore.safeStore(value));
return value;
},
rem: function(key){
this.interruptAccess();
var beforeDelete = this.get(key);
this.db.f_delete_cookie(key);
return beforeDelete;
}
})
$.jStore.Engines.flash = jStoreFlash;
// Store the ordering preference
$.jStore.EngineOrder[ 2 ] = 'flash';
/**
* Flash Detection functions copied from the jQuery Flash Plugin
* Copyright (c) 2006 Luke Lutman (http://jquery.lukelutman.com/plugins/flash)
* Dual licensed under the MIT and GPL licenses.
* http://www.opensource.org/licenses/mit-license.php
* http://www.opensource.org/licenses/gpl-license.php
*/
$.jStore.hasFlash = function(version){
var pv = $.jStore.flashVersion().match(/\d+/g),
rv = version.match(/\d+/g);
for(var i = 0; i < 3; i++) {
pv[i] = parseInt(pv[i] || 0);
rv[i] = parseInt(rv[i] || 0);
// player is less than required
if(pv[i] < rv[i]) return false;
// player is greater than required
if(pv[i] > rv[i]) return true;
}
// major version, minor version and revision match exactly
return true;
}
$.jStore.flashVersion = function(){
// ie
try {
try {
// avoid fp6 minor version lookup issues
// see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
try { axo.AllowScriptAccess = 'always'; }
catch(e) { return '6,0,0'; }
} catch(e) {
return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
}
// other browsers
} catch(e) {
try {
if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){
return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
}
} catch(e) {}
}
return '0,0,0';
}
})(jQuery);
// Callback fired when ExternalInterface is established
function flash_ready(){
$.jStore.delegate.trigger('flash-ready');
}
/*!
* jStore Google Gears Storage Engine
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
(function($){
// Set up a static test function for this instance
var avilability = $.jStore.Availability.gears = function(){
return !!(window.google && window.google.gears)
}
this.jStoreGears = StorageEngine.extend({
init: function(project, name){
// Call the parental init object
this._super(project, name);
// The type of storage engine
this.type = 'Google Gears';
// Add required third-party scripts
this.includes.push('http://code.google.com/apis/gears/gears_init.js');
// Allow Autoloading on fail
this.autoload = true;
},
connect: function(){
// Create our database connection
var db = this.db = google.gears.factory.create('beta.database');
db.open( 'jstore-' + this.project );
db.execute( 'CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)' );
// Cache the data from the table
this.updateCache();
},
updateCache: function(){
// Read the database into our cache object
var result = this.db.execute( 'SELECT k,v FROM jstore' );
while (result.isValidRow()){
this.data[result.field(0)] = $.jStore.safeResurrect( result.field(1) );
result.next();
} result.close();
// Fire our delegate to indicate we're ready for data transactions
this.delegate.trigger('engine-ready');
},
isAvailable: avilability,
set: function(key, value){
this.interruptAccess();
// Update the database
var db = this.db;
db.execute( 'BEGIN' );
db.execute( 'INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)', [key,$.jStore.safeStore(value)] );
db.execute( 'COMMIT' );
return this._super(key, value);
},
rem: function(key){
this.interruptAccess();
// Update the database
var db = this.db;
db.execute( 'BEGIN' );
db.execute( 'DELETE FROM jstore WHERE k = ?', [key] );
db.execute( 'COMMIT' );
return this._super(key);
}
})
$.jStore.Engines.gears = jStoreGears;
// Store the ordering preference
$.jStore.EngineOrder[ 3 ] = 'gears';
})(jQuery);
/*!
* jStore HTML5 Specification Storage Engine
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
(function($){
// Set up a static test function for this instance
var avilability = $.jStore.Availability.html5 = function(){
return !!window.openDatabase
}
this.jStoreHtml5 = StorageEngine.extend({
init: function(project, name){
// Call the parental init object
this._super(project, name);
// The type of storage engine
this.type = 'HTML5';
// Set the Database limit
this.limit = 1024 * 200;
},
connect: function(){
// Create our database connection
var db = this.db = openDatabase('jstore-' + this.project, '1.0', this.project, this.limit);
if (!db) throw 'JSTORE_ENGINE_HTML5_NODB';
db.transaction(function(db){
db.executeSql( 'CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)' );
});
// Cache the data from the table
this.updateCache();
},
updateCache: function(){
var self = this;
// Read the database into our cache object
this.db.transaction(function(db){
db.executeSql( 'SELECT k,v FROM jstore', [], function(db, result){
var rows = result.rows, i = 0, row;
for (; i < rows.length; ++i){
row = rows.item(i);
self.data[row.k] = $.jStore.safeResurrect( row.v );
}
// Fire our delegate to indicate we're ready for data transactions
self.delegate.trigger('engine-ready');
});
});
},
isAvailable: avilability,
set: function(key, value){
this.interruptAccess();
// Update the database
this.db.transaction(function(db){
db.executeSql( 'INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)', [key,$.jStore.safeStore(value)]);
});
return this._super(key, value);
},
rem: function(key){
this.interruptAccess();
// Update the database
this.db.transaction(function(db){
db.executeSql( 'DELETE FROM jstore WHERE k = ?', [key] )
})
return this._super(key);
}
})
$.jStore.Engines.html5 = jStoreHtml5;
// Store the ordering preference
$.jStore.EngineOrder[ 0 ] = 'html5';
})(jQuery);
/*!*
* jStore IE Storage Engine
* Copyright (c) 2009 Eric Garside (http://eric.garside.name)
*/
(function($){
// Set up a static test function for this instance
var avilability = $.jStore.Availability.ie = function(){
return !!window.ActiveXObject;
}
this.jStoreIE = StorageEngine.extend({
init: function(project, name){
// Call the parental init object
this._super(project, name);
// The type of storage engine
this.type = 'IE';
// Allow Autoloading on fail
this.limit = 64 * 1024;
},
connect: function(){
// Create a hidden div to store attributes in
this.db = $('<div style="display:none;behavior:url(\'#default#userData\')" id="jstore-' + this.project + '"></div>')
.appendTo(document.body).get(0);
// Fire our delegate to indicate we're ready for data transactions
this.delegate.trigger('engine-ready');
},
isAvailable: avilability,
get: function(key){
this.interruptAccess();
this.db.load(this.project);
return $.jStore.safeResurrect( this.db.getAttribute(key) );
},
set: function(key, value){
this.interruptAccess();
this.db.setAttribute(key, $.jStore.safeStore(value));
this.db.save(this.project);
return value;
},
rem: function(key){
this.interruptAccess();
var beforeDelete = this.get(key);
this.db.removeAttribute(key);
this.db.save(this.project);
return beforeDelete;
}
})
$.jStore.Engines.ie = jStoreIE;
// Store the ordering preference
$.jStore.EngineOrder[ 4 ] = 'ie';
})(jQuery);

View File

@ -1,230 +0,0 @@
/**
* jQuery MD5 hash algorithm function
*
* <code>
* Calculate the md5 hash of a String
* String $.md5 ( String str )
* </code>
*
* Calculates the MD5 hash of str using the » RSA Data Security, Inc. MD5 Message-Digest Algorithm, and returns that hash.
* MD5 (Message-Digest algorithm 5) is a widely-used cryptographic hash function with a 128-bit hash value. MD5 has been employed in a wide variety of security applications, and is also commonly used to check the integrity of data. The generated hash is also non-reversable. Data cannot be retrieved from the message digest, the digest uniquely identifies the data.
* MD5 was developed by Professor Ronald L. Rivest in 1994. Its 128 bit (16 byte) message digest makes it a faster implementation than SHA-1.
* This script is used to process a variable length message into a fixed-length output of 128 bits using the MD5 algorithm. It is fully compatible with UTF-8 encoding. It is very useful when u want to transfer encrypted passwords over the internet. If you plan using UTF-8 encoding in your project don't forget to set the page encoding to UTF-8 (Content-Type meta tag).
* This function orginally get from the WebToolkit and rewrite for using as the jQuery plugin.
*
* Example
* Code
* <code>
* $.md5("I'm Persian.");
* </code>
* Result
* <code>
* "b8c901d0f02223f9761016cfff9d68df"
* </code>
*
* @alias Muhammad Hussein Fattahizadeh < muhammad [AT] semnanweb [DOT] com >
* @link http://www.semnanweb.com/jquery-plugin/md5.html
* @see http://www.webtoolkit.info/
* @license http://www.gnu.org/licenses/gpl.html [GNU General Public License]
* @param {jQuery} {md5:function(string))
* @return string
*/
(function($){
var rotateLeft = function(lValue, iShiftBits) {
return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
}
var addUnsigned = function(lX, lY) {
var lX4, lY4, lX8, lY8, lResult;
lX8 = (lX & 0x80000000);
lY8 = (lY & 0x80000000);
lX4 = (lX & 0x40000000);
lY4 = (lY & 0x40000000);
lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
if (lX4 | lY4) {
if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
else return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
} else {
return (lResult ^ lX8 ^ lY8);
}
}
var F = function(x, y, z) {
return (x & y) | ((~ x) & z);
}
var G = function(x, y, z) {
return (x & z) | (y & (~ z));
}
var H = function(x, y, z) {
return (x ^ y ^ z);
}
var I = function(x, y, z) {
return (y ^ (x | (~ z)));
}
var FF = function(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(F(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var GG = function(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(G(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var HH = function(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(H(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var II = function(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(I(b, c, d), x), ac));
return addUnsigned(rotateLeft(a, s), b);
};
var convertToWordArray = function(string) {
var lWordCount;
var lMessageLength = string.length;
var lNumberOfWordsTempOne = lMessageLength + 8;
var lNumberOfWordsTempTwo = (lNumberOfWordsTempOne - (lNumberOfWordsTempOne % 64)) / 64;
var lNumberOfWords = (lNumberOfWordsTempTwo + 1) * 16;
var lWordArray = Array(lNumberOfWords - 1);
var lBytePosition = 0;
var lByteCount = 0;
while (lByteCount < lMessageLength) {
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition));
lByteCount++;
}
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
return lWordArray;
};
var wordToHex = function(lValue) {
var WordToHexValue = "", WordToHexValueTemp = "", lByte, lCount;
for (lCount = 0; lCount <= 3; lCount++) {
lByte = (lValue >>> (lCount * 8)) & 255;
WordToHexValueTemp = "0" + lByte.toString(16);
WordToHexValue = WordToHexValue + WordToHexValueTemp.substr(WordToHexValueTemp.length - 2, 2);
}
return WordToHexValue;
};
var uTF8Encode = function(string) {
string = string.replace(/\x0d\x0a/g, "\x0a");
var output = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
output += String.fromCharCode(c);
} else if ((c > 127) && (c < 2048)) {
output += String.fromCharCode((c >> 6) | 192);
output += String.fromCharCode((c & 63) | 128);
} else {
output += String.fromCharCode((c >> 12) | 224);
output += String.fromCharCode(((c >> 6) & 63) | 128);
output += String.fromCharCode((c & 63) | 128);
}
}
return output;
};
$.extend({
md5: function(string) {
var x = Array();
var k, AA, BB, CC, DD, a, b, c, d;
var S11=7, S12=12, S13=17, S14=22;
var S21=5, S22=9 , S23=14, S24=20;
var S31=4, S32=11, S33=16, S34=23;
var S41=6, S42=10, S43=15, S44=21;
string = uTF8Encode(string);
x = convertToWordArray(string);
a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
for (k = 0; k < x.length; k += 16) {
AA = a; BB = b; CC = c; DD = d;
a = FF(a, b, c, d, x[k+0], S11, 0xD76AA478);
d = FF(d, a, b, c, x[k+1], S12, 0xE8C7B756);
c = FF(c, d, a, b, x[k+2], S13, 0x242070DB);
b = FF(b, c, d, a, x[k+3], S14, 0xC1BDCEEE);
a = FF(a, b, c, d, x[k+4], S11, 0xF57C0FAF);
d = FF(d, a, b, c, x[k+5], S12, 0x4787C62A);
c = FF(c, d, a, b, x[k+6], S13, 0xA8304613);
b = FF(b, c, d, a, x[k+7], S14, 0xFD469501);
a = FF(a, b, c, d, x[k+8], S11, 0x698098D8);
d = FF(d, a, b, c, x[k+9], S12, 0x8B44F7AF);
c = FF(c, d, a, b, x[k+10], S13, 0xFFFF5BB1);
b = FF(b, c, d, a, x[k+11], S14, 0x895CD7BE);
a = FF(a, b, c, d, x[k+12], S11, 0x6B901122);
d = FF(d, a, b, c, x[k+13], S12, 0xFD987193);
c = FF(c, d, a, b, x[k+14], S13, 0xA679438E);
b = FF(b, c, d, a, x[k+15], S14, 0x49B40821);
a = GG(a, b, c, d, x[k+1], S21, 0xF61E2562);
d = GG(d, a, b, c, x[k+6], S22, 0xC040B340);
c = GG(c, d, a, b, x[k+11], S23, 0x265E5A51);
b = GG(b, c, d, a, x[k+0], S24, 0xE9B6C7AA);
a = GG(a, b, c, d, x[k+5], S21, 0xD62F105D);
d = GG(d, a, b, c, x[k+10], S22, 0x2441453);
c = GG(c, d, a, b, x[k+15], S23, 0xD8A1E681);
b = GG(b, c, d, a, x[k+4], S24, 0xE7D3FBC8);
a = GG(a, b, c, d, x[k+9], S21, 0x21E1CDE6);
d = GG(d, a, b, c, x[k+14], S22, 0xC33707D6);
c = GG(c, d, a, b, x[k+3], S23, 0xF4D50D87);
b = GG(b, c, d, a, x[k+8], S24, 0x455A14ED);
a = GG(a, b, c, d, x[k+13], S21, 0xA9E3E905);
d = GG(d, a, b, c, x[k+2], S22, 0xFCEFA3F8);
c = GG(c, d, a, b, x[k+7], S23, 0x676F02D9);
b = GG(b, c, d, a, x[k+12], S24, 0x8D2A4C8A);
a = HH(a, b, c, d, x[k+5], S31, 0xFFFA3942);
d = HH(d, a, b, c, x[k+8], S32, 0x8771F681);
c = HH(c, d, a, b, x[k+11], S33, 0x6D9D6122);
b = HH(b, c, d, a, x[k+14], S34, 0xFDE5380C);
a = HH(a, b, c, d, x[k+1], S31, 0xA4BEEA44);
d = HH(d, a, b, c, x[k+4], S32, 0x4BDECFA9);
c = HH(c, d, a, b, x[k+7], S33, 0xF6BB4B60);
b = HH(b, c, d, a, x[k+10], S34, 0xBEBFBC70);
a = HH(a, b, c, d, x[k+13], S31, 0x289B7EC6);
d = HH(d, a, b, c, x[k+0], S32, 0xEAA127FA);
c = HH(c, d, a, b, x[k+3], S33, 0xD4EF3085);
b = HH(b, c, d, a, x[k+6], S34, 0x4881D05);
a = HH(a, b, c, d, x[k+9], S31, 0xD9D4D039);
d = HH(d, a, b, c, x[k+12], S32, 0xE6DB99E5);
c = HH(c, d, a, b, x[k+15], S33, 0x1FA27CF8);
b = HH(b, c, d, a, x[k+2], S34, 0xC4AC5665);
a = II(a, b, c, d, x[k+0], S41, 0xF4292244);
d = II(d, a, b, c, x[k+7], S42, 0x432AFF97);
c = II(c, d, a, b, x[k+14], S43, 0xAB9423A7);
b = II(b, c, d, a, x[k+5], S44, 0xFC93A039);
a = II(a, b, c, d, x[k+12], S41, 0x655B59C3);
d = II(d, a, b, c, x[k+3], S42, 0x8F0CCC92);
c = II(c, d, a, b, x[k+10], S43, 0xFFEFF47D);
b = II(b, c, d, a, x[k+1], S44, 0x85845DD1);
a = II(a, b, c, d, x[k+8], S41, 0x6FA87E4F);
d = II(d, a, b, c, x[k+15], S42, 0xFE2CE6E0);
c = II(c, d, a, b, x[k+6], S43, 0xA3014314);
b = II(b, c, d, a, x[k+13], S44, 0x4E0811A1);
a = II(a, b, c, d, x[k+4], S41, 0xF7537E82);
d = II(d, a, b, c, x[k+11], S42, 0xBD3AF235);
c = II(c, d, a, b, x[k+2], S43, 0x2AD7D2BB);
b = II(b, c, d, a, x[k+9], S44, 0xEB86D391);
a = addUnsigned(a, AA);
b = addUnsigned(b, BB);
c = addUnsigned(c, CC);
d = addUnsigned(d, DD);
}
var tempValue = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
return tempValue.toLowerCase();
}
});
})(jQuery);

View File

@ -1,8 +0,0 @@
Emoticons and "error" icon from "LED Icon Set" by led24.de
----------------------------------------------------------
You can do whatever you want with these icons (use on web or in desktop applications) as long as you dont pass them off as your own and remove this readme file. A credit statement and a link back to
http://led24.de/iconset/ or http://led24.de/ would be appreciated.
Follow us on twitter http://twitter.com/gasyoun or email leds24@gmail.com
512 icons 20/05/2009
----------------------------------------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 868 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 814 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 850 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 843 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 846 B

Some files were not shown because too many files have changed in this diff Show More