diff --git a/Makefile b/Makefile new file mode 100644 index 00000000000..0a4d41800e0 --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +.PHONY: all release clean + +HOST = 127.0.0.1 +PORT = 8080 + + +all: run + +run: + python openerp-web.py -a ${HOST} -p ${PORT} + +release: + python setup.py sdist + +install: + python setup.py install + +clean: + @find . -name '*.pyc' -exec rm -f {} + + @find . -name '*.pyo' -exec rm -f {} + + @find . -name '*.swp' -exec rm -f {} + + @find . -name '*~' -exec rm -f {} + + @rm -rf build + @rm -rf dist + @rm -rf *.egg-info + +cloc: + cloc openerpweb/*.py addons/*/controllers/*.py addons/*/static/src/*.js addons/*/static/src/js/*.js addons/*/static/src/css/*.css addons/*/static/src/xml/*.xml + diff --git a/addons/base/controllers/main.py b/addons/base/controllers/main.py index efd4a7bcef9..bdedb85e63d 100644 --- a/addons/base/controllers/main.py +++ b/addons/base/controllers/main.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import glob, os +import pprint from xml.etree import ElementTree from cStringIO import StringIO @@ -9,6 +10,8 @@ import openerpweb import openerpweb.ast import openerpweb.nonliterals +import cherrypy + # Should move to openerpweb.Xml2Json class Xml2Json: # xml2json-direct @@ -55,13 +58,17 @@ class Xml2Json: class Session(openerpweb.Controller): _cp_path = "/base/session" - def manifest_glob(self, modlist, key): + def manifest_glob(self, addons, key): files = [] - for i in modlist: - globlist = openerpweb.addons_manifest.get(i, {}).get(key, []) - for j in globlist: - for k in glob.glob(os.path.join(openerpweb.path_addons, i, j)): - files.append(k[len(openerpweb.path_addons):]) + for addon in addons: + globlist = openerpweb.addons_manifest.get(addon, {}).get(key, []) + + files.extend([ + resource_path[len(openerpweb.path_addons):] + for pattern in globlist + for resource_path in glob.glob(os.path.join( + openerpweb.path_addons, addon, pattern)) + ]) return files def concat_files(self, file_list): @@ -93,14 +100,16 @@ class Session(openerpweb.Controller): @openerpweb.jsonrequest def modules(self, req): - return {"modules": ["base", "base_hello", "base_calendar", "base_gantt", "base_graph"]} + return {"modules": [name + for name, manifest in openerpweb.addons_manifest.iteritems() + if manifest.get('active', True)]} @openerpweb.jsonrequest - def csslist(self, req, mods='base,base_hello'): + def csslist(self, req, mods='base'): return {'files': self.manifest_glob(mods.split(','), 'css')} @openerpweb.jsonrequest - def jslist(self, req, mods='base,base_hello'): + def jslist(self, req, mods='base'): return {'files': self.manifest_glob(mods.split(','), 'js')} def css(self, req, mods='base,base_hello'): @@ -169,25 +178,70 @@ class Session(openerpweb.Controller): 'group_by': group_by_sequence } + @openerpweb.jsonrequest + def save_session_action(self, req, the_action): + """ + This method store an action object in the session object and returns an integer + identifying that action. The method get_session_action() can be used to get + back the action. + + :param the_action: The action to save in the session. + :type the_action: anything + :return: A key identifying the saved action. + :rtype: integer + """ + saved_actions = cherrypy.session.get('saved_actions') + if not saved_actions: + saved_actions = {"next":0, "actions":{}} + cherrypy.session['saved_actions'] = saved_actions + # we don't allow more than 10 stored actions + if len(saved_actions["actions"]) >= 10: + del saved_actions["actions"][min(saved_actions["actions"].keys())] + key = saved_actions["next"] + saved_actions["actions"][key] = the_action + saved_actions["next"] = key + 1 + return key + + @openerpweb.jsonrequest + def get_session_action(self, req, key): + """ + Gets back a previously saved action. This method can return None if the action + was saved since too much time (this case should be handled in a smart way). + + :param key: The key given by save_session_action() + :type key: integer + :return: The saved action or None. + :rtype: anything + """ + saved_actions = cherrypy.session.get('saved_actions') + if not saved_actions: + return None + return saved_actions["actions"].get(key) + + def load_actions_from_ir_values(req, key, key2, models, meta, context): Values = req.session.model('ir.values') actions = Values.get(key, key2, models, meta, context) for _, _, action in actions: - # values come from the server, we can just eval them - if isinstance(action['context'], basestring): - action['context'] = eval( - action['context'], - req.session.evaluation_context()) or {} + clean_action(action, req.session) - if isinstance(action['domain'], basestring): - action['domain'] = eval( - action['domain'], - req.session.evaluation_context( - action['context'])) or [] - fix_view_modes(action) return actions +def clean_action(action, session): + # values come from the server, we can just eval them + if isinstance(action['context'], basestring): + action['context'] = eval( + action['context'], + session.evaluation_context()) or {} + + if isinstance(action['domain'], basestring): + action['domain'] = eval( + action['domain'], + session.evaluation_context( + action['context'])) or [] + fix_view_modes(action) + def fix_view_modes(action): """ For historical reasons, OpenERP has weird dealings in relation to view_mode and the view_type attribute (on window actions): @@ -239,7 +293,7 @@ class Menu(openerpweb.Controller): menu_items = Menus.read(menu_ids, ['name', 'sequence', 'parent_id']) menu_root = {'id': False, 'name': 'root', 'parent_id': [-1, '']} menu_items.append(menu_root) - + # 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: @@ -287,18 +341,17 @@ class DataSet(openerpweb.Controller): :param int offset: from which index should the results start being returned :param int limit: the maximum number of records to return :param list domain: the search domain for the query - :param dict context: the context in which the search should be executed :param list sort: sorting directives :returns: a list of result records :rtype: list """ Model = request.session.model(model) ids = Model.search(domain or [], offset or 0, limit or False, - sort or False, context or False) + sort or False, request.context) if fields and fields == ['id']: # shortcut read if we only want the ids return map(lambda id: {'id': id}, ids) - return Model.read(ids, fields or False) + return Model.read(ids, fields or False, request.context) @openerpweb.jsonrequest def get(self, request, model, ids, fields=False): @@ -316,6 +369,9 @@ class DataSet(openerpweb.Controller): :type model: str :param ids: a list of identifiers :type ids: list + :param fields: a list of fields to fetch, ``False`` or empty to fetch + all fields in the model + :type fields: list | False :returns: a list of records, in the same order as the list of ids :rtype: list """ @@ -335,6 +391,12 @@ class DataSet(openerpweb.Controller): value = r[0] return {'value': value} + @openerpweb.jsonrequest + def create(self, req, model, data, context={}): + m = req.session.model(model) + r = m.create(data, context) + return {'result': r} + @openerpweb.jsonrequest def save(self, req, model, id, data, context={}): m = req.session.model(model) @@ -354,16 +416,20 @@ class DataSet(openerpweb.Controller): return {'result': r} class View(openerpweb.Controller): - def fields_view_get(self, session, model, view_id, view_type, transform=True): - Model = session.model(model) - r = Model.fields_view_get(view_id, view_type) + def fields_view_get(self, request, model, view_id, view_type, + transform=True, toolbar=False, submenu=False): + Model = request.session.model(model) + fvg = Model.fields_view_get(view_id, view_type, request.context, + toolbar, submenu) if transform: - context = {} # TODO: dict(ctx_sesssion, **ctx_action) - xml = self.transform_view(r['arch'], session, context) + evaluation_context = request.session.evaluation_context( + request.context or {}) + xml = self.transform_view( + fvg['arch'], request.session, evaluation_context) else: - xml = ElementTree.fromstring(r['arch']) - r['arch'] = Xml2Json.convert_element(xml) - return r + xml = ElementTree.fromstring(fvg['arch']) + fvg['arch'] = Xml2Json.convert_element(xml) + return fvg def normalize_attrs(self, elem, context): """ Normalize @attrs, @invisible, @required, @readonly and @states, so @@ -377,19 +443,16 @@ class View(openerpweb.Controller): :param dict context: evaluation context """ # If @attrs is normalized in json by server, the eval should be replaced by simplejson.loads - attrs = eval(elem.attrib.get('attrs', '{}')) + attrs = openerpweb.ast.literal_eval(elem.get('attrs', '{}')) if 'states' in elem.attrib: - if 'invisible' not in attrs: - attrs['invisible'] = [] - # This should be done by the server - attrs['invisible'].append(('state', 'not in', elem.attrib['states'].split(','))) - del(elem.attrib['states']) + attrs.setdefault('invisible', [])\ + .append(('state', 'not in', elem.attrib.pop('states').split(','))) if attrs: - elem.attrib['attrs'] = simplejson.dumps(attrs) + elem.set('attrs', simplejson.dumps(attrs)) for a in ['invisible', 'readonly', 'required']: if a in elem.attrib: # In the XML we trust - avalue = bool(eval(elem.attrib.get(a, 'False'), + avalue = bool(eval(elem.get(a, 'False'), {'context': context or {}})) if not avalue: del elem.attrib[a] @@ -460,35 +523,97 @@ class FormView(View): _cp_path = "/base/formview" @openerpweb.jsonrequest - def load(self, req, model, view_id): - fields_view = self.fields_view_get(req.session, model, view_id, 'form') + def load(self, req, model, view_id, toolbar=False): + fields_view = self.fields_view_get(req, model, view_id, 'form', toolbar=toolbar) return {'fields_view': fields_view} class ListView(View): _cp_path = "/base/listview" @openerpweb.jsonrequest - def load(self, req, model, view_id): - fields_view = self.fields_view_get(req.session, model, view_id, 'tree') + def load(self, req, model, view_id, toolbar=False): + fields_view = self.fields_view_get(req, model, view_id, 'tree', toolbar=toolbar) return {'fields_view': fields_view} + def fields_view_get(self, request, model, view_id, view_type="tree", + transform=True, toolbar=False, submenu=False): + """ Sets @editable on the view's arch if it isn't already set and + ``set_editable`` is present in the request context + """ + view = super(ListView, self).fields_view_get( + request, model, view_id, view_type, transform, toolbar, submenu) + + view_attributes = view['arch']['attrs'] + if request.context.get('set_editable')\ + and 'editable' not in view_attributes: + view_attributes['editable'] = 'bottom' + return view + + @openerpweb.jsonrequest + def fill(self, request, model, id, domain, + offset=0, limit=False): + return self.do_fill(request, model, id, domain, offset, limit) + + def do_fill(self, request, model, id, domain, + offset=0, limit=False): + """ Returns all information needed to fill a table: + + * view with processed ``editable`` flag + * fields (columns) with processed ``invisible`` flag + * rows with processed ``attrs`` and ``colors`` + + .. note:: context is passed through ``request`` parameter + + :param request: OpenERP request + :type request: openerpweb.openerpweb.JsonRequest + :type str model: OpenERP model for this list view + :type int id: view_id, or False if none provided + :param list domain: the search domain to search for + :param int offset: search offset, for pagination + :param int limit: search limit, for pagination + :returns: hell if I have any idea yet + """ + view = self.fields_view_get(request, model, id) + + rows = DataSet().do_search_read(request, model, + offset=offset, limit=limit, + domain=domain) + eval_context = request.session.evaluation_context( + request.context) + return [ + {'data': dict((key, {'value': value}) + for key, value in row.iteritems()), + 'color': self.process_colors(view, row, eval_context)} + for row in rows + ] + + def process_colors(self, view, row, context): + colors = view['arch']['attrs'].get('colors') + + if not colors: + return None + + color = [ + pair.split(':')[0] + for pair in colors.split(';') + if eval(pair.split(':')[1], dict(context, **row)) + ] + + if not color: + return None + elif len(color) == 1: + return color[0] + return 'maroon' + + class SearchView(View): _cp_path = "/base/searchview" @openerpweb.jsonrequest def load(self, req, model, view_id): - fields_view = self.fields_view_get(req.session, model, view_id, 'search') + fields_view = self.fields_view_get(req, model, view_id, 'search') return {'fields_view': fields_view} -class SideBar(View): - _cp_path = "/base/sidebar" - - @openerpweb.jsonrequest - def get_actions(self, request, model, object_id=0): - result = load_actions_from_ir_values(request, "action", "client_action_multi", - [[model, object_id]], False, {}) - return result - class Action(openerpweb.Controller): _cp_path = "/base/action" diff --git a/addons/base/static/lib/jquery.ba-bbq/jquery.ba-bbq.js b/addons/base/static/lib/jquery.ba-bbq/jquery.ba-bbq.js new file mode 100644 index 00000000000..f251123acd7 --- /dev/null +++ b/addons/base/static/lib/jquery.ba-bbq/jquery.ba-bbq.js @@ -0,0 +1,1137 @@ +/*! + * jQuery BBQ: Back Button & Query Library - v1.2.1 - 2/17/2010 + * http://benalman.com/projects/jquery-bbq-plugin/ + * + * Copyright (c) 2010 "Cowboy" Ben Alman + * Dual licensed under the MIT and GPL licenses. + * http://benalman.com/about/license/ + */ + +// Script: jQuery BBQ: Back Button & Query Library +// +// *Version: 1.2.1, Last updated: 2/17/2010* +// +// Project Home - http://benalman.com/projects/jquery-bbq-plugin/ +// GitHub - http://github.com/cowboy/jquery-bbq/ +// Source - http://github.com/cowboy/jquery-bbq/raw/master/jquery.ba-bbq.js +// (Minified) - http://github.com/cowboy/jquery-bbq/raw/master/jquery.ba-bbq.min.js (4.0kb) +// +// About: License +// +// Copyright (c) 2010 "Cowboy" Ben Alman, +// Dual licensed under the MIT and GPL licenses. +// http://benalman.com/about/license/ +// +// About: Examples +// +// These working examples, complete with fully commented code, illustrate a few +// ways in which this plugin can be used. +// +// Basic AJAX - http://benalman.com/code/projects/jquery-bbq/examples/fragment-basic/ +// Advanced AJAX - http://benalman.com/code/projects/jquery-bbq/examples/fragment-advanced/ +// jQuery UI Tabs - http://benalman.com/code/projects/jquery-bbq/examples/fragment-jquery-ui-tabs/ +// Deparam - http://benalman.com/code/projects/jquery-bbq/examples/deparam/ +// +// About: Support and Testing +// +// Information about what version or versions of jQuery this plugin has been +// tested with, what browsers it has been tested in, and where the unit tests +// reside (so you can test it yourself). +// +// jQuery Versions - 1.3.2, 1.4.1, 1.4.2 +// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.7, Safari 3-4, +// Chrome 4-5, Opera 9.6-10.1. +// Unit Tests - http://benalman.com/code/projects/jquery-bbq/unit/ +// +// About: Release History +// +// 1.2.1 - (2/17/2010) Actually fixed the stale window.location Safari bug from +// in BBQ, which was the main reason for the +// previous release! +// 1.2 - (2/16/2010) Integrated v1.2, which fixes a +// Safari bug, the event can now be bound before DOM ready, and IE6/7 +// page should no longer scroll when the event is first bound. Also +// added the method, and reworked the +// internal "add" method to be compatible with +// changes made to the jQuery 1.4.2 special events API. +// 1.1.1 - (1/22/2010) Integrated v1.1, which fixes an +// obscure IE8 EmulateIE7 meta tag compatibility mode bug. +// 1.1 - (1/9/2010) Broke out the jQuery BBQ event.special +// functionality into a separate plugin for users who want just the +// basic event & back button support, without all the extra awesomeness +// that BBQ provides. This plugin will be included as part of jQuery BBQ, +// but also be available separately. See +// plugin for more information. Also added the +// method and added additional examples. +// 1.0.3 - (12/2/2009) Fixed an issue in IE 6 where location.search and +// location.hash would report incorrectly if the hash contained the ? +// character. Also and +// will no longer parse params out of a URL that doesn't contain ? or #, +// respectively. +// 1.0.2 - (10/10/2009) Fixed an issue in IE 6/7 where the hidden IFRAME caused +// a "This page contains both secure and nonsecure items." warning when +// used on an https:// page. +// 1.0.1 - (10/7/2009) Fixed an issue in IE 8. Since both "IE7" and "IE8 +// Compatibility View" modes erroneously report that the browser +// supports the native window.onhashchange event, a slightly more +// robust test needed to be added. +// 1.0 - (10/2/2009) Initial release + +(function($,window){ + '$:nomunge'; // Used by YUI compressor. + + // Some convenient shortcuts. + var undefined, + aps = Array.prototype.slice, + decode = decodeURIComponent, + + // Method / object references. + jq_param = $.param, + jq_param_fragment, + jq_deparam, + jq_deparam_fragment, + jq_bbq = $.bbq = $.bbq || {}, + jq_bbq_pushState, + jq_bbq_getState, + jq_elemUrlAttr, + jq_event_special = $.event.special, + + // Reused strings. + str_hashchange = 'hashchange', + str_querystring = 'querystring', + str_fragment = 'fragment', + str_elemUrlAttr = 'elemUrlAttr', + str_location = 'location', + str_href = 'href', + str_src = 'src', + + // Reused RegExp. + re_trim_querystring = /^.*\?|#.*$/g, + re_trim_fragment = /^.*\#/, + re_no_escape, + + // Used by jQuery.elemUrlAttr. + elemUrlAttr_cache = {}; + + // A few commonly used bits, broken out to help reduce minified file size. + + function is_string( arg ) { + return typeof arg === 'string'; + }; + + // Why write the same function twice? Let's curry! Mmmm, curry.. + + function curry( func ) { + var args = aps.call( arguments, 1 ); + + return function() { + return func.apply( this, args.concat( aps.call( arguments ) ) ); + }; + }; + + // Get location.hash (or what you'd expect location.hash to be) sans any + // leading #. Thanks for making this necessary, Firefox! + function get_fragment( url ) { + return url.replace( /^[^#]*#?(.*)$/, '$1' ); + }; + + // Get location.search (or what you'd expect location.search to be) sans any + // leading #. Thanks for making this necessary, IE6! + function get_querystring( url ) { + return url.replace( /(?:^[^?#]*\?([^#]*).*$)?.*/, '$1' ); + }; + + // Section: Param (to string) + // + // Method: jQuery.param.querystring + // + // Retrieve the query string from a URL or if no arguments are passed, the + // current window.location. + // + // Usage: + // + // > jQuery.param.querystring( [ url ] ); + // + // Arguments: + // + // url - (String) A URL containing query string params to be parsed. If url + // is not passed, the current window.location is used. + // + // Returns: + // + // (String) The parsed query string, with any leading "?" removed. + // + + // Method: jQuery.param.querystring (build url) + // + // Merge a URL, with or without pre-existing query string params, plus any + // object, params string or URL containing query string params into a new URL. + // + // Usage: + // + // > jQuery.param.querystring( url, params [, merge_mode ] ); + // + // Arguments: + // + // url - (String) A valid URL for params to be merged into. This URL may + // contain a query string and/or fragment (hash). + // params - (String) A params string or URL containing query string params to + // be merged into url. + // params - (Object) A params object to be merged into url. + // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not + // specified, and is as-follows: + // + // * 0: params in the params argument will override any query string + // params in url. + // * 1: any query string params in url will override params in the params + // argument. + // * 2: params argument will completely replace any query string in url. + // + // Returns: + // + // (String) Either a params string with urlencoded data or a URL with a + // urlencoded query string in the format 'a=b&c=d&e=f'. + + // Method: jQuery.param.fragment + // + // Retrieve the fragment (hash) from a URL or if no arguments are passed, the + // current window.location. + // + // Usage: + // + // > jQuery.param.fragment( [ url ] ); + // + // Arguments: + // + // url - (String) A URL containing fragment (hash) params to be parsed. If + // url is not passed, the current window.location is used. + // + // Returns: + // + // (String) The parsed fragment (hash) string, with any leading "#" removed. + + // Method: jQuery.param.fragment (build url) + // + // Merge a URL, with or without pre-existing fragment (hash) params, plus any + // object, params string or URL containing fragment (hash) params into a new + // URL. + // + // Usage: + // + // > jQuery.param.fragment( url, params [, merge_mode ] ); + // + // Arguments: + // + // url - (String) A valid URL for params to be merged into. This URL may + // contain a query string and/or fragment (hash). + // params - (String) A params string or URL containing fragment (hash) params + // to be merged into url. + // params - (Object) A params object to be merged into url. + // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not + // specified, and is as-follows: + // + // * 0: params in the params argument will override any fragment (hash) + // params in url. + // * 1: any fragment (hash) params in url will override params in the + // params argument. + // * 2: params argument will completely replace any query string in url. + // + // Returns: + // + // (String) Either a params string with urlencoded data or a URL with a + // urlencoded fragment (hash) in the format 'a=b&c=d&e=f'. + + function jq_param_sub( is_fragment, get_func, url, params, merge_mode ) { + var result, + qs, + matches, + url_params, + hash; + + if ( params !== undefined ) { + // Build URL by merging params into url string. + + // matches[1] = url part that precedes params, not including trailing ?/# + // matches[2] = params, not including leading ?/# + // matches[3] = if in 'querystring' mode, hash including leading #, otherwise '' + matches = url.match( is_fragment ? /^([^#]*)\#?(.*)$/ : /^([^#?]*)\??([^#]*)(#?.*)/ ); + + // Get the hash if in 'querystring' mode, and it exists. + hash = matches[3] || ''; + + if ( merge_mode === 2 && is_string( params ) ) { + // If merge_mode is 2 and params is a string, merge the fragment / query + // string into the URL wholesale, without converting it into an object. + qs = params.replace( is_fragment ? re_trim_fragment : re_trim_querystring, '' ); + + } else { + // Convert relevant params in url to object. + url_params = jq_deparam( matches[2] ); + + params = is_string( params ) + + // Convert passed params string into object. + ? jq_deparam[ is_fragment ? str_fragment : str_querystring ]( params ) + + // Passed params object. + : params; + + qs = merge_mode === 2 ? params // passed params replace url params + : merge_mode === 1 ? $.extend( {}, params, url_params ) // url params override passed params + : $.extend( {}, url_params, params ); // passed params override url params + + // Convert params object to a string. + qs = jq_param( qs ); + + // Unescape characters specified via $.param.noEscape. Since only hash- + // history users have requested this feature, it's only enabled for + // fragment-related params strings. + if ( is_fragment ) { + qs = qs.replace( re_no_escape, decode ); + } + } + + // Build URL from the base url, querystring and hash. In 'querystring' + // mode, ? is only added if a query string exists. In 'fragment' mode, # + // is always added. + result = matches[1] + ( is_fragment ? '#' : qs || !matches[1] ? '?' : '' ) + qs + hash; + + } else { + // If URL was passed in, parse params from URL string, otherwise parse + // params from window.location. + result = get_func( url !== undefined ? url : window[ str_location ][ str_href ] ); + } + + return result; + }; + + jq_param[ str_querystring ] = curry( jq_param_sub, 0, get_querystring ); + jq_param[ str_fragment ] = jq_param_fragment = curry( jq_param_sub, 1, get_fragment ); + + // Method: jQuery.param.fragment.noEscape + // + // Specify characters that will be left unescaped when fragments are created + // or merged using , or when the fragment is modified + // using . This option only applies to serialized data + // object fragments, and not set-as-string fragments. Does not affect the + // query string. Defaults to ",/" (comma, forward slash). + // + // Note that this is considered a purely aesthetic option, and will help to + // create URLs that "look pretty" in the address bar or bookmarks, without + // affecting functionality in any way. That being said, be careful to not + // unescape characters that are used as delimiters or serve a special + // purpose, such as the "#?&=+" (octothorpe, question mark, ampersand, + // equals, plus) characters. + // + // Usage: + // + // > jQuery.param.fragment.noEscape( [ chars ] ); + // + // Arguments: + // + // chars - (String) The characters to not escape in the fragment. If + // unspecified, defaults to empty string (escape all characters). + // + // Returns: + // + // Nothing. + + jq_param_fragment.noEscape = function( chars ) { + chars = chars || ''; + var arr = $.map( chars.split(''), encodeURIComponent ); + re_no_escape = new RegExp( arr.join('|'), 'g' ); + }; + + // A sensible default. These are the characters people seem to complain about + // "uglifying up the URL" the most. + jq_param_fragment.noEscape( ',/' ); + + // Section: Deparam (from string) + // + // Method: jQuery.deparam + // + // Deserialize a params string into an object, optionally coercing numbers, + // booleans, null and undefined values; this method is the counterpart to the + // internal jQuery.param method. + // + // Usage: + // + // > jQuery.deparam( params [, coerce ] ); + // + // Arguments: + // + // params - (String) A params string to be parsed. + // coerce - (Boolean) If true, coerces any numbers or true, false, null, and + // undefined to their actual value. Defaults to false if omitted. + // + // Returns: + // + // (Object) An object representing the deserialized params string. + + $.deparam = jq_deparam = function( params, coerce ) { + var obj = {}, + coerce_types = { 'true': !0, 'false': !1, 'null': null }; + + // Iterate over all name=value pairs. + $.each( params.replace( /\+/g, ' ' ).split( '&' ), function(j,v){ + var param = v.split( '=' ), + key = decode( param[0] ), + val, + cur = obj, + i = 0, + + // If key is more complex than 'foo', like 'a[]' or 'a[b][c]', split it + // into its component parts. + keys = key.split( '][' ), + keys_last = keys.length - 1; + + // If the first keys part contains [ and the last ends with ], then [] + // are correctly balanced. + if ( /\[/.test( keys[0] ) && /\]$/.test( keys[ keys_last ] ) ) { + // Remove the trailing ] from the last keys part. + keys[ keys_last ] = keys[ keys_last ].replace( /\]$/, '' ); + + // Split first keys part into two parts on the [ and add them back onto + // the beginning of the keys array. + keys = keys.shift().split('[').concat( keys ); + + keys_last = keys.length - 1; + } else { + // Basic 'foo' style key. + keys_last = 0; + } + + // Are we dealing with a name=value pair, or just a name? + if ( param.length === 2 ) { + val = decode( param[1] ); + + // Coerce values. + if ( coerce ) { + val = val && !isNaN(val) ? +val // number + : val === 'undefined' ? undefined // undefined + : coerce_types[val] !== undefined ? coerce_types[val] // true, false, null + : val; // string + } + + if ( keys_last ) { + // Complex key, build deep object structure based on a few rules: + // * The 'cur' pointer starts at the object top-level. + // * [] = array push (n is set to array length), [n] = array if n is + // numeric, otherwise object. + // * If at the last keys part, set the value. + // * For each keys part, if the current level is undefined create an + // object or array based on the type of the next keys part. + // * Move the 'cur' pointer to the next level. + // * Rinse & repeat. + for ( ; i <= keys_last; i++ ) { + key = keys[i] === '' ? cur.length : keys[i]; + cur = cur[key] = i < keys_last + ? cur[key] || ( keys[i+1] && isNaN( keys[i+1] ) ? {} : [] ) + : val; + } + + } else { + // Simple key, even simpler rules, since only scalars and shallow + // arrays are allowed. + + if ( $.isArray( obj[key] ) ) { + // val is already an array, so push on the next value. + obj[key].push( val ); + + } else if ( obj[key] !== undefined ) { + // val isn't an array, but since a second value has been specified, + // convert val into an array. + obj[key] = [ obj[key], val ]; + + } else { + // val is a scalar. + obj[key] = val; + } + } + + } else if ( key ) { + // No value was defined, so set something meaningful. + obj[key] = coerce + ? undefined + : ''; + } + }); + + return obj; + }; + + // Method: jQuery.deparam.querystring + // + // Parse the query string from a URL or the current window.location, + // deserializing it into an object, optionally coercing numbers, booleans, + // null and undefined values. + // + // Usage: + // + // > jQuery.deparam.querystring( [ url ] [, coerce ] ); + // + // Arguments: + // + // url - (String) An optional params string or URL containing query string + // params to be parsed. If url is omitted, the current window.location + // is used. + // coerce - (Boolean) If true, coerces any numbers or true, false, null, and + // undefined to their actual value. Defaults to false if omitted. + // + // Returns: + // + // (Object) An object representing the deserialized params string. + + // Method: jQuery.deparam.fragment + // + // Parse the fragment (hash) from a URL or the current window.location, + // deserializing it into an object, optionally coercing numbers, booleans, + // null and undefined values. + // + // Usage: + // + // > jQuery.deparam.fragment( [ url ] [, coerce ] ); + // + // Arguments: + // + // url - (String) An optional params string or URL containing fragment (hash) + // params to be parsed. If url is omitted, the current window.location + // is used. + // coerce - (Boolean) If true, coerces any numbers or true, false, null, and + // undefined to their actual value. Defaults to false if omitted. + // + // Returns: + // + // (Object) An object representing the deserialized params string. + + function jq_deparam_sub( is_fragment, url_or_params, coerce ) { + if ( url_or_params === undefined || typeof url_or_params === 'boolean' ) { + // url_or_params not specified. + coerce = url_or_params; + url_or_params = jq_param[ is_fragment ? str_fragment : str_querystring ](); + } else { + url_or_params = is_string( url_or_params ) + ? url_or_params.replace( is_fragment ? re_trim_fragment : re_trim_querystring, '' ) + : url_or_params; + } + + return jq_deparam( url_or_params, coerce ); + }; + + jq_deparam[ str_querystring ] = curry( jq_deparam_sub, 0 ); + jq_deparam[ str_fragment ] = jq_deparam_fragment = curry( jq_deparam_sub, 1 ); + + // Section: Element manipulation + // + // Method: jQuery.elemUrlAttr + // + // Get the internal "Default URL attribute per tag" list, or augment the list + // with additional tag-attribute pairs, in case the defaults are insufficient. + // + // In the and methods, this list + // is used to determine which attribute contains the URL to be modified, if + // an "attr" param is not specified. + // + // Default Tag-Attribute List: + // + // a - href + // base - href + // iframe - src + // img - src + // input - src + // form - action + // link - href + // script - src + // + // Usage: + // + // > jQuery.elemUrlAttr( [ tag_attr ] ); + // + // Arguments: + // + // tag_attr - (Object) An object containing a list of tag names and their + // associated default attribute names in the format { tag: 'attr', ... } to + // be merged into the internal tag-attribute list. + // + // Returns: + // + // (Object) An object containing all stored tag-attribute values. + + // Only define function and set defaults if function doesn't already exist, as + // the urlInternal plugin will provide this method as well. + $[ str_elemUrlAttr ] || ($[ str_elemUrlAttr ] = function( obj ) { + return $.extend( elemUrlAttr_cache, obj ); + })({ + a: str_href, + base: str_href, + iframe: str_src, + img: str_src, + input: str_src, + form: 'action', + link: str_href, + script: str_src + }); + + jq_elemUrlAttr = $[ str_elemUrlAttr ]; + + // Method: jQuery.fn.querystring + // + // Update URL attribute in one or more elements, merging the current URL (with + // or without pre-existing query string params) plus any params object or + // string into a new URL, which is then set into that attribute. Like + // , but for all elements in a jQuery + // collection. + // + // Usage: + // + // > jQuery('selector').querystring( [ attr, ] params [, merge_mode ] ); + // + // Arguments: + // + // attr - (String) Optional name of an attribute that will contain a URL to + // merge params or url into. See for a list of default + // attributes. + // params - (Object) A params object to be merged into the URL attribute. + // params - (String) A URL containing query string params, or params string + // to be merged into the URL attribute. + // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not + // specified, and is as-follows: + // + // * 0: params in the params argument will override any params in attr URL. + // * 1: any params in attr URL will override params in the params argument. + // * 2: params argument will completely replace any query string in attr + // URL. + // + // Returns: + // + // (jQuery) The initial jQuery collection of elements, but with modified URL + // attribute values. + + // Method: jQuery.fn.fragment + // + // Update URL attribute in one or more elements, merging the current URL (with + // or without pre-existing fragment/hash params) plus any params object or + // string into a new URL, which is then set into that attribute. Like + // , but for all elements in a jQuery + // collection. + // + // Usage: + // + // > jQuery('selector').fragment( [ attr, ] params [, merge_mode ] ); + // + // Arguments: + // + // attr - (String) Optional name of an attribute that will contain a URL to + // merge params into. See for a list of default + // attributes. + // params - (Object) A params object to be merged into the URL attribute. + // params - (String) A URL containing fragment (hash) params, or params + // string to be merged into the URL attribute. + // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not + // specified, and is as-follows: + // + // * 0: params in the params argument will override any params in attr URL. + // * 1: any params in attr URL will override params in the params argument. + // * 2: params argument will completely replace any fragment (hash) in attr + // URL. + // + // Returns: + // + // (jQuery) The initial jQuery collection of elements, but with modified URL + // attribute values. + + function jq_fn_sub( mode, force_attr, params, merge_mode ) { + if ( !is_string( params ) && typeof params !== 'object' ) { + // force_attr not specified. + merge_mode = params; + params = force_attr; + force_attr = undefined; + } + + return this.each(function(){ + var that = $(this), + + // Get attribute specified, or default specified via $.elemUrlAttr. + attr = force_attr || jq_elemUrlAttr()[ ( this.nodeName || '' ).toLowerCase() ] || '', + + // Get URL value. + url = attr && that.attr( attr ) || ''; + + // Update attribute with new URL. + that.attr( attr, jq_param[ mode ]( url, params, merge_mode ) ); + }); + + }; + + $.fn[ str_querystring ] = curry( jq_fn_sub, str_querystring ); + $.fn[ str_fragment ] = curry( jq_fn_sub, str_fragment ); + + // Section: History, hashchange event + // + // Method: jQuery.bbq.pushState + // + // Adds a 'state' into the browser history at the current position, setting + // location.hash and triggering any bound callbacks + // (provided the new state is different than the previous state). + // + // If no arguments are passed, an empty state is created, which is just a + // shortcut for jQuery.bbq.pushState( {}, 2 ). + // + // Usage: + // + // > jQuery.bbq.pushState( [ params [, merge_mode ] ] ); + // + // Arguments: + // + // params - (String) A serialized params string or a hash string beginning + // with # to merge into location.hash. + // params - (Object) A params object to merge into location.hash. + // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not + // specified (unless a hash string beginning with # is specified, in which + // case merge behavior defaults to 2), and is as-follows: + // + // * 0: params in the params argument will override any params in the + // current state. + // * 1: any params in the current state will override params in the params + // argument. + // * 2: params argument will completely replace current state. + // + // Returns: + // + // Nothing. + // + // Additional Notes: + // + // * Setting an empty state may cause the browser to scroll. + // * Unlike the fragment and querystring methods, if a hash string beginning + // with # is specified as the params agrument, merge_mode defaults to 2. + + jq_bbq.pushState = jq_bbq_pushState = function( params, merge_mode ) { + if ( is_string( params ) && /^#/.test( params ) && merge_mode === undefined ) { + // Params string begins with # and merge_mode not specified, so completely + // overwrite window.location.hash. + merge_mode = 2; + } + + var has_args = params !== undefined, + // Merge params into window.location using $.param.fragment. + url = jq_param_fragment( window[ str_location ][ str_href ], + has_args ? params : {}, has_args ? merge_mode : 2 ); + + // Set new window.location.href. If hash is empty, use just # to prevent + // browser from reloading the page. Note that Safari 3 & Chrome barf on + // location.hash = '#'. + window[ str_location ][ str_href ] = url + ( /#/.test( url ) ? '' : '#' ); + }; + + // Method: jQuery.bbq.getState + // + // Retrieves the current 'state' from the browser history, parsing + // location.hash for a specific key or returning an object containing the + // entire state, optionally coercing numbers, booleans, null and undefined + // values. + // + // Usage: + // + // > jQuery.bbq.getState( [ key ] [, coerce ] ); + // + // Arguments: + // + // key - (String) An optional state key for which to return a value. + // coerce - (Boolean) If true, coerces any numbers or true, false, null, and + // undefined to their actual value. Defaults to false. + // + // Returns: + // + // (Anything) If key is passed, returns the value corresponding with that key + // in the location.hash 'state', or undefined. If not, an object + // representing the entire 'state' is returned. + + jq_bbq.getState = jq_bbq_getState = function( key, coerce ) { + return key === undefined || typeof key === 'boolean' + ? jq_deparam_fragment( key ) // 'key' really means 'coerce' here + : jq_deparam_fragment( coerce )[ key ]; + }; + + // Method: jQuery.bbq.removeState + // + // Remove one or more keys from the current browser history 'state', creating + // a new state, setting location.hash and triggering any bound + // callbacks (provided the new state is different than + // the previous state). + // + // If no arguments are passed, an empty state is created, which is just a + // shortcut for jQuery.bbq.pushState( {}, 2 ). + // + // Usage: + // + // > jQuery.bbq.removeState( [ key [, key ... ] ] ); + // + // Arguments: + // + // key - (String) One or more key values to remove from the current state, + // passed as individual arguments. + // key - (Array) A single array argument that contains a list of key values + // to remove from the current state. + // + // Returns: + // + // Nothing. + // + // Additional Notes: + // + // * Setting an empty state may cause the browser to scroll. + + jq_bbq.removeState = function( arr ) { + var state = {}; + + // If one or more arguments is passed.. + if ( arr !== undefined ) { + + // Get the current state. + state = jq_bbq_getState(); + + // For each passed key, delete the corresponding property from the current + // state. + $.each( $.isArray( arr ) ? arr : arguments, function(i,v){ + delete state[ v ]; + }); + } + + // Set the state, completely overriding any existing state. + jq_bbq_pushState( state, 2 ); + }; + + // Event: hashchange event (BBQ) + // + // Usage in jQuery 1.4 and newer: + // + // In jQuery 1.4 and newer, the event object passed into any hashchange event + // callback is augmented with a copy of the location.hash fragment at the time + // the event was triggered as its event.fragment property. In addition, the + // event.getState method operates on this property (instead of location.hash) + // which allows this fragment-as-a-state to be referenced later, even after + // window.location may have changed. + // + // Note that event.fragment and event.getState are not defined according to + // W3C (or any other) specification, but will still be available whether or + // not the hashchange event exists natively in the browser, because of the + // utility they provide. + // + // The event.fragment property contains the output of + // and the event.getState method is equivalent to the + // method. + // + // > $(window).bind( 'hashchange', function( event ) { + // > var hash_str = event.fragment, + // > param_obj = event.getState(), + // > param_val = event.getState( 'param_name' ), + // > param_val_coerced = event.getState( 'param_name', true ); + // > ... + // > }); + // + // Usage in jQuery 1.3.2: + // + // In jQuery 1.3.2, the event object cannot to be augmented as in jQuery 1.4+, + // so the fragment state isn't bound to the event object and must instead be + // parsed using the and methods. + // + // > $(window).bind( 'hashchange', function( event ) { + // > var hash_str = $.param.fragment(), + // > param_obj = $.bbq.getState(), + // > param_val = $.bbq.getState( 'param_name' ), + // > param_val_coerced = $.bbq.getState( 'param_name', true ); + // > ... + // > }); + // + // Additional Notes: + // + // * Due to changes in the special events API, jQuery BBQ v1.2 or newer is + // required to enable the augmented event object in jQuery 1.4.2 and newer. + // * See for more detailed information. + + jq_event_special[ str_hashchange ] = $.extend( jq_event_special[ str_hashchange ], { + + // Augmenting the event object with the .fragment property and .getState + // method requires jQuery 1.4 or newer. Note: with 1.3.2, everything will + // work, but the event won't be augmented) + add: function( handleObj ) { + var old_handler; + + function new_handler(e) { + // e.fragment is set to the value of location.hash (with any leading # + // removed) at the time the event is triggered. + var hash = e[ str_fragment ] = jq_param_fragment(); + + // e.getState() works just like $.bbq.getState(), but uses the + // e.fragment property stored on the event object. + e.getState = function( key, coerce ) { + return key === undefined || typeof key === 'boolean' + ? jq_deparam( hash, key ) // 'key' really means 'coerce' here + : jq_deparam( hash, coerce )[ key ]; + }; + + old_handler.apply( this, arguments ); + }; + + // This may seem a little complicated, but it normalizes the special event + // .add method between jQuery 1.4/1.4.1 and 1.4.2+ + if ( $.isFunction( handleObj ) ) { + // 1.4, 1.4.1 + old_handler = handleObj; + return new_handler; + } else { + // 1.4.2+ + old_handler = handleObj.handler; + handleObj.handler = new_handler; + } + } + + }); + +})(jQuery,this); + +/*! + * jQuery hashchange event - v1.2 - 2/11/2010 + * http://benalman.com/projects/jquery-hashchange-plugin/ + * + * Copyright (c) 2010 "Cowboy" Ben Alman + * Dual licensed under the MIT and GPL licenses. + * http://benalman.com/about/license/ + */ + +// Script: jQuery hashchange event +// +// *Version: 1.2, Last updated: 2/11/2010* +// +// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/ +// GitHub - http://github.com/cowboy/jquery-hashchange/ +// Source - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js +// (Minified) - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (1.1kb) +// +// About: License +// +// Copyright (c) 2010 "Cowboy" Ben Alman, +// Dual licensed under the MIT and GPL licenses. +// http://benalman.com/about/license/ +// +// About: Examples +// +// This working example, complete with fully commented code, illustrate one way +// in which this plugin can be used. +// +// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/ +// +// About: Support and Testing +// +// Information about what version or versions of jQuery this plugin has been +// tested with, what browsers it has been tested in, and where the unit tests +// reside (so you can test it yourself). +// +// jQuery Versions - 1.3.2, 1.4.1, 1.4.2 +// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.7, Safari 3-4, Chrome, Opera 9.6-10.1. +// Unit Tests - http://benalman.com/code/projects/jquery-hashchange/unit/ +// +// About: Known issues +// +// While this jQuery hashchange event implementation is quite stable and robust, +// there are a few unfortunate browser bugs surrounding expected hashchange +// event-based behaviors, independent of any JavaScript window.onhashchange +// abstraction. See the following examples for more information: +// +// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/ +// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/ +// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/ +// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/ +// +// About: Release History +// +// 1.2 - (2/11/2010) Fixed a bug where coming back to a page using this plugin +// from a page on another domain would cause an error in Safari 4. Also, +// IE6/7 Iframe is now inserted after the body (this actually works), +// which prevents the page from scrolling when the event is first bound. +// Event can also now be bound before DOM ready, but it won't be usable +// before then in IE6/7. +// 1.1 - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug +// where browser version is incorrectly reported as 8.0, despite +// inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag. +// 1.0 - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special +// window.onhashchange functionality into a separate plugin for users +// who want just the basic event & back button support, without all the +// extra awesomeness that BBQ provides. This plugin will be included as +// part of jQuery BBQ, but also be available separately. + +(function($,window,undefined){ + '$:nomunge'; // Used by YUI compressor. + + // Method / object references. + var fake_onhashchange, + jq_event_special = $.event.special, + + // Reused strings. + str_location = 'location', + str_hashchange = 'hashchange', + str_href = 'href', + + // IE6/7 specifically need some special love when it comes to back-button + // support, so let's do a little browser sniffing.. + browser = $.browser, + mode = document.documentMode, + is_old_ie = browser.msie && ( mode === undefined || mode < 8 ), + + // Does the browser support window.onhashchange? Test for IE version, since + // IE8 incorrectly reports this when in "IE7" or "IE8 Compatibility View"! + supports_onhashchange = 'on' + str_hashchange in window && !is_old_ie; + + // Get location.hash (or what you'd expect location.hash to be) sans any + // leading #. Thanks for making this necessary, Firefox! + function get_fragment( url ) { + url = url || window[ str_location ][ str_href ]; + return url.replace( /^[^#]*#?(.*)$/, '$1' ); + }; + + // Property: jQuery.hashchangeDelay + // + // The numeric interval (in milliseconds) at which the + // polling loop executes. Defaults to 100. + + $[ str_hashchange + 'Delay' ] = 100; + + // Event: hashchange event + // + // Fired when location.hash changes. In browsers that support it, the native + // window.onhashchange event is used (IE8, FF3.6), otherwise a polling loop is + // initialized, running every milliseconds to see if + // the hash has changed. In IE 6 and 7, a hidden Iframe is created to allow + // the back button and hash-based history to work. + // + // Usage: + // + // > $(window).bind( 'hashchange', function(e) { + // > var hash = location.hash; + // > ... + // > }); + // + // Additional Notes: + // + // * The polling loop and Iframe are not created until at least one callback + // is actually bound to 'hashchange'. + // * If you need the bound callback(s) to execute immediately, in cases where + // the page 'state' exists on page load (via bookmark or page refresh, for + // example) use $(window).trigger( 'hashchange' ); + // * The event can be bound before DOM ready, but since it won't be usable + // before then in IE6/7 (due to the necessary Iframe), recommended usage is + // to bind it inside a $(document).ready() callback. + + jq_event_special[ str_hashchange ] = $.extend( jq_event_special[ str_hashchange ], { + + // Called only when the first 'hashchange' event is bound to window. + setup: function() { + // If window.onhashchange is supported natively, there's nothing to do.. + if ( supports_onhashchange ) { return false; } + + // Otherwise, we need to create our own. And we don't want to call this + // until the user binds to the event, just in case they never do, since it + // will create a polling loop and possibly even a hidden Iframe. + $( fake_onhashchange.start ); + }, + + // Called only when the last 'hashchange' event is unbound from window. + teardown: function() { + // If window.onhashchange is supported natively, there's nothing to do.. + if ( supports_onhashchange ) { return false; } + + // Otherwise, we need to stop ours (if possible). + $( fake_onhashchange.stop ); + } + + }); + + // fake_onhashchange does all the work of triggering the window.onhashchange + // event for browsers that don't natively support it, including creating a + // polling loop to watch for hash changes and in IE 6/7 creating a hidden + // Iframe to enable back and forward. + fake_onhashchange = (function(){ + var self = {}, + timeout_id, + iframe, + set_history, + get_history; + + // Initialize. In IE 6/7, creates a hidden Iframe for history handling. + function init(){ + // Most browsers don't need special methods here.. + set_history = get_history = function(val){ return val; }; + + // But IE6/7 do! + if ( is_old_ie ) { + + // Create hidden Iframe after the end of the body to prevent initial + // page load from scrolling unnecessarily. + iframe = $(''; - } else { ii="";} - $("
").append(ii).insertBefore(gv); - $("
"+this.p.loadtext+"
").insertBefore(gv); - $(this).attr({cellspacing:"0",cellpadding:"0",border:"0","role":"grid","aria-multiselectable":!!this.p.multiselect,"aria-labelledby":"gbox_"+this.id}); - var sortkeys = ["shiftKey","altKey","ctrlKey"], - intNum = function(val,defval) { - val = parseInt(val,10); - if (isNaN(val)) { return defval ? defval : 0;} - else {return val;} - }, - formatCol = function (pos, rowInd, tv, rawObject, rowId, rdata){ - var cm = ts.p.colModel[pos], - ral = cm.align, result="style=\"", clas = cm.classes, nm = cm.name, celp, acp=[]; - if(ral) { result += "text-align:"+ral+";"; } - if(cm.hidden===true) { result += "display:none;"; } - if(rowInd===0) { - result += "width: "+grid.headers[pos].width+"px;"; - } else if (cm.cellattr && $.isFunction(cm.cellattr)) - { - celp = cm.cellattr.call(ts, rowId, tv, rawObject, cm, rdata); - if(celp && typeof(celp) === "string") { - celp = celp.replace(/style/i,'style').replace(/title/i,'title'); - if(celp.indexOf('title') > -1) { cm.title=false;} - if(celp.indexOf('class') > -1) { clas = undefined;} - acp = celp.split("style"); - if(acp.length === 2 ) { - acp[1] = $.trim(acp[1].replace("=","")); - if(acp[1].indexOf("'") === 0 || acp[1].indexOf('"') === 0) { - acp[1] = acp[1].substring(1); - } - result += acp[1].replace(/'/gi,'"'); - } else { - result += "\""; - } - } - } - if(!acp.length) { acp[0] = ""; result += "\"";} - result += (clas !== undefined ? (" class=\""+clas+"\"") :"") + ((cm.title && tv) ? (" title=\""+$.jgrid.stripHtml(tv)+"\"") :""); - result += " aria-describedby=\""+ts.p.id+"_"+nm+"\""; - return result + acp[0]; - }, - cellVal = function (val) { - return val === undefined || val === null || val === "" ? " " : (ts.p.autoencode ? $.jgrid.htmlEncode(val) : val+""); - }, - formatter = function (rowId, cellval , colpos, rwdat, _act){ - var cm = ts.p.colModel[colpos],v; - if(typeof cm.formatter !== 'undefined') { - var opts= {rowId: rowId, colModel:cm, gid:ts.p.id, pos:colpos }; - if($.isFunction( cm.formatter ) ) { - v = cm.formatter.call(ts,cellval,opts,rwdat,_act); - } else if($.fmatter){ - v = $.fn.fmatter(cm.formatter, cellval,opts, rwdat, _act); - } else { - v = cellVal(cellval); - } - } else { - v = cellVal(cellval); - } - return v; - }, - addCell = function(rowId,cell,pos,irow, srvr) { - var v,prp; - v = formatter(rowId,cell,pos,srvr,'add'); - prp = formatCol( pos,irow, v, srvr, rowId, true); - return ""+v+""; - }, - addMulti = function(rowid,pos,irow){ - var v = "", - prp = formatCol( pos,irow,'',null, rowid, true); - return ""+v+""; - }, - addRowNum = function (pos,irow,pG,rN) { - var v = (parseInt(pG,10)-1)*parseInt(rN,10)+1+irow, - prp = formatCol( pos,irow,v, null, irow, true); - return ""+v+""; - }, - reader = function (datatype) { - var field, f=[], j=0, i; - for(i =0; idiv:first", parent).css({height:"auto"}).children("div:first").css({height:0,display:"none"}); - parent.scrollTop = 0; - } - }, - refreshIndex = function() { - var datalen = ts.p.data.length, idname, i, val, - ni = ts.p.rownumbers===true ? 1 :0, - gi = ts.p.multiselect ===true ? 1 :0, - si = ts.p.subGrid===true ? 1 :0; - - if(ts.p.keyIndex === false || ts.p.loadonce === true) { - idname = ts.p.localReader.id; - } else { - idname = ts.p.colModel[ts.p.keyIndex+gi+si+ni].name; - } - for(i =0;i < datalen; i++) { - val = $.jgrid.getAccessor(ts.p.data[i],idname); - ts.p._index[val] = i; - } - }, - addXmlData = function (xml,t, rcnt, more, adjust) { - var startReq = new Date(), - locdata = (ts.p.datatype != "local" && ts.p.loadonce) || ts.p.datatype == "xmlstring", - xmlid, - frd = ts.p.datatype == "local" ? "local" : "xml"; - if(locdata) { - ts.p.data = []; - ts.p._index = {}; - ts.p.localReader.id = xmlid = "_id_"; - } - ts.p.reccount = 0; - if($.isXMLDoc(xml)) { - if(ts.p.treeANode===-1 && !ts.p.scroll) { - emptyRows(t,false); - rcnt=1; - } else { rcnt = rcnt > 1 ? rcnt :1; } - } else { return; } - var i,fpos,ir=0,v,row,gi=0,si=0,ni=0,idn, getId,f=[],F,rd ={}, xmlr,rid, rowData=[], cn=(ts.p.altRows === true) ? " "+ts.p.altclass:"",cn1; - if(!ts.p.xmlReader.repeatitems) {f = reader(frd);} - if( ts.p.keyIndex===false) { - idn = ts.p.xmlReader.id; - } else { - idn = ts.p.keyIndex; - } - if(f.length>0 && !isNaN(idn)) { - if (ts.p.remapColumns && ts.p.remapColumns.length) { - idn = $.inArray(idn, ts.p.remapColumns); - } - idn=f[idn]; - } - if( (idn+"").indexOf("[") === -1 ) { - if (f.length) { - getId = function( trow, k) {return $(idn,trow).text() || k;}; - } else { - getId = function( trow, k) {return $(ts.p.xmlReader.cell,trow).eq(idn).text() || k;}; - } - } - else { - getId = function( trow, k) {return trow.getAttribute(idn.replace(/[\[\]]/g,"")) || k;}; - } - ts.p.userData = {}; - $(ts.p.xmlReader.page,xml).each(function() {ts.p.page = this.textContent || this.text || 0; }); - $(ts.p.xmlReader.total,xml).each(function() {ts.p.lastpage = this.textContent || this.text; if(ts.p.lastpage===undefined) { ts.p.lastpage=1; } } ); - $(ts.p.xmlReader.records,xml).each(function() {ts.p.records = this.textContent || this.text || 0; } ); - $(ts.p.xmlReader.userdata,xml).each(function() {ts.p.userData[this.getAttribute("name")]=this.textContent || this.text;}); - var gxml = $(ts.p.xmlReader.root+" "+ts.p.xmlReader.row,xml); - if (!gxml) { gxml = []; } - var gl = gxml.length, j=0, grpdata={}, rn; - if(gxml && gl){ - rn = parseInt(ts.p.rowNum,10); - var br=ts.p.scroll?(parseInt(ts.p.page,10)-1)*rn+1:1,altr; - if (adjust) { rn *= adjust+1; } - var afterInsRow = $.isFunction(ts.p.afterInsertRow), hiderow=""; - if(ts.p.grouping && ts.p.groupingView.groupCollapse === true) { - hiderow = " style=\"display:none;\""; - } - while (j" ); - if(ts.p.rownumbers===true) { - rowData.push( addRowNum(0,j,ts.p.page,ts.p.rowNum) ); - ni=1; - } - if(ts.p.multiselect===true) { - rowData.push( addMulti(rid,ni,j) ); - gi=1; - } - if (ts.p.subGrid===true) { - rowData.push( $(ts).jqGrid("addSubGridCell",gi+ni,j+rcnt) ); - si= 1; - } - if(ts.p.xmlReader.repeatitems){ - if (!F) { F=orderedCols(gi+si+ni); } - var cells = $(ts.p.xmlReader.cell,xmlr); - $.each(F, function (k) { - var cell = cells[this]; - if (!cell) { return false; } - v = cell.textContent || cell.text; - rd[ts.p.colModel[k+gi+si+ni].name] = v; - rowData.push( addCell(rid,v,k+gi+si+ni,j+rcnt,xmlr) ); - }); - } else { - for(i = 0; i < f.length;i++) { - v = $(f[i],xmlr).text(); - rd[ts.p.colModel[i+gi+si+ni].name] = v; - rowData.push( addCell(rid, v, i+gi+si+ni, j+rcnt, xmlr) ); - } - } - rowData.push(""); - if(ts.p.grouping) { - var grlen = ts.p.groupingView.groupField.length, grpitem = []; - for(var z=0;z -1 ? ts.p.treeANode: 0; - row = $(rowData.join(''))[0]; // speed overhead - $(ts.rows[j+fpos]).after(row); - try {$(ts).jqGrid("setTreeNode",rd,row);} catch (e) {} - } else { - $("tbody:first",t).append(rowData.join('')); - } - if (ts.p.subGrid===true) { - try {$(ts).jqGrid("addSubGrid",ts.rows[ts.rows.length-1],gi+ni);} catch (_){} - } - if(afterInsRow) {ts.p.afterInsertRow.call(ts,rid,rd,xmlr);} - rowData=[]; - } - rd={}; - ir++; - j++; - if(ir==rn) {break;} - } - } - if(ts.p.gridview === true) { - if(ts.p.grouping) { - $(ts).jqGrid('groupingRender',grpdata,ts.p.colModel.length); - grpdata = null; - } else { - $("tbody:first",t).append(rowData.join('')); - } - } - ts.p.totaltime = new Date() - startReq; - if(ir>0) { if(ts.p.records===0) { ts.p.records=gl;} } - rowData =null; - if(!ts.p.treeGrid && !ts.p.scroll) {ts.grid.bDiv.scrollTop = 0;} - ts.p.reccount=ir; - ts.p.treeANode = -1; - if(ts.p.userDataOnFooter) { $(ts).jqGrid("footerData","set",ts.p.userData,true); } - if(locdata) { - ts.p.records = gl; - ts.p.lastpage = Math.ceil(gl/ rn); - } - if (!more) { ts.updatepager(false,true); } - if(locdata) { - while (ir 1 ? rcnt :1; } - } else { return; } - - var dReader, locid, frd, - locdata = (ts.p.datatype != "local" && ts.p.loadonce) || ts.p.datatype == "jsonstring"; - if(locdata) { ts.p.data = []; ts.p._index = {}; locid = ts.p.localReader.id = "_id_";} - ts.p.reccount = 0; - if(ts.p.datatype == "local") { - dReader = ts.p.localReader; - frd= 'local'; - } else { - dReader = ts.p.jsonReader; - frd='json'; - } - var ir=0,v,i,j,row,f=[],F,cur,gi=0,si=0,ni=0,len,drows,idn,rd={}, fpos, idr,rowData=[],cn=(ts.p.altRows === true) ? " "+ts.p.altclass:"",cn1,lp; - ts.p.page = $.jgrid.getAccessor(data,dReader.page) || 0; - lp = $.jgrid.getAccessor(data,dReader.total); - ts.p.lastpage = lp === undefined ? 1 : lp; - ts.p.records = $.jgrid.getAccessor(data,dReader.records) || 0; - ts.p.userData = $.jgrid.getAccessor(data,dReader.userdata) || {}; - if(!dReader.repeatitems) { - F = f = reader(frd); - } - if( ts.p.keyIndex===false ) { - idn = dReader.id; - } else { - idn = ts.p.keyIndex; - } - if(f.length>0 && !isNaN(idn)) { - if (ts.p.remapColumns && ts.p.remapColumns.length) { - idn = $.inArray(idn, ts.p.remapColumns); - } - idn=f[idn]; - } - drows = $.jgrid.getAccessor(data,dReader.root); - if (!drows) { drows = []; } - len = drows.length; i=0; - var rn = parseInt(ts.p.rowNum,10),br=ts.p.scroll?(parseInt(ts.p.page,10)-1)*rn+1:1, altr; - if (adjust) { rn *= adjust+1; } - var afterInsRow = $.isFunction(ts.p.afterInsertRow), grpdata={}, hiderow=""; - if(ts.p.grouping && ts.p.groupingView.groupCollapse === true) { - hiderow = " style=\"display:none;\""; - } - while (i"); - if(ts.p.rownumbers===true) { - rowData.push( addRowNum(0,i,ts.p.page,ts.p.rowNum) ); - ni=1; - } - if(ts.p.multiselect){ - rowData.push( addMulti(idr,ni,i) ); - gi = 1; - } - if (ts.p.subGrid) { - rowData.push( $(ts).jqGrid("addSubGridCell",gi+ni,i+rcnt) ); - si= 1; - } - if (dReader.repeatitems) { - if(dReader.cell) {cur = $.jgrid.getAccessor(cur,dReader.cell);} - if (!F) { F=orderedCols(gi+si+ni); } - } - for (j=0;j" ); - if(ts.p.grouping) { - var grlen = ts.p.groupingView.groupField.length, grpitem = []; - for(var z=0;z -1 ? ts.p.treeANode: 0; - row = $(rowData.join(''))[0]; - $(ts.rows[i+fpos]).after(row); - try {$(ts).jqGrid("setTreeNode",rd,row);} catch (e) {} - } else { - $("#"+$.jgrid.jqID(ts.p.id)+" tbody:first").append(rowData.join('')); - } - if(ts.p.subGrid === true ) { - try { $(ts).jqGrid("addSubGrid",ts.rows[ts.rows.length-1],gi+ni);} catch (_){} - } - if(afterInsRow) {ts.p.afterInsertRow.call(ts,idr,rd,cur);} - rowData=[];//ari=0; - } - rd={}; - ir++; - i++; - if(ir==rn) { break; } - } - if(ts.p.gridview === true ) { - if(ts.p.grouping) { - $(ts).jqGrid('groupingRender',grpdata,ts.p.colModel.length); - grpdata = null; - } else { - $("#"+$.jgrid.jqID(ts.p.id)+" tbody:first").append(rowData.join('')); - } - } - ts.p.totaltime = new Date() - startReq; - if(ir>0) { - if(ts.p.records===0) { ts.p.records=len; } - } - rowData = null; - if(!ts.p.treeGrid && !ts.p.scroll) {ts.grid.bDiv.scrollTop = 0;} - ts.p.reccount=ir; - ts.p.treeANode = -1; - if(ts.p.userDataOnFooter) { $(ts).jqGrid("footerData","set",ts.p.userData,true); } - if(locdata) { - ts.p.records = len; - ts.p.lastpage = Math.ceil(len/ rn); - } - if (!more) { ts.updatepager(false,true); } - if(locdata) { - while (ir0) { - var result = query.select(); - query = $.jgrid.from( result); - } - try{ - for (index = 0; index < group.rules.length; index++) { - rule = group.rules[index]; - opr = group.groupOp.toString().toUpperCase(); - if (compareFnMap[rule.op] && rule.field ) { - if(s > 0 && opr && opr === "OR") { - query = query.or(); - } - query = compareFnMap[rule.op](query, opr)(rule.field, rule.data, cmtypes[rule.field]); - } - s++; - } - } catch (g) {alert(g);} - } - } - - if (ts.p.search === true) { - var srules = ts.p.postData.filters; - if(srules) { - if(typeof srules == "string") { srules = $.jgrid.parse(srules);} - tojLinq( srules ); - } else { - try { - query = compareFnMap[ts.p.postData.searchOper](query)(ts.p.postData.searchField, ts.p.postData.searchString,cmtypes[ts.p.postData.searchField]); - } catch (se){} - } - } - if(ts.p.grouping) { - query.orderBy(grindexes,grpview.groupOrder[0],grtypes[0].stype, grtypes[0].srcfmt); - grpview.groupDataSorted = true; - } - if (st && ts.p.sortorder && fndsort) { - if(ts.p.sortorder.toUpperCase() == "DESC") { - query.orderBy(ts.p.sortname, "d", cmtypes[st].stype, cmtypes[st].srcfmt); - } else { - query.orderBy(ts.p.sortname, "a", cmtypes[st].stype, cmtypes[st].srcfmt); - } - } - var queryResults = query.select(), - recordsperpage = parseInt(ts.p.rowNum,10), - total = queryResults.length, - page = parseInt(ts.p.page,10), - totalpages = Math.ceil(total / recordsperpage), - retresult = {}; - queryResults = queryResults.slice( (page-1)*recordsperpage , page*recordsperpage ); - query = null; - cmtypes = null; - retresult[ts.p.localReader.total] = totalpages; - retresult[ts.p.localReader.page] = page; - retresult[ts.p.localReader.records] = total; - retresult[ts.p.localReader.root] = queryResults; - queryResults = null; - return retresult; - }, - updatepager = function(rn, dnd) { - var cp, last, base, from,to,tot,fmt, pgboxes = ""; - base = parseInt(ts.p.page,10)-1; - if(base < 0) { base = 0; } - base = base*parseInt(ts.p.rowNum,10); - to = base + ts.p.reccount; - if (ts.p.scroll) { - var rows = $("tbody:first > tr:gt(0)", ts.grid.bDiv); - base = to - rows.length; - ts.p.reccount = rows.length; - var rh = rows.outerHeight() || ts.grid.prevRowHeight; - if (rh) { - var top = base * rh; - var height = parseInt(ts.p.records,10) * rh; - $(">div:first",ts.grid.bDiv).css({height : height}).children("div:first").css({height:top,display:top?"":"none"}); - } - ts.grid.bDiv.scrollLeft = ts.grid.hDiv.scrollLeft; - } - pgboxes = ts.p.pager ? ts.p.pager : ""; - pgboxes += ts.p.toppager ? (pgboxes ? "," + ts.p.toppager : ts.p.toppager) : ""; - if(pgboxes) { - fmt = $.jgrid.formatter.integer || {}; - cp = intNum(ts.p.page); - last = intNum(ts.p.lastpage); - $(".selbox",pgboxes).attr("disabled",false); - if(ts.p.pginput===true) { - $('.ui-pg-input',pgboxes).val(ts.p.page); - $('#sp_1',pgboxes).html($.fmatter ? $.fmatter.util.NumberFormat(ts.p.lastpage,fmt):ts.p.lastpage); - - } - if (ts.p.viewrecords){ - if(ts.p.reccount === 0) { - $(".ui-paging-info",pgboxes).html(ts.p.emptyrecords); - } else { - from = base+1; - tot=ts.p.records; - if($.fmatter) { - from = $.fmatter.util.NumberFormat(from,fmt); - to = $.fmatter.util.NumberFormat(to,fmt); - tot = $.fmatter.util.NumberFormat(tot,fmt); - } - $(".ui-paging-info",pgboxes).html($.jgrid.format(ts.p.recordtext,from,to,tot)); - } - } - if(ts.p.pgbuttons===true) { - if(cp<=0) {cp = last = 0;} - if(cp==1 || cp === 0) { - $("#first, #prev",ts.p.pager).addClass('ui-state-disabled').removeClass('ui-state-hover'); - if(ts.p.toppager) { $("#first_t, #prev_t",ts.p.toppager).addClass('ui-state-disabled').removeClass('ui-state-hover'); } - } else { - $("#first, #prev",ts.p.pager).removeClass('ui-state-disabled'); - if(ts.p.toppager) { $("#first_t, #prev_t",ts.p.toppager).removeClass('ui-state-disabled'); } - } - if(cp==last || cp === 0) { - $("#next, #last",ts.p.pager).addClass('ui-state-disabled').removeClass('ui-state-hover'); - if(ts.p.toppager) { $("#next_t, #last_t",ts.p.toppager).addClass('ui-state-disabled').removeClass('ui-state-hover'); } - } else { - $("#next, #last",ts.p.pager).removeClass('ui-state-disabled'); - if(ts.p.toppager) { $("#next_t, #last_t",ts.p.toppager).removeClass('ui-state-disabled'); } - } - } - } - if(rn===true && ts.p.rownumbers === true) { - $("td.jqgrid-rownum",ts.rows).each(function(i){ - $(this).html(base+1+i); - }); - } - if(dnd && ts.p.jqgdnd) { $(ts).jqGrid('gridDnD','updateDnD');} - if($.isFunction(ts.p.gridComplete)) {ts.p.gridComplete.call(ts);} - }, - beginReq = function() { - ts.grid.hDiv.loading = true; - if(ts.p.hiddengrid) { return;} - switch(ts.p.loadui) { - case "disable": - break; - case "enable": - $("#load_"+$.jgrid.jqID(ts.p.id)).show(); - break; - case "block": - $("#lui_"+$.jgrid.jqID(ts.p.id)).show(); - $("#load_"+$.jgrid.jqID(ts.p.id)).show(); - break; - } - }, - endReq = function() { - ts.grid.hDiv.loading = false; - switch(ts.p.loadui) { - case "disable": - break; - case "enable": - $("#load_"+$.jgrid.jqID(ts.p.id)).hide(); - break; - case "block": - $("#lui_"+$.jgrid.jqID(ts.p.id)).hide(); - $("#load_"+$.jgrid.jqID(ts.p.id)).hide(); - break; - } - }, - populate = function (npage) { - if(!ts.grid.hDiv.loading) { - var pvis = ts.p.scroll && npage === false; - var prm = {}, dt, dstr, pN=ts.p.prmNames; - if(ts.p.page <=0) { ts.p.page = 1; } - if(pN.search !== null) {prm[pN.search] = ts.p.search;} if(pN.nd !== null) {prm[pN.nd] = new Date().getTime();} - if(pN.rows !== null) {prm[pN.rows]= ts.p.rowNum;} if(pN.page !== null) {prm[pN.page]= ts.p.page;} - if(pN.sort !== null) {prm[pN.sort]= ts.p.sortname;} if(pN.order !== null) {prm[pN.order]= ts.p.sortorder;} - if(ts.p.rowTotal !== null && pN.totalrows !== null) { prm[pN.totalrows]= ts.p.rowTotal; } - var lc = ts.p.loadComplete; - var lcf = $.isFunction(lc); - if (!lcf) { lc = null; } - var adjust = 0; - npage = npage || 1; - if (npage > 1) { - if(pN.npage !== null) { - prm[pN.npage] = npage; - adjust = npage - 1; - npage = 1; - } else { - lc = function(req) { - ts.p.page++; - ts.grid.hDiv.loading = false; - if (lcf) { - ts.p.loadComplete.call(ts,req); - } - populate(npage-1); - }; - } - } else if (pN.npage !== null) { - delete ts.p.postData[pN.npage]; - } - if(ts.p.grouping) { - $(ts).jqGrid('groupingSetup'); - if(ts.p.groupingView.groupDataSorted === true) { - prm[pN.sort] = ts.p.groupingView.groupField[0] +" "+ ts.p.groupingView.groupOrder[0]+", "+prm[pN.sort]; - } - } - $.extend(ts.p.postData,prm); - var rcnt = !ts.p.scroll ? 1 : ts.rows.length-1; - if ($.isFunction(ts.p.datatype)) { ts.p.datatype.call(ts,ts.p.postData,"load_"+ts.p.id); return;} - else if($.isFunction(ts.p.beforeRequest)) {ts.p.beforeRequest.call(ts);} - dt = ts.p.datatype.toLowerCase(); - switch(dt) - { - case "json": - case "jsonp": - case "xml": - case "script": - $.ajax($.extend({ - url:ts.p.url, - type:ts.p.mtype, - dataType: dt , - data: $.isFunction(ts.p.serializeGridData)? ts.p.serializeGridData.call(ts,ts.p.postData) : ts.p.postData, - success:function(data,st) { - if(dt === "xml") { addXmlData(data,ts.grid.bDiv,rcnt,npage>1,adjust); } - else { addJSONData(data,ts.grid.bDiv,rcnt,npage>1,adjust); } - if(lc) { lc.call(ts,data); } - if (pvis) { ts.grid.populateVisible(); } - if( ts.p.loadonce || ts.p.treeGrid) {ts.p.datatype = "local";} - data=null; - endReq(); - }, - error:function(xhr,st,err){ - if($.isFunction(ts.p.loadError)) { ts.p.loadError.call(ts,xhr,st,err); } - endReq(); - xhr=null; - }, - beforeSend: function(xhr){ - beginReq(); - if($.isFunction(ts.p.loadBeforeSend)) { ts.p.loadBeforeSend.call(ts,xhr); } - } - },$.jgrid.ajaxOptions, ts.p.ajaxGridOptions)); - break; - case "xmlstring": - beginReq(); - dstr = $.jgrid.stringToDoc(ts.p.datastr); - addXmlData(dstr,ts.grid.bDiv); - if(lcf) {ts.p.loadComplete.call(ts,dstr);} - ts.p.datatype = "local"; - ts.p.datastr = null; - endReq(); - break; - case "jsonstring": - beginReq(); - if(typeof ts.p.datastr == 'string') { dstr = $.jgrid.parse(ts.p.datastr); } - else { dstr = ts.p.datastr; } - addJSONData(dstr,ts.grid.bDiv); - if(lcf) {ts.p.loadComplete.call(ts,dstr);} - ts.p.datatype = "local"; - ts.p.datastr = null; - endReq(); - break; - case "local": - case "clientside": - beginReq(); - ts.p.datatype = "local"; - var req = addLocalData(); - addJSONData(req,ts.grid.bDiv,rcnt,npage>1,adjust); - if(lc) { lc.call(ts,req); } - if (pvis) { ts.grid.populateVisible(); } - endReq(); - break; - } - } - }, - setPager = function (pgid, tp){ - // TBD - consider escaping pgid with pgid = $.jgrid.jqID(pgid); - var sep = "", - pginp = "", - pgl="", - str="", pgcnt, lft, cent, rgt, twd, tdw, i, - clearVals = function(onpaging){ - var ret; - if ($.isFunction(ts.p.onPaging) ) { ret = ts.p.onPaging.call(ts,onpaging); } - ts.p.selrow = null; - if(ts.p.multiselect) {ts.p.selarrrow =[];$('#cb_'+$.jgrid.jqID(ts.p.id),ts.grid.hDiv).attr("checked",false);} - ts.p.savedRow = []; - if(ret=='stop') {return false;} - return true; - }; - pgid = pgid.substr(1); - pgcnt = "pg_"+pgid; - lft = pgid+"_left"; cent = pgid+"_center"; rgt = pgid+"_right"; - $("#"+$.jgrid.jqID(pgid) ) - .append("
") - .attr("dir","ltr"); //explicit setting - if(ts.p.rowList.length >0){ - str = ""; - str +=""; - } - if(dir=="rtl") { pgl += str; } - if(ts.p.pginput===true) { pginp= ""+$.jgrid.format(ts.p.pgtext || "","","")+"";} - if(ts.p.pgbuttons===true) { - var po=["first"+tp,"prev"+tp, "next"+tp,"last"+tp]; if(dir=="rtl") { po.reverse(); } - pgl += ""; - pgl += ""; - pgl += pginp !== "" ? sep+pginp+sep:""; - pgl += ""; - pgl += ""; - } else if (pginp !== "") { pgl += pginp; } - if(dir=="ltr") { pgl += str; } - pgl += ""; - if(ts.p.viewrecords===true) {$("td#"+pgid+"_"+ts.p.recordpos,"#"+pgcnt).append("
");} - $("td#"+pgid+"_"+ts.p.pagerpos,"#"+pgcnt).append(pgl); - tdw = $(".ui-jqgrid").css("font-size") || "11px"; - $(document.body).append(""); - twd = $(pgl).clone().appendTo("#testpg").width(); - $("#testpg").remove(); - if(twd > 0) { - if(pginp !== "") { twd += 50; } //should be param - $("td#"+pgid+"_"+ts.p.pagerpos,"#"+pgcnt).width(twd); - } - ts.p._nvtd = []; - ts.p._nvtd[0] = twd ? Math.floor((ts.p.width - twd)/2) : Math.floor(ts.p.width/3); - ts.p._nvtd[1] = 0; - pgl=null; - $('.ui-pg-selbox',"#"+pgcnt).bind('change',function() { - ts.p.page = Math.round(ts.p.rowNum*(ts.p.page-1)/this.value-0.5)+1; - ts.p.rowNum = this.value; - if(tp) { $('.ui-pg-selbox',ts.p.pager).val(this.value); } - else if(ts.p.toppager) { $('.ui-pg-selbox',ts.p.toppager).val(this.value); } - if(!clearVals('records')) { return false; } - populate(); - return false; - }); - if(ts.p.pgbuttons===true) { - $(".ui-pg-button","#"+pgcnt).hover(function(e){ - if($(this).hasClass('ui-state-disabled')) { - this.style.cursor='default'; - } else { - $(this).addClass('ui-state-hover'); - this.style.cursor='pointer'; - } - },function(e) { - if($(this).hasClass('ui-state-disabled')) { - } else { - $(this).removeClass('ui-state-hover'); - this.style.cursor= "default"; - } - }); - $("#first"+tp+", #prev"+tp+", #next"+tp+", #last"+tp,"#"+pgid).click( function(e) { - var cp = intNum(ts.p.page,1), - last = intNum(ts.p.lastpage,1), selclick = false, - fp=true, pp=true, np=true,lp=true; - if(last ===0 || last===1) {fp=false;pp=false;np=false;lp=false; } - else if( last>1 && cp >=1) { - if( cp === 1) { fp=false; pp=false; } - else if( cp>1 && cp 1 && cp===0 ) { np=false;lp=false; cp=last-1;} - if( this.id === 'first'+tp && fp ) { ts.p.page=1; selclick=true;} - if( this.id === 'prev'+tp && pp) { ts.p.page=(cp-1); selclick=true;} - if( this.id === 'next'+tp && np) { ts.p.page=(cp+1); selclick=true;} - if( this.id === 'last'+tp && lp) { ts.p.page=last; selclick=true;} - if(selclick) { - if(!clearVals(this.id)) { return false; } - populate(); - } - return false; - }); - } - if(ts.p.pginput===true) { - $('input.ui-pg-input',"#"+pgcnt).keypress( function(e) { - var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0; - if(key == 13) { - ts.p.page = ($(this).val()>0) ? $(this).val():ts.p.page; - if(!clearVals('user')) { return false; } - populate(); - return false; - } - return this; - }); - } - }, - sortData = function (index, idxcol,reload,sor){ - if(!ts.p.colModel[idxcol].sortable) { return; } - var so; - if(ts.p.savedRow.length > 0) {return;} - if(!reload) { - if( ts.p.lastsort == idxcol ) { - if( ts.p.sortorder == 'asc') { - ts.p.sortorder = 'desc'; - } else if(ts.p.sortorder == 'desc') { ts.p.sortorder = 'asc';} - } else { ts.p.sortorder = ts.p.colModel[idxcol].firstsortorder || 'asc'; } - ts.p.page = 1; - } - if(sor) { - if(ts.p.lastsort == idxcol && ts.p.sortorder == sor && !reload) { return; } - else { ts.p.sortorder = sor; } - } - var thd= $("thead:first",ts.grid.hDiv).get(0); - $("tr th:eq("+ts.p.lastsort+") span.ui-grid-ico-sort",thd).addClass('ui-state-disabled'); - $("tr th:eq("+ts.p.lastsort+")",thd).attr("aria-selected","false"); - $("tr th:eq("+idxcol+") span.ui-icon-"+ts.p.sortorder,thd).removeClass('ui-state-disabled'); - $("tr th:eq("+idxcol+")",thd).attr("aria-selected","true"); - if(!ts.p.viewsortcols[0]) { - if(ts.p.lastsort != idxcol) { - $("tr th:eq("+ts.p.lastsort+") span.s-ico",thd).hide(); - $("tr th:eq("+idxcol+") span.s-ico",thd).show(); - } - } - index = index.substring(5); - ts.p.sortname = ts.p.colModel[idxcol].index || index; - so = ts.p.sortorder; - if($.isFunction(ts.p.onSortCol)) {if (ts.p.onSortCol.call(ts,index,idxcol,so)=='stop') {ts.p.lastsort = idxcol; return;}} - if(ts.p.datatype == "local") { - if(ts.p.deselectAfterSort) {$(ts).jqGrid("resetSelection");} - } else { - ts.p.selrow = null; - if(ts.p.multiselect){$("#cb_"+$.jgrid.jqID(ts.p.id),ts.grid.hDiv).attr("checked",false);} - ts.p.selarrrow =[]; - ts.p.savedRow =[]; - } - if(ts.p.scroll) { - var sscroll = ts.grid.bDiv.scrollLeft; - emptyRows(ts.grid.bDiv,true); - ts.grid.hDiv.scrollLeft = sscroll; - } - if(ts.p.subGrid && ts.p.datatype=='local') { - $("td.sgexpanded","#"+$.jgrid.jqID(ts.p.id)).each(function(){ - $(this).trigger("click"); - }); - } - populate(); - ts.p.lastsort = idxcol; - if(ts.p.sortname != index && idxcol) {ts.p.lastsort = idxcol;} - }, - setColWidth = function () { - var initwidth = 0, brd=ts.p.cellLayout, vc=0, lvc, scw=ts.p.scrollOffset,cw,hs=false,aw,tw=0,gw=0, - cl = 0, cr; - if (isSafari) { brd=0; } - $.each(ts.p.colModel, function(i) { - if(typeof this.hidden === 'undefined') {this.hidden=false;} - if(this.hidden===false){ - initwidth += intNum(this.width,0); - if(this.fixed) { - tw += this.width; - gw += this.width+brd; - } else { - vc++; - } - cl++; - } - }); - if (ts.p.shrinkToFit === false) {initwidth += brd*cl;} - if(isNaN(ts.p.width)) {ts.p.width = grid.width = initwidth;} - else { grid.width = ts.p.width;} - ts.p.tblwidth = initwidth; - if(ts.p.shrinkToFit ===false && ts.p.forceFit === true) {ts.p.forceFit=false;} - if(ts.p.shrinkToFit===true && vc > 0) { - aw = grid.width-brd*vc-gw; - if(isNaN(ts.p.height)) { - } else { - aw -= scw; - hs = true; - } - initwidth =0; - $.each(ts.p.colModel, function(i) { - if(this.hidden === false && !this.fixed){ - cw = Math.round(aw*this.width/(ts.p.tblwidth-tw)); - this.width =cw; - initwidth += cw; - lvc = i; - } - }); - cr =0; - if (hs) { - if(grid.width-gw-(initwidth+brd*vc) !== scw){ - cr = grid.width-gw-(initwidth+brd*vc)-scw; - } - } else if(!hs && Math.abs(grid.width-gw-(initwidth+brd*vc)) !== 1) { - cr = grid.width-gw-(initwidth+brd*vc); - } - ts.p.colModel[lvc].width += cr; - ts.p.tblwidth = initwidth+cr+tw+cl*brd; - if(ts.p.tblwidth > ts.p.width) { - ts.p.colModel[lvc].width -= (ts.p.tblwidth - parseInt(ts.p.width,10)); - ts.p.tblwidth = ts.p.width; - } - } - }, - nextVisible= function(iCol) { - var ret = iCol, j=iCol, i; - for (i = iCol+1;i"); - this.p.colModel.unshift({name:'cb',width:isSafari ? ts.p.multiselectWidth+ts.p.cellLayout : ts.p.multiselectWidth,sortable:false,resizable:false,hidedlg:true,search:false,align:'center',fixed:true}); - } - if(this.p.rownumbers) { - this.p.colNames.unshift(""); - this.p.colModel.unshift({name:'rn',width:ts.p.rownumWidth,sortable:false,resizable:false,hidedlg:true,search:false,align:'center',fixed:true}); - } - ts.p.xmlReader = $.extend(true,{ - root: "rows", - row: "row", - page: "rows>page", - total: "rows>total", - records : "rows>records", - repeatitems: true, - cell: "cell", - id: "[id]", - userdata: "userdata", - subgrid: {root:"rows", row: "row", repeatitems: true, cell:"cell"} - }, ts.p.xmlReader); - ts.p.jsonReader = $.extend(true,{ - root: "rows", - page: "page", - total: "total", - records: "records", - repeatitems: true, - cell: "cell", - id: "id", - userdata: "userdata", - subgrid: {root:"rows", repeatitems: true, cell:"cell"} - },ts.p.jsonReader); - ts.p.localReader = $.extend(true,{ - root: "rows", - page: "page", - total: "total", - records: "records", - repeatitems: false, - cell: "cell", - id: "id", - userdata: "userdata", - subgrid: {root:"rows", repeatitems: true, cell:"cell"} - },ts.p.localReader); - if(ts.p.scroll){ - ts.p.pgbuttons = false; ts.p.pginput=false; ts.p.rowList=[]; - } - if(ts.p.data.length) { refreshIndex(); } - var thead = "", - tdc, idn, w, res, sort, - td, ptr, tbody, imgs,iac="",idc=""; - if(ts.p.shrinkToFit===true && ts.p.forceFit===true) { - for (i=ts.p.colModel.length-1;i>=0;i--){ - if(!ts.p.colModel[i].hidden) { - ts.p.colModel[i].resizable=false; - break; - } - } - } - if(ts.p.viewsortcols[1] == 'horizontal') {iac=" ui-i-asc";idc=" ui-i-desc";} - tdc = isMSIE ? "class='ui-th-div-ie'" :""; - imgs = ""; - for(i=0;i"; - idn = ts.p.colModel[i].index || ts.p.colModel[i].name; - thead += "
"+ts.p.colNames[i]; - if(!ts.p.colModel[i].width) { ts.p.colModel[i].width = 150; } - else { ts.p.colModel[i].width = parseInt(ts.p.colModel[i].width,10); } - if(typeof(ts.p.colModel[i].title) !== "boolean") { ts.p.colModel[i].title = true; } - if (idn == ts.p.sortname) { - ts.p.lastsort = i; - } - thead += imgs+"
"; - } - thead += ""; - imgs = null; - $(this).append(thead); - $("thead tr:first th",this).hover(function(){$(this).addClass('ui-state-hover');},function(){$(this).removeClass('ui-state-hover');}); - if(this.p.multiselect) { - var emp=[], chk; - $('#cb_'+$.jgrid.jqID(ts.p.id),this).bind('click',function(){ - ts.p.selarrrow = []; - if (this.checked) { - $("[id^=jqg_"+ts.p.id+"_"+"]").attr("checked","checked"); - $(ts.rows).each(function(i) { - if ( i>0 ) { - if(!$(this).hasClass("subgrid") && !$(this).hasClass("jqgroup")){ - $(this).addClass("ui-state-highlight").attr("aria-selected","true"); - ts.p.selarrrow.push(this.id); - ts.p.selrow = this.id; - } - } - }); - chk=true; - emp=[]; - } - else { - $("[id^=jqg_"+ts.p.id+"_"+"]").removeAttr("checked"); - $(ts.rows).each(function(i) { - if(i>0) { - if(!$(this).hasClass("subgrid")){ - $(this).removeClass("ui-state-highlight").attr("aria-selected","false"); - emp.push(this.id); - } - } - }); - ts.p.selrow = null; - chk=false; - } - if($.isFunction(ts.p.onSelectAll)) {ts.p.onSelectAll.call(ts, chk ? ts.p.selarrrow : emp,chk);} - }); - } - - if(ts.p.autowidth===true) { - var pw = $(eg).innerWidth(); - ts.p.width = pw > 0? pw: 'nw'; - } - setColWidth(); - $(eg).css("width",grid.width+"px").append("
 
"); - $(gv).css("width",grid.width+"px"); - thead = $("thead:first",ts).get(0); - var tfoot = ""; - if(ts.p.footerrow) { tfoot += ""; } - var thr = $("tr:first",thead), - firstr = ""; - ts.p.disableClick=false; - $("th",thr).each(function ( j ) { - w = ts.p.colModel[j].width; - if(typeof ts.p.colModel[j].resizable === 'undefined') {ts.p.colModel[j].resizable = true;} - if(ts.p.colModel[j].resizable){ - res = document.createElement("span"); - $(res).html(" ").addClass('ui-jqgrid-resize ui-jqgrid-resize-'+dir); - if(!$.browser.opera) { $(res).css("cursor","col-resize"); } - $(this).addClass(ts.p.resizeclass); - } else { - res = ""; - } - $(this).css("width",w+"px").prepend(res); - var hdcol = ""; - if( ts.p.colModel[j].hidden ) { - $(this).css("display","none"); - hdcol = "display:none;"; - } - firstr += ""; - grid.headers[j] = { width: w, el: this }; - sort = ts.p.colModel[j].sortable; - if( typeof sort !== 'boolean') {ts.p.colModel[j].sortable = true; sort=true;} - var nm = ts.p.colModel[j].name; - if( !(nm == 'cb' || nm=='subgrid' || nm=='rn') ) { - if(ts.p.viewsortcols[2]){ - $("div",this).addClass('ui-jqgrid-sortable'); - } - } - if(sort) { - if(ts.p.viewsortcols[0]) {$("div span.s-ico",this).show(); if(j==ts.p.lastsort){ $("div span.ui-icon-"+ts.p.sortorder,this).removeClass("ui-state-disabled");}} - else if( j == ts.p.lastsort) {$("div span.s-ico",this).show();$("div span.ui-icon-"+ts.p.sortorder,this).removeClass("ui-state-disabled");} - } - if(ts.p.footerrow) { tfoot += ""; } - }).mousedown(function(e) { - if ($(e.target).closest("th>span.ui-jqgrid-resize").length != 1) { return; } - var ci = $.jgrid.getCellIndex(this); - if(ts.p.forceFit===true) {ts.p.nv= nextVisible(ci);} - grid.dragStart(ci, e, getOffset(ci)); - return false; - }).click(function(e) { - if (ts.p.disableClick) { - ts.p.disableClick = false; - return false; - } - var s = "th>div.ui-jqgrid-sortable",r,d; - if (!ts.p.viewsortcols[2]) { s = "th>div>span>span.ui-grid-ico-sort"; } - var t = $(e.target).closest(s); - if (t.length != 1) { return; } - var ci = $.jgrid.getCellIndex(this); - if (!ts.p.viewsortcols[2]) { r=true;d=t.attr("sort"); } - sortData( $('div',this)[0].id, ci, r, d); - return false; - }); - if (ts.p.sortable && $.fn.sortable) { - try { - $(ts).jqGrid("sortableColumns", thr); - } catch (e){} - } - if(ts.p.footerrow) { tfoot += "
 
"; } - firstr += ""; - tbody = document.createElement("tbody"); - this.appendChild(tbody); - $(this).addClass('ui-jqgrid-btable').append(firstr); - firstr = null; - var hTable = $("
").append(thead), - hg = (ts.p.caption && ts.p.hiddengrid===true) ? true : false, - hb = $("
"); - thead = null; - grid.hDiv = document.createElement("div"); - $(grid.hDiv) - .css({ width: grid.width+"px"}) - .addClass("ui-state-default ui-jqgrid-hdiv") - .append(hb); - $(hb).append(hTable); - hTable = null; - if(hg) { $(grid.hDiv).hide(); } - if(ts.p.pager){ - // TBD -- escape ts.p.pager here? - if(typeof ts.p.pager == "string") {if(ts.p.pager.substr(0,1) !="#") { ts.p.pager = "#"+ts.p.pager;} } - else { ts.p.pager = "#"+ $(ts.p.pager).attr("id");} - $(ts.p.pager).css({width: grid.width+"px"}).appendTo(eg).addClass('ui-state-default ui-jqgrid-pager ui-corner-bottom'); - if(hg) {$(ts.p.pager).hide();} - setPager(ts.p.pager,''); - } - if( ts.p.cellEdit === false && ts.p.hoverrows === true) { - $(ts).bind('mouseover',function(e) { - ptr = $(e.target).closest("tr.jqgrow"); - if($(ptr).attr("class") !== "subgrid") { - $(ptr).addClass("ui-state-hover"); - } - return false; - }).bind('mouseout',function(e) { - ptr = $(e.target).closest("tr.jqgrow"); - $(ptr).removeClass("ui-state-hover"); - return false; - }); - } - var ri,ci; - $(ts).before(grid.hDiv).click(function(e) { - td = e.target; - var scb = $(td).hasClass("cbox"); - ptr = $(td,ts.rows).closest("tr.jqgrow"); - if($(ptr).length === 0 ) { - return this; - } - var cSel = true; - if($.isFunction(ts.p.beforeSelectRow)) { cSel = ts.p.beforeSelectRow.call(ts,ptr[0].id, e); } - if (td.tagName == 'A' || ((td.tagName == 'INPUT' || td.tagName == 'TEXTAREA' || td.tagName == 'OPTION' || td.tagName == 'SELECT' ) && !scb) ) { return this; } - if(cSel === true) { - if(ts.p.cellEdit === true) { - if(ts.p.multiselect && scb){ - $(ts).jqGrid("setSelection",ptr[0].id,true); - } else { - ri = ptr[0].rowIndex; - ci = $.jgrid.getCellIndex(td); - try {$(ts).jqGrid("editCell",ri,ci,true);} catch (_) {} - } - } else if ( !ts.p.multikey ) { - if(ts.p.multiselect && ts.p.multiboxonly) { - if(scb){$(ts).jqGrid("setSelection",ptr[0].id,true);} - else { - $(ts.p.selarrrow).each(function(i,n){ - var ind = ts.rows.namedItem(n); - $(ind).removeClass("ui-state-highlight"); - $("#jqg_"+$.jgrid.jqID(ts.p.id)+"_"+$.jgrid.jqID(n)).attr("checked",false); - }); - ts.p.selarrrow = []; - $("#cb_"+$.jgrid.jqID(ts.p.id),ts.grid.hDiv).attr("checked",false); - $(ts).jqGrid("setSelection",ptr[0].id,true); - } - } else { - $(ts).jqGrid("setSelection",ptr[0].id,true); - } - } else { - if(e[ts.p.multikey]) { - $(ts).jqGrid("setSelection",ptr[0].id,true); - } else if(ts.p.multiselect && scb) { - scb = $("[id^=jqg_"+ts.p.id+"_"+"]").attr("checked"); - $("[id^=jqg_"+ts.p.id+"_"+"]").attr("checked",!scb); - } - } - if($.isFunction(ts.p.onCellSelect)) { - ri = ptr[0].id; - ci = $.jgrid.getCellIndex(td); - ts.p.onCellSelect.call(ts,ri,ci,$(td).html(),e); - } - e.stopPropagation(); - } else { - return this; - } - }).bind('reloadGrid', function(e,opts) { - if(ts.p.treeGrid ===true) { ts.p.datatype = ts.p.treedatatype;} - if (opts && opts.current) { - ts.grid.selectionPreserver(ts); - } - if(ts.p.datatype=="local"){ $(ts).jqGrid("resetSelection"); if(ts.p.data.length) { refreshIndex();} } - else if(!ts.p.treeGrid) { - ts.p.selrow=null; - if(ts.p.multiselect) {ts.p.selarrrow =[];$('#cb_'+$.jgrid.jqID(ts.p.id),ts.grid.hDiv).attr("checked",false);} - ts.p.savedRow = []; - } - if(ts.p.scroll) {emptyRows(ts.grid.bDiv,true);} - if (opts && opts.page) { - var page = opts.page; - if (page > ts.p.lastpage) { page = ts.p.lastpage; } - if (page < 1) { page = 1; } - ts.p.page = page; - if (ts.grid.prevRowHeight) { - ts.grid.bDiv.scrollTop = (page - 1) * ts.grid.prevRowHeight * ts.p.rowNum; - } else { - ts.grid.bDiv.scrollTop = 0; - } - } - if (ts.grid.prevRowHeight && ts.p.scroll) { - delete ts.p.lastpage; - ts.grid.populateVisible(); - } else { - ts.grid.populate(); - } - return false; - }); - if( $.isFunction(this.p.ondblClickRow) ) { - $(this).dblclick(function(e) { - td = e.target; - ptr = $(td,ts.rows).closest("tr.jqgrow"); - if($(ptr).length === 0 ){return false;} - ri = ptr[0].rowIndex; - ci = $.jgrid.getCellIndex(td); - ts.p.ondblClickRow.call(ts,$(ptr).attr("id"),ri,ci, e); - return false; - }); - } - if ($.isFunction(this.p.onRightClickRow)) { - $(this).bind('contextmenu', function(e) { - td = e.target; - ptr = $(td,ts.rows).closest("tr.jqgrow"); - if($(ptr).length === 0 ){return false;} - if(!ts.p.multiselect) { $(ts).jqGrid("setSelection",ptr[0].id,true); } - ri = ptr[0].rowIndex; - ci = $.jgrid.getCellIndex(td); - ts.p.onRightClickRow.call(ts,$(ptr).attr("id"),ri,ci, e); - return false; - }); - } - grid.bDiv = document.createElement("div"); - $(grid.bDiv) - .append($('
').append('
').append(this)) - .addClass("ui-jqgrid-bdiv") - .css({ height: ts.p.height+(isNaN(ts.p.height)?"":"px"), width: (grid.width)+"px"}) - .scroll(grid.scrollGrid); - $("table:first",grid.bDiv).css({width:ts.p.tblwidth+"px"}); - if( isMSIE ) { - if( $("tbody",this).size() == 2 ) { $("tbody:gt(0)",this).remove();} - if( ts.p.multikey) {$(grid.bDiv).bind("selectstart",function(){return false;});} - } else { - if( ts.p.multikey) {$(grid.bDiv).bind("mousedown",function(){return false;});} - } - if(hg) {$(grid.bDiv).hide();} - grid.cDiv = document.createElement("div"); - var arf = ts.p.hidegrid===true ? $("").addClass('ui-jqgrid-titlebar-close HeaderButton').hover( - function(){ arf.addClass('ui-state-hover');}, - function() {arf.removeClass('ui-state-hover');}) - .append("").css((dir=="rtl"?"left":"right"),"0px") : ""; - $(grid.cDiv).append(arf).append(""+ts.p.caption+"") - .addClass("ui-jqgrid-titlebar ui-widget-header ui-corner-top ui-helper-clearfix"); - $(grid.cDiv).insertBefore(grid.hDiv); - if( ts.p.toolbar[0] ) { - grid.uDiv = document.createElement("div"); - if(ts.p.toolbar[1] == "top") {$(grid.uDiv).insertBefore(grid.hDiv);} - else if (ts.p.toolbar[1]=="bottom" ) {$(grid.uDiv).insertAfter(grid.hDiv);} - if(ts.p.toolbar[1]=="both") { - grid.ubDiv = document.createElement("div"); - $(grid.uDiv).insertBefore(grid.hDiv).addClass("ui-userdata ui-state-default").attr("id","t_"+this.id); - $(grid.ubDiv).insertAfter(grid.hDiv).addClass("ui-userdata ui-state-default").attr("id","tb_"+this.id); - if(hg) {$(grid.ubDiv).hide();} - } else { - $(grid.uDiv).width(grid.width).addClass("ui-userdata ui-state-default").attr("id","t_"+this.id); - } - if(hg) {$(grid.uDiv).hide();} - } - if(ts.p.toppager) { - ts.p.toppager = $.jgrid.jqID(ts.p.id)+"_toppager"; - grid.topDiv = $("
")[0]; - ts.p.toppager = "#"+ts.p.toppager; - $(grid.topDiv).insertBefore(grid.hDiv).addClass('ui-state-default ui-jqgrid-toppager').width(grid.width); - setPager(ts.p.toppager,'_t'); - } - if(ts.p.footerrow) { - grid.sDiv = $("
")[0]; - hb = $("
"); - $(grid.sDiv).append(hb).insertAfter(grid.hDiv).width(grid.width); - $(hb).append(tfoot); - grid.footers = $(".ui-jqgrid-ftable",grid.sDiv)[0].rows[0].cells; - if(ts.p.rownumbers) { grid.footers[0].className = 'ui-state-default jqgrid-rownum'; } - if(hg) {$(grid.sDiv).hide();} - } - hb = null; - if(ts.p.caption) { - var tdt = ts.p.datatype; - if(ts.p.hidegrid===true) { - $(".ui-jqgrid-titlebar-close",grid.cDiv).click( function(e){ - var onHdCl = $.isFunction(ts.p.onHeaderClick), - elems = ".ui-jqgrid-bdiv, .ui-jqgrid-hdiv, .ui-jqgrid-pager, .ui-jqgrid-sdiv", - counter, self = this; - if(ts.p.toolbar[0]===true) { - if( ts.p.toolbar[1]=='both') { - elems += ', #' + $(grid.ubDiv).attr('id'); - } - elems += ', #' + $(grid.uDiv).attr('id'); - } - counter = $(elems,"#gview_"+$.jgrid.jqID(ts.p.id)).length; - - if(ts.p.gridstate == 'visible') { - $(elems,"#gbox_"+$.jgrid.jqID(ts.p.id)).slideUp("fast", function() { - counter--; - if (counter === 0) { - $("span",self).removeClass("ui-icon-circle-triangle-n").addClass("ui-icon-circle-triangle-s"); - ts.p.gridstate = 'hidden'; - if($("#gbox_"+$.jgrid.jqID(ts.p.id)).hasClass("ui-resizable")) { $(".ui-resizable-handle","#gbox_"+$.jgrid.jqID(ts.p.id)).hide(); } - if(onHdCl) {if(!hg) {ts.p.onHeaderClick.call(ts,ts.p.gridstate,e);}} - } - }); - } else if(ts.p.gridstate == 'hidden'){ - $(elems,"#gbox_"+$.jgrid.jqID(ts.p.id)).slideDown("fast", function() { - counter--; - if (counter === 0) { - $("span",self).removeClass("ui-icon-circle-triangle-s").addClass("ui-icon-circle-triangle-n"); - if(hg) {ts.p.datatype = tdt;populate();hg=false;} - ts.p.gridstate = 'visible'; - if($("#gbox_"+$.jgrid.jqID(ts.p.id)).hasClass("ui-resizable")) { $(".ui-resizable-handle","#gbox_"+$.jgrid.jqID(ts.p.id)).show(); } - if(onHdCl) {if(!hg) {ts.p.onHeaderClick.call(ts,ts.p.gridstate,e);}} - } - }); - } - return false; - }); - if(hg) {ts.p.datatype="local"; $(".ui-jqgrid-titlebar-close",grid.cDiv).trigger("click");} - } - } else {$(grid.cDiv).hide();} - $(grid.hDiv).after(grid.bDiv) - .mousemove(function (e) { - if(grid.resizing){grid.dragMove(e);return false;} - }); - $(".ui-jqgrid-labels",grid.hDiv).bind("selectstart", function () { return false; }); - $(document).mouseup(function (e) { - if(grid.resizing) { grid.dragEnd(); return false;} - return true; - }); - ts.formatCol = formatCol; - ts.sortData = sortData; - ts.updatepager = updatepager; - ts.refreshIndex = refreshIndex; - ts.formatter = function ( rowId, cellval , colpos, rwdat, act){return formatter(rowId, cellval , colpos, rwdat, act);}; - $.extend(grid,{populate : populate, emptyRows: emptyRows}); - this.grid = grid; - ts.addXmlData = function(d) {addXmlData(d,ts.grid.bDiv);}; - ts.addJSONData = function(d) {addJSONData(d,ts.grid.bDiv);}; - this.grid.cols = this.rows[0].cells; - - populate();ts.p.hiddengrid=false; - $(window).unload(function () { - ts = null; - }); - }); -}; -$.jgrid.extend({ - getGridParam : function(pName) { - var $t = this[0]; - if (!$t || !$t.grid) {return;} - if (!pName) { return $t.p; } - else {return typeof($t.p[pName]) != "undefined" ? $t.p[pName] : null;} - }, - setGridParam : function (newParams){ - return this.each(function(){ - if (this.grid && typeof(newParams) === 'object') {$.extend(true,this.p,newParams);} - }); - }, - getDataIDs : function () { - var ids=[], i=0, len, j=0; - this.each(function(){ - len = this.rows.length; - if(len && len>0){ - while(i= ch+st) { $($t.grid.bDiv)[0].scrollTop = rpos-(ch+st)+rh+st; } - else if(rpos < ch+st) { - if(rpos < st) { - $($t.grid.bDiv)[0].scrollTop = rpos; - } - } - } - if($t.p.scrollrows===true) { - ner = $t.rows.namedItem(selection).rowIndex; - if(ner >=0 ){ - scrGrid(ner); - } - } - if(!$t.p.multiselect) { - if(pt.className !== "ui-subgrid") { - if( $t.p.selrow ) { - $($t.rows.namedItem($t.p.selrow)).removeClass("ui-state-highlight").attr("aria-selected","false"); - } - if( $t.p.selrow != pt.id) { - $t.p.selrow = pt.id; - $(pt).addClass("ui-state-highlight").attr("aria-selected","true"); - stat = true; - } else { - stat = false; - $t.p.selrow = null; - } - if( $t.p.onSelectRow && onsr) { $t.p.onSelectRow.call($t, pt.id, stat); } - } - } else { - $t.p.selrow = pt.id; - ia = $.inArray($t.p.selrow,$t.p.selarrrow); - if ( ia === -1 ){ - if(pt.className !== "ui-subgrid") { $(pt).addClass("ui-state-highlight").attr("aria-selected","true");} - stat = true; - $("#jqg_"+$.jgrid.jqID($t.p.id)+"_"+$.jgrid.jqID($t.p.selrow)).attr("checked",stat); - $t.p.selarrrow.push($t.p.selrow); - } else { - if(pt.className !== "ui-subgrid") { $(pt).removeClass("ui-state-highlight").attr("aria-selected","false");} - stat = false; - $("#jqg_"+$.jgrid.jqID($t.p.id)+"_"+$.jgrid.jqID($t.p.selrow)).attr("checked",stat); - $t.p.selarrrow.splice(ia,1); - tpsr = $t.p.selarrrow[0]; - $t.p.selrow = (tpsr === undefined) ? null : tpsr; - } - if( $t.p.onSelectRow && onsr) { $t.p.onSelectRow.call($t, pt.id , stat); } - } - }); - }, - resetSelection : function(){ - return this.each(function(){ - var t = this, ind; - if(!t.p.multiselect) { - if(t.p.selrow) { - $("#"+$.jgrid.jqID(t.p.id)+" tbody:first tr#"+$.jgrid.jqID(t.p.selrow)).removeClass("ui-state-highlight").attr("aria-selected","false"); - t.p.selrow = null; - } - } else { - $(t.p.selarrrow).each(function(i,n){ - ind = t.rows.namedItem(n); - $(ind).removeClass("ui-state-highlight").attr("aria-selected","false"); - $("#jqg_"+$.jgrid.jqID(t.p.id)+"_"+$.jgrid.jqID(n)).attr("checked",false); - }); - $("#cb_"+$.jgrid.jqID(t.p.id)).attr("checked",false); - t.p.selarrrow = []; - } - t.p.savedRow = []; - }); - }, - getRowData : function( rowid ) { - var res = {}, resall, getall=false, len, j=0; - this.each(function(){ - var $t = this,nm,ind; - if(typeof(rowid) == 'undefined') { - getall = true; - resall = []; - len = $t.rows.length; - } else { - ind = $t.rows.namedItem(rowid); - if(!ind) { return res; } - len = 2; - } - while(j span:first",ind).html(vl).attr(title); - } else { - $("td:eq("+i+")",ind).html(vl).attr(title); - } - } - }); - if(t.p.datatype == 'local') { - var pos = t.p._index[rowid]; - if(typeof(pos) != 'undefined') { - t.p.data[pos] = $.extend(true, t.p.data[pos], lcdata); - } - lcdata = null; - } - } catch (e) { - success = false; - } - } - if(success) { - if(cp === 'string') {$(ind).addClass(cssp);} else if(cp === 'object') {$(ind).css(cssp);} - } - }); - return success; - }, - addRowData : function(rowid,rdata,pos,src) { - if(!pos) {pos = "last";} - var success = false, nm, row, gi, si, ni,sind, i, v, prp="", aradd, cnm, cn, data, cm; - if(rdata) { - if($.isArray(rdata)) { - aradd=true; - pos = "last"; - cnm = rowid; - } else { - rdata = [rdata]; - aradd = false; - } - this.each(function() { - var t = this, datalen = rdata.length; - ni = t.p.rownumbers===true ? 1 :0; - gi = t.p.multiselect ===true ? 1 :0; - si = t.p.subGrid===true ? 1 :0; - if(!aradd) { - if(typeof(rowid) != 'undefined') { rowid = rowid+"";} - else { - rowid = (t.p.records+1)+""; - if(t.p.keyIndex !== false) { - cnm = t.p.colModel[t.p.keyIndex+gi+si+ni].name; - if(typeof rdata[0][cnm] != "undefined") { rowid = rdata[0][cnm]; } - } - } - } - cn = t.p.altclass; - var k = 0, cna ="", lcdata = {}, - air = $.isFunction(t.p.afterInsertRow) ? true : false; - while(k < datalen) { - data = rdata[k]; - row=""; - if(aradd) { - try {rowid = data[cnm];} - catch (e) {rowid = (t.p.records+1)+"";} - cna = t.p.altRows === true ? (t.rows.length-1)%2 === 0 ? cn : "" : ""; - } - if(ni){ - prp = t.formatCol(0,1,'',null,rowid, true); - row += "0"; - } - if(gi) { - v = ""; - prp = t.formatCol(ni,1,'', null, rowid, true); - row += ""+v+""; - } - if(si) { - row += $(t).jqGrid("addSubGridCell",gi+ni,1); - } - for(i = gi+si+ni; i < t.p.colModel.length;i++){ - cm = t.p.colModel[i]; - nm = cm.name; - lcdata[nm] = cm.formatter && typeof(cm.formatter) === 'string' && cm.formatter == 'date' ? $.unformat.date(data[nm],cm) : data[nm]; - v = t.formatter( rowid, $.jgrid.getAccessor(data,nm), i, data, 'edit'); - prp = t.formatCol(i,1,v, rowid, data, true); - row += ""+v+""; - } - row = "" + row+""; - if(t.p.subGrid===true) { - row = $(row)[0]; - $(t).jqGrid("addSubGrid",row,gi+ni); - } - if(t.rows.length === 0){ - $("table:first",t.grid.bDiv).append(row); - } else { - switch (pos) { - case 'last': - $(t.rows[t.rows.length-1]).after(row); - break; - case 'first': - $(t.rows[0]).after(row); - break; - case 'after': - sind = t.rows.namedItem(src); - if (sind) { - if($(t.rows[sind.rowIndex+1]).hasClass("ui-subgrid")) { $(t.rows[sind.rowIndex+1]).after(row); } - else { $(sind).after(row); } - } - break; - case 'before': - sind = t.rows.namedItem(src); - if(sind) {$(sind).before(row);sind=sind.rowIndex;} - break; - } - } - t.p.records++; - t.p.reccount++; - if(air) { t.p.afterInsertRow.call(t,rowid,data,data); } - k++; - if(t.p.datatype == 'local') { - t.p._index[rowid] = t.p.data.length; - t.p.data.push(lcdata); - lcdata = {}; - } - } - if( t.p.altRows === true && !aradd) { - if (pos == "last") { - if ((t.rows.length-1)%2 == 1) {$(t.rows[t.rows.length-1]).addClass(cn);} - } else { - $(t.rows).each(function(i){ - if(i % 2 ==1) { $(this).addClass(cn); } - else { $(this).removeClass(cn); } - }); - } - } - t.updatepager(true,true); - success = true; - }); - } - return success; - }, - footerData : function(action,data, format) { - var nm, success=false, res={}, title; - function isEmpty(obj) { - for(var i in obj) { - if (obj.hasOwnProperty(i)) { return false; } - } - return true; - } - if(typeof(action) == "undefined") { action = "get"; } - if(typeof(format) != "boolean") { format = true; } - action = action.toLowerCase(); - this.each(function(){ - var t = this, vl; - if(!t.grid || !t.p.footerrow) {return false;} - if(action == "set") { if(isEmpty(data)) { return false; } } - success=true; - $(this.p.colModel).each(function(i){ - nm = this.name; - if(action == "set") { - if( data[nm] !== undefined) { - vl = format ? t.formatter( "", data[nm], i, data, 'edit') : data[nm]; - title = this.title ? {"title":$.jgrid.stripHtml(vl)} : {}; - $("tr.footrow td:eq("+i+")",t.grid.sDiv).html(vl).attr(title); - success = true; - } - } else if(action == "get") { - res[nm] = $("tr.footrow td:eq("+i+")",t.grid.sDiv).html(); - } - }); - }); - return action == "get" ? res : success; - }, - ShowHideCol : function(colname,show) { - return this.each(function() { - var $t = this, fndh=false; - if (!$t.grid ) {return;} - if( typeof colname === 'string') {colname=[colname];} - show = show != "none" ? "" : "none"; - var sw = show === "" ? true :false; - $(this.p.colModel).each(function(i) { - if ($.inArray(this.name,colname) !== -1 && this.hidden === sw) { - $("tr",$t.grid.hDiv).each(function(){ - $(this).children("th:eq("+i+")").css("display",show); - }); - $($t.rows).each(function(j){ - $(this).children("td:eq("+i+")").css("display",show); - }); - if($t.p.footerrow) { $($t.grid.sDiv).children("td:eq("+i+")").css("display", show); } - if(show == "none") { $t.p.tblwidth -= this.width+$t.p.cellLayout;} else {$t.p.tblwidth += this.width;} - this.hidden = !sw; - fndh=true; - } - }); - if(fndh===true) { - $("table:first",$t.grid.hDiv).width($t.p.tblwidth); - $("table:first",$t.grid.bDiv).width($t.p.tblwidth); - $t.grid.hDiv.scrollLeft = $t.grid.bDiv.scrollLeft; - if($t.p.footerrow) { - $("table:first",$t.grid.sDiv).width($t.p.tblwidth); - $t.grid.sDiv.scrollLeft = $t.grid.bDiv.scrollLeft; - } - if($t.p.shrinkToFit===true) { - $($t).jqGrid("setGridWidth",$t.grid.width-0.001,true); - } - } - }); - }, - hideCol : function (colname) { - return this.each(function(){$(this).jqGrid("ShowHideCol",colname,"none");}); - }, - showCol : function(colname) { - return this.each(function(){$(this).jqGrid("ShowHideCol",colname,"");}); - }, - remapColumns : function(permutation, updateCells, keepHeader) - { - function resortArray(a) { - var ac; - if (a.length) { - ac = $.makeArray(a); - } else { - ac = $.extend({}, a); - } - $.each(permutation, function(i) { - a[i] = ac[this]; - }); - } - var ts = this.get(0); - function resortRows(parent, clobj) { - $(">tr"+(clobj||""), parent).each(function() { - var row = this; - var elems = $.makeArray(row.cells); - $.each(permutation, function() { - var e = elems[this]; - if (e) { - row.appendChild(e); - } - }); - }); - } - resortArray(ts.p.colModel); - resortArray(ts.p.colNames); - resortArray(ts.grid.headers); - resortRows($("thead:first", ts.grid.hDiv), keepHeader && ":not(.ui-jqgrid-labels)"); - if (updateCells) { - resortRows($("#"+$.jgrid.jqID(ts.p.id)+" tbody:first"), ".jqgfirstrow, tr.jqgrow, tr.jqfoot"); - } - if (ts.p.footerrow) { - resortRows($("tbody:first", ts.grid.sDiv)); - } - if (ts.p.remapColumns) { - if (!ts.p.remapColumns.length){ - ts.p.remapColumns = $.makeArray(permutation); - } else { - resortArray(ts.p.remapColumns); - } - } - ts.p.lastsort = $.inArray(ts.p.lastsort, permutation); - if(ts.p.treeGrid) { ts.p.expColInd = $.inArray(ts.p.expColInd, permutation); } - }, - setGridWidth : function(nwidth, shrink) { - return this.each(function(){ - if (!this.grid ) {return;} - var $t = this, cw, - initwidth = 0, brd=$t.p.cellLayout, lvc, vc=0, hs=false, scw=$t.p.scrollOffset, aw, gw=0, tw=0, - cl = 0,cr; - if(typeof shrink != 'boolean') { - shrink=$t.p.shrinkToFit; - } - if(isNaN(nwidth)) {return;} - else { nwidth = parseInt(nwidth,10); $t.grid.width = $t.p.width = nwidth;} - $("#gbox_"+$.jgrid.jqID($t.p.id)).css("width",nwidth+"px"); - $("#gview_"+$.jgrid.jqID($t.p.id)).css("width",nwidth+"px"); - $($t.grid.bDiv).css("width",nwidth+"px"); - $($t.grid.hDiv).css("width",nwidth+"px"); - if($t.p.pager ) {$($t.p.pager).css("width",nwidth+"px");} - if($t.p.toppager ) {$($t.p.toppager).css("width",nwidth+"px");} - if($t.p.toolbar[0] === true){ - $($t.grid.uDiv).css("width",nwidth+"px"); - if($t.p.toolbar[1]=="both") {$($t.grid.ubDiv).css("width",nwidth+"px");} - } - if($t.p.footerrow) { $($t.grid.sDiv).css("width",nwidth+"px"); } - if(shrink ===false && $t.p.forceFit === true) {$t.p.forceFit=false;} - if(shrink===true) { - if ($.browser.safari) { brd=0;} - $.each($t.p.colModel, function(i) { - if(this.hidden===false){ - initwidth += parseInt(this.width,10); - if(this.fixed) { - tw += this.width; - gw += this.width+brd; - } else { - vc++; - } - cl++; - } - }); - if(vc === 0) { return; } - $t.p.tblwidth = initwidth; - aw = nwidth-brd*vc-gw; - if(!isNaN($t.p.height)) { - if($($t.grid.bDiv)[0].clientHeight < $($t.grid.bDiv)[0].scrollHeight || $t.rows.length === 1){ - hs = true; - aw -= scw; - } - } - initwidth =0; - var cle = $t.grid.cols.length >0; - $.each($t.p.colModel, function(i) { - if(this.hidden === false && !this.fixed){ - cw = Math.round(aw*this.width/($t.p.tblwidth-tw)); - if (cw < 0) { return; } - this.width =cw; - initwidth += cw; - $t.grid.headers[i].width=cw; - $t.grid.headers[i].el.style.width=cw+"px"; - if($t.p.footerrow) { $t.grid.footers[i].style.width = cw+"px"; } - if(cle) { $t.grid.cols[i].style.width = cw+"px"; } - lvc = i; - } - }); - cr =0; - if (hs) { - if(nwidth-gw-(initwidth+brd*vc) !== scw){ - cr = nwidth-gw-(initwidth+brd*vc)-scw; - } - } else if( Math.abs(nwidth-gw-(initwidth+brd*vc)) !== 1) { - cr = nwidth-gw-(initwidth+brd*vc); - } - $t.p.colModel[lvc].width += cr; - $t.p.tblwidth = initwidth+cr+tw+brd*cl; - if($t.p.tblwidth > nwidth) { - var delta = $t.p.tblwidth - parseInt(nwidth,10); - $t.p.tblwidth = nwidth; - cw = $t.p.colModel[lvc].width = $t.p.colModel[lvc].width-delta; - } else { - cw= $t.p.colModel[lvc].width; - } - $t.grid.headers[lvc].width = cw; - $t.grid.headers[lvc].el.style.width=cw+"px"; - if(cle) { $t.grid.cols[lvc].style.width = cw+"px"; } - $('table:first',$t.grid.bDiv).css("width",$t.p.tblwidth+"px"); - $('table:first',$t.grid.hDiv).css("width",$t.p.tblwidth+"px"); - $t.grid.hDiv.scrollLeft = $t.grid.bDiv.scrollLeft; - if($t.p.footerrow) { - $t.grid.footers[lvc].style.width = cw+"px"; - $('table:first',$t.grid.sDiv).css("width",$t.p.tblwidth+"px"); - } - } - }); - }, - setGridHeight : function (nh) { - return this.each(function (){ - var $t = this; - if(!$t.grid) {return;} - $($t.grid.bDiv).css({height: nh+(isNaN(nh)?"":"px")}); - $t.p.height = nh; - if ($t.p.scroll) { $t.grid.populateVisible(); } - }); - }, - setCaption : function (newcap){ - return this.each(function(){ - this.p.caption=newcap; - $("span.ui-jqgrid-title",this.grid.cDiv).html(newcap); - $(this.grid.cDiv).show(); - }); - }, - setLabel : function(colname, nData, prop, attrp ){ - return this.each(function(){ - var $t = this, pos=-1; - if(!$t.grid) {return;} - if(isNaN(colname)) { - $($t.p.colModel).each(function(i){ - if (this.name == colname) { - pos = i;return false; - } - }); - } else {pos = parseInt(colname,10);} - if(pos>=0) { - var thecol = $("tr.ui-jqgrid-labels th:eq("+pos+")",$t.grid.hDiv); - if (nData){ - var ico = $(".s-ico",thecol); - $("[id^=jqgh_]",thecol).empty().html(nData).append(ico); - $t.p.colNames[pos] = nData; - } - if (prop) { - if(typeof prop === 'string') {$(thecol).addClass(prop);} else {$(thecol).css(prop);} - } - if(typeof attrp === 'object') {$(thecol).attr(attrp);} - } - }); - }, - setCell : function(rowid,colname,nData,cssp,attrp, forceupd) { - return this.each(function(){ - var $t = this, pos =-1,v, title; - if(!$t.grid) {return;} - if(isNaN(colname)) { - $($t.p.colModel).each(function(i){ - if (this.name == colname) { - pos = i;return false; - } - }); - } else {pos = parseInt(colname,10);} - if(pos>=0) { - var ind = $t.rows.namedItem(rowid); - if (ind){ - var tcell = $("td:eq("+pos+")",ind); - if(nData !== "" || forceupd === true) { - v = $t.formatter(rowid, nData, pos,ind,'edit'); - title = $t.p.colModel[pos].title ? {"title":$.jgrid.stripHtml(v)} : {}; - if($t.p.treeGrid && $(".tree-wrap",$(tcell)).length>0) { - $("span",$(tcell)).html(v).attr(title); - } else { - $(tcell).html(v).attr(title); - } - if($t.p.datatype == "local") { - var cm = $t.p.colModel[pos], index; - nData = cm.formatter && typeof(cm.formatter) === 'string' && cm.formatter == 'date' ? $.unformat.date(nData,cm) : nData; - index = $t.p._index[rowid]; - if(typeof index != "undefined") { - $t.p.data[index][cm.name] = nData; - } - } - } - if(typeof cssp === 'string'){ - $(tcell).addClass(cssp); - } else if(cssp) { - $(tcell).css(cssp); - } - if(typeof attrp === 'object') {$(tcell).attr(attrp);} - } - } - }); - }, - getCell : function(rowid,col) { - var ret = false; - this.each(function(){ - var $t=this, pos=-1; - if(!$t.grid) {return;} - if(isNaN(col)) { - $($t.p.colModel).each(function(i){ - if (this.name === col) { - pos = i;return false; - } - }); - } else {pos = parseInt(col,10);} - if(pos>=0) { - var ind = $t.rows.namedItem(rowid); - if(ind) { - try { - ret = $.unformat($("td:eq("+pos+")",ind),{rowId:ind.id, colModel:$t.p.colModel[pos]},pos); - } catch (e){ - ret = $.jgrid.htmlDecode($("td:eq("+pos+")",ind).html()); - } - } - } - }); - return ret; - }, - getCol : function (col, obj, mathopr) { - var ret = [], val, sum=0; - obj = typeof (obj) != 'boolean' ? false : obj; - if(typeof mathopr == 'undefined') { mathopr = false; } - this.each(function(){ - var $t=this, pos=-1; - if(!$t.grid) {return;} - if(isNaN(col)) { - $($t.p.colModel).each(function(i){ - if (this.name === col) { - pos = i;return false; - } - }); - } else {pos = parseInt(col,10);} - if(pos>=0) { - var ln = $t.rows.length, i =0; - if (ln && ln>0){ - while(i0) { - // prevent second click on that field and enable selects - if (ed===true ) { - if(iRow == $t.p.iRow && iCol == $t.p.iCol){ - return; - } - } - // save the cell - $($t).jqGrid("saveCell",$t.p.savedRow[0].id,$t.p.savedRow[0].ic); - } else { - window.setTimeout(function () { $("#"+$t.p.knv).attr("tabindex","-1").focus();},0); - } - nm = $t.p.colModel[iCol].name; - if (nm=='subgrid' || nm=='cb' || nm=='rn') {return;} - cc = $("td:eq("+iCol+")",$t.rows[iRow]); - if ($t.p.colModel[iCol].editable===true && ed===true && !cc.hasClass("not-editable-cell")) { - if(parseInt($t.p.iCol,10)>=0 && parseInt($t.p.iRow,10)>=0) { - $("td:eq("+$t.p.iCol+")",$t.rows[$t.p.iRow]).removeClass("edit-cell ui-state-highlight"); - $($t.rows[$t.p.iRow]).removeClass("selected-row ui-state-hover"); - } - $(cc).addClass("edit-cell ui-state-highlight"); - $($t.rows[iRow]).addClass("selected-row ui-state-hover"); - try { - tmp = $.unformat(cc,{rowId: $t.rows[iRow].id, colModel:$t.p.colModel[iCol]},iCol); - } catch (_) { - tmp = $(cc).html(); - } - if($t.p.autoencode) { tmp = $.jgrid.htmlDecode(tmp); } - if (!$t.p.colModel[iCol].edittype) {$t.p.colModel[iCol].edittype = "text";} - $t.p.savedRow.push({id:iRow,ic:iCol,name:nm,v:tmp}); - if($.isFunction($t.p.formatCell)) { - var tmp2 = $t.p.formatCell.call($t, $t.rows[iRow].id,nm,tmp,iRow,iCol); - if(tmp2 !== undefined ) {tmp = tmp2;} - } - var opt = $.extend({}, $t.p.colModel[iCol].editoptions || {} ,{id:iRow+"_"+nm,name:nm}); - var elc = $.jgrid.createEl($t.p.colModel[iCol].edittype,opt,tmp,true,$.extend({},$.jgrid.ajaxOptions,$t.p.ajaxSelectOptions || {})); - if ($.isFunction($t.p.beforeEditCell)) { - $t.p.beforeEditCell.call($t, $t.rows[iRow].id,nm,tmp,iRow,iCol); - } - $(cc).html("").append(elc).attr("tabindex","0"); - window.setTimeout(function () { $(elc).focus();},0); - $("input, select, textarea",cc).bind("keydown",function(e) { - if (e.keyCode === 27) { - if($("input.hasDatepicker",cc).length >0) { - if( $(".ui-datepicker").is(":hidden") ) { $($t).jqGrid("restoreCell",iRow,iCol); } - else { $("input.hasDatepicker",cc).datepicker('hide'); } - } else { - $($t).jqGrid("restoreCell",iRow,iCol); - } - } //ESC - if (e.keyCode === 13) {$($t).jqGrid("saveCell",iRow,iCol);}//Enter - if (e.keyCode == 9) { - if(!$t.grid.hDiv.loading ) { - if (e.shiftKey) {$($t).jqGrid("prevCell",iRow,iCol);} //Shift TAb - else {$($t).jqGrid("nextCell",iRow,iCol);} //Tab - } else { - return false; - } - } - e.stopPropagation(); - }); - if ($.isFunction($t.p.afterEditCell)) { - $t.p.afterEditCell.call($t, $t.rows[iRow].id,nm,tmp,iRow,iCol); - } - } else { - if (parseInt($t.p.iCol,10)>=0 && parseInt($t.p.iRow,10)>=0) { - $("td:eq("+$t.p.iCol+")",$t.rows[$t.p.iRow]).removeClass("edit-cell ui-state-highlight"); - $($t.rows[$t.p.iRow]).removeClass("selected-row ui-state-hover"); - } - cc.addClass("edit-cell ui-state-highlight"); - $($t.rows[iRow]).addClass("selected-row ui-state-hover"); - if ($.isFunction($t.p.onSelectCell)) { - tmp = cc.html().replace(/\ \;/ig,''); - $t.p.onSelectCell.call($t, $t.rows[iRow].id,nm,tmp,iRow,iCol); - } - } - $t.p.iCol = iCol; $t.p.iRow = iRow; - }); - }, - saveCell : function (iRow, iCol){ - return this.each(function(){ - var $t= this, fr; - if (!$t.grid || $t.p.cellEdit !== true) {return;} - if ( $t.p.savedRow.length >= 1) {fr = 0;} else {fr=null;} - if(fr !== null) { - var cc = $("td:eq("+iCol+")",$t.rows[iRow]),v,v2, - cm = $t.p.colModel[iCol], nm = cm.name, nmjq = $.jgrid.jqID(nm) ; - switch (cm.edittype) { - case "select": - if(!cm.editoptions.multiple) { - v = $("#"+iRow+"_"+nmjq+">option:selected",$t.rows[iRow]).val(); - v2 = $("#"+iRow+"_"+nmjq+">option:selected",$t.rows[iRow]).text(); - } else { - var sel = $("#"+iRow+"_"+nmjq,$t.rows[iRow]), selectedText = []; - v = $(sel).val(); - if(v) { v.join(",");} else { v=""; } - $("option:selected",sel).each( - function(i,selected){ - selectedText[i] = $(selected).text(); - } - ); - v2 = selectedText.join(","); - } - if(cm.formatter) { v2 = v; } - break; - case "checkbox": - var cbv = ["Yes","No"]; - if(cm.editoptions){ - cbv = cm.editoptions.value.split(":"); - } - v = $("#"+iRow+"_"+nmjq,$t.rows[iRow]).attr("checked") ? cbv[0] : cbv[1]; - v2=v; - break; - case "password": - case "text": - case "textarea": - case "button" : - v = $("#"+iRow+"_"+nmjq,$t.rows[iRow]).val(); - v2=v; - break; - case 'custom' : - try { - if(cm.editoptions && $.isFunction(cm.editoptions.custom_value)) { - v = cm.editoptions.custom_value.call($t, $(".customelement",cc),'get'); - if (v===undefined) { throw "e2";} else { v2=v; } - } else { throw "e1"; } - } catch (e) { - if (e=="e1") { $.jgrid.info_dialog(jQuery.jgrid.errors.errcap,"function 'custom_value' "+$.jgrid.edit.msg.nodefined,jQuery.jgrid.edit.bClose); } - if (e=="e2") { $.jgrid.info_dialog(jQuery.jgrid.errors.errcap,"function 'custom_value' "+$.jgrid.edit.msg.novalue,jQuery.jgrid.edit.bClose); } - else {$.jgrid.info_dialog(jQuery.jgrid.errors.errcap,e.message,jQuery.jgrid.edit.bClose); } - } - break; - } - // The common approach is if nothing changed do not do anything - if (v2 != $t.p.savedRow[fr].v){ - if ($.isFunction($t.p.beforeSaveCell)) { - var vv = $t.p.beforeSaveCell.call($t, $t.rows[iRow].id,nm, v, iRow,iCol); - if (vv) {v = vv; v2=vv;} - } - var cv = $.jgrid.checkValues(v,iCol,$t); - if(cv[0] === true) { - var addpost = {}; - if ($.isFunction($t.p.beforeSubmitCell)) { - addpost = $t.p.beforeSubmitCell.call($t, $t.rows[iRow].id,nm, v, iRow,iCol); - if (!addpost) {addpost={};} - } - if( $("input.hasDatepicker",cc).length >0) { $("input.hasDatepicker",cc).datepicker('hide'); } - if ($t.p.cellsubmit == 'remote') { - if ($t.p.cellurl) { - var postdata = {}; - if($t.p.autoencode) { v = $.jgrid.htmlEncode(v); } - postdata[nm] = v; - var idname,oper, opers; - opers = $t.p.prmNames; - idname = opers.id; - oper = opers.oper; - postdata[idname] = $t.rows[iRow].id; - postdata[oper] = opers.editoper; - postdata = $.extend(addpost,postdata); - $("#lui_"+$t.p.id).show(); - $t.grid.hDiv.loading = true; - $.ajax( $.extend( { - url: $t.p.cellurl, - data :$.isFunction($t.p.serializeCellData) ? $t.p.serializeCellData.call($t, postdata) : postdata, - type: "POST", - complete: function (result, stat) { - $("#lui_"+$t.p.id).hide(); - $t.grid.hDiv.loading = false; - if (stat == 'success') { - if ($.isFunction($t.p.afterSubmitCell)) { - var ret = $t.p.afterSubmitCell.call($t, result,postdata.id,nm,v,iRow,iCol); - if(ret[0] === true) { - $(cc).empty(); - $($t).jqGrid("setCell",$t.rows[iRow].id, iCol, v2, false, false, true); - $(cc).addClass("dirty-cell"); - $($t.rows[iRow]).addClass("edited"); - if ($.isFunction($t.p.afterSaveCell)) { - $t.p.afterSaveCell.call($t, $t.rows[iRow].id,nm, v, iRow,iCol); - } - $t.p.savedRow.splice(0,1); - } else { - $.jgrid.info_dialog($.jgrid.errors.errcap,ret[1],$.jgrid.edit.bClose); - $($t).jqGrid("restoreCell",iRow,iCol); - } - } else { - $(cc).empty(); - $($t).jqGrid("setCell",$t.rows[iRow].id, iCol, v2, false, false, true); - $(cc).addClass("dirty-cell"); - $($t.rows[iRow]).addClass("edited"); - if ($.isFunction($t.p.afterSaveCell)) { - $t.p.afterSaveCell.call($t, $t.rows[iRow].id,nm, v, iRow,iCol); - } - $t.p.savedRow.splice(0,1); - } - } - }, - error:function(res,stat) { - $("#lui_"+$t.p.id).hide(); - $t.grid.hDiv.loading = false; - if ($.isFunction($t.p.errorCell)) { - $t.p.errorCell.call($t, res,stat); - $($t).jqGrid("restoreCell",iRow,iCol); - } else { - $.jgrid.info_dialog($.jgrid.errors.errcap,res.status+" : "+res.statusText+"
"+stat,$.jgrid.edit.bClose); - $($t).jqGrid("restoreCell",iRow,iCol); - } - } - }, $.jgrid.ajaxOptions, $t.p.ajaxCellOptions || {})); - } else { - try { - $.jgrid.info_dialog($.jgrid.errors.errcap,$.jgrid.errors.nourl,$.jgrid.edit.bClose); - $($t).jqGrid("restoreCell",iRow,iCol); - } catch (e) {} - } - } - if ($t.p.cellsubmit == 'clientArray') { - $(cc).empty(); - $($t).jqGrid("setCell",$t.rows[iRow].id,iCol, v2, false, false, true); - $(cc).addClass("dirty-cell"); - $($t.rows[iRow]).addClass("edited"); - if ($.isFunction($t.p.afterSaveCell)) { - $t.p.afterSaveCell.call($t, $t.rows[iRow].id,nm, v, iRow,iCol); - } - $t.p.savedRow.splice(0,1); - } - } else { - try { - window.setTimeout(function(){$.jgrid.info_dialog($.jgrid.errors.errcap,v+" "+cv[1],$.jgrid.edit.bClose);},100); - $($t).jqGrid("restoreCell",iRow,iCol); - } catch (e) {} - } - } else { - $($t).jqGrid("restoreCell",iRow,iCol); - } - } - if ($.browser.opera) { - $("#"+$t.p.knv).attr("tabindex","-1").focus(); - } else { - window.setTimeout(function () { $("#"+$t.p.knv).attr("tabindex","-1").focus();},0); - } - }); - }, - restoreCell : function(iRow, iCol) { - return this.each(function(){ - var $t= this, fr; - if (!$t.grid || $t.p.cellEdit !== true ) {return;} - if ( $t.p.savedRow.length >= 1) {fr = 0;} else {fr=null;} - if(fr !== null) { - var cc = $("td:eq("+iCol+")",$t.rows[iRow]); - // datepicker fix - if($.isFunction($.fn.datepicker)) { - try { - $("input.hasDatepicker",cc).datepicker('hide'); - } catch (e) {} - } - $(cc).empty().attr("tabindex","-1"); - $($t).jqGrid("setCell",$t.rows[iRow].id, iCol, $t.p.savedRow[fr].v, false, false, true); - if ($.isFunction($t.p.afterRestoreCell)) { - $t.p.afterRestoreCell.call($t, $t.rows[iRow].id, $t.p.savedRow[fr].v, iRow, iCol); - } - $t.p.savedRow.splice(0,1); - } - window.setTimeout(function () { $("#"+$t.p.knv).attr("tabindex","-1").focus();},0); - }); - }, - nextCell : function (iRow,iCol) { - return this.each(function (){ - var $t = this, nCol=false; - if (!$t.grid || $t.p.cellEdit !== true) {return;} - // try to find next editable cell - for (var i=iCol+1; i<$t.p.colModel.length; i++) { - if ( $t.p.colModel[i].editable ===true) { - nCol = i; break; - } - } - if(nCol !== false) { - $($t).jqGrid("editCell",iRow,nCol,true); - } else { - if ($t.p.savedRow.length >0) { - $($t).jqGrid("saveCell",iRow,iCol); - } - } - }); - }, - prevCell : function (iRow,iCol) { - return this.each(function (){ - var $t = this, nCol=false; - if (!$t.grid || $t.p.cellEdit !== true) {return;} - // try to find next editable cell - for (var i=iCol-1; i>=0; i--) { - if ( $t.p.colModel[i].editable ===true) { - nCol = i; break; - } - } - if(nCol !== false) { - $($t).jqGrid("editCell",iRow,nCol,true); - } else { - if ($t.p.savedRow.length >0) { - $($t).jqGrid("saveCell",iRow,iCol); - } - } - }); - }, - GridNav : function() { - return this.each(function () { - var $t = this; - if (!$t.grid || $t.p.cellEdit !== true ) {return;} - // trick to process keydown on non input elements - $t.p.knv = $t.p.id + "_kn"; - var selection = $(""), - i, kdir; - $(selection).insertBefore($t.grid.cDiv); - $("#"+$t.p.knv) - .focus() - .keydown(function (e){ - kdir = e.keyCode; - if($t.p.direction == "rtl") { - if(kdir==37) { kdir = 39;} - else if (kdir==39) { kdir = 37; } - } - switch (kdir) { - case 38: - if ($t.p.iRow-1 >0 ) { - scrollGrid($t.p.iRow-1,$t.p.iCol,'vu'); - $($t).jqGrid("editCell",$t.p.iRow-1,$t.p.iCol,false); - } - break; - case 40 : - if ($t.p.iRow+1 <= $t.rows.length-1) { - scrollGrid($t.p.iRow+1,$t.p.iCol,'vd'); - $($t).jqGrid("editCell",$t.p.iRow+1,$t.p.iCol,false); - } - break; - case 37 : - if ($t.p.iCol -1 >= 0) { - i = findNextVisible($t.p.iCol-1,'lft'); - scrollGrid($t.p.iRow, i,'h'); - $($t).jqGrid("editCell",$t.p.iRow, i,false); - } - break; - case 39 : - if ($t.p.iCol +1 <= $t.p.colModel.length-1) { - i = findNextVisible($t.p.iCol+1,'rgt'); - scrollGrid($t.p.iRow,i,'h'); - $($t).jqGrid("editCell",$t.p.iRow,i,false); - } - break; - case 13: - if (parseInt($t.p.iCol,10)>=0 && parseInt($t.p.iRow,10)>=0) { - $($t).jqGrid("editCell",$t.p.iRow,$t.p.iCol,true); - } - break; - } - return false; - }); - function scrollGrid(iR, iC, tp){ - if (tp.substr(0,1)=='v') { - var ch = $($t.grid.bDiv)[0].clientHeight, - st = $($t.grid.bDiv)[0].scrollTop, - nROT = $t.rows[iR].offsetTop+$t.rows[iR].clientHeight, - pROT = $t.rows[iR].offsetTop; - if(tp == 'vd') { - if(nROT >= ch) { - $($t.grid.bDiv)[0].scrollTop = $($t.grid.bDiv)[0].scrollTop + $t.rows[iR].clientHeight; - } - } - if(tp == 'vu'){ - if (pROT < st ) { - $($t.grid.bDiv)[0].scrollTop = $($t.grid.bDiv)[0].scrollTop - $t.rows[iR].clientHeight; - } - } - } - if(tp=='h') { - var cw = $($t.grid.bDiv)[0].clientWidth, - sl = $($t.grid.bDiv)[0].scrollLeft, - nCOL = $t.rows[iR].cells[iC].offsetLeft+$t.rows[iR].cells[iC].clientWidth, - pCOL = $t.rows[iR].cells[iC].offsetLeft; - if(nCOL >= cw+parseInt(sl,10)) { - $($t.grid.bDiv)[0].scrollLeft = $($t.grid.bDiv)[0].scrollLeft + $t.rows[iR].cells[iC].clientWidth; - } else if (pCOL < sl) { - $($t.grid.bDiv)[0].scrollLeft = $($t.grid.bDiv)[0].scrollLeft - $t.rows[iR].cells[iC].clientWidth; - } - } - } - function findNextVisible(iC,act){ - var ind, i; - if(act == 'lft') { - ind = iC+1; - for (i=iC;i>=0;i--){ - if ($t.p.colModel[i].hidden !== true) { - ind = i; - break; - } - } - } - if(act == 'rgt') { - ind = iC-1; - for (i=iC; i<$t.p.colModel.length;i++){ - if ($t.p.colModel[i].hidden !== true) { - ind = i; - break; - } - } - } - return ind; - } - }); - }, - getChangedCells : function (mthd) { - var ret=[]; - if (!mthd) {mthd='all';} - this.each(function(){ - var $t= this,nm; - if (!$t.grid || $t.p.cellEdit !== true ) {return;} - $($t.rows).each(function(j){ - var res = {}; - if ($(this).hasClass("edited")) { - $('td',this).each( function(i) { - nm = $t.p.colModel[i].name; - if ( nm !== 'cb' && nm !== 'subgrid') { - if (mthd=='dirty') { - if ($(this).hasClass('dirty-cell')) { - try { - res[nm] = $.unformat(this,{rowId:$t.rows[j].id, colModel:$t.p.colModel[i]},i); - } catch (e){ - res[nm] = $.jgrid.htmlDecode($(this).html()); - } - } - } else { - try { - res[nm] = $.unformat(this,{rowId:$t.rows[j].id,colModel:$t.p.colModel[i]},i); - } catch (e) { - res[nm] = $.jgrid.htmlDecode($(this).html()); - } - } - } - }); - res.id = this.id; - ret.push(res); - } - }); - }); - return ret; - } -/// end cell editing -}); -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/grid.common.js b/addons/base/static/lib/jquery.jqGrid/js/grid.common.js deleted file mode 100644 index 5f0a4a3d589..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/grid.common.js +++ /dev/null @@ -1,656 +0,0 @@ -;(function($){ -/* - * jqGrid common function - * Tony Tomov tony@trirand.com - * http://trirand.com/blog/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl-2.0.html -*/ -/*global jQuery, $ */ - -$.extend($.jgrid,{ -// Modal functions - showModal : function(h) { - h.w.show(); - }, - closeModal : function(h) { - h.w.hide().attr("aria-hidden","true"); - if(h.o) { h.o.remove(); } - }, - hideModal : function (selector,o) { - o = $.extend({jqm : true, gb :''}, o || {}); - if(o.onClose) { - var oncret = o.onClose(selector); - if (typeof oncret == 'boolean' && !oncret ) { return; } - } - if ($.fn.jqm && o.jqm === true) { - $(selector).attr("aria-hidden","true").jqmHide(); - } else { - if(o.gb !== '') { - try {$(".jqgrid-overlay:first",o.gb).hide();} catch (e){} - } - $(selector).hide().attr("aria-hidden","true"); - } - }, -//Helper functions - findPos : function(obj) { - var curleft = 0, curtop = 0; - if (obj.offsetParent) { - do { - curleft += obj.offsetLeft; - curtop += obj.offsetTop; - } while (obj = obj.offsetParent); - //do not change obj == obj.offsetParent - } - return [curleft,curtop]; - }, - createModal : function(aIDs, content, p, insertSelector, posSelector, appendsel) { - var mw = document.createElement('div'), rtlsup, self = this; - rtlsup = $(p.gbox).attr("dir") == "rtl" ? true : false; - mw.className= "ui-widget ui-widget-content ui-corner-all ui-jqdialog"; - mw.id = aIDs.themodal; - var mh = document.createElement('div'); - mh.className = "ui-jqdialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix"; - mh.id = aIDs.modalhead; - $(mh).append(""+p.caption+""); - var ahr= $("
") - .hover(function(){ahr.addClass('ui-state-hover');}, - function(){ahr.removeClass('ui-state-hover');}) - .append(""); - $(mh).append(ahr); - if(rtlsup) { - mw.dir = "rtl"; - $(".ui-jqdialog-title",mh).css("float","right"); - $(".ui-jqdialog-titlebar-close",mh).css("left",0.3+"em"); - } else { - mw.dir = "ltr"; - $(".ui-jqdialog-title",mh).css("float","left"); - $(".ui-jqdialog-titlebar-close",mh).css("right",0.3+"em"); - } - var mc = document.createElement('div'); - $(mc).addClass("ui-jqdialog-content ui-widget-content").attr("id",aIDs.modalcontent); - $(mc).append(content); - mw.appendChild(mc); - $(mw).prepend(mh); - if(appendsel===true) { $('body').append(mw); } //append as first child in body -for alert dialog - else {$(mw).insertBefore(insertSelector);} - if(typeof p.jqModal === 'undefined') {p.jqModal = true;} // internal use - var coord = {}; - if ( $.fn.jqm && p.jqModal === true) { - if(p.left ===0 && p.top===0) { - var pos = []; - pos = this.findPos(posSelector); - p.left = pos[0] + 4; - p.top = pos[1] + 4; - } - coord.top = p.top+"px"; - coord.left = p.left; - } else if(p.left !==0 || p.top!==0) { - coord.left = p.left; - coord.top = p.top+"px"; - } - $("a.ui-jqdialog-titlebar-close",mh).click(function(e){ - var oncm = $("#"+aIDs.themodal).data("onClose") || p.onClose; - var gboxclose = $("#"+aIDs.themodal).data("gbox") || p.gbox; - self.hideModal("#"+aIDs.themodal,{gb:gboxclose,jqm:p.jqModal,onClose:oncm}); - return false; - }); - if (p.width === 0 || !p.width) {p.width = 300;} - if(p.height === 0 || !p.height) {p.height =200;} - if(!p.zIndex) { - var parentZ = $(insertSelector).parents("*[role=dialog]").first().css("z-index"); - if(parentZ) { - p.zIndex = parseInt(parentZ,10)+1; - } else { - p.zIndex = 950; - } - } - var rtlt = 0; - if( rtlsup && coord.left && !appendsel) { - rtlt = $(p.gbox).width()- (!isNaN(p.width) ? parseInt(p.width,10) :0) - 8; // to do - // just in case - coord.left = parseInt(coord.left,10) + parseInt(rtlt,10); - } - if(coord.left) { coord.left += "px"; } - $(mw).css($.extend({ - width: isNaN(p.width) ? "auto": p.width+"px", - height:isNaN(p.height) ? "auto" : p.height + "px", - zIndex:p.zIndex, - overflow: 'hidden' - },coord)) - .attr({tabIndex: "-1","role":"dialog","aria-labelledby":aIDs.modalhead,"aria-hidden":"true"}); - if(typeof p.drag == 'undefined') { p.drag=true;} - if(typeof p.resize == 'undefined') {p.resize=true;} - if (p.drag) { - $(mh).css('cursor','move'); - if($.fn.jqDrag) { - $(mw).jqDrag(mh); - } else { - try { - $(mw).draggable({handle: $("#"+mh.id)}); - } catch (e) {} - } - } - if(p.resize) { - if($.fn.jqResize) { - $(mw).append("
"); - $("#"+aIDs.themodal).jqResize(".jqResize",aIDs.scrollelm ? "#"+aIDs.scrollelm : false); - } else { - try { - $(mw).resizable({handles: 'se, sw',alsoResize: aIDs.scrollelm ? "#"+aIDs.scrollelm : false}); - } catch (r) {} - } - } - if(p.closeOnEscape === true){ - $(mw).keydown( function( e ) { - if( e.which == 27 ) { - var cone = $("#"+aIDs.themodal).data("onClose") || p.onClose; - self.hideModal(this,{gb:p.gbox,jqm:p.jqModal,onClose: cone}); - } - }); - } - }, - viewModal : function (selector,o){ - o = $.extend({ - toTop: true, - overlay: 10, - modal: false, - onShow: this.showModal, - onHide: this.closeModal, - gbox: '', - jqm : true, - jqM : true - }, o || {}); - if ($.fn.jqm && o.jqm === true) { - if(o.jqM) { $(selector).attr("aria-hidden","false").jqm(o).jqmShow(); } - else {$(selector).attr("aria-hidden","false").jqmShow();} - } else { - if(o.gbox !== '') { - $(".jqgrid-overlay:first",o.gbox).show(); - $(selector).data("gbox",o.gbox); - } - $(selector).show().attr("aria-hidden","false"); - try{$(':input:visible',selector)[0].focus();}catch(_){} - } - }, - - info_dialog : function(caption, content,c_b, modalopt) { - var mopt = { - width:290, - height:'auto', - dataheight: 'auto', - drag: true, - resize: false, - caption:""+caption+"", - left:250, - top:170, - zIndex : 1000, - jqModal : true, - modal : false, - closeOnEscape : true, - align: 'center', - buttonalign : 'center', - buttons : [] - // {text:'textbutt', id:"buttid", onClick : function(){...}} - // if the id is not provided we set it like info_button_+ the index in the array - i.e info_button_0,info_button_1... - }; - $.extend(mopt,modalopt || {}); - var jm = mopt.jqModal, self = this; - if($.fn.jqm && !jm) { jm = false; } - // in case there is no jqModal - var buttstr =""; - if(mopt.buttons.length > 0) { - for(var i=0;i"+mopt.buttons[i].text+""; - } - } - var dh = isNaN(mopt.dataheight) ? mopt.dataheight : mopt.dataheight+"px", - cn = "text-align:"+mopt.align+";"; - var cnt = "
"; - cnt += "
"+content+"
"; - cnt += c_b ? "
"+c_b+""+buttstr+"
" : - buttstr !== "" ? "
"+buttstr+"
" : ""; - cnt += "
"; - - try { - if($("#info_dialog").attr("aria-hidden") == "false") { - this.hideModal("#info_dialog",{jqm:jm}); - } - $("#info_dialog").remove(); - } catch (e){} - this.createModal({ - themodal:'info_dialog', - modalhead:'info_head', - modalcontent:'info_content', - scrollelm: 'infocnt'}, - cnt, - mopt, - '','',true - ); - // attach onclick after inserting into the dom - if(buttstr) { - $.each(mopt.buttons,function(i){ - $("#"+this.id,"#info_id").bind('click',function(){mopt.buttons[i].onClick.call($("#info_dialog")); return false;}); - }); - } - $("#closedialog", "#info_id").click(function(e){ - self.hideModal("#info_dialog",{jqm:jm}); - return false; - }); - $(".fm-button","#info_dialog").hover( - function(){$(this).addClass('ui-state-hover');}, - function(){$(this).removeClass('ui-state-hover');} - ); - if($.isFunction(mopt.beforeOpen) ) { mopt.beforeOpen(); } - this.viewModal("#info_dialog",{ - onHide: function(h) { - h.w.hide().remove(); - if(h.o) { h.o.remove(); } - }, - modal :mopt.modal, - jqm:jm - }); - if($.isFunction(mopt.afterOpen) ) { mopt.afterOpen(); } - try{ $("#info_dialog").focus();} catch (m){} - }, -// Form Functions - createEl : function(eltype,options,vl,autowidth, ajaxso) { - var elem = ""; - function bindEv (el, opt) { - if($.isFunction(opt.dataInit)) { - opt.dataInit(el); - } - if(opt.dataEvents) { - $.each(opt.dataEvents, function() { - if (this.data !== undefined) { - $(el).bind(this.type, this.data, this.fn); - } else { - $(el).bind(this.type, this.fn); - } - }); - } - return opt; - } - function setAttributes(elm, atr) { - var exclude = ['dataInit','dataEvents', 'value','dataUrl', 'buildSelect']; - $.each(atr, function(key, value){ - if($.inArray(key, exclude) === -1) { - $(elem).attr(key,value); - } - }); - } - switch (eltype) - { - case "textarea" : - elem = document.createElement("textarea"); - if(autowidth) { - if(!options.cols) { $(elem).css({width:"98%"});} - } else if (!options.cols) { options.cols = 20; } - if(!options.rows) { options.rows = 2; } - if(vl==' ' || vl==' ' || (vl.length==1 && vl.charCodeAt(0)==160)) {vl="";} - elem.value = vl; - setAttributes(elem, options); - options = bindEv(elem,options); - $(elem).attr({"role":"textbox","multiline":"true"}); - break; - case "checkbox" : //what code for simple checkbox - elem = document.createElement("input"); - elem.type = "checkbox"; - if( !options.value ) { - var vl1 = vl.toLowerCase(); - if(vl1.search(/(false|0|no|off|undefined)/i)<0 && vl1!=="") { - elem.checked=true; - elem.defaultChecked=true; - elem.value = vl; - } else { - elem.value = "on"; - } - $(elem).attr("offval","off"); - } else { - var cbval = options.value.split(":"); - if(vl === cbval[0]) { - elem.checked=true; - elem.defaultChecked=true; - } - elem.value = cbval[0]; - $(elem).attr("offval",cbval[1]); - } - setAttributes(elem, options); - options = bindEv(elem,options); - $(elem).attr("role","checkbox"); - break; - case "select" : - elem = document.createElement("select"); - elem.setAttribute("role","select"); - var msl, ovm = []; - if(options.multiple===true) { - msl = true; - elem.multiple="multiple"; - $(elem).attr("aria-multiselectable","true"); - } else { msl = false; } - if(typeof(options.dataUrl) != "undefined") { - $.ajax($.extend({ - url: options.dataUrl, - type : "GET", - dataType: "html", - success: function(data,status){ - var a; - if(typeof(options.buildSelect) != "undefined") { - var b = options.buildSelect(data); - a = $(b).html(); - } else { - a = $(data).html(); - } - if(a) { - $(elem).append(a); - setAttributes(elem, options); - options = bindEv(elem,options); - if(typeof options.size === 'undefined') { options.size = msl ? 3 : 1;} - if(msl) { - ovm = vl.split(","); - ovm = $.map(ovm,function(n){return $.trim(n);}); - } else { - ovm[0] = $.trim(vl); - } - //$(elem).attr(options); - setTimeout(function(){ - $("option",elem).each(function(i){ - //if(i===0) { this.selected = ""; } - $(this).attr("role","option"); - if($.inArray($.trim($(this).text()),ovm) > -1 || $.inArray($.trim($(this).val()),ovm) > -1 ) { - this.selected= "selected"; - if(!msl) { return false; } - } - }); - },0); - } - } - },ajaxso || {})); - } else if(options.value) { - var i; - if(msl) { - ovm = vl.split(","); - ovm = $.map(ovm,function(n){return $.trim(n);}); - if(typeof options.size === 'undefined') {options.size = 3;} - } else { - options.size = 1; - } - if(typeof options.value === 'function') { options.value = options.value(); } - var so,sv, ov; - if(typeof options.value === 'string') { - so = options.value.split(";"); - for(i=0; i 2 ) { - sv[1] = $.map(sv,function(n,i){if(i>0) { return n;} }).join(":"); - } - ov = document.createElement("option"); - ov.setAttribute("role","option"); - ov.value = sv[0]; ov.innerHTML = sv[1]; - if (!msl && ($.trim(sv[0]) == $.trim(vl) || $.trim(sv[1]) == $.trim(vl))) { ov.selected ="selected"; } - if (msl && ($.inArray($.trim(sv[1]), ovm)>-1 || $.inArray($.trim(sv[0]), ovm)>-1)) {ov.selected ="selected";} - elem.appendChild(ov); - } - } else if (typeof options.value === 'object') { - var oSv = options.value; - for ( var key in oSv) { - if (oSv.hasOwnProperty(key ) ){ - ov = document.createElement("option"); - ov.setAttribute("role","option"); - ov.value = key; ov.innerHTML = oSv[key]; - if (!msl && ( $.trim(key) == $.trim(vl) || $.trim(oSv[key]) == $.trim(vl)) ) { ov.selected ="selected"; } - if (msl && ($.inArray($.trim(oSv[key]),ovm)>-1 || $.inArray($.trim(key),ovm)>-1)) { ov.selected ="selected"; } - elem.appendChild(ov); - } - } - } - setAttributes(elem, options); - options = bindEv(elem,options); - } - break; - case "text" : - case "password" : - case "button" : - var role; - if(eltype=="button") { role = "button"; } - else { role = "textbox"; } - elem = document.createElement("input"); - elem.type = eltype; - elem.value = vl; - setAttributes(elem, options); - options = bindEv(elem,options); - if(eltype != "button"){ - if(autowidth) { - if(!options.size) { $(elem).css({width:"98%"}); } - } else if (!options.size) { options.size = 20; } - } - $(elem).attr("role",role); - break; - case "image" : - case "file" : - elem = document.createElement("input"); - elem.type = eltype; - setAttributes(elem, options); - options = bindEv(elem,options); - break; - case "custom" : - elem = document.createElement("span"); - try { - if($.isFunction(options.custom_element)) { - var celm = options.custom_element.call(this,vl,options); - if(celm) { - celm = $(celm).addClass("customelement").attr({id:options.id,name:options.name}); - $(elem).empty().append(celm); - } else { - throw "e2"; - } - } else { - throw "e1"; - } - } catch (e) { - if (e=="e1") { this.info_dialog($.jgrid.errors.errcap,"function 'custom_element' "+$.jgrid.edit.msg.nodefined, $.jgrid.edit.bClose);} - if (e=="e2") { this.info_dialog($.jgrid.errors.errcap,"function 'custom_element' "+$.jgrid.edit.msg.novalue,$.jgrid.edit.bClose);} - else { this.info_dialog($.jgrid.errors.errcap,typeof(e)==="string"?e:e.message,$.jgrid.edit.bClose); } - } - break; - } - return elem; - }, -// Date Validation Javascript - checkDate : function (format, date) { - var daysInFebruary = function(year){ - // February has 29 days in any year evenly divisible by four, - // EXCEPT for centurial years which are not also divisible by 400. - return (((year % 4 === 0) && ( year % 100 !== 0 || (year % 400 === 0))) ? 29 : 28 ); - }, - DaysArray = function(n) { - for (var i = 1; i <= n; i++) { - this[i] = 31; - if (i==4 || i==6 || i==9 || i==11) {this[i] = 30;} - if (i==2) {this[i] = 29;} - } - return this; - }; - - var tsp = {}, sep; - format = format.toLowerCase(); - //we search for /,-,. for the date separator - if(format.indexOf("/") != -1) { - sep = "/"; - } else if(format.indexOf("-") != -1) { - sep = "-"; - } else if(format.indexOf(".") != -1) { - sep = "."; - } else { - sep = "/"; - } - format = format.split(sep); - date = date.split(sep); - if (date.length != 3) { return false; } - var j=-1,yln, dln=-1, mln=-1; - for(var i=0;i12){ - return false; - } - } - if(dln === -1) { - return false; - } else { - strDate = tsp[format[dln]].toString(); - if (strDate.length<1 || tsp[format[dln]]<1 || tsp[format[dln]]>31 || (tsp[format[mln]]==2 && tsp[format[dln]]>daysInFebruary(tsp[format[j]])) || tsp[format[dln]] > daysInMonth[tsp[format[mln]]]){ - return false; - } - } - return true; - }, - isEmpty : function(val) - { - if (val.match(/^\s+$/) || val === "") { - return true; - } else { - return false; - } - }, - checkTime : function(time){ - // checks only hh:ss (and optional am/pm) - var re = /^(\d{1,2}):(\d{2})([ap]m)?$/,regs; - if(!this.isEmpty(time)) - { - regs = time.match(re); - if(regs) { - if(regs[3]) { - if(regs[1] < 1 || regs[1] > 12) { return false; } - } else { - if(regs[1] > 23) { return false; } - } - if(regs[2] > 59) { - return false; - } - } else { - return false; - } - } - return true; - }, - checkValues : function(val, valref,g, customobject, nam) { - var edtrul,i, nm, dft, len; - if(typeof(customobject) === "undefined") { - if(typeof(valref)=='string'){ - for( i =0, len=g.p.colModel.length;i=0) { - edtrul = g.p.colModel[valref].editrules; - } - } else { - edtrul = customobject; - nm = nam===undefined ? "_" : nam; - } - if(edtrul) { - if(!nm) { nm = g.p.colNames[valref]; } - if(edtrul.required === true) { - if( this.isEmpty(val) ) { return [false,nm+": "+$.jgrid.edit.msg.required,""]; } - } - // force required - var rqfield = edtrul.required === false ? false : true; - if(edtrul.number === true) { - if( !(rqfield === false && this.isEmpty(val)) ) { - if(isNaN(val)) { return [false,nm+": "+$.jgrid.edit.msg.number,""]; } - } - } - if(typeof edtrul.minValue != 'undefined' && !isNaN(edtrul.minValue)) { - if (parseFloat(val) < parseFloat(edtrul.minValue) ) { return [false,nm+": "+$.jgrid.edit.msg.minValue+" "+edtrul.minValue,""];} - } - if(typeof edtrul.maxValue != 'undefined' && !isNaN(edtrul.maxValue)) { - if (parseFloat(val) > parseFloat(edtrul.maxValue) ) { return [false,nm+": "+$.jgrid.edit.msg.maxValue+" "+edtrul.maxValue,""];} - } - var filter; - if(edtrul.email === true) { - if( !(rqfield === false && this.isEmpty(val)) ) { - // taken from $ Validate plugin - filter = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i; - if(!filter.test(val)) {return [false,nm+": "+$.jgrid.edit.msg.email,""];} - } - } - if(edtrul.integer === true) { - if( !(rqfield === false && this.isEmpty(val)) ) { - if(isNaN(val)) { return [false,nm+": "+$.jgrid.edit.msg.integer,""]; } - if ((val % 1 !== 0) || (val.indexOf('.') != -1)) { return [false,nm+": "+$.jgrid.edit.msg.integer,""];} - } - } - if(edtrul.date === true) { - if( !(rqfield === false && this.isEmpty(val)) ) { - if(g.p.colModel[valref].formatoptions && g.p.colModel[valref].formatoptions.newformat) { - dft = g.p.colModel[valref].formatoptions.newformat; - } else { - dft = g.p.colModel[valref].datefmt || "Y-m-d"; - } - if(!this.checkDate (dft, val)) { return [false,nm+": "+$.jgrid.edit.msg.date+" - "+dft,""]; } - } - } - if(edtrul.time === true) { - if( !(rqfield === false && this.isEmpty(val)) ) { - if(!this.checkTime (val)) { return [false,nm+": "+$.jgrid.edit.msg.date+" - hh:mm (am/pm)",""]; } - } - } - if(edtrul.url === true) { - if( !(rqfield === false && this.isEmpty(val)) ) { - filter = /^(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i; - if(!filter.test(val)) {return [false,nm+": "+$.jgrid.edit.msg.url,""];} - } - } - if(edtrul.custom === true) { - if( !(rqfield === false && this.isEmpty(val)) ) { - if($.isFunction(edtrul.custom_func)) { - var ret = edtrul.custom_func.call(g,val,nm); - if($.isArray(ret)) { - return ret; - } else { - return [false,$.jgrid.edit.msg.customarray,""]; - } - } else { - return [false,$.jgrid.edit.msg.customfcheck,""]; - } - } - } - } - return [true,"",""]; - } -}); -})(jQuery); \ No newline at end of file diff --git a/addons/base/static/lib/jquery.jqGrid/js/grid.custom.js b/addons/base/static/lib/jquery.jqGrid/js/grid.custom.js deleted file mode 100644 index 0640f21c30b..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/grid.custom.js +++ /dev/null @@ -1,440 +0,0 @@ -(function($){ -/** - * jqGrid extension for custom methods - * Tony Tomov tony@trirand.com - * http://trirand.com/blog/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl-2.0.html -**/ -/*global jQuery, $ */ - -$.jgrid.extend({ - getColProp : function(colname){ - var ret ={}, $t = this[0]; - if ( !$t.grid ) { return false; } - var cM = $t.p.colModel; - for ( var i =0;i0 ? true : false; - if(p.stringResult === true || $t.p.datatype == "local") { - var ruleGroup = "{\"groupOp\":\"" + p.groupOp + "\",\"rules\":["; - var gi=0; - $.each(sdata,function(i,n){ - if (gi > 0) {ruleGroup += ",";} - ruleGroup += "{\"field\":\"" + i + "\","; - ruleGroup += "\"op\":\"" + sopt[i] + "\","; - n+=""; - ruleGroup += "\"data\":\"" + n.replace(/\\/g,'\\\\').replace(/\"/g,'\\"') + "\"}"; - gi++; - }); - ruleGroup += "]}"; - $.extend($t.p.postData,{filters:ruleGroup}); - $.each(['searchField', 'searchString', 'searchOper'], function(i, n){ - if($t.p.postData.hasOwnProperty(n)) { delete $t.p.postData[n];} - }); - } else { - $.extend($t.p.postData,sdata); - } - var saveurl; - if($t.p.searchurl) { - saveurl = $t.p.url; - $($t).jqGrid("setGridParam",{url:$t.p.searchurl}); - } - var bsr = false; - if($.isFunction(p.beforeSearch)){bsr = p.beforeSearch.call($t);} - if(!bsr) { $($t).jqGrid("setGridParam",{search:sd}).trigger("reloadGrid",[{page:1}]); } - if(saveurl) {$($t).jqGrid("setGridParam",{url:saveurl});} - if($.isFunction(p.afterSearch)){p.afterSearch();} - }; - var clearToolbar = function(trigger){ - var sdata={}, v, j=0, nm; - trigger = (typeof trigger != 'boolean') ? true : trigger; - $.each($t.p.colModel,function(i,n){ - v = (this.searchoptions && this.searchoptions.defaultValue) ? this.searchoptions.defaultValue : ""; - nm = this.index || this.name; - switch (this.stype) { - case 'select' : - var v1; - $("select[name="+nm+"] option",$t.grid.hDiv).each(function (i){ - if(i===0) { this.selected = true; } - if ($(this).text() == v) { - this.selected = true; - v1 = $(this).val(); - return false; - } - }); - if (v1) { - // post the key and not the text - sdata[nm] = v1; - j++; - } else { - try { - delete $t.p.postData[nm]; - } catch(e) {} - } - break; - case 'text': - $("input[name="+nm+"]",$t.grid.hDiv).val(v); - if(v) { - sdata[nm] = v; - j++; - } else { - try { - delete $t.p.postData[nm]; - } catch (y){} - } - break; - } - }); - var sd = j>0 ? true : false; - if(p.stringResult === true || $t.p.datatype == "local") { - var ruleGroup = "{\"groupOp\":\"" + p.groupOp + "\",\"rules\":["; - var gi=0; - $.each(sdata,function(i,n){ - if (gi > 0) {ruleGroup += ",";} - ruleGroup += "{\"field\":\"" + i + "\","; - ruleGroup += "\"op\":\"" + "eq" + "\","; - n+=""; - ruleGroup += "\"data\":\"" + n.replace(/\\/g,'\\\\').replace(/\"/g,'\\"') + "\"}"; - gi++; - }); - ruleGroup += "]}"; - $.extend($t.p.postData,{filters:ruleGroup}); - $.each(['searchField', 'searchString', 'searchOper'], function(i, n){ - if($t.p.postData.hasOwnProperty(n)) { delete $t.p.postData[n];} - }); - } else { - $.extend($t.p.postData,sdata); - } - var saveurl; - if($t.p.searchurl) { - saveurl = $t.p.url; - $($t).jqGrid("setGridParam",{url:$t.p.searchurl}); - } - var bcv = false; - if($.isFunction(p.beforeClear)){bcv = p.beforeClear.call($t);} - if(!bcv) { - if(trigger) { - $($t).jqGrid("setGridParam",{search:sd}).trigger("reloadGrid",[{page:1}]); - } - } - if(saveurl) {$($t).jqGrid("setGridParam",{url:saveurl});} - if($.isFunction(p.afterClear)){p.afterClear();} - }; - var toggleToolbar = function(){ - var trow = $("tr.ui-search-toolbar",$t.grid.hDiv); - if(trow.css("display")=='none') { trow.show(); } - else { trow.hide(); } - }; - // create the row - function bindEvents(selector, events) { - var jElem = $(selector); - if (jElem[0]) { - jQuery.each(events, function() { - if (this.data !== undefined) { - jElem.bind(this.type, this.data, this.fn); - } else { - jElem.bind(this.type, this.fn); - } - }); - } - } - var tr = $(""); - var timeoutHnd; - $.each($t.p.colModel,function(i,n){ - var cm=this, thd , th, soptions,surl,self; - th = $(""); - thd = $("
"); - if(this.hidden===true) { $(th).css("display","none");} - this.search = this.search === false ? false : true; - if(typeof this.stype == 'undefined' ) {this.stype='text';} - soptions = $.extend({},this.searchoptions || {}); - if(this.search){ - switch (this.stype) - { - case "select": - surl = this.surl || soptions.dataUrl; - if(surl) { - // data returned should have already constructed html select - // primitive jQuery load - self = thd; - $.ajax($.extend({ - url: surl, - dataType: "html", - complete: function(res,status) { - if(soptions.buildSelect !== undefined) { - var d = soptions.buildSelect(res); - if (d) { $(self).append(d); } - } else { - $(self).append(res.responseText); - } - if(soptions.defaultValue) { $("select",self).val(soptions.defaultValue); } - $("select",self).attr({name:cm.index || cm.name, id: "gs_"+cm.name}); - if(soptions.attr) {$("select",self).attr(soptions.attr);} - $("select",self).css({width: "100%"}); - // preserve autoserch - if(soptions.dataInit !== undefined) { soptions.dataInit($("select",self)[0]); } - if(soptions.dataEvents !== undefined) { bindEvents($("select",self)[0],soptions.dataEvents); } - if(p.autosearch===true){ - $("select",self).change(function(e){ - triggerToolbar(); - return false; - }); - } - res=null; - } - }, $.jgrid.ajaxOptions, $t.p.ajaxSelectOptions || {} )); - } else { - var oSv; - if(cm.searchoptions && cm.searchoptions.value) { - oSv = cm.searchoptions.value; - } else if(cm.editoptions && cm.editoptions.value) { - oSv = cm.editoptions.value; - } - if (oSv) { - var elem = document.createElement("select"); - elem.style.width = "100%"; - $(elem).attr({name:cm.index || cm.name, id: "gs_"+cm.name}); - var so, sv, ov; - if(typeof oSv === "string") { - so = oSv.split(";"); - for(var k=0; k"); - if(soptions.attr) {$("input",thd).attr(soptions.attr);} - if(soptions.dataInit !== undefined) { soptions.dataInit($("input",thd)[0]); } - if(soptions.dataEvents !== undefined) { bindEvents($("input",thd)[0], soptions.dataEvents); } - if(p.autosearch===true){ - if(p.searchOnEnter) { - $("input",thd).keypress(function(e){ - var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0; - if(key == 13){ - triggerToolbar(); - return false; - } - return this; - }); - } else { - $("input",thd).keydown(function(e){ - var key = e.which; - switch (key) { - case 13: - return false; - case 9 : - case 16: - case 37: - case 38: - case 39: - case 40: - case 27: - break; - default : - if(timeoutHnd) { clearTimeout(timeoutHnd); } - timeoutHnd = setTimeout(function(){triggerToolbar();},500); - } - }); - } - } - break; - } - } - $(th).append(thd); - $(tr).append(th); - }); - $("table thead",$t.grid.hDiv).append(tr); - this.ftoolbar = true; - this.triggerToolbar = triggerToolbar; - this.clearToolbar = clearToolbar; - this.toggleToolbar = toggleToolbar; - }); - } -}); -})(jQuery); \ No newline at end of file diff --git a/addons/base/static/lib/jquery.jqGrid/js/grid.filter.js b/addons/base/static/lib/jquery.jqGrid/js/grid.filter.js deleted file mode 100644 index c0c9d07c240..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/grid.filter.js +++ /dev/null @@ -1,675 +0,0 @@ -/* - * jqFilter jQuery jqGrid filter addon. - * Copyright (c) 2011, Tony Tomov, tony@trirand.com - * Dual licensed under the MIT and GPL licenses - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl-2.0.html - * - * The work is inspired from this Stefan Pirvu - * http://www.codeproject.com/KB/scripting/json-filtering.aspx - * - * The filter uses JSON entities to hold filter rules and groups. Here is an example of a filter: - -{ "groupOp": "AND", - "groups" : [ - { "groupOp": "OR", - "rules": [ - { "field": "name", "op": "eq", "data": "England" }, - { "field": "id", "op": "le", "data": "5"} - ] - } - ], - "rules": [ - { "field": "name", "op": "eq", "data": "Romania" }, - { "field": "id", "op": "le", "data": "1"} - ] -} -*/ -/*global jQuery, $ */ - -(function ($) { - -$.fn.jqFilter = function( arg ) { - if (typeof arg === 'string') { - - var fn = $.fn.jqFilter[arg]; - if (!fn) { - throw ("jqFilter - No such method: " + arg); - } - var args = $.makeArray(arguments).slice(1); - return fn.apply(this,args); - } - - var p = $.extend(true,{ - filter: null, - columns: [], - onChange : null, - checkValues : null, - error: false, - errmsg : "", - errorcheck : true, - showQuery : true, - sopt : null, - ops : [ - {"name": "eq", "description": "equal", "operator":"="}, - {"name": "ne", "description": "not equal", "operator":"<>"}, - {"name": "lt", "description": "less", "operator":"<"}, - {"name": "le", "description": "less or equal","operator":"<="}, - {"name": "gt", "description": "greater", "operator":">"}, - {"name": "ge", "description": "greater or equal", "operator":">="}, - {"name": "bw", "description": "begins with", "operator":"LIKE"}, - {"name": "bn", "description": "does not begin with", "operator":"NOT LIKE"}, - {"name": "in", "description": "in", "operator":"IN"}, - {"name": "ni", "description": "not in", "operator":"NOT IN"}, - {"name": "ew", "description": "ends with", "operator":"LIKE"}, - {"name": "en", "description": "does not end with", "operator":"NOT LIKE"}, - {"name": "cn", "description": "contains", "operator":"LIKE"}, - {"name": "nc", "description": "does not contain", "operator":"NOT LIKE"}, - {"name": "nu", "description": "is null", "operator":"IS NULL"}, - {"name": "nn", "description": "is not null", "operator":"IS NOT NULL"} - ], - numopts : ['eq','ne', 'lt', 'le', 'gt', 'ge', 'nu', 'nn', 'in', 'ni'], - stropts : ['eq', 'ne', 'bw', 'bn', 'ew', 'en', 'cn', 'nc', 'nu', 'nn', 'in', 'ni'], - _gridsopt : [], // grid translated strings, do not tuch - groupOps : ["AND", "OR"], - groupButton : true - }, arg || {}); - return this.each( function() { - if (this.filter) {return;} - this.p = p; - // setup filter in case if they is not defined - if (this.p.filter === null || this.p.filter === undefined) { - this.p.filter = { - groupOp: this.p.groupOps[0], - rules: [], - groups: [] - }; - } - var i, len = this.p.columns.length, cl; - - // translating the options - if(this.p._gridsopt.length) { - // ['eq','ne','lt','le','gt','ge','bw','bn','in','ni','ew','en','cn','nc'] - for(i=0;i"); - } - /* - *Perform checking. - * - */ - var checkData = function(val, colModelItem) { - var ret = [true,""]; - if($.isFunction(colModelItem.searchrules)) { - ret = colModelItem.searchrules(val, colModelItem); - } else if($.jgrid && $.jgrid.checkValues) { - try { - ret = $.jgrid.checkValues(val, -1, null, colModelItem.searchrules, colModelItem.label); - } catch (e) {} - } - if(ret && ret.length && ret[0] === false) { - p.error = !ret[0]; - p.errmsg = ret[1]; - } - }, - randId = function() { - return Math.floor(Math.random()*10000).toString(); - }; - - this.onchange = function ( ){ - // clear any error - this.p.error = false; - this.p.errmsg=""; - return $.isFunction(this.p.onChange) ? this.p.onChange.call( this, this.p ) : false; - }; - /* - * Redrow the filter every time when new field is added/deleted - * and field is changed - */ - this.reDraw = function() { - $("table.group:first",this).remove(); - var t = this.createTableForGroup(p.filter, null); - $(this).append(t); - }; - /* - * Creates a grouping data for the filter - * @param group - object - * @param parentgroup - object - */ - this.createTableForGroup = function(group, parentgroup) { - var that = this, i; - - // this table will hold all the group (tables) and rules (rows) - var table = $(""); - // create error message row - if(parentgroup === null) { - $(table).append(""); - } - - var tr = $(""); - $(table).append(tr); - // this header will hold the group operator type and group action buttons for - // creating subgroup "+ {}", creating rule "+" or deleting the group "-" - var th = $(""); - tr.append(th); - - // dropdown for: choosing group operator type - var groupOpSelect = $(""); - th.append(groupOpSelect); - // populate dropdown with all posible group operators: or, and - var str= "", selected; - for (i = 0; i < p.groupOps.length; i++) { - selected = group.groupOp === that.p.groupOps[i] ? " selected='selected'" :""; - str += ""; - } - - groupOpSelect - .append(str) - .bind('change',function() { - group.groupOp = $(groupOpSelect).val(); - that.onchange(); // signals that the filter has changed - }); - - // button for adding a new subgroup - var inputAddSubgroup; - if(this.p.groupButton) { - inputAddSubgroup = $(""); - inputAddSubgroup.bind('click',function() { - if (group.groups === undefined ) { - group.groups = []; - } - - group.groups.push({ - groupOp: p.groupOps[0], - rules: [], - groups: [] - }); // adding a new group - - that.reDraw(); // the html has changed, force reDraw - - that.onchange(); // signals that the filter has changed - return false; - }); - } else { - inputAddSubgroup = ""; - } - th.append(inputAddSubgroup); - - // button for adding a new rule - var inputAddRule = $(""), cm; - inputAddRule.bind('click',function() { - //if(!group) { group = {};} - if (group.rules === undefined) { - group.rules = []; - } - for (i = 0; i < that.p.columns.length; i++) { - // but show only serchable and serchhidden = true fields - var searchable = (typeof that.p.columns[i].search === 'undefined') ? true: that.p.columns[i].search , - hidden = (that.p.columns[i].hidden === true), - ignoreHiding = (that.p.columns[i].searchoptions.searchhidden === true); - if ((ignoreHiding && searchable) || (searchable && !hidden)) { - cm = that.p.columns[i]; - break; - } - } - var opr; - if( cm.searchoptions.sopt ) {opr = cm.searchoptions.sopt;} - else if(that.p.sopt) { opr= that.p.sopt; } - else if (cm.searchtype === 'string') {opr = that.p.stropts;} - else {opr = that.p.numopts;} - - group.rules.push({ - field: cm.name, - op: opr[0], - data: "" - }); // adding a new rule - - that.reDraw(); // the html has changed, force reDraw - // for the moment no change have been made to the rule, so - // this will not trigger onchange event - return false; - }); - th.append(inputAddRule); - - // button for delete the group - if (parentgroup !== null) { // ignore the first group - var inputDeleteGroup = $(""); - th.append(inputDeleteGroup); - inputDeleteGroup.bind('click',function() { - // remove group from parent - for (i = 0; i < parentgroup.groups.length; i++) { - if (parentgroup.groups[i] === group) { - parentgroup.groups.splice(i, 1); - break; - } - } - - that.reDraw(); // the html has changed, force reDraw - - that.onchange(); // signals that the filter has changed - return false; - }); - } - - // append subgroup rows - if (group.groups !== undefined) { - for (i = 0; i < group.groups.length; i++) { - var trHolderForSubgroup = $(""); - table.append(trHolderForSubgroup); - - var tdFirstHolderForSubgroup = $(""); - trHolderForSubgroup.append(tdFirstHolderForSubgroup); - - var tdMainHolderForSubgroup = $(""); - tdMainHolderForSubgroup.append(this.createTableForGroup(group.groups[i], group)); - trHolderForSubgroup.append(tdMainHolderForSubgroup); - } - } - if(group.groupOp === undefined) { - group.groupOp = that.p.groupOps[0]; - } - - // append rules rows - if (group.rules !== undefined) { - for (i = 0; i < group.rules.length; i++) { - table.append( - this.createTableRowForRule(group.rules[i], group) - ); - } - } - - return table; - }; - /* - * Create the rule data for the filter - */ - this.createTableRowForRule = function(rule, group) { - // save current entity in a variable so that it could - // be referenced in anonimous method calls - - var that=this, tr = $(""), - //document.createElement("tr"), - - // first column used for padding - //tdFirstHolderForRule = document.createElement("td"), - i, op, trpar, cm, str="", selected; - //tdFirstHolderForRule.setAttribute("class", "first"); - tr.append(""); - - - // create field container - var ruleFieldTd = $(""); - tr.append(ruleFieldTd); - - - // dropdown for: choosing field - var ruleFieldSelect = $(""); - ruleFieldTd.append(ruleFieldSelect); - ruleFieldSelect.bind('change',function() { - rule.field = $(ruleFieldSelect).val(); - - trpar = $(this).parents("tr:first"); - for (i=0;i"+that.p.ops[i].description+""; - } - } - $(".selectopts",trpar).empty().append( s ); - - // data - $(".data",trpar).empty().append( elm ); - $(".input-elm",trpar).bind('change',function() { - rule.data = $(this).val(); - if($.isArray(rule.data)) { rule.data = rule.data.join(","); } - that.onchange(); // signals that the filter has changed - }); - setTimeout(function(){ //IE, Opera, Chrome - rule.data = $(elm).val(); - that.onchange(); // signals that the filter has changed - }, 0); - }); - - // populate drop down with user provided column definitions - var j=0; - for (i = 0; i < that.p.columns.length; i++) { - // but show only serchable and serchhidden = true fields - var searchable = (typeof that.p.columns[i].search === 'undefined') ? true: that.p.columns[i].search , - hidden = (that.p.columns[i].hidden === true), - ignoreHiding = (that.p.columns[i].searchoptions.searchhidden === true); - if ((ignoreHiding && searchable) || (searchable && !hidden)) { - selected = ""; - if(rule.field === that.p.columns[i].name) { - selected = " selected='selected'"; - j=i; - } - str += ""; - } - } - ruleFieldSelect.append( str ); - - - // create operator container - var ruleOperatorTd = $(""); - tr.append(ruleOperatorTd); - cm = p.columns[j]; - // create it here so it can be referentiated in the onchange event - //var RD = that.createElement(rule, rule.data); - cm.searchoptions.id = randId(); - var ruleDataInput = $.jgrid.createEl(cm.inputtype,cm.searchoptions, rule.data, true, that.p.ajaxSelectOptions, true); - - // dropdown for: choosing operator - var ruleOperatorSelect = $(""); - ruleOperatorTd.append(ruleOperatorSelect); - ruleOperatorSelect.bind('change',function() { - rule.op = $(ruleOperatorSelect).val(); - trpar = $(this).parents("tr:first"); - var rd = $(".input-elm",trpar)[0]; - if (rule.op === "nu" || rule.op === "nn") { // disable for operator "is null" and "is not null" - rule.data = ""; - rd.value = ""; - rd.setAttribute("readonly", "true"); - rd.setAttribute("disabled", "true"); - } else { - rd.removeAttribute("readonly"); - rd.removeAttribute("disabled"); - } - - that.onchange(); // signals that the filter has changed - }); - - // populate drop down with all available operators - if( cm.searchoptions.sopt ) {op = cm.searchoptions.sopt;} - else if(that.p.sopt) { op= that.p.sopt; } - else if (cm.searchtype === 'string') {op = p.stropts;} - else {op = that.p.numopts;} - str=""; - for ( i = 0; i < that.p.ops.length; i++) { - if($.inArray(that.p.ops[i].name, op) !== -1) { - selected = rule.op === that.p.ops[i].name ? " selected='selected'" : ""; - str += ""; - } - } - ruleOperatorSelect.append( str ); - // create data container - var ruleDataTd = $(""); - tr.append(ruleDataTd); - - // textbox for: data - // is created previously - //ruleDataInput.setAttribute("type", "text"); - ruleDataTd.append(ruleDataInput); - - $(ruleDataInput) - .addClass("input-elm") - .bind('change', function() { - rule.data = $(this).val(); - if($.isArray(rule.data)) { rule.data = rule.data.join(","); } - - that.onchange(); // signals that the filter has changed - }); - - // create action container - var ruleDeleteTd = $(""); - tr.append(ruleDeleteTd); - - // create button for: delete rule - var ruleDeleteInput = $(""); - ruleDeleteTd.append(ruleDeleteInput); - //$(ruleDeleteInput).html("").height(20).width(30).button({icons: { primary: "ui-icon-minus", text:false}}); - ruleDeleteInput.bind('click',function() { - // remove rule from group - for (i = 0; i < group.rules.length; i++) { - if (group.rules[i] === rule) { - group.rules.splice(i, 1); - break; - } - } - - that.reDraw(); // the html has changed, force reDraw - - that.onchange(); // signals that the filter has changed - return false; - }); - - return tr; - }; - - this.getStringForGroup = function(group) { - var s = "(", index; - if (group.groups !== undefined) { - for (index = 0; index < group.groups.length; index++) { - if (s.length > 1) { - s += " " + group.groupOp + " "; - } - try { - s += this.getStringForGroup(group.groups[index]); - } catch (eg) {alert(eg);} - } - } - - if (group.rules !== undefined) { - try{ - for (index = 0; index < group.rules.length; index++) { - if (s.length > 1) { - s += " " + group.groupOp + " "; - } - s += this.getStringForRule(group.rules[index]); - } - } catch (e) {alert(e);} - } - - s += ")"; - - if (s === "()") { - return ""; // ignore groups that don't have rules - } else { - return s; - } - }; - this.getStringForRule = function(rule) { - var opUF = "",opC="", i, cm, ret, val, - numtypes = ['int', 'integer', 'float', 'number', 'currency']; // jqGrid - for (i = 0; i < this.p.ops.length; i++) { - if (this.p.ops[i].name === rule.op) { - opUF = this.p.ops[i].operator; - opC = this.p.ops[i].name; - break; - } - } - for (i=0; i 1) { - if (group.groupOp === "OR") { - s += " || "; - } - else { - s += " && "; - } - } - s += getStringForGroup(group.groups[index]); - } - } - - if (group.rules !== undefined) { - for (index = 0; index < group.rules.length; index++) { - if (s.length > 1) { - if (group.groupOp === "OR") { - s += " || "; - } - else { - s += " && "; - } - } - s += getStringRule(group.rules[index]); - } - } - - s += ")"; - - if (s === "()") { - return ""; // ignore groups that don't have rules - } else { - return s; - } - } - - return getStringForGroup(this.p.filter); - }; - - // Here we init the filter - this.reDraw(); - - if(this.p.showQuery) { - this.onchange(); - } - // mark is as created so that it will not be created twice on this element - this.filter = true; - }); -}; -$.extend($.fn.jqFilter,{ - /* - * Return SQL like string. Can be used directly - */ - toSQLString : function() - { - var s =""; - this.each(function(){ - s = this.toUserFriendlyString(); - }); - return s; - }, - /* - * Return filter data as object. - */ - filterData : function() - { - var s; - this.each(function(){ - s = this.p.filter; - }); - return s; - - }, - getParameter : function (param) { - if(param !== undefined) { - if (this.p.hasOwnProperty(param) ) { - return this.p[param]; - } - } - return this.p; - }, - resetFilter: function() { - return this.each(function(){ - this.resetFilter(); - }); - } - -}); -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/grid.formedit.js b/addons/base/static/lib/jquery.jqGrid/js/grid.formedit.js deleted file mode 100644 index aea99600a62..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/grid.formedit.js +++ /dev/null @@ -1,1888 +0,0 @@ -(function($){ -/** - * jqGrid extension for form editing Grid Data - * Tony Tomov tony@trirand.com - * http://trirand.com/blog/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl-2.0.html -**/ -/*global xmlJsonClass, jQuery, $ */ -var rp_ge = null; -$.jgrid.extend({ - searchGrid : function (p) { - p = $.extend({ - recreateFilter: false, - drag: true, - sField:'searchField', - sValue:'searchString', - sOper: 'searchOper', - sFilter: 'filters', - loadDefaults: true, // this options activates loading of default filters from grid's postData for Multipe Search only. - beforeShowSearch: null, - afterShowSearch : null, - onInitializeSearch: null, - closeAfterSearch : false, - closeAfterReset: false, - closeOnEscape : false, - multipleSearch : false, - multipleGroup : false, - //cloneSearchRowOnAdd: true, - top : 0, - left: 0, - jqModal : true, - modal: true, - resize : false, - width: 450, - height: 'auto', - dataheight: 'auto', - showQuery: true, - errorcheck : true, - // translation - // if you want to change or remove the order change it in sopt - // ['eq','ne','lt','le','gt','ge','bw','bn','in','ni','ew','en','cn','nc'], - sopt: null, - stringResult: undefined, - onClose : null, - onSearch : null, - onReset : null, - overlay : 10, - columns : [] - }, $.jgrid.search, p || {}); - return this.each(function() { - var $t = this; - if(!$t.grid) {return;} - var fid = "fbox_"+$t.p.id, - showFrm = true, - IDs = {themodal:'editmod'+fid,modalhead:'edithd'+fid,modalcontent:'editcnt'+fid, scrollelm : fid}, - defaultFilters = $t.p.postData[p.sFilter], - fil = $("
").insertBefore("#gview_"+$t.p.id); - if(typeof(defaultFilters) === "string") { - defaultFilters = $.jgrid.parse( defaultFilters ); - } - if(p.recreateFilter === true) { - $("#"+IDs.themodal).remove(); - } - function showFilter() { - if($.isFunction(p.beforeShowSearch)) { - showFrm = p.beforeShowSearch($("#"+fid)); - if(typeof(showFrm) === "undefined") { - showFrm = true; - } - } - if(showFrm) { - $.jgrid.viewModal("#"+IDs.themodal,{gbox:"#gbox_"+fid,jqm:p.jqModal, modal:p.modal, overlay: p.overlay}); - if($.isFunction(p.afterShowSearch)) { - p.afterShowSearch($("#"+fid)); - } - } - } - if ( $("#"+IDs.themodal).html() !== null ) { - showFilter(); - } else { - if($.isFunction(p.onInitializeSearch) ) { - p.onInitializeSearch($("#"+fid)); - } - var columns = $.extend([],$t.p.colModel), - bS =""+p.Find+"", - bC =""+p.Reset+"", - bQ = ""; - if(p.showQuery) { - bQ ="Query"; - } - var bt = "

"+bC+""+bQ+bS+"
", - colnm, found=false; - if(!p.columns.length) { - $.each(columns, function(i,n){ - if(!n.label) { - n.label = $t.p.colNames[i]; - } - // find first searchable column and set it if no default filter - if(!found) { - var searchable = (typeof n.search === 'undefined') ? true: n.search , - hidden = (n.hidden === true), - ignoreHiding = (n.searchoptions && n.searchoptions.searchhidden === true); - if ((ignoreHiding && searchable) || (searchable && !hidden)) { - found = true; - colnm = n.name; - } - } - }); - } else { - columns = p.columns; - } - // old behaviour - if( (!defaultFilters && colnm) || p.multipleSearch === false ) { - defaultFilters = {"groupOp": "AND",rules:[{"field":colnm,"op":"eq","data":""}]}; - } - $("#"+fid).jqFilter({ - columns : columns, - filter: p.loadDefaults ? defaultFilters : null, - showQuery: p.showQuery, - errorcheck : p.errorcheck, - sopt: p.sopt, - groupButton : p.multipleGroup, - _gridsopt : $.jgrid.search.odata, - onChange : function( sp ) { - if(this.p.showQuery) { - $('.query',this).html(this.toUserFriendlyString()); - } - } - }); - fil.append( bt ); - if(p.multipleSearch === false) { - $(".add-rule","#"+fid).hide(); - $(".delete-rule","#"+fid).hide(); - } - if($.isFunction(p.onInitializeSearch) ) { - p.onInitializeSearch($("#"+fid)); - } - $.jgrid.createModal(IDs ,fil,p,"#gview_"+$t.p.id,$("#gbox_"+$t.p.id)[0]); - if(bQ) { - $("#"+fid+"_query").bind('click', function(e){ - $(".queryresult", fil).toggle(); - return false; - }); - } - if (p.stringResult===undefined) { - // to provide backward compatibility, inferring stringResult value from multipleSearch - p.stringResult = p.multipleSearch; - } - $("#"+fid+"_search").bind('click', function(){ - var fl = $("#"+fid), - sdata={}, res , - filters = fl.jqFilter('filterData'); - if(p.errorcheck) { - fl[0].hideError(); - if(!p.showQuery) { fl.jqFilter('toSQLString'); } - if(fl[0].p.error) { - fl[0].showError(); - return false; - } - } - - if(p.stringResult && $t.p.datatype !== "local") { - try { - // xmlJsonClass or JSON.stringify - res = xmlJsonClass.toJson(filters, '', '', false); - } catch (e) { - try { - res = JSON.stringify(filters); - } catch (e2) { } - } - if(typeof(res)==="string") { - sdata[p.sFilter] = res; - $.each([p.sField,p.sValue, p.sOper], function() { sdata[this] = "";}); - } - } else { - if(p.multipleSearch) { - sdata[p.sFilter] = filters; - $.each([p.sField,p.sValue, p.sOper], function() { sdata[this] = "";}); - } else { - sdata[p.sField] = filters.rules[0].field; - sdata[p.sValue] = filters.rules[0].data; - sdata[p.sOper] = filters.rules[0].op; - sdata[p.sFilter] = ""; - } - } - $t.p.search = true; - $.extend($t.p.postData,sdata); - $($t).trigger("reloadGrid",[{page:1}]); - if($.isFunction(p.onSearch) ) { - p.onSearch(); - } - if(p.closeAfterSearch) { - $.jgrid.hideModal("#"+IDs.themodal,{gb:"#gbox_"+$t.p.id,jqm:p.jqModal,onClose: p.onClose}); - } - return false; - }); - $("#"+fid+"_reset").bind('click', function(){ - var sdata={}, - fl = $("#"+fid); - $t.p.search = false; - if(p.multipleSearch===false) { - sdata[p.sField] = sdata[p.sValue] = sdata[p.sOper] = ""; - } else { - sdata[p.sFilter] = ""; - } - fl[0].resetFilter(); - $.extend($t.p.postData,sdata); - $($t).trigger("reloadGrid",[{page:1}]); - if($.isFunction(p.onReset) ) { - p.onReset(); - } - return false; - }); - showFilter(); - $(".fm-button:not(.ui-state-disabled)",fil).hover( - function(){$(this).addClass('ui-state-hover');}, - function(){$(this).removeClass('ui-state-hover');} - ); - } - }); - }, - editGridRow : function(rowid, p){ - p = $.extend({ - top : 0, - left: 0, - width: 300, - height: 'auto', - dataheight: 'auto', - modal: false, - overlay : 10, - drag: true, - resize: true, - url: null, - mtype : "POST", - clearAfterAdd :true, - closeAfterEdit : false, - reloadAfterSubmit : true, - onInitializeForm: null, - beforeInitData: null, - beforeShowForm: null, - afterShowForm: null, - beforeSubmit: null, - afterSubmit: null, - onclickSubmit: null, - afterComplete: null, - onclickPgButtons : null, - afterclickPgButtons: null, - editData : {}, - recreateForm : false, - jqModal : true, - closeOnEscape : false, - addedrow : "first", - topinfo : '', - bottominfo: '', - saveicon : [], - closeicon : [], - savekey: [false,13], - navkeys: [false,38,40], - checkOnSubmit : false, - checkOnUpdate : false, - _savedData : {}, - processing : false, - onClose : null, - ajaxEditOptions : {}, - serializeEditData : null, - viewPagerButtons : true - }, $.jgrid.edit, p || {}); - rp_ge = p; - return this.each(function(){ - var $t = this; - if (!$t.grid || !rowid) { return; } - var gID = $t.p.id, - frmgr = "FrmGrid_"+gID,frmtb = "TblGrid_"+gID, - IDs = {themodal:'editmod'+gID,modalhead:'edithd'+gID,modalcontent:'editcnt'+gID, scrollelm : frmgr}, - onBeforeShow = $.isFunction(rp_ge.beforeShowForm) ? rp_ge.beforeShowForm : false, - onAfterShow = $.isFunction(rp_ge.afterShowForm) ? rp_ge.afterShowForm : false, - onBeforeInit = $.isFunction(rp_ge.beforeInitData) ? rp_ge.beforeInitData : false, - onInitializeForm = $.isFunction(rp_ge.onInitializeForm) ? rp_ge.onInitializeForm : false, - copydata = null, - showFrm = true, - maxCols = 1, maxRows=0, postdata, extpost, newData, diff; - if (rowid === "new") { - rowid = "_empty"; - p.caption=rp_ge.addCaption; - } else { - p.caption=rp_ge.editCaption; - } - if(p.recreateForm===true && $("#"+IDs.themodal).html() !== null) { - $("#"+IDs.themodal).remove(); - } - var closeovrl = true; - if(p.checkOnUpdate && p.jqModal && !p.modal) { - closeovrl = false; - } - function getFormData(){ - $(".FormElement", "#"+frmtb).each(function(i) { - var celm = $(".customelement", this); - if (celm.length) { - var elem = celm[0], nm = $(elem).attr('name'); - $.each($t.p.colModel, function(i,n){ - if(this.name === nm && this.editoptions && $.isFunction(this.editoptions.custom_value)) { - try { - postdata[nm] = this.editoptions.custom_value($("#"+$.jgrid.jqID(nm),"#"+frmtb),'get'); - if (postdata[nm] === undefined) { throw "e1"; } - } catch (e) { - if (e==="e1") { $.jgrid.info_dialog(jQuery.jgrid.errors.errcap,"function 'custom_value' "+$.jgrid.edit.msg.novalue,jQuery.jgrid.edit.bClose);} - else { $.jgrid.info_dialog(jQuery.jgrid.errors.errcap,e.message,jQuery.jgrid.edit.bClose); } - } - return true; - } - }); - } else { - switch ($(this).get(0).type) { - case "checkbox": - if($(this).attr("checked")) { - postdata[this.name]= $(this).val(); - }else { - var ofv = $(this).attr("offval"); - postdata[this.name]= ofv; - } - break; - case "select-one": - postdata[this.name]= $("option:selected",this).val(); - extpost[this.name]= $("option:selected",this).text(); - break; - case "select-multiple": - postdata[this.name]= $(this).val(); - if(postdata[this.name]) { postdata[this.name] = postdata[this.name].join(","); } - else { postdata[this.name] =""; } - var selectedText = []; - $("option:selected",this).each( - function(i,selected){ - selectedText[i] = $(selected).text(); - } - ); - extpost[this.name]= selectedText.join(","); - break; - case "password": - case "text": - case "textarea": - case "button": - postdata[this.name] = $(this).val(); - - break; - } - if($t.p.autoencode) { postdata[this.name] = $.jgrid.htmlEncode(postdata[this.name]); } - } - }); - return true; - } - function createData(rowid,obj,tb,maxcols){ - var nm, hc,trdata, cnt=0,tmp, dc,elc, retpos=[], ind=false, - tdtmpl = "  ", tmpl="", i; //*2 - for (i =1; i<=maxcols;i++) { - tmpl += tdtmpl; - } - if(rowid != '_empty') { - ind = $(obj).jqGrid("getInd",rowid); - } - $(obj.p.colModel).each( function(i) { - nm = this.name; - // hidden fields are included in the form - if(this.editrules && this.editrules.edithidden === true) { - hc = false; - } else { - hc = this.hidden === true ? true : false; - } - dc = hc ? "style='display:none'" : ""; - if ( nm !== 'cb' && nm !== 'subgrid' && this.editable===true && nm !== 'rn') { - if(ind === false) { - tmp = ""; - } else { - if(nm == obj.p.ExpandColumn && obj.p.treeGrid === true) { - tmp = $("td:eq("+i+")",obj.rows[ind]).text(); - } else { - try { - tmp = $.unformat($("td:eq("+i+")",obj.rows[ind]),{rowId:rowid, colModel:this},i); - } catch (_) { - tmp = $("td:eq("+i+")",obj.rows[ind]).html(); - } - } - } - var opt = $.extend({}, this.editoptions || {} ,{id:nm,name:nm}), - frmopt = $.extend({}, {elmprefix:'',elmsuffix:'',rowabove:false,rowcontent:''}, this.formoptions || {}), - rp = parseInt(frmopt.rowpos,10) || cnt+1, - cp = parseInt((parseInt(frmopt.colpos,10) || 1)*2,10); - if(rowid == "_empty" && opt.defaultValue ) { - tmp = $.isFunction(opt.defaultValue) ? opt.defaultValue() : opt.defaultValue; - } - if(!this.edittype) { this.edittype = "text"; } - if($t.p.autoencode) { tmp = $.jgrid.htmlDecode(tmp); } - elc = $.jgrid.createEl(this.edittype,opt,tmp,false,$.extend({},$.jgrid.ajaxOptions,obj.p.ajaxSelectOptions || {})); - if(tmp === "" && this.edittype == "checkbox") {tmp = $(elc).attr("offval");} - if(tmp === "" && this.edittype == "select") {tmp = $("option:eq(0)",elc).text();} - if(rp_ge.checkOnSubmit || rp_ge.checkOnUpdate) { rp_ge._savedData[nm] = tmp; } - $(elc).addClass("FormElement"); - if(this.edittype == 'text' || this.edittype == 'textarea') { - $(elc).addClass("ui-widget-content ui-corner-all"); - } - trdata = $(tb).find("tr[rowpos="+rp+"]"); - if(frmopt.rowabove) { - var newdata = $(""+frmopt.rowcontent+""); - $(tb).append(newdata); - newdata[0].rp = rp; - } - if ( trdata.length===0 ) { - trdata = $("").addClass("FormData").attr("id","tr_"+nm); - $(trdata).append(tmpl); - $(tb).append(trdata); - trdata[0].rp = rp; - } - $("td:eq("+(cp-2)+")",trdata[0]).html( typeof frmopt.label === 'undefined' ? obj.p.colNames[i]: frmopt.label); - $("td:eq("+(cp-1)+")",trdata[0]).append(frmopt.elmprefix).append(elc).append(frmopt.elmsuffix); - retpos[cnt] = i; - cnt++; - } - }); - if( cnt > 0) { - var idrow = $(""); - idrow[0].rp = cnt+999; - $(tb).append(idrow); - if(rp_ge.checkOnSubmit || rp_ge.checkOnUpdate) { rp_ge._savedData[obj.p.id+"_id"] = rowid; } - } - return retpos; - } - function fillData(rowid,obj,fmid){ - var nm,cnt=0,tmp, fld,opt,vl,vlc; - if(rp_ge.checkOnSubmit || rp_ge.checkOnUpdate) {rp_ge._savedData = {};rp_ge._savedData[obj.p.id+"_id"]=rowid;} - var cm = obj.p.colModel; - if(rowid == '_empty') { - $(cm).each(function(i){ - nm = this.name; - opt = $.extend({}, this.editoptions || {} ); - fld = $("#"+$.jgrid.jqID(nm),"#"+fmid); - if(fld[0] !== null) { - vl = ""; - if(opt.defaultValue ) { - vl = $.isFunction(opt.defaultValue) ? opt.defaultValue() : opt.defaultValue; - if(fld[0].type=='checkbox') { - vlc = vl.toLowerCase(); - if(vlc.search(/(false|0|no|off|undefined)/i)<0 && vlc!=="") { - fld[0].checked = true; - fld[0].defaultChecked = true; - fld[0].value = vl; - } else { - fld.attr({checked:"",defaultChecked:""}); - } - } else {fld.val(vl); } - } else { - if( fld[0].type=='checkbox' ) { - fld[0].checked = false; - fld[0].defaultChecked = false; - vl = $(fld).attr("offval"); - } else if (fld[0].type && fld[0].type.substr(0,6)=='select') { - fld[0].selectedIndex = 0; - } else { - fld.val(vl); - } - } - if(rp_ge.checkOnSubmit===true || rp_ge.checkOnUpdate) { rp_ge._savedData[nm] = vl; } - } - }); - $("#id_g","#"+fmid).val(rowid); - return; - } - var tre = $(obj).jqGrid("getInd",rowid,true); - if(!tre) { return; } - $('td',tre).each( function(i) { - nm = cm[i].name; - // hidden fields are included in the form - if ( nm !== 'cb' && nm !== 'subgrid' && nm !== 'rn' && cm[i].editable===true) { - if(nm == obj.p.ExpandColumn && obj.p.treeGrid === true) { - tmp = $(this).text(); - } else { - try { - tmp = $.unformat($(this),{rowId:rowid, colModel:cm[i]},i); - } catch (_) { - tmp = $(this).html(); - } - } - if($t.p.autoencode) { tmp = $.jgrid.htmlDecode(tmp); } - if(rp_ge.checkOnSubmit===true || rp_ge.checkOnUpdate) { rp_ge._savedData[nm] = tmp; } - nm = $.jgrid.jqID(nm); - switch (cm[i].edittype) { - case "password": - case "text": - case "button" : - case "image": - $("#"+nm,"#"+fmid).val(tmp); - break; - case "textarea": - if(tmp == " " || tmp == " " || (tmp.length==1 && tmp.charCodeAt(0)==160) ) {tmp='';} - $("#"+nm,"#"+fmid).val(tmp); - break; - case "select": - var opv = tmp.split(","); - opv = $.map(opv,function(n){return $.trim(n);}); - $("#"+nm+" option","#"+fmid).each(function(j){ - if (!cm[i].editoptions.multiple && (opv[0] == $.trim($(this).text()) || opv[0] == $.trim($(this).val())) ){ - this.selected= true; - } else if (cm[i].editoptions.multiple){ - if( $.inArray($.trim($(this).text()), opv ) > -1 || $.inArray($.trim($(this).val()), opv ) > -1 ){ - this.selected = true; - }else{ - this.selected = false; - } - } else { - this.selected = false; - } - }); - break; - case "checkbox": - tmp = tmp+""; - if(cm[i].editoptions && cm[i].editoptions.value) { - var cb = cm[i].editoptions.value.split(":"); - if(cb[0] == tmp) { - $("#"+nm,"#"+fmid).attr("checked",true); - $("#"+nm,"#"+fmid).attr("defaultChecked",true); //ie - } else { - $("#"+nm,"#"+fmid).attr("checked",false); - $("#"+nm,"#"+fmid).attr("defaultChecked",""); //ie - } - } else { - tmp = tmp.toLowerCase(); - if(tmp.search(/(false|0|no|off|undefined)/i)<0 && tmp!=="") { - $("#"+nm,"#"+fmid).attr("checked",true); - $("#"+nm,"#"+fmid).attr("defaultChecked",true); //ie - } else { - $("#"+nm,"#"+fmid).attr("checked",false); - $("#"+nm,"#"+fmid).attr("defaultChecked",""); //ie - } - } - break; - case 'custom' : - try { - if(cm[i].editoptions && $.isFunction(cm[i].editoptions.custom_value)) { - cm[i].editoptions.custom_value($("#"+nm,"#"+fmid),'set',tmp); - } else { throw "e1"; } - } catch (e) { - if (e=="e1") { $.jgrid.info_dialog(jQuery.jgrid.errors.errcap,"function 'custom_value' "+$.jgrid.edit.msg.nodefined,jQuery.jgrid.edit.bClose);} - else { $.jgrid.info_dialog(jQuery.jgrid.errors.errcap,e.message,jQuery.jgrid.edit.bClose); } - } - break; - } - cnt++; - } - }); - if(cnt>0) { $("#id_g","#"+frmtb).val(rowid); } - } - function postIt() { - var copydata, ret=[true,"",""], onCS = {}, opers = $t.p.prmNames, idname, oper, key; - if($.isFunction(rp_ge.beforeCheckValues)) { - var retvals = rp_ge.beforeCheckValues(postdata,$("#"+frmgr),postdata[$t.p.id+"_id"] == "_empty" ? opers.addoper : opers.editoper); - if(retvals && typeof(retvals) === 'object') { postdata = retvals; } - } - for( key in postdata ){ - if(postdata.hasOwnProperty(key)) { - ret = $.jgrid.checkValues(postdata[key],key,$t); - if(ret[0] === false) { break; } - } - } - if(ret[0]) { - if( $.isFunction( rp_ge.onclickSubmit)) { onCS = rp_ge.onclickSubmit(rp_ge,postdata) || {}; } - if( $.isFunction(rp_ge.beforeSubmit)) { ret = rp_ge.beforeSubmit(postdata,$("#"+frmgr)); } - } - - if(ret[0] && !rp_ge.processing) { - rp_ge.processing = true; - $("#sData", "#"+frmtb+"_2").addClass('ui-state-active'); - oper = opers.oper; - idname = opers.id; - // we add to pos data array the action - the name is oper - postdata[oper] = ($.trim(postdata[$t.p.id+"_id"]) == "_empty") ? opers.addoper : opers.editoper; - if(postdata[oper] != opers.addoper) { - postdata[idname] = postdata[$t.p.id+"_id"]; - } else { - // check to see if we have allredy this field in the form and if yes lieve it - if( postdata[idname] === undefined ) { postdata[idname] = postdata[$t.p.id+"_id"]; } - } - delete postdata[$t.p.id+"_id"]; - postdata = $.extend(postdata,rp_ge.editData,onCS); - - var ajaxOptions = $.extend({ - url: rp_ge.url ? rp_ge.url : $($t).jqGrid('getGridParam','editurl'), - type: rp_ge.mtype, - data: $.isFunction(rp_ge.serializeEditData) ? rp_ge.serializeEditData(postdata) : postdata, - complete:function(data,Status){ - if(Status != "success") { - ret[0] = false; - if ($.isFunction(rp_ge.errorTextFormat)) { - ret[1] = rp_ge.errorTextFormat(data); - } else { - ret[1] = Status + " Status: '" + data.statusText + "'. Error code: " + data.status; - } - } else { - // data is posted successful - // execute aftersubmit with the returned data from server - if( $.isFunction(rp_ge.afterSubmit) ) { - ret = rp_ge.afterSubmit(data,postdata); - } - } - if(ret[0] === false) { - $("#FormError>td","#"+frmtb).html(ret[1]); - $("#FormError","#"+frmtb).show(); - } else { - // remove some values if formattaer select or checkbox - $.each($t.p.colModel, function(i,n){ - if(extpost[this.name] && this.formatter && this.formatter=='select') { - try {delete extpost[this.name];} catch (e) {} - } - }); - postdata = $.extend(postdata,extpost); - if($t.p.autoencode) { - $.each(postdata,function(n,v){ - postdata[n] = $.jgrid.htmlDecode(v); - }); - } - rp_ge.reloadAfterSubmit = rp_ge.reloadAfterSubmit && $t.p.datatype != "local"; - // the action is add - if(postdata[oper] == opers.addoper ) { - //id processing - // user not set the id ret[2] - if(!ret[2]) { ret[2] = (parseInt($t.p.records,10)+1)+""; } - postdata[idname] = ret[2]; - if(rp_ge.closeAfterAdd) { - if(rp_ge.reloadAfterSubmit) { $($t).trigger("reloadGrid"); } - else { - $($t).jqGrid("addRowData",ret[2],postdata,p.addedrow); - $($t).jqGrid("setSelection",ret[2]); - } - $.jgrid.hideModal("#"+IDs.themodal,{gb:"#gbox_"+gID,jqm:p.jqModal,onClose: rp_ge.onClose}); - } else if (rp_ge.clearAfterAdd) { - if(rp_ge.reloadAfterSubmit) { $($t).trigger("reloadGrid"); } - else { $($t).jqGrid("addRowData",ret[2],postdata,p.addedrow); } - fillData("_empty",$t,frmgr); - } else { - if(rp_ge.reloadAfterSubmit) { $($t).trigger("reloadGrid"); } - else { $($t).jqGrid("addRowData",ret[2],postdata,p.addedrow); } - } - } else { - // the action is update - if(rp_ge.reloadAfterSubmit) { - $($t).trigger("reloadGrid"); - if( !rp_ge.closeAfterEdit ) { setTimeout(function(){$($t).jqGrid("setSelection",postdata[idname]);},1000); } - } else { - if($t.p.treeGrid === true) { - $($t).jqGrid("setTreeRow",postdata[idname],postdata); - } else { - $($t).jqGrid("setRowData",postdata[idname],postdata); - } - } - if(rp_ge.closeAfterEdit) { $.jgrid.hideModal("#"+IDs.themodal,{gb:"#gbox_"+gID,jqm:p.jqModal,onClose: rp_ge.onClose}); } - } - if($.isFunction(rp_ge.afterComplete)) { - copydata = data; - setTimeout(function(){rp_ge.afterComplete(copydata,postdata,$("#"+frmgr));copydata=null;},500); - } - } - rp_ge.processing=false; - if(rp_ge.checkOnSubmit || rp_ge.checkOnUpdate) { - $("#"+frmgr).data("disabled",false); - if(rp_ge._savedData[$t.p.id+"_id"] !="_empty"){ - for(var key in rp_ge._savedData) { - if(postdata[key]) { - rp_ge._savedData[key] = postdata[key]; - } - } - } - } - $("#sData", "#"+frmtb+"_2").removeClass('ui-state-active'); - try{$(':input:visible',"#"+frmgr)[0].focus();} catch (e){} - }, - error:function(xhr,st,err){ - $("#FormError>td","#"+frmtb).html(st+ " : "+err); - $("#FormError","#"+frmtb).show(); - rp_ge.processing=false; - $("#"+frmgr).data("disabled",false); - $("#sData", "#"+frmtb+"_2").removeClass('ui-state-active'); - } - }, $.jgrid.ajaxOptions, rp_ge.ajaxEditOptions ); - - if (!ajaxOptions.url && !rp_ge.useDataProxy) { - if ($.isFunction($t.p.dataProxy)) { - rp_ge.useDataProxy = true; - } else { - ret[0]=false; ret[1] += " "+$.jgrid.errors.nourl; - } - } - if (ret[0]) { - if (rp_ge.useDataProxy) { $t.p.dataProxy.call($t, ajaxOptions, "set_"+$t.p.id); } - else { $.ajax(ajaxOptions); } - } - } - if(ret[0] === false) { - $("#FormError>td","#"+frmtb).html(ret[1]); - $("#FormError","#"+frmtb).show(); - // return; - } - } - function compareData(nObj, oObj ) { - var ret = false,key; - for (key in nObj) { - if(nObj[key] != oObj[key]) { - ret = true; - break; - } - } - return ret; - } - function checkUpdates () { - var stat = true; - $("#FormError","#"+frmtb).hide(); - if(rp_ge.checkOnUpdate) { - postdata = {}; extpost={}; - getFormData(); - newData = $.extend({},postdata,extpost); - diff = compareData(newData,rp_ge._savedData); - if(diff) { - $("#"+frmgr).data("disabled",true); - $(".confirm","#"+IDs.themodal).show(); - stat = false; - } - } - return stat; - } - function restoreInline() - { - if (rowid !== "_empty" && typeof($t.p.savedRow) !== "undefined" && $t.p.savedRow.length > 0 && $.isFunction($.fn.jqGrid.restoreRow)) { - for (var i=0;i<$t.p.savedRow.length;i++) { - if ($t.p.savedRow[i].id == rowid) { - $($t).jqGrid('restoreRow',rowid); - break; - } - } - } - } - function updateNav(cr,totr){ - if (cr===0) { $("#pData","#"+frmtb+"_2").addClass('ui-state-disabled'); } else { $("#pData","#"+frmtb+"_2").removeClass('ui-state-disabled'); } - if (cr==totr) { $("#nData","#"+frmtb+"_2").addClass('ui-state-disabled'); } else { $("#nData","#"+frmtb+"_2").removeClass('ui-state-disabled'); } - } - function getCurrPos() { - var rowsInGrid = $($t).jqGrid("getDataIDs"), - selrow = $("#id_g","#"+frmtb).val(), - pos = $.inArray(selrow,rowsInGrid); - return [pos,rowsInGrid]; - } - - if ( $("#"+IDs.themodal).html() !== null ) { - if(onBeforeInit) { - showFrm = onBeforeInit($("#"+frmgr)); - if(typeof(showFrm) == "undefined") { - showFrm = true; - } - } - if(showFrm === false) { return; } - restoreInline(); - $(".ui-jqdialog-title","#"+IDs.modalhead).html(p.caption); - $("#FormError","#"+frmtb).hide(); - if(rp_ge.topinfo) { - $(".topinfo","#"+frmtb+"_2").html(rp_ge.topinfo); - $(".tinfo","#"+frmtb+"_2").show(); - } else { - $(".tinfo","#"+frmtb+"_2").hide(); - } - if(rp_ge.bottominfo) { - $(".bottominfo","#"+frmtb+"_2").html(rp_ge.bottominfo); - $(".binfo","#"+frmtb+"_2").show(); - } else { - $(".binfo","#"+frmtb+"_2").hide(); - } - // filldata - fillData(rowid,$t,frmgr); - /// - if(rowid=="_empty" || !rp_ge.viewPagerButtons) { - $("#pData, #nData","#"+frmtb+"_2").hide(); - } else { - $("#pData, #nData","#"+frmtb+"_2").show(); - } - if(rp_ge.processing===true) { - rp_ge.processing=false; - $("#sData", "#"+frmtb+"_2").removeClass('ui-state-active'); - } - if($("#"+frmgr).data("disabled")===true) { - $(".confirm","#"+IDs.themodal).hide(); - $("#"+frmgr).data("disabled",false); - } - if(onBeforeShow) { onBeforeShow($("#"+frmgr)); } - $("#"+IDs.themodal).data("onClose",rp_ge.onClose); - $.jgrid.viewModal("#"+IDs.themodal,{gbox:"#gbox_"+gID,jqm:p.jqModal, jqM: false, overlay: p.overlay, modal:p.modal}); - if(!closeovrl) { - $(".jqmOverlay").click(function(){ - if(!checkUpdates()) { return false; } - $.jgrid.hideModal("#"+IDs.themodal,{gb:"#gbox_"+gID,jqm:p.jqModal, onClose: rp_ge.onClose}); - return false; - }); - } - if(onAfterShow) { onAfterShow($("#"+frmgr)); } - } else { - var dh = isNaN(p.dataheight) ? p.dataheight : p.dataheight+"px", - frm = $("
").data("disabled",false), - tbl = $("
"); - if(onBeforeInit) { - showFrm = onBeforeInit($("#"+frmgr)); - if(typeof(showFrm) == "undefined") { - showFrm = true; - } - } - if(showFrm === false) { return; } - restoreInline(); - $($t.p.colModel).each( function(i) { - var fmto = this.formoptions; - maxCols = Math.max(maxCols, fmto ? fmto.colpos || 0 : 0 ); - maxRows = Math.max(maxRows, fmto ? fmto.rowpos || 0 : 0 ); - }); - $(frm).append(tbl); - var flr = $(""); - flr[0].rp = 0; - $(tbl).append(flr); - //topinfo - flr = $(""+rp_ge.topinfo+""); - flr[0].rp = 0; - $(tbl).append(flr); - // set the id. - // use carefull only to change here colproperties. - // create data - var rtlb = $t.p.direction == "rtl" ? true :false, - bp = rtlb ? "nData" : "pData", - bn = rtlb ? "pData" : "nData"; - createData(rowid,$t,tbl,maxCols); - // buttons at footer - var bP = "", - bN = "", - bS =""+p.bSubmit+"", - bC =""+p.bCancel+""; - var bt = ""; - bt += ""; - bt += "

"+bS+bC+"
"; - if(maxRows > 0) { - var sd=[]; - $.each($(tbl)[0].rows,function(i,r){ - sd[i] = r; - }); - sd.sort(function(a,b){ - if(a.rp > b.rp) {return 1;} - if(a.rp < b.rp) {return -1;} - return 0; - }); - $.each(sd, function(index, row) { - $('tbody',tbl).append(row); - }); - } - p.gbox = "#gbox_"+gID; - var cle = false; - if(p.closeOnEscape===true){ - p.closeOnEscape = false; - cle = true; - } - var tms = $("").append(frm).append(bt); - $.jgrid.createModal(IDs,tms,p,"#gview_"+$t.p.id,$("#gbox_"+$t.p.id)[0]); - if(rtlb) { - $("#pData, #nData","#"+frmtb+"_2").css("float","right"); - $(".EditButton","#"+frmtb+"_2").css("text-align","left"); - } - if(rp_ge.topinfo) { $(".tinfo","#"+frmtb+"_2").show(); } - if(rp_ge.bottominfo) { $(".binfo","#"+frmtb+"_2").show(); } - tms = null; bt=null; - $("#"+IDs.themodal).keydown( function( e ) { - var wkey = e.target; - if ($("#"+frmgr).data("disabled")===true ) { return false; }//?? - if(rp_ge.savekey[0] === true && e.which == rp_ge.savekey[1]) { // save - if(wkey.tagName != "TEXTAREA") { - $("#sData", "#"+frmtb+"_2").trigger("click"); - return false; - } - } - if(e.which === 27) { - if(!checkUpdates()) { return false; } - if(cle) { $.jgrid.hideModal(this,{gb:p.gbox,jqm:p.jqModal, onClose: rp_ge.onClose}); } - return false; - } - if(rp_ge.navkeys[0]===true) { - if($("#id_g","#"+frmtb).val() == "_empty") { return true; } - if(e.which == rp_ge.navkeys[1]){ //up - $("#pData", "#"+frmtb+"_2").trigger("click"); - return false; - } - if(e.which == rp_ge.navkeys[2]){ //down - $("#nData", "#"+frmtb+"_2").trigger("click"); - return false; - } - } - }); - if(p.checkOnUpdate) { - $("a.ui-jqdialog-titlebar-close span","#"+IDs.themodal).removeClass("jqmClose"); - $("a.ui-jqdialog-titlebar-close","#"+IDs.themodal).unbind("click") - .click(function(){ - if(!checkUpdates()) { return false; } - $.jgrid.hideModal("#"+IDs.themodal,{gb:"#gbox_"+gID,jqm:p.jqModal,onClose: rp_ge.onClose}); - return false; - }); - } - p.saveicon = $.extend([true,"left","ui-icon-disk"],p.saveicon); - p.closeicon = $.extend([true,"left","ui-icon-close"],p.closeicon); - // beforeinitdata after creation of the form - if(p.saveicon[0]===true) { - $("#sData","#"+frmtb+"_2").addClass(p.saveicon[1] == "right" ? 'fm-button-icon-right' : 'fm-button-icon-left') - .append(""); - } - if(p.closeicon[0]===true) { - $("#cData","#"+frmtb+"_2").addClass(p.closeicon[1] == "right" ? 'fm-button-icon-right' : 'fm-button-icon-left') - .append(""); - } - if(rp_ge.checkOnSubmit || rp_ge.checkOnUpdate) { - bS =""+p.bYes+""; - bN =""+p.bNo+""; - bC =""+p.bExit+""; - var ii, zI = p.zIndex || 999; zI ++; - if ($.browser.msie && $.browser.version ==6) { - ii = ''; - } else { ii="";} - $("
"+p.saveData+"

"+bS+bN+bC+"
").insertAfter("#"+frmgr); - $("#sNew","#"+IDs.themodal).click(function(){ - postIt(); - $("#"+frmgr).data("disabled",false); - $(".confirm","#"+IDs.themodal).hide(); - return false; - }); - $("#nNew","#"+IDs.themodal).click(function(){ - $(".confirm","#"+IDs.themodal).hide(); - $("#"+frmgr).data("disabled",false); - setTimeout(function(){$(":input","#"+frmgr)[0].focus();},0); - return false; - }); - $("#cNew","#"+IDs.themodal).click(function(){ - $(".confirm","#"+IDs.themodal).hide(); - $("#"+frmgr).data("disabled",false); - $.jgrid.hideModal("#"+IDs.themodal,{gb:"#gbox_"+gID,jqm:p.jqModal,onClose: rp_ge.onClose}); - return false; - }); - } - // here initform - only once - if(onInitializeForm) { onInitializeForm($("#"+frmgr)); } - if(rowid=="_empty" || !rp_ge.viewPagerButtons) { $("#pData,#nData","#"+frmtb+"_2").hide(); } else { $("#pData,#nData","#"+frmtb+"_2").show(); } - if(onBeforeShow) { onBeforeShow($("#"+frmgr)); } - $("#"+IDs.themodal).data("onClose",rp_ge.onClose); - $.jgrid.viewModal("#"+IDs.themodal,{gbox:"#gbox_"+gID,jqm:p.jqModal, overlay: p.overlay,modal:p.modal}); - if(!closeovrl) { - $(".jqmOverlay").click(function(){ - if(!checkUpdates()) { return false; } - $.jgrid.hideModal("#"+IDs.themodal,{gb:"#gbox_"+gID,jqm:p.jqModal, onClose: rp_ge.onClose}); - return false; - }); - } - if(onAfterShow) { onAfterShow($("#"+frmgr)); } - $(".fm-button","#"+IDs.themodal).hover( - function(){$(this).addClass('ui-state-hover');}, - function(){$(this).removeClass('ui-state-hover');} - ); - $("#sData", "#"+frmtb+"_2").click(function(e){ - postdata = {}; extpost={}; - $("#FormError","#"+frmtb).hide(); - // all depend on ret array - //ret[0] - succes - //ret[1] - msg if not succes - //ret[2] - the id that will be set if reload after submit false - getFormData(); - if(postdata[$t.p.id+"_id"] == "_empty") { postIt(); } - else if(p.checkOnSubmit===true ) { - newData = $.extend({},postdata,extpost); - diff = compareData(newData,rp_ge._savedData); - if(diff) { - $("#"+frmgr).data("disabled",true); - $(".confirm","#"+IDs.themodal).show(); - } else { - postIt(); - } - } else { - postIt(); - } - return false; - }); - $("#cData", "#"+frmtb+"_2").click(function(e){ - if(!checkUpdates()) { return false; } - $.jgrid.hideModal("#"+IDs.themodal,{gb:"#gbox_"+gID,jqm:p.jqModal,onClose: rp_ge.onClose}); - return false; - }); - $("#nData", "#"+frmtb+"_2").click(function(e){ - if(!checkUpdates()) { return false; } - $("#FormError","#"+frmtb).hide(); - var npos = getCurrPos(); - npos[0] = parseInt(npos[0],10); - if(npos[0] != -1 && npos[1][npos[0]+1]) { - if($.isFunction(p.onclickPgButtons)) { - p.onclickPgButtons('next',$("#"+frmgr),npos[1][npos[0]]); - } - fillData(npos[1][npos[0]+1],$t,frmgr); - $($t).jqGrid("setSelection",npos[1][npos[0]+1]); - if($.isFunction(p.afterclickPgButtons)) { - p.afterclickPgButtons('next',$("#"+frmgr),npos[1][npos[0]+1]); - } - updateNav(npos[0]+1,npos[1].length-1); - } - return false; - }); - $("#pData", "#"+frmtb+"_2").click(function(e){ - if(!checkUpdates()) { return false; } - $("#FormError","#"+frmtb).hide(); - var ppos = getCurrPos(); - if(ppos[0] != -1 && ppos[1][ppos[0]-1]) { - if($.isFunction(p.onclickPgButtons)) { - p.onclickPgButtons('prev',$("#"+frmgr),ppos[1][ppos[0]]); - } - fillData(ppos[1][ppos[0]-1],$t,frmgr); - $($t).jqGrid("setSelection",ppos[1][ppos[0]-1]); - if($.isFunction(p.afterclickPgButtons)) { - p.afterclickPgButtons('prev',$("#"+frmgr),ppos[1][ppos[0]-1]); - } - updateNav(ppos[0]-1,ppos[1].length-1); - } - return false; - }); - } - var posInit =getCurrPos(); - updateNav(posInit[0],posInit[1].length-1); - - }); - }, - viewGridRow : function(rowid, p){ - p = $.extend({ - top : 0, - left: 0, - width: 0, - height: 'auto', - dataheight: 'auto', - modal: false, - overlay: 10, - drag: true, - resize: true, - jqModal: true, - closeOnEscape : false, - labelswidth: '30%', - closeicon: [], - navkeys: [false,38,40], - onClose: null, - beforeShowForm : null, - beforeInitData : null, - viewPagerButtons : true - }, $.jgrid.view, p || {}); - return this.each(function(){ - var $t = this; - if (!$t.grid || !rowid) { return; } - if(!p.imgpath) { p.imgpath= $t.p.imgpath; } - // I hate to rewrite code, but ... - var gID = $t.p.id, - frmgr = "ViewGrid_"+gID , frmtb = "ViewTbl_"+gID, - IDs = {themodal:'viewmod'+gID,modalhead:'viewhd'+gID,modalcontent:'viewcnt'+gID, scrollelm : frmgr}, - onBeforeInit = $.isFunction(p.beforeInitData) ? p.beforeInitData : false, - showFrm = true, - maxCols = 1, maxRows=0; - function focusaref(){ //Sfari 3 issues - if(p.closeOnEscape===true || p.navkeys[0]===true) { - setTimeout(function(){$(".ui-jqdialog-titlebar-close","#"+IDs.modalhead).focus();},0); - } - } - function createData(rowid,obj,tb,maxcols){ - var nm, hc,trdata, cnt=0,tmp, dc, retpos=[], ind=false, - tdtmpl = "  ", tmpl="", - tdtmpl2 = "  ", - fmtnum = ['integer','number','currency'],max1 =0, max2=0 ,maxw,setme, viewfld; - for (var i =1;i<=maxcols;i++) { - tmpl += i == 1 ? tdtmpl : tdtmpl2; - } - // find max number align rigth with property formatter - $(obj.p.colModel).each( function(i) { - if(this.editrules && this.editrules.edithidden === true) { - hc = false; - } else { - hc = this.hidden === true ? true : false; - } - if(!hc && this.align==='right') { - if(this.formatter && $.inArray(this.formatter,fmtnum) !== -1 ) { - max1 = Math.max(max1,parseInt(this.width,10)); - } else { - max2 = Math.max(max2,parseInt(this.width,10)); - } - } - }); - maxw = max1 !==0 ? max1 : max2 !==0 ? max2 : 0; - ind = $(obj).jqGrid("getInd",rowid); - $(obj.p.colModel).each( function(i) { - nm = this.name; - setme = false; - // hidden fields are included in the form - if(this.editrules && this.editrules.edithidden === true) { - hc = false; - } else { - hc = this.hidden === true ? true : false; - } - dc = hc ? "style='display:none'" : ""; - viewfld = (typeof this.viewable != 'boolean') ? true : this.viewable; - if ( nm !== 'cb' && nm !== 'subgrid' && nm !== 'rn' && viewfld) { - if(ind === false) { - tmp = ""; - } else { - if(nm == obj.p.ExpandColumn && obj.p.treeGrid === true) { - tmp = $("td:eq("+i+")",obj.rows[ind]).text(); - } else { - tmp = $("td:eq("+i+")",obj.rows[ind]).html(); - } - } - setme = this.align === 'right' && maxw !==0 ? true : false; - var opt = $.extend({}, this.editoptions || {} ,{id:nm,name:nm}), - frmopt = $.extend({},{rowabove:false,rowcontent:''}, this.formoptions || {}), - rp = parseInt(frmopt.rowpos,10) || cnt+1, - cp = parseInt((parseInt(frmopt.colpos,10) || 1)*2,10); - if(frmopt.rowabove) { - var newdata = $(""+frmopt.rowcontent+""); - $(tb).append(newdata); - newdata[0].rp = rp; - } - trdata = $(tb).find("tr[rowpos="+rp+"]"); - if ( trdata.length===0 ) { - trdata = $("").addClass("FormData").attr("id","trv_"+nm); - $(trdata).append(tmpl); - $(tb).append(trdata); - trdata[0].rp = rp; - } - $("td:eq("+(cp-2)+")",trdata[0]).html(''+ (typeof frmopt.label === 'undefined' ? obj.p.colNames[i]: frmopt.label)+''); - $("td:eq("+(cp-1)+")",trdata[0]).append(""+tmp+"").attr("id","v_"+nm); - if(setme){ - $("td:eq("+(cp-1)+") span",trdata[0]).css({'text-align':'right',width:maxw+"px"}); - } - retpos[cnt] = i; - cnt++; - } - }); - if( cnt > 0) { - var idrow = $(""); - idrow[0].rp = cnt+99; - $(tb).append(idrow); - } - return retpos; - } - function fillData(rowid,obj){ - var nm, hc,cnt=0,tmp, opt,trv; - trv = $(obj).jqGrid("getInd",rowid,true); - if(!trv) { return; } - $('td',trv).each( function(i) { - nm = obj.p.colModel[i].name; - // hidden fields are included in the form - if(obj.p.colModel[i].editrules && obj.p.colModel[i].editrules.edithidden === true) { - hc = false; - } else { - hc = obj.p.colModel[i].hidden === true ? true : false; - } - if ( nm !== 'cb' && nm !== 'subgrid' && nm !== 'rn') { - if(nm == obj.p.ExpandColumn && obj.p.treeGrid === true) { - tmp = $(this).text(); - } else { - tmp = $(this).html(); - } - opt = $.extend({},obj.p.colModel[i].editoptions || {}); - nm = $.jgrid.jqID("v_"+nm); - $("#"+nm+" span","#"+frmtb).html(tmp); - if (hc) { $("#"+nm,"#"+frmtb).parents("tr:first").hide(); } - cnt++; - } - }); - if(cnt>0) { $("#id_g","#"+frmtb).val(rowid); } - } - function updateNav(cr,totr){ - if (cr===0) { $("#pData","#"+frmtb+"_2").addClass('ui-state-disabled'); } else { $("#pData","#"+frmtb+"_2").removeClass('ui-state-disabled'); } - if (cr==totr) { $("#nData","#"+frmtb+"_2").addClass('ui-state-disabled'); } else { $("#nData","#"+frmtb+"_2").removeClass('ui-state-disabled'); } - } - function getCurrPos() { - var rowsInGrid = $($t).jqGrid("getDataIDs"), - selrow = $("#id_g","#"+frmtb).val(), - pos = $.inArray(selrow,rowsInGrid); - return [pos,rowsInGrid]; - } - - if ( $("#"+IDs.themodal).html() !== null ) { - if(onBeforeInit) { - showFrm = onBeforeInit($("#"+frmgr)); - if(typeof(showFrm) == "undefined") { - showFrm = true; - } - } - if(showFrm === false) { return; } - $(".ui-jqdialog-title","#"+IDs.modalhead).html(p.caption); - $("#FormError","#"+frmtb).hide(); - fillData(rowid,$t); - if($.isFunction(p.beforeShowForm)) { p.beforeShowForm($("#"+frmgr)); } - $.jgrid.viewModal("#"+IDs.themodal,{gbox:"#gbox_"+gID,jqm:p.jqModal, jqM: false, overlay: p.overlay, modal:p.modal}); - focusaref(); - } else { - var dh = isNaN(p.dataheight) ? p.dataheight : p.dataheight+"px"; - var frm = $("
"), - tbl =$("
"); - if(onBeforeInit) { - showFrm = onBeforeInit($("#"+frmgr)); - if(typeof(showFrm) == "undefined") { - showFrm = true; - } - } - if(showFrm === false) { return; } - $($t.p.colModel).each( function(i) { - var fmto = this.formoptions; - maxCols = Math.max(maxCols, fmto ? fmto.colpos || 0 : 0 ); - maxRows = Math.max(maxRows, fmto ? fmto.rowpos || 0 : 0 ); - }); - // set the id. - $(frm).append(tbl); - createData(rowid, $t, tbl, maxCols); - var rtlb = $t.p.direction == "rtl" ? true :false, - bp = rtlb ? "nData" : "pData", - bn = rtlb ? "pData" : "nData", - - // buttons at footer - bP = "", - bN = "", - bC =""+p.bClose+""; - if(maxRows > 0) { - var sd=[]; - $.each($(tbl)[0].rows,function(i,r){ - sd[i] = r; - }); - sd.sort(function(a,b){ - if(a.rp > b.rp) {return 1;} - if(a.rp < b.rp) {return -1;} - return 0; - }); - $.each(sd, function(index, row) { - $('tbody',tbl).append(row); - }); - } - p.gbox = "#gbox_"+gID; - var cle = false; - if(p.closeOnEscape===true){ - p.closeOnEscape = false; - cle = true; - } - var bt = $("").append(frm).append("
"+bC+"
"); - $.jgrid.createModal(IDs,bt,p,"#gview_"+$t.p.id,$("#gview_"+$t.p.id)[0]); - if(rtlb) { - $("#pData, #nData","#"+frmtb+"_2").css("float","right"); - $(".EditButton","#"+frmtb+"_2").css("text-align","left"); - } - if(!p.viewPagerButtons) { $("#pData, #nData","#"+frmtb+"_2").hide(); } - bt = null; - $("#"+IDs.themodal).keydown( function( e ) { - if(e.which === 27) { - if(cle) { $.jgrid.hideModal(this,{gb:p.gbox,jqm:p.jqModal, onClose: p.onClose}); } - return false; - } - if(p.navkeys[0]===true) { - if(e.which === p.navkeys[1]){ //up - $("#pData", "#"+frmtb+"_2").trigger("click"); - return false; - } - if(e.which === p.navkeys[2]){ //down - $("#nData", "#"+frmtb+"_2").trigger("click"); - return false; - } - } - }); - p.closeicon = $.extend([true,"left","ui-icon-close"],p.closeicon); - if(p.closeicon[0]===true) { - $("#cData","#"+frmtb+"_2").addClass(p.closeicon[1] == "right" ? 'fm-button-icon-right' : 'fm-button-icon-left') - .append(""); - } - if($.isFunction(p.beforeShowForm)) { p.beforeShowForm($("#"+frmgr)); } - $.jgrid.viewModal("#"+IDs.themodal,{gbox:"#gbox_"+gID,jqm:p.jqModal, modal:p.modal}); - $(".fm-button:not(.ui-state-disabled)","#"+frmtb+"_2").hover( - function(){$(this).addClass('ui-state-hover');}, - function(){$(this).removeClass('ui-state-hover');} - ); - focusaref(); - $("#cData", "#"+frmtb+"_2").click(function(e){ - $.jgrid.hideModal("#"+IDs.themodal,{gb:"#gbox_"+gID,jqm:p.jqModal, onClose: p.onClose}); - return false; - }); - $("#nData", "#"+frmtb+"_2").click(function(e){ - $("#FormError","#"+frmtb).hide(); - var npos = getCurrPos(); - npos[0] = parseInt(npos[0],10); - if(npos[0] != -1 && npos[1][npos[0]+1]) { - if($.isFunction(p.onclickPgButtons)) { - p.onclickPgButtons('next',$("#"+frmgr),npos[1][npos[0]]); - } - fillData(npos[1][npos[0]+1],$t); - $($t).jqGrid("setSelection",npos[1][npos[0]+1]); - if($.isFunction(p.afterclickPgButtons)) { - p.afterclickPgButtons('next',$("#"+frmgr),npos[1][npos[0]+1]); - } - updateNav(npos[0]+1,npos[1].length-1); - } - focusaref(); - return false; - }); - $("#pData", "#"+frmtb+"_2").click(function(e){ - $("#FormError","#"+frmtb).hide(); - var ppos = getCurrPos(); - if(ppos[0] != -1 && ppos[1][ppos[0]-1]) { - if($.isFunction(p.onclickPgButtons)) { - p.onclickPgButtons('prev',$("#"+frmgr),ppos[1][ppos[0]]); - } - fillData(ppos[1][ppos[0]-1],$t); - $($t).jqGrid("setSelection",ppos[1][ppos[0]-1]); - if($.isFunction(p.afterclickPgButtons)) { - p.afterclickPgButtons('prev',$("#"+frmgr),ppos[1][ppos[0]-1]); - } - updateNav(ppos[0]-1,ppos[1].length-1); - } - focusaref(); - return false; - }); - } - var posInit =getCurrPos(); - updateNav(posInit[0],posInit[1].length-1); - }); - }, - delGridRow : function(rowids,p) { - p = $.extend({ - top : 0, - left: 0, - width: 240, - height: 'auto', - dataheight : 'auto', - modal: false, - overlay: 10, - drag: true, - resize: true, - url : '', - mtype : "POST", - reloadAfterSubmit: true, - beforeShowForm: null, - beforeInitData : null, - afterShowForm: null, - beforeSubmit: null, - onclickSubmit: null, - afterSubmit: null, - jqModal : true, - closeOnEscape : false, - delData: {}, - delicon : [], - cancelicon : [], - onClose : null, - ajaxDelOptions : {}, - processing : false, - serializeDelData : null, - useDataProxy : false - }, $.jgrid.del, p ||{}); - rp_ge = p; - return this.each(function(){ - var $t = this; - if (!$t.grid ) { return; } - if(!rowids) { return; } - var onBeforeShow = typeof p.beforeShowForm === 'function' ? true: false, - onAfterShow = typeof p.afterShowForm === 'function' ? true: false, - onBeforeInit = $.isFunction(p.beforeInitData) ? p.beforeInitData : false, - gID = $t.p.id, onCS = {}, - showFrm = true, - dtbl = "DelTbl_"+gID,postd, idname, opers, oper, - IDs = {themodal:'delmod'+gID,modalhead:'delhd'+gID,modalcontent:'delcnt'+gID, scrollelm: dtbl}; - if (jQuery.isArray(rowids)) { rowids = rowids.join(); } - if ( $("#"+IDs.themodal).html() !== null ) { - if(onBeforeInit) { - showFrm = onBeforeInit( $("#"+dtbl)); - if(typeof(showFrm) == "undefined") { - showFrm = true; - } - } - if(showFrm === false) { return; } - $("#DelData>td","#"+dtbl).text(rowids); - $("#DelError","#"+dtbl).hide(); - if( rp_ge.processing === true) { - rp_ge.processing=false; - $("#dData", "#"+dtbl).removeClass('ui-state-active'); - } - if(onBeforeShow) { p.beforeShowForm($("#"+dtbl)); } - $.jgrid.viewModal("#"+IDs.themodal,{gbox:"#gbox_"+gID,jqm:p.jqModal,jqM: false, overlay: p.overlay, modal:p.modal}); - if(onAfterShow) { p.afterShowForm($("#"+dtbl)); } - } else { - var dh = isNaN(p.dataheight) ? p.dataheight : p.dataheight+"px"; - var tbl = "
"; - tbl += ""; - // error data - tbl += ""; - tbl += ""; - tbl += ""; - // buttons at footer - tbl += "
"+p.msg+"
 
"; - var bS = ""+p.bSubmit+"", - bC = ""+p.bCancel+""; - tbl += "

"+bS+" "+bC+"
"; - p.gbox = "#gbox_"+gID; - $.jgrid.createModal(IDs,tbl,p,"#gview_"+$t.p.id,$("#gview_"+$t.p.id)[0]); - - if(onBeforeInit) { - showFrm = onBeforeInit( $("#"+dtbl) ); - if(typeof(showFrm) == "undefined") { - showFrm = true; - } - } - if(showFrm === false) { return; } - - $(".fm-button","#"+dtbl+"_2").hover( - function(){$(this).addClass('ui-state-hover');}, - function(){$(this).removeClass('ui-state-hover');} - ); - p.delicon = $.extend([true,"left","ui-icon-scissors"],p.delicon); - p.cancelicon = $.extend([true,"left","ui-icon-cancel"],p.cancelicon); - if(p.delicon[0]===true) { - $("#dData","#"+dtbl+"_2").addClass(p.delicon[1] == "right" ? 'fm-button-icon-right' : 'fm-button-icon-left') - .append(""); - } - if(p.cancelicon[0]===true) { - $("#eData","#"+dtbl+"_2").addClass(p.cancelicon[1] == "right" ? 'fm-button-icon-right' : 'fm-button-icon-left') - .append(""); - } - $("#dData","#"+dtbl+"_2").click(function(e){ - var ret=[true,""]; onCS = {}; - var postdata = $("#DelData>td","#"+dtbl).text(); //the pair is name=val1,val2,... - if( typeof p.onclickSubmit === 'function' ) { onCS = p.onclickSubmit(rp_ge, postdata) || {}; } - if( typeof p.beforeSubmit === 'function' ) { ret = p.beforeSubmit(postdata); } - if(ret[0] && !rp_ge.processing) { - rp_ge.processing = true; - $(this).addClass('ui-state-active'); - opers = $t.p.prmNames; - postd = $.extend({},rp_ge.delData, onCS); - oper = opers.oper; - postd[oper] = opers.deloper; - idname = opers.id; - postd[idname] = postdata; - - var ajaxOptions = $.extend({ - url: rp_ge.url ? rp_ge.url : $($t).jqGrid('getGridParam','editurl'), - type: p.mtype, - data: $.isFunction(p.serializeDelData) ? p.serializeDelData(postd) : postd, - complete:function(data,Status){ - if(Status != "success") { - ret[0] = false; - if ($.isFunction(rp_ge.errorTextFormat)) { - ret[1] = rp_ge.errorTextFormat(data); - } else { - ret[1] = Status + " Status: '" + data.statusText + "'. Error code: " + data.status; - } - } else { - // data is posted successful - // execute aftersubmit with the returned data from server - if( typeof rp_ge.afterSubmit === 'function' ) { - ret = rp_ge.afterSubmit(data,postd); - } - } - if(ret[0] === false) { - $("#DelError>td","#"+dtbl).html(ret[1]); - $("#DelError","#"+dtbl).show(); - } else { - if(rp_ge.reloadAfterSubmit && $t.p.datatype != "local") { - $($t).trigger("reloadGrid"); - } else { - var toarr = []; - toarr = postdata.split(","); - if($t.p.treeGrid===true){ - try {$($t).jqGrid("delTreeNode",toarr[0]);} catch(e){} - } else { - for(var i=0;itd","#"+dtbl).html(st+ " : "+err); - $("#DelError","#"+dtbl).show(); - rp_ge.processing=false; - $("#dData", "#"+dtbl+"_2").removeClass('ui-state-active'); - } - }, $.jgrid.ajaxOptions, p.ajaxDelOptions); - - - if (!ajaxOptions.url && !rp_ge.useDataProxy) { - if ($.isFunction($t.p.dataProxy)) { - rp_ge.useDataProxy = true; - } else { - ret[0]=false; ret[1] += " "+$.jgrid.errors.nourl; - } - } - if (ret[0]) { - if (rp_ge.useDataProxy) { $t.p.dataProxy.call($t, ajaxOptions, "del_"+$t.p.id); } - else { $.ajax(ajaxOptions); } - } - } - - if(ret[0] === false) { - $("#DelError>td","#"+dtbl).html(ret[1]); - $("#DelError","#"+dtbl).show(); - } - return false; - }); - $("#eData", "#"+dtbl+"_2").click(function(e){ - $.jgrid.hideModal("#"+IDs.themodal,{gb:"#gbox_"+gID,jqm:p.jqModal, onClose: rp_ge.onClose}); - return false; - }); - if(onBeforeShow) { p.beforeShowForm($("#"+dtbl)); } - $.jgrid.viewModal("#"+IDs.themodal,{gbox:"#gbox_"+gID,jqm:p.jqModal, overlay: p.overlay, modal:p.modal}); - if(onAfterShow) { p.afterShowForm($("#"+dtbl)); } - } - if(p.closeOnEscape===true) { - setTimeout(function(){$(".ui-jqdialog-titlebar-close","#"+IDs.modalhead).focus();},0); - } - }); - }, - navGrid : function (elem, o, pEdit,pAdd,pDel,pSearch, pView) { - o = $.extend({ - edit: true, - editicon: "ui-icon-pencil", - add: true, - addicon:"ui-icon-plus", - del: true, - delicon:"ui-icon-trash", - search: true, - searchicon:"ui-icon-search", - refresh: true, - refreshicon:"ui-icon-refresh", - refreshstate: 'firstpage', - view: false, - viewicon : "ui-icon-document", - position : "left", - closeOnEscape : true, - beforeRefresh : null, - afterRefresh : null, - cloneToTop : false - }, $.jgrid.nav, o ||{}); - return this.each(function() { - if(this.nav) { return; } - var alertIDs = {themodal:'alertmod',modalhead:'alerthd',modalcontent:'alertcnt'}, - $t = this, vwidth, vheight, twd, tdw; - if(!$t.grid || typeof elem != 'string') { return; } - if ($("#"+alertIDs.themodal).html() === null) { - if (typeof window.innerWidth != 'undefined') { - vwidth = window.innerWidth; - vheight = window.innerHeight; - } else if (typeof document.documentElement != 'undefined' && typeof document.documentElement.clientWidth != 'undefined' && document.documentElement.clientWidth !== 0) { - vwidth = document.documentElement.clientWidth; - vheight = document.documentElement.clientHeight; - } else { - vwidth=1024; - vheight=768; - } - $.jgrid.createModal(alertIDs,"
"+o.alerttext+"
",{gbox:"#gbox_"+$t.p.id,jqModal:true,drag:true,resize:true,caption:o.alertcap,top:vheight/2-25,left:vwidth/2-100,width:200,height:'auto',closeOnEscape:o.closeOnEscape},"","",true); - } - var clone = 1; - if(o.cloneToTop && $t.p.toppager) { clone = 2; } - for(var i = 0; i"), - sep = "", - pgid, elemids; - if(i===0) { - pgid = elem; - elemids = $t.p.id; - if(pgid == $t.p.toppager) { - elemids += "_top"; - clone = 1; - } - } else { - pgid = $t.p.toppager; - elemids = $t.p.id+"_top"; - } - if($t.p.direction == "rtl") { $(navtbl).attr("dir","rtl").css("float","right"); } - if (o.add) { - pAdd = pAdd || {}; - tbd = $(""); - $(tbd).append("
"+o.addtext+"
"); - $("tr",navtbl).append(tbd); - $(tbd,navtbl) - .attr({"title":o.addtitle || "",id : pAdd.id || "add_"+elemids}) - .click(function(){ - if (!$(this).hasClass('ui-state-disabled')) { - if (typeof o.addfunc == 'function') { - o.addfunc(); - } else { - $($t).jqGrid("editGridRow","new",pAdd); - } - } - return false; - }).hover( - function () { - if (!$(this).hasClass('ui-state-disabled')) { - $(this).addClass("ui-state-hover"); - } - }, - function () {$(this).removeClass("ui-state-hover");} - ); - tbd = null; - } - if (o.edit) { - tbd = $(""); - pEdit = pEdit || {}; - $(tbd).append("
"+o.edittext+"
"); - $("tr",navtbl).append(tbd); - $(tbd,navtbl) - .attr({"title":o.edittitle || "",id: pEdit.id || "edit_"+elemids}) - .click(function(){ - if (!$(this).hasClass('ui-state-disabled')) { - var sr = $t.p.selrow; - if (sr) { - if(typeof o.editfunc == 'function') { - o.editfunc(sr); - } else { - $($t).jqGrid("editGridRow",sr,pEdit); - } - } else { - $.jgrid.viewModal("#"+alertIDs.themodal,{gbox:"#gbox_"+$t.p.id,jqm:true}); - $("#jqg_alrt").focus(); - } - } - return false; - }).hover( - function () { - if (!$(this).hasClass('ui-state-disabled')) { - $(this).addClass("ui-state-hover"); - } - }, - function () {$(this).removeClass("ui-state-hover");} - ); - tbd = null; - } - if (o.view) { - tbd = $(""); - pView = pView || {}; - $(tbd).append("
"+o.viewtext+"
"); - $("tr",navtbl).append(tbd); - $(tbd,navtbl) - .attr({"title":o.viewtitle || "",id: pView.id || "view_"+elemids}) - .click(function(){ - if (!$(this).hasClass('ui-state-disabled')) { - var sr = $t.p.selrow; - if (sr) { - $($t).jqGrid("viewGridRow",sr,pView); - } else { - $.jgrid.viewModal("#"+alertIDs.themodal,{gbox:"#gbox_"+$t.p.id,jqm:true}); - $("#jqg_alrt").focus(); - } - } - return false; - }).hover( - function () { - if (!$(this).hasClass('ui-state-disabled')) { - $(this).addClass("ui-state-hover"); - } - }, - function () {$(this).removeClass("ui-state-hover");} - ); - tbd = null; - } - if (o.del) { - tbd = $(""); - pDel = pDel || {}; - $(tbd).append("
"+o.deltext+"
"); - $("tr",navtbl).append(tbd); - $(tbd,navtbl) - .attr({"title":o.deltitle || "",id: pDel.id || "del_"+elemids}) - .click(function(){ - if (!$(this).hasClass('ui-state-disabled')) { - var dr; - if($t.p.multiselect) { - dr = $t.p.selarrrow; - if(dr.length===0) { dr = null; } - } else { - dr = $t.p.selrow; - } - if(dr){ - if("function" == typeof o.delfunc){ - o.delfunc(dr); - }else{ - $($t).jqGrid("delGridRow",dr,pDel); - } - } else { - $.jgrid.viewModal("#"+alertIDs.themodal,{gbox:"#gbox_"+$t.p.id,jqm:true}); $("#jqg_alrt").focus(); - } - } - return false; - }).hover( - function () { - if (!$(this).hasClass('ui-state-disabled')) { - $(this).addClass("ui-state-hover"); - } - }, - function () {$(this).removeClass("ui-state-hover");} - ); - tbd = null; - } - if(o.add || o.edit || o.del || o.view) { $("tr",navtbl).append(sep); } - if (o.search) { - tbd = $(""); - pSearch = pSearch || {}; - $(tbd).append("
"+o.searchtext+"
"); - $("tr",navtbl).append(tbd); - $(tbd,navtbl) - .attr({"title":o.searchtitle || "",id:pSearch.id || "search_"+elemids}) - .click(function(){ - if (!$(this).hasClass('ui-state-disabled')) { - $($t).jqGrid("searchGrid",pSearch); - } - return false; - }).hover( - function () { - if (!$(this).hasClass('ui-state-disabled')) { - $(this).addClass("ui-state-hover"); - } - }, - function () {$(this).removeClass("ui-state-hover");} - ); - tbd = null; - } - if (o.refresh) { - tbd = $(""); - $(tbd).append("
"+o.refreshtext+"
"); - $("tr",navtbl).append(tbd); - $(tbd,navtbl) - .attr({"title":o.refreshtitle || "",id: "refresh_"+elemids}) - .click(function(){ - if (!$(this).hasClass('ui-state-disabled')) { - if($.isFunction(o.beforeRefresh)) { o.beforeRefresh(); } - $t.p.search = false; - try { - var gID = $t.p.id; - $t.p.postData.filters =""; - $("#fbox_"+gID).jqFilter('resetFilter'); - if($.isFunction($t.clearToolbar)) { $t.clearToolbar(false); } - } catch (e) {} - switch (o.refreshstate) { - case 'firstpage': - $($t).trigger("reloadGrid", [{page:1}]); - break; - case 'current': - $($t).trigger("reloadGrid", [{current:true}]); - break; - } - if($.isFunction(o.afterRefresh)) { o.afterRefresh(); } - } - return false; - }).hover( - function () { - if (!$(this).hasClass('ui-state-disabled')) { - $(this).addClass("ui-state-hover"); - } - }, - function () {$(this).removeClass("ui-state-hover");} - ); - tbd = null; - } - tdw = $(".ui-jqgrid").css("font-size") || "11px"; - $('body').append(""); - twd = $(navtbl).clone().appendTo("#testpg2").width(); - $("#testpg2").remove(); - $(pgid+"_"+o.position,pgid).append(navtbl); - if($t.p._nvtd) { - if(twd > $t.p._nvtd[0] ) { - $(pgid+"_"+o.position,pgid).width(twd); - $t.p._nvtd[0] = twd; - } - $t.p._nvtd[1] = twd; - } - tdw =null; twd=null; navtbl =null; - this.nav = true; - } - }); - }, - navButtonAdd : function (elem, p) { - p = $.extend({ - caption : "newButton", - title: '', - buttonicon : 'ui-icon-newwin', - onClickButton: null, - position : "last", - cursor : 'pointer' - }, p ||{}); - return this.each(function() { - if( !this.grid) { return; } - if( elem.indexOf("#") !== 0) { elem = "#"+elem; } - var findnav = $(".navtable",elem)[0], $t = this; - if (findnav) { - if( p.id && $("#"+p.id, findnav).html() !== null ) { return; } - var tbd = $(""); - if(p.buttonicon.toString().toUpperCase() == "NONE") { - $(tbd).addClass('ui-pg-button ui-corner-all').append("
"+p.caption+"
"); - } else { - $(tbd).addClass('ui-pg-button ui-corner-all').append("
"+p.caption+"
"); - } - if(p.id) {$(tbd).attr("id",p.id);} - if(p.position=='first'){ - if(findnav.rows[0].cells.length ===0 ) { - $("tr",findnav).append(tbd); - } else { - $("tr td:eq(0)",findnav).before(tbd); - } - } else { - $("tr",findnav).append(tbd); - } - $(tbd,findnav) - .attr("title",p.title || "") - .click(function(e){ - if (!$(this).hasClass('ui-state-disabled')) { - if ($.isFunction(p.onClickButton) ) { p.onClickButton.call($t,e); } - } - return false; - }) - .hover( - function () { - if (!$(this).hasClass('ui-state-disabled')) { - $(this).addClass('ui-state-hover'); - } - }, - function () {$(this).removeClass("ui-state-hover");} - ); - } - }); - }, - navSeparatorAdd:function (elem,p) { - p = $.extend({ - sepclass : "ui-separator", - sepcontent: '' - }, p ||{}); - return this.each(function() { - if( !this.grid) { return; } - if( elem.indexOf("#") !== 0) { elem = "#"+elem; } - var findnav = $(".navtable",elem)[0]; - if(findnav) { - var sep = ""+p.sepcontent+""; - $("tr",findnav).append(sep); - } - }); - }, - GridToForm : function( rowid, formid ) { - return this.each(function(){ - var $t = this; - if (!$t.grid) { return; } - var rowdata = $($t).jqGrid("getRowData",rowid); - if (rowdata) { - for(var i in rowdata) { - if ( $("[name="+i+"]",formid).is("input:radio") || $("[name="+i+"]",formid).is("input:checkbox")) { - $("[name="+i+"]",formid).each( function() { - if( $(this).val() == rowdata[i] ) { - $(this).attr("checked","checked"); - } else { - $(this).attr("checked",""); - } - }); - } else { - // this is very slow on big table and form. - $("[name="+i+"]",formid).val(rowdata[i]); - } - } - } - }); - }, - FormToGrid : function(rowid, formid, mode, position){ - return this.each(function() { - var $t = this; - if(!$t.grid) { return; } - if(!mode) { mode = 'set'; } - if(!position) { position = 'first'; } - var fields = $(formid).serializeArray(); - var griddata = {}; - $.each(fields, function(i, field){ - griddata[field.name] = field.value; - }); - if(mode=='add') { $($t).jqGrid("addRowData",rowid,griddata, position); } - else if(mode=='set') { $($t).jqGrid("setRowData",rowid,griddata); } - }); - } -}); -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/grid.grouping.js b/addons/base/static/lib/jquery.jqGrid/js/grid.grouping.js deleted file mode 100644 index 1efa53165e5..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/grid.grouping.js +++ /dev/null @@ -1,255 +0,0 @@ -// Grouping module -;(function($){ -$.jgrid.extend({ - groupingSetup : function () { - return this.each(function (){ - var $t = this, - grp = $t.p.groupingView; - if(grp !== null && ( (typeof grp === 'object') || $.isFunction(grp) ) ) { - if(!grp.groupField.length) { - $t.p.grouping = false; - } else { - for(var i=0;i"; - try { - gv = $t.formatter(hid, grp.sortnames[0][i], cp, grp.sortitems[0] ); - } catch (egv) { - gv = grp.sortnames[0][i]; - } - str += ""+icon+$.jgrid.format(grp.groupText[0], gv, grdata[n].length)+""; - for(var kk=0;kk"; - var fdata = grp.summaryval[0][n], - cm = $t.p.colModel, - vv, grlen = grdata[n].length; - for(var k=0; k ", - tplfld = "{0}"; - $.each(fdata,function(){ - if(this.nm == cm[k].name) { - if(cm[k].summaryTpl) { - tplfld = cm[k].summaryTpl; - } - if(this.st == 'avg') { - if(this.v && grlen > 0) { - this.v = (this.v/grlen); - } - } - try { - vv = $t.formatter('', this.v, k, this); - } catch (ef) { - vv = this.v; - } - tmpdata= ""+$.jgrid.format(tplfld,vv)+ ""; - return false; - } - }); - str += tmpdata; - } - str += ""; - } - }); - $("#"+$t.p.id+" tbody:first").append(str); - // free up memory - str = null; - }); - }, - groupingGroupBy : function (name, options, current) { - return this.each(function(){ - var $t = this; - if(typeof(name) == "string") { - name = [name]; - } - var grp = $t.p.groupingView; - $t.p.grouping = true; - // show previoous hidden groups if they are hidden - for(var i=0;igrid", - data: "roots>rows" - }, - jsonGrid :{ - config : "grid", - data: "data" - }, - ajaxOptions :{} - }, o || {}); - return this.each(function(){ - var $t = this; - var XmlConvert = function (xml,o) { - var cnfg = $(o.xmlGrid.config,xml)[0]; - var xmldata = $(o.xmlGrid.data,xml)[0], jstr, jstr1; - if(xmlJsonClass.xml2json && $.jgrid.parse) { - jstr = xmlJsonClass.xml2json(cnfg," "); - jstr = $.jgrid.parse(jstr); - for(var key in jstr) { - if(jstr.hasOwnProperty(key)) { - jstr1=jstr[key]; - } - } - if(xmldata) { - // save the datatype - var svdatatype = jstr.grid.datatype; - jstr.grid.datatype = 'xmlstring'; - jstr.grid.datastr = xml; - $($t).jqGrid( jstr1 ).jqGrid("setGridParam",{datatype:svdatatype}); - } else { - $($t).jqGrid( jstr1 ); - } - jstr = null;jstr1=null; - } else { - alert("xml2json or parse are not present"); - } - }; - var JsonConvert = function (jsonstr,o){ - if (jsonstr && typeof jsonstr == 'string') { - var json = $.jgrid.parse(jsonstr); - var gprm = json[o.jsonGrid.config]; - var jdata = json[o.jsonGrid.data]; - if(jdata) { - var svdatatype = gprm.datatype; - gprm.datatype = 'jsonstring'; - gprm.datastr = jdata; - $($t).jqGrid( gprm ).jqGrid("setGridParam",{datatype:svdatatype}); - } else { - $($t).jqGrid( gprm ); - } - } - }; - switch (o.imptype){ - case 'xml': - $.ajax($.extend({ - url:o.impurl, - type:o.mtype, - data: o.impData, - dataType:"xml", - complete: function(xml,stat) { - if(stat == 'success') { - XmlConvert(xml.responseXML,o); - if($.isFunction(o.importComplete)) { - o.importComplete(xml); - } - } - xml=null; - } - }, o.ajaxOptions)); - break; - case 'xmlstring' : - // we need to make just the conversion and use the same code as xml - if(o.impstring && typeof o.impstring == 'string') { - var xmld = $.jgrid.stringToDoc(o.impstring); - if(xmld) { - XmlConvert(xmld,o); - if($.isFunction(o.importComplete)) { - o.importComplete(xmld); - } - o.impstring = null; - } - xmld = null; - } - break; - case 'json': - $.ajax($.extend({ - url:o.impurl, - type:o.mtype, - data: o.impData, - dataType:"json", - complete: function(json,stat) { - if(stat == 'success') { - JsonConvert(json.responseText,o ); - if($.isFunction(o.importComplete)) { - o.importComplete(json); - } - } - json=null; - } - }, o.ajaxOptions )); - break; - case 'jsonstring' : - if(o.impstring && typeof o.impstring == 'string') { - JsonConvert(o.impstring,o ); - if($.isFunction(o.importComplete)) { - o.importComplete(o.impstring); - } - o.impstring = null; - } - break; - } - }); - }, - jqGridExport : function(o) { - o = $.extend({ - exptype : "xmlstring", - root: "grid", - ident: "\t" - }, o || {}); - var ret = null; - this.each(function () { - if(!this.grid) { return;} - var gprm = $.extend({},$(this).jqGrid("getGridParam")); - // we need to check for: - // 1.multiselect, 2.subgrid 3. treegrid and remove the unneded columns from colNames - if(gprm.rownumbers) { - gprm.colNames.splice(0,1); - gprm.colModel.splice(0,1); - } - if(gprm.multiselect) { - gprm.colNames.splice(0,1); - gprm.colModel.splice(0,1); - } - if(gprm.subGrid) { - gprm.colNames.splice(0,1); - gprm.colModel.splice(0,1); - } - gprm.knv = null; - if(gprm.treeGrid) { - for (var key in gprm.treeReader) { - if(gprm.treeReader.hasOwnProperty(key)) { - gprm.colNames.splice(gprm.colNames.length-1); - gprm.colModel.splice(gprm.colModel.length-1); - } - } - } - switch (o.exptype) { - case 'xmlstring' : - ret = "<"+o.root+">"+xmlJsonClass.json2xml(gprm,o.ident)+""; - break; - case 'jsonstring' : - ret = "{"+ xmlJsonClass.toJson(gprm,o.root,o.ident)+"}"; - if(gprm.postData.filters !== undefined) { - ret=ret.replace(/filters":"/,'filters":'); - ret=ret.replace(/}]}"/,'}]}'); - } - break; - } - }); - return ret; - }, - excelExport : function(o) { - o = $.extend({ - exptype : "remote", - url : null, - oper: "oper", - tag: "excel", - exportOptions : {} - }, o || {}); - return this.each(function(){ - if(!this.grid) { return;} - var url; - if(o.exptype == "remote") { - var pdata = $.extend({},this.p.postData); - pdata[o.oper] = o.tag; - var params = jQuery.param(pdata); - if(o.url.indexOf("?") != -1) { url = o.url+"&"+params; } - else { url = o.url+"?"+params; } - window.location = url; - } - }); - } - }); -})(jQuery); \ No newline at end of file diff --git a/addons/base/static/lib/jquery.jqGrid/js/grid.inlinedit.js b/addons/base/static/lib/jquery.jqGrid/js/grid.inlinedit.js deleted file mode 100644 index 9f8e921f7a7..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/grid.inlinedit.js +++ /dev/null @@ -1,255 +0,0 @@ -;(function($){ -/** - * jqGrid extension for manipulating Grid Data - * Tony Tomov tony@trirand.com - * http://trirand.com/blog/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl-2.0.html -**/ -$.jgrid.extend({ -//Editing - editRow : function(rowid,keys,oneditfunc,succesfunc, url, extraparam, aftersavefunc,errorfunc, afterrestorefunc) { - return this.each(function(){ - var $t = this, nm, tmp, editable, cnt=0, focus=null, svr={}, ind,cm; - if (!$t.grid ) { return; } - ind = $($t).jqGrid("getInd",rowid,true); - if( ind === false ) {return;} - editable = $(ind).attr("editable") || "0"; - if (editable == "0" && !$(ind).hasClass("not-editable-row")) { - cm = $t.p.colModel; - $('td',ind).each( function(i) { - nm = cm[i].name; - var treeg = $t.p.treeGrid===true && nm == $t.p.ExpandColumn; - if(treeg) { tmp = $("span:first",this).html();} - else { - try { - tmp = $.unformat(this,{rowId:rowid, colModel:cm[i]},i); - } catch (_) { - tmp = $(this).html(); - } - } - if ( nm != 'cb' && nm != 'subgrid' && nm != 'rn') { - if($t.p.autoencode) { tmp = $.jgrid.htmlDecode(tmp); } - svr[nm]=tmp; - if(cm[i].editable===true) { - if(focus===null) { focus = i; } - if (treeg) { $("span:first",this).html(""); } - else { $(this).html(""); } - var opt = $.extend({},cm[i].editoptions || {},{id:rowid+"_"+nm,name:nm}); - if(!cm[i].edittype) { cm[i].edittype = "text"; } - var elc = $.jgrid.createEl(cm[i].edittype,opt,tmp,true,$.extend({},$.jgrid.ajaxOptions,$t.p.ajaxSelectOptions || {})); - $(elc).addClass("editable"); - if(treeg) { $("span:first",this).append(elc); } - else { $(this).append(elc); } - //Again IE - if(cm[i].edittype == "select" && cm[i].editoptions.multiple===true && $.browser.msie) { - $(elc).width($(elc).width()); - } - cnt++; - } - } - }); - if(cnt > 0) { - svr.id = rowid; $t.p.savedRow.push(svr); - $(ind).attr("editable","1"); - $("td:eq("+focus+") input",ind).focus(); - if(keys===true) { - $(ind).bind("keydown",function(e) { - if (e.keyCode === 27) {$($t).jqGrid("restoreRow",rowid, afterrestorefunc);} - if (e.keyCode === 13) { - var ta = e.target; - if(ta.tagName == 'TEXTAREA') { return true; } - $($t).jqGrid("saveRow",rowid,succesfunc, url, extraparam, aftersavefunc,errorfunc, afterrestorefunc ); - return false; - } - e.stopPropagation(); - }); - } - if( $.isFunction(oneditfunc)) { oneditfunc.call($t, rowid); } - } - } - }); - }, - saveRow : function(rowid, succesfunc, url, extraparam, aftersavefunc,errorfunc, afterrestorefunc) { - return this.each(function(){ - var $t = this, nm, tmp={}, tmp2={}, editable, fr, cv, ind; - if (!$t.grid ) { return; } - ind = $($t).jqGrid("getInd",rowid,true); - if(ind === false) {return;} - editable = $(ind).attr("editable"); - url = url ? url : $t.p.editurl; - if (editable==="1") { - var cm; - $("td",ind).each(function(i) { - cm = $t.p.colModel[i]; - nm = cm.name; - if ( nm != 'cb' && nm != 'subgrid' && cm.editable===true && nm != 'rn') { - switch (cm.edittype) { - case "checkbox": - var cbv = ["Yes","No"]; - if(cm.editoptions ) { - cbv = cm.editoptions.value.split(":"); - } - tmp[nm]= $("input",this).attr("checked") ? cbv[0] : cbv[1]; - break; - case 'text': - case 'password': - case 'textarea': - case "button" : - tmp[nm]=$("input, textarea",this).val(); - break; - case 'select': - if(!cm.editoptions.multiple) { - tmp[nm] = $("select>option:selected",this).val(); - tmp2[nm] = $("select>option:selected", this).text(); - } else { - var sel = $("select",this), selectedText = []; - tmp[nm] = $(sel).val(); - if(tmp[nm]) { tmp[nm]= tmp[nm].join(","); } else { tmp[nm] =""; } - $("select > option:selected",this).each( - function(i,selected){ - selectedText[i] = $(selected).text(); - } - ); - tmp2[nm] = selectedText.join(","); - } - if(cm.formatter && cm.formatter == 'select') { tmp2={}; } - break; - case 'custom' : - try { - if(cm.editoptions && $.isFunction(cm.editoptions.custom_value)) { - tmp[nm] = cm.editoptions.custom_value.call($t, $(".customelement",this),'get'); - if (tmp[nm] === undefined) { throw "e2"; } - } else { throw "e1"; } - } catch (e) { - if (e=="e1") { $.jgrid.info_dialog(jQuery.jgrid.errors.errcap,"function 'custom_value' "+$.jgrid.edit.msg.nodefined,jQuery.jgrid.edit.bClose); } - if (e=="e2") { $.jgrid.info_dialog(jQuery.jgrid.errors.errcap,"function 'custom_value' "+$.jgrid.edit.msg.novalue,jQuery.jgrid.edit.bClose); } - else { $.jgrid.info_dialog(jQuery.jgrid.errors.errcap,e.message,jQuery.jgrid.edit.bClose); } - } - break; - } - cv = $.jgrid.checkValues(tmp[nm],i,$t); - if(cv[0] === false) { - cv[1] = tmp[nm] + " " + cv[1]; - return false; - } - if($t.p.autoencode) { tmp[nm] = $.jgrid.htmlEncode(tmp[nm]); } - } - }); - if (cv[0] === false){ - try { - var positions = $.jgrid.findPos($("#"+$.jgrid.jqID(rowid), $t.grid.bDiv)[0]); - $.jgrid.info_dialog($.jgrid.errors.errcap,cv[1],$.jgrid.edit.bClose,{left:positions[0],top:positions[1]}); - } catch (e) { - alert(cv[1]); - } - return; - } - if(tmp) { - var idname, opers, oper; - opers = $t.p.prmNames; - oper = opers.oper; - idname = opers.id; - tmp[oper] = opers.editoper; - tmp[idname] = rowid; - if(typeof($t.p.inlineData) == 'undefined') { $t.p.inlineData ={}; } - if(typeof(extraparam) == 'undefined') { extraparam ={}; } - tmp = $.extend({},tmp,$t.p.inlineData,extraparam); - } - if (url == 'clientArray') { - tmp = $.extend({},tmp, tmp2); - if($t.p.autoencode) { - $.each(tmp,function(n,v){ - tmp[n] = $.jgrid.htmlDecode(v); - }); - } - var resp = $($t).jqGrid("setRowData",rowid,tmp); - $(ind).attr("editable","0"); - for( var k=0;k<$t.p.savedRow.length;k++) { - if( $t.p.savedRow[k].id == rowid) {fr = k; break;} - } - if(fr >= 0) { $t.p.savedRow.splice(fr,1); } - if( $.isFunction(aftersavefunc) ) { aftersavefunc.call($t, rowid,resp); } - } else { - $("#lui_"+$t.p.id).show(); - $.ajax($.extend({ - url:url, - data: $.isFunction($t.p.serializeRowData) ? $t.p.serializeRowData.call($t, tmp) : tmp, - type: "POST", - complete: function(res,stat){ - $("#lui_"+$t.p.id).hide(); - if (stat === "success"){ - var ret; - if( $.isFunction(succesfunc)) { ret = succesfunc.call($t, res);} - else { ret = true; } - if (ret===true) { - if($t.p.autoencode) { - $.each(tmp,function(n,v){ - tmp[n] = $.jgrid.htmlDecode(v); - }); - } - tmp = $.extend({},tmp, tmp2); - $($t).jqGrid("setRowData",rowid,tmp); - $(ind).attr("editable","0"); - for( var k=0;k<$t.p.savedRow.length;k++) { - if( $t.p.savedRow[k].id == rowid) {fr = k; break;} - } - if(fr >= 0) { $t.p.savedRow.splice(fr,1); } - if( $.isFunction(aftersavefunc) ) { aftersavefunc.call($t, rowid,res); } - } else { - if($.isFunction(errorfunc) ) { - errorfunc.call($t, rowid, res, stat); - } - $($t).jqGrid("restoreRow",rowid, afterrestorefunc); - } - } - }, - error:function(res,stat){ - $("#lui_"+$t.p.id).hide(); - if($.isFunction(errorfunc) ) { - errorfunc.call($t, rowid, res, stat); - } else { - alert("Error Row: "+rowid+" Result: " +res.status+":"+res.statusText+" Status: "+stat); - } - $($t).jqGrid("restoreRow",rowid, afterrestorefunc); - } - }, $.jgrid.ajaxOptions, $t.p.ajaxRowOptions || {})); - } - $(ind).unbind("keydown"); - } - }); - }, - restoreRow : function(rowid, afterrestorefunc) { - return this.each(function(){ - var $t= this, fr, ind, ares={}; - if (!$t.grid ) { return; } - ind = $($t).jqGrid("getInd",rowid,true); - if(ind === false) {return;} - for( var k=0;k<$t.p.savedRow.length;k++) { - if( $t.p.savedRow[k].id == rowid) {fr = k; break;} - } - if(fr >= 0) { - if($.isFunction($.fn.datepicker)) { - try { - $("input.hasDatepicker","#"+$.jgrid.jqID(ind.id)).datepicker('hide'); - } catch (e) {} - } - $.each($t.p.colModel, function(i,n){ - if(this.editable === true && this.name in $t.p.savedRow[fr]) { - ares[this.name] = $t.p.savedRow[fr][this.name]; - } - }); - $($t).jqGrid("setRowData",rowid,ares); - $(ind).attr("editable","0").unbind("keydown"); - $t.p.savedRow.splice(fr,1); - } - if ($.isFunction(afterrestorefunc)) - { - afterrestorefunc.call($t, rowid); - } - }); - } -//end inline edit -}); -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/grid.jqueryui.js b/addons/base/static/lib/jquery.jqGrid/js/grid.jqueryui.js deleted file mode 100644 index 38b30919683..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/grid.jqueryui.js +++ /dev/null @@ -1,504 +0,0 @@ -;(function($){ -/* -** - * jqGrid addons using jQuery UI - * Author: Mark Williams - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl-2.0.html - * depends on jQuery UI -**/ -if ($.browser.msie && $.browser.version==8) { - $.expr[":"].hidden = function(elem) { - return elem.offsetWidth === 0 || elem.offsetHeight === 0 || - elem.style.display == "none"; - }; -} -// requiere load multiselect before grid -$.jgrid._multiselect = false; -if($.ui) { - if ($.ui.multiselect ) { - if($.ui.multiselect.prototype._setSelected) { - var setSelected = $.ui.multiselect.prototype._setSelected; - $.ui.multiselect.prototype._setSelected = function(item,selected) { - var ret = setSelected.call(this,item,selected); - if (selected && this.selectedList) { - var elt = this.element; - this.selectedList.find('li').each(function() { - if ($(this).data('optionLink')) { - $(this).data('optionLink').remove().appendTo(elt); - } - }); - } - return ret; - }; - } - if($.ui.multiselect.prototype.destroy) { - $.ui.multiselect.prototype.destroy = function() { - this.element.show(); - this.container.remove(); - if ($.Widget === undefined) { - $.widget.prototype.destroy.apply(this, arguments); - } else { - $.Widget.prototype.destroy.apply(this, arguments); - } - }; - } - $.jgrid._multiselect = true; - } -} - -$.jgrid.extend({ - sortableColumns : function (tblrow) - { - return this.each(function (){ - var ts = this; - function start() {ts.p.disableClick = true;} - var sortable_opts = { - "tolerance" : "pointer", - "axis" : "x", - "scrollSensitivity": "1", - "items": '>th:not(:has(#jqgh_cb,#jqgh_rn,#jqgh_subgrid),:hidden)', - "placeholder": { - element: function(item) { - var el = $(document.createElement(item[0].nodeName)) - .addClass(item[0].className+" ui-sortable-placeholder ui-state-highlight") - .removeClass("ui-sortable-helper")[0]; - return el; - }, - update: function(self, p) { - p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); - p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); - } - }, - "update": function(event, ui) { - var p = $(ui.item).parent(); - var th = $(">th", p); - var colModel = ts.p.colModel; - var cmMap = {}; - $.each(colModel, function(i) { cmMap[this.name]=i; }); - var permutation = []; - th.each(function(i) { - var id = $(">div", this).get(0).id.replace(/^jqgh_/, ""); - if (id in cmMap) { - permutation.push(cmMap[id]); - } - }); - - $(ts).jqGrid("remapColumns",permutation, true, true); - if ($.isFunction(ts.p.sortable.update)) { - ts.p.sortable.update(permutation); - } - setTimeout(function(){ts.p.disableClick=false;}, 50); - } - }; - if (ts.p.sortable.options) { - $.extend(sortable_opts, ts.p.sortable.options); - } else if ($.isFunction(ts.p.sortable)) { - ts.p.sortable = { "update" : ts.p.sortable }; - } - if (sortable_opts.start) { - var s = sortable_opts.start; - sortable_opts.start = function(e,ui) { - start(); - s.call(this,e,ui); - }; - } else { - sortable_opts.start = start; - } - if (ts.p.sortable.exclude) { - sortable_opts.items += ":not("+ts.p.sortable.exclude+")"; - } - tblrow.sortable(sortable_opts).data("sortable").floating = true; - }); - }, - columnChooser : function(opts) { - var self = this; - if($("#colchooser_"+self[0].p.id).length ) { return; } - var selector = $('
'); - var select = $('select', selector); - - function insert(perm,i,v) { - if(i>=0){ - var a = perm.slice(); - var b = a.splice(i,Math.max(perm.length-i,i)); - if(i>perm.length) { i = perm.length; } - a[i] = v; - return a.concat(b); - } - } - opts = $.extend({ - "width" : 420, - "height" : 240, - "classname" : null, - "done" : function(perm) { if (perm) { self.jqGrid("remapColumns", perm, true); } }, - /* msel is either the name of a ui widget class that - extends a multiselect, or a function that supports - creating a multiselect object (with no argument, - or when passed an object), and destroying it (when - passed the string "destroy"). */ - "msel" : "multiselect", - /* "msel_opts" : {}, */ - - /* dlog is either the name of a ui widget class that - behaves in a dialog-like way, or a function, that - supports creating a dialog (when passed dlog_opts) - or destroying a dialog (when passed the string - "destroy") - */ - "dlog" : "dialog", - - /* dlog_opts is either an option object to be passed - to "dlog", or (more likely) a function that creates - the options object. - The default produces a suitable options object for - ui.dialog */ - "dlog_opts" : function(opts) { - var buttons = {}; - buttons[opts.bSubmit] = function() { - opts.apply_perm(); - opts.cleanup(false); - }; - buttons[opts.bCancel] = function() { - opts.cleanup(true); - }; - return { - "buttons": buttons, - "close": function() { - opts.cleanup(true); - }, - "modal" : opts.modal ? opts.modal : false, - "resizable": opts.resizable ? opts.resizable : true, - "width": opts.width+20 - }; - }, - /* Function to get the permutation array, and pass it to the - "done" function */ - "apply_perm" : function() { - $('option',select).each(function(i) { - if (this.selected) { - self.jqGrid("showCol", colModel[this.value].name); - } else { - self.jqGrid("hideCol", colModel[this.value].name); - } - }); - - var perm = []; - //fixedCols.slice(0); - $('option[selected]',select).each(function() { perm.push(parseInt(this.value,10)); }); - $.each(perm, function() { delete colMap[colModel[parseInt(this,10)].name]; }); - $.each(colMap, function() { - var ti = parseInt(this,10); - perm = insert(perm,ti,ti); - }); - if (opts.done) { - opts.done.call(self, perm); - } - }, - /* Function to cleanup the dialog, and select. Also calls the - done function with no permutation (to indicate that the - columnChooser was aborted */ - "cleanup" : function(calldone) { - call(opts.dlog, selector, 'destroy'); - call(opts.msel, select, 'destroy'); - selector.remove(); - if (calldone && opts.done) { - opts.done.call(self); - } - }, - "msel_opts" : {} - }, $.jgrid.col, opts || {}); - if($.ui) { - if ($.ui.multiselect ) { - if(opts.msel == "multiselect") { - if(!$.jgrid._multiselect) { - // should be in language file - alert("Multiselect plugin loaded after jqGrid. Please load the plugin before the jqGrid!"); - return; - } - opts.msel_opts = $.extend($.ui.multiselect.defaults,opts.msel_opts); - } - } - } - if (opts.caption) { - selector.attr("title", opts.caption); - } - if (opts.classname) { - selector.addClass(opts.classname); - select.addClass(opts.classname); - } - if (opts.width) { - $(">div",selector).css({"width": opts.width,"margin":"0 auto"}); - select.css("width", opts.width); - } - if (opts.height) { - $(">div",selector).css("height", opts.height); - select.css("height", opts.height - 10); - } - var colModel = self.jqGrid("getGridParam", "colModel"); - var colNames = self.jqGrid("getGridParam", "colNames"); - var colMap = {}, fixedCols = []; - - select.empty(); - $.each(colModel, function(i) { - colMap[this.name] = i; - if (this.hidedlg) { - if (!this.hidden) { - fixedCols.push(i); - } - return; - } - - select.append(""); - }); - function call(fn, obj) { - if (!fn) { return; } - if (typeof fn == 'string') { - if ($.fn[fn]) { - $.fn[fn].apply(obj, $.makeArray(arguments).slice(2)); - } - } else if ($.isFunction(fn)) { - fn.apply(obj, $.makeArray(arguments).slice(2)); - } - } - - var dopts = $.isFunction(opts.dlog_opts) ? opts.dlog_opts.call(self, opts) : opts.dlog_opts; - call(opts.dlog, selector, dopts); - var mopts = $.isFunction(opts.msel_opts) ? opts.msel_opts.call(self, opts) : opts.msel_opts; - call(opts.msel, select, mopts); - }, - sortableRows : function (opts) { - // Can accept all sortable options and events - return this.each(function(){ - var $t = this; - if(!$t.grid) { return; } - // Currently we disable a treeGrid sortable - if($t.p.treeGrid) { return; } - if($.fn.sortable) { - opts = $.extend({ - "cursor":"move", - "axis" : "y", - "items": ".jqgrow" - }, - opts || {}); - if(opts.start && $.isFunction(opts.start)) { - opts._start_ = opts.start; - delete opts.start; - } else {opts._start_=false;} - if(opts.update && $.isFunction(opts.update)) { - opts._update_ = opts.update; - delete opts.update; - } else {opts._update_ = false;} - opts.start = function(ev,ui) { - $(ui.item).css("border-width","0px"); - $("td",ui.item).each(function(i){ - this.style.width = $t.grid.cols[i].style.width; - }); - if($t.p.subGrid) { - var subgid = $(ui.item).attr("id"); - try { - $($t).jqGrid('collapseSubGridRow',subgid); - } catch (e) {} - } - if(opts._start_) { - opts._start_.apply(this,[ev,ui]); - } - }; - opts.update = function (ev,ui) { - $(ui.item).css("border-width",""); - if($t.p.rownumbers === true) { - $("td.jqgrid-rownum",$t.rows).each(function(i){ - $(this).html(i+1); - }); - } - if(opts._update_) { - opts._update_.apply(this,[ev,ui]); - } - }; - $("tbody:first",$t).sortable(opts); - $("tbody:first",$t).disableSelection(); - } - }); - }, - gridDnD : function(opts) { - return this.each(function(){ - var $t = this; - if(!$t.grid) { return; } - // Currently we disable a treeGrid drag and drop - if($t.p.treeGrid) { return; } - if(!$.fn.draggable || !$.fn.droppable) { return; } - function updateDnD () - { - var datadnd = $.data($t,"dnd"); - $("tr.jqgrow:not(.ui-draggable)",$t).draggable($.isFunction(datadnd.drag) ? datadnd.drag.call($($t),datadnd) : datadnd.drag); - } - var appender = "
"; - if($("#jqgrid_dnd").html() === null) { - $('body').append(appender); - } - - if(typeof opts == 'string' && opts == 'updateDnD' && $t.p.jqgdnd===true) { - updateDnD(); - return; - } - opts = $.extend({ - "drag" : function (opts) { - return $.extend({ - start : function (ev, ui) { - // if we are in subgrid mode try to collapse the node - if($t.p.subGrid) { - var subgid = $(ui.helper).attr("id"); - try { - $($t).jqGrid('collapseSubGridRow',subgid); - } catch (e) {} - } - // hack - // drag and drop does not insert tr in table, when the table has no rows - // we try to insert new empty row on the target(s) - for (var i=0;i<$.data($t,"dnd").connectWith.length;i++){ - if($($.data($t,"dnd").connectWith[i]).jqGrid('getGridParam','reccount') == "0" ){ - $($.data($t,"dnd").connectWith[i]).jqGrid('addRowData','jqg_empty_row',{}); - } - } - ui.helper.addClass("ui-state-highlight"); - $("td",ui.helper).each(function(i) { - this.style.width = $t.grid.headers[i].width+"px"; - }); - if(opts.onstart && $.isFunction(opts.onstart) ) { opts.onstart.call($($t),ev,ui); } - }, - stop :function(ev,ui) { - if(ui.helper.dropped) { - var ids = $(ui.helper).attr("id"); - $($t).jqGrid('delRowData',ids ); - } - // if we have a empty row inserted from start event try to delete it - for (var i=0;i<$.data($t,"dnd").connectWith.length;i++){ - $($.data($t,"dnd").connectWith[i]).jqGrid('delRowData','jqg_empty_row'); - } - if(opts.onstop && $.isFunction(opts.onstop) ) { opts.onstop.call($($t),ev,ui); } - } - },opts.drag_opts || {}); - }, - "drop" : function (opts) { - return $.extend({ - accept: function(d) { - if (!$(d).hasClass('jqgrow')) { return d;} - var tid = $(d).closest("table.ui-jqgrid-btable"); - if(tid.length > 0 && $.data(tid[0],"dnd") !== undefined) { - var cn = $.data(tid[0],"dnd").connectWith; - return $.inArray('#'+this.id,cn) != -1 ? true : false; - } - return d; - }, - drop: function(ev, ui) { - if (!$(ui.draggable).hasClass('jqgrow')) { return; } - var accept = $(ui.draggable).attr("id"); - var getdata = ui.draggable.parent().parent().jqGrid('getRowData',accept); - if(!opts.dropbyname) { - var j =0, tmpdata = {}, dropname; - var dropmodel = $("#"+this.id).jqGrid('getGridParam','colModel'); - try { - for (var key in getdata) { - if(getdata.hasOwnProperty(key) && dropmodel[j]) { - dropname = dropmodel[j].name; - tmpdata[dropname] = getdata[key]; - } - j++; - } - getdata = tmpdata; - } catch (e) {} - } - ui.helper.dropped = true; - if(opts.beforedrop && $.isFunction(opts.beforedrop) ) { - //parameters to this callback - event, element, data to be inserted, sender, reciever - // should return object which will be inserted into the reciever - var datatoinsert = opts.beforedrop.call(this,ev,ui,getdata,$('#'+$t.id),$(this)); - if (typeof datatoinsert != "undefined" && datatoinsert !== null && typeof datatoinsert == "object") { getdata = datatoinsert; } - } - if(ui.helper.dropped) { - var grid; - if(opts.autoid) { - if($.isFunction(opts.autoid)) { - grid = opts.autoid.call(this,getdata); - } else { - grid = Math.ceil(Math.random()*1000); - grid = opts.autoidprefix+grid; - } - } - // NULL is interpreted as undefined while null as object - $("#"+this.id).jqGrid('addRowData',grid,getdata,opts.droppos); - } - if(opts.ondrop && $.isFunction(opts.ondrop) ) { opts.ondrop.call(this,ev,ui, getdata); } - }}, opts.drop_opts || {}); - }, - "onstart" : null, - "onstop" : null, - "beforedrop": null, - "ondrop" : null, - "drop_opts" : { - "activeClass": "ui-state-active", - "hoverClass": "ui-state-hover" - }, - "drag_opts" : { - "revert": "invalid", - "helper": "clone", - "cursor": "move", - "appendTo" : "#jqgrid_dnd", - "zIndex": 5000 - }, - "dropbyname" : false, - "droppos" : "first", - "autoid" : true, - "autoidprefix" : "dnd_" - }, opts || {}); - - if(!opts.connectWith) { return; } - opts.connectWith = opts.connectWith.split(","); - opts.connectWith = $.map(opts.connectWith,function(n){return $.trim(n);}); - $.data($t,"dnd",opts); - - if($t.p.reccount != "0" && !$t.p.jqgdnd) { - updateDnD(); - } - $t.p.jqgdnd = true; - for (var i=0;i"; - } else { - return ""; - } -}, -addSubGrid : function(t,pos) { - return this.each(function(){ - var ts = this; - if (!ts.grid ) { return; } - //------------------------- - var subGridCell = function(trdiv,cell,pos){ - var tddiv = $("").html(cell); - $(trdiv).append(tddiv); - }; - var subGridXml = function(sjxml, sbid){ - var tddiv, i, sgmap, - dummy = $("
"), - trdiv = $(""); - for (i = 0; i"); - $(tddiv).html(ts.p.subGridModel[0].name[i]); - $(tddiv).width( ts.p.subGridModel[0].width[i]); - $(trdiv).append(tddiv); - } - $(dummy).append(trdiv); - if (sjxml){ - sgmap = ts.p.xmlReader.subgrid; - $(sgmap.root+" "+sgmap.row, sjxml).each( function(){ - trdiv = $(""); - if(sgmap.repeatitems === true) { - $(sgmap.cell,this).each( function(i) { - subGridCell(trdiv, $(this).text() || ' ',i); - }); - } else { - var f = ts.p.subGridModel[0].mapping || ts.p.subGridModel[0].name; - if (f) { - for (i=0;i"), - trdiv = $(""); - for (i = 0; i"); - $(tddiv).html(ts.p.subGridModel[0].name[i]); - $(tddiv).width( ts.p.subGridModel[0].width[i]); - $(trdiv).append(tddiv); - } - $(dummy).append(trdiv); - if (sjxml){ - sgmap = ts.p.jsonReader.subgrid; - result = sjxml[sgmap.root]; - if ( typeof result !== 'undefined' ) { - for (i=0;i"); - if(sgmap.repeatitems === true) { - if(sgmap.cell) { cur=cur[sgmap.cell]; } - for (j=0;j=1 ? " ":""; - _id = $(res).attr("id"); - bfsc =true; - if($.isFunction(ts.p.subGridBeforeExpand)) { - bfsc = ts.p.subGridBeforeExpand.call(ts, pID+"_"+_id,_id); - } - if(bfsc === false) {return false;} - nhc = 0; - $.each(ts.p.colModel,function(i,v){ - if(this.hidden === true || this.name == 'rn' || this.name == 'cb') {nhc++;} - }); - subdata = ""+atd+"
"; - $(this).parent().after( subdata+ "
" ); - if( $.isFunction(ts.p.subGridRowExpanded)) { - ts.p.subGridRowExpanded.call(ts, pID+"_"+ _id,_id); - } else { - populatesubgrid(res); - } - $(this).html("").removeClass("sgcollapsed").addClass("sgexpanded"); - } else if($(this).hasClass("sgexpanded")) { - bfsc = true; - if( $.isFunction(ts.p.subGridRowColapsed)) { - res = $(this).parent(); - _id = $(res).attr("id"); - bfsc = ts.p.subGridRowColapsed.call(ts, pID+"_"+_id,_id ); - } - if(bfsc===false) {return false;} - $(this).parent().next().remove(".ui-subgrid"); - $(this).html("").removeClass("sgexpanded").addClass("sgcollapsed"); - } - return false; - }); - ts.subGridXml = function(xml,sid) {subGridXml(xml,sid);}; - ts.subGridJson = function(json,sid) {subGridJson(json,sid);}; - }); -}, -expandSubGridRow : function(rowid) { - return this.each(function () { - var $t = this; - if(!$t.grid && !rowid) {return;} - if($t.p.subGrid===true) { - var rc = $(this).jqGrid("getInd",rowid,true); - if(rc) { - var sgc = $("td.sgcollapsed",rc)[0]; - if(sgc) { - $(sgc).trigger("click"); - } - } - } - }); -}, -collapseSubGridRow : function(rowid) { - return this.each(function () { - var $t = this; - if(!$t.grid && !rowid) {return;} - if($t.p.subGrid===true) { - var rc = $(this).jqGrid("getInd",rowid,true); - if(rc) { - var sgc = $("td.sgexpanded",rc)[0]; - if(sgc) { - $(sgc).trigger("click"); - } - } - } - }); -}, -toggleSubGridRow : function(rowid) { - return this.each(function () { - var $t = this; - if(!$t.grid && !rowid) {return;} - if($t.p.subGrid===true) { - var rc = $(this).jqGrid("getInd",rowid,true); - if(rc) { - var sgc = $("td.sgcollapsed",rc)[0]; - if(sgc) { - $(sgc).trigger("click"); - } else { - sgc = $("td.sgexpanded",rc)[0]; - if(sgc) { - $(sgc).trigger("click"); - } - } - } - } - }); -} -}); -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/grid.tbltogrid.js b/addons/base/static/lib/jquery.jqGrid/js/grid.tbltogrid.js deleted file mode 100644 index 364d4181433..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/grid.tbltogrid.js +++ /dev/null @@ -1,106 +0,0 @@ -/* - Transform a table to a jqGrid. - Peter Romianowski - If the first column of the table contains checkboxes or - radiobuttons then the jqGrid is made selectable. -*/ -// Addition - selector can be a class or id -function tableToGrid(selector, options) { -jQuery(selector).each(function() { - if(this.grid) {return;} //Adedd from Tony Tomov - // This is a small "hack" to make the width of the jqGrid 100% - jQuery(this).width("99%"); - var w = jQuery(this).width(); - - // Text whether we have single or multi select - var inputCheckbox = jQuery('input[type=checkbox]:first', jQuery(this)); - var inputRadio = jQuery('input[type=radio]:first', jQuery(this)); - var selectMultiple = inputCheckbox.length > 0; - var selectSingle = !selectMultiple && inputRadio.length > 0; - var selectable = selectMultiple || selectSingle; - //var inputName = inputCheckbox.attr("name") || inputRadio.attr("name"); - - // Build up the columnModel and the data - var colModel = []; - var colNames = []; - jQuery('th', jQuery(this)).each(function() { - if (colModel.length === 0 && selectable) { - colModel.push({ - name: '__selection__', - index: '__selection__', - width: 0, - hidden: true - }); - colNames.push('__selection__'); - } else { - colModel.push({ - name: jQuery(this).attr("id") || jQuery.trim(jQuery.jgrid.stripHtml(jQuery(this).html())).split(' ').join('_'), - index: jQuery(this).attr("id") || jQuery.trim(jQuery.jgrid.stripHtml(jQuery(this).html())).split(' ').join('_'), - width: jQuery(this).width() || 150 - }); - colNames.push(jQuery(this).html()); - } - }); - var data = []; - var rowIds = []; - var rowChecked = []; - jQuery('tbody > tr', jQuery(this)).each(function() { - var row = {}; - var rowPos = 0; - jQuery('td', jQuery(this)).each(function() { - if (rowPos === 0 && selectable) { - var input = jQuery('input', jQuery(this)); - var rowId = input.attr("value"); - rowIds.push(rowId || data.length); - if (input.attr("checked")) { - rowChecked.push(rowId); - } - row[colModel[rowPos].name] = input.attr("value"); - } else { - row[colModel[rowPos].name] = jQuery(this).html(); - } - rowPos++; - }); - if(rowPos >0) { data.push(row); } - }); - - // Clear the original HTML table - jQuery(this).empty(); - - // Mark it as jqGrid - jQuery(this).addClass("scroll"); - - jQuery(this).jqGrid(jQuery.extend({ - datatype: "local", - width: w, - colNames: colNames, - colModel: colModel, - multiselect: selectMultiple - //inputName: inputName, - //inputValueCol: imputName != null ? "__selection__" : null - }, options || {})); - - // Add data - var a; - for (a = 0; a < data.length; a++) { - var id = null; - if (rowIds.length > 0) { - id = rowIds[a]; - if (id && id.replace) { - // We have to do this since the value of a checkbox - // or radio button can be anything - id = encodeURIComponent(id).replace(/[.\-%]/g, "_"); - } - } - if (id === null) { - id = a + 1; - } - jQuery(this).jqGrid("addRowData",id, data[a]); - } - - // Set the selection - for (a = 0; a < rowChecked.length; a++) { - jQuery(this).jqGrid("setSelection",rowChecked[a]); - } -}); -}; diff --git a/addons/base/static/lib/jquery.jqGrid/js/grid.treegrid.js b/addons/base/static/lib/jquery.jqGrid/js/grid.treegrid.js deleted file mode 100644 index 94ec770c153..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/grid.treegrid.js +++ /dev/null @@ -1,490 +0,0 @@ -;(function($) { -/* -** - * jqGrid extension - Tree Grid - * Tony Tomov tony@trirand.com - * http://trirand.com/blog/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid.extend({ - setTreeNode : function(rd, row){ - return this.each(function(){ - var $t = this; - if( !$t.grid || !$t.p.treeGrid ) { return; } - var expCol = $t.p.expColInd, - expanded = $t.p.treeReader.expanded_field, - isLeaf = $t.p.treeReader.leaf_field, - level = $t.p.treeReader.level_field, - loaded = $t.p.treeReader.loaded; - - row.level = rd[level]; - - if($t.p.treeGridModel == 'nested') { - var lft = rd[$t.p.treeReader.left_field], - rgt = rd[$t.p.treeReader.right_field]; - if(!rd[isLeaf]) { - // NS Model - rd[isLeaf] = (parseInt(rgt,10) === parseInt(lft,10)+1) ? 'true' : 'false'; - } - } else { - //row.parent_id = rd[$t.p.treeReader.parent_id_field]; - } - var curLevel = parseInt(rd[level],10), ident,lftpos; - if($t.p.tree_root_level === 0) { - ident = curLevel+1; - lftpos = curLevel; - } else { - ident = curLevel; - lftpos = curLevel -1; - } - var twrap = "
"; - twrap += "
").prepend(twrap); - $(".treeclick",row).bind("click",function(e){ - var target = e.target || e.srcElement, - ind2 =$(target,$t.rows).closest("tr.jqgrow")[0].id, - pos = $t.p._index[ind2], - isLeaf = $t.p.treeReader.leaf_field, - expanded = $t.p.treeReader.expanded_field; - if(!$t.p.data[pos][isLeaf]){ - if($t.p.data[pos][expanded]){ - $($t).jqGrid("collapseRow",$t.p.data[pos]); - $($t).jqGrid("collapseNode",$t.p.data[pos]); - } else { - $($t).jqGrid("expandRow",$t.p.data[pos]); - $($t).jqGrid("expandNode",$t.p.data[pos]); - } - } - return false; - }); - if($t.p.ExpandColClick === true) { - $("span", row).css("cursor","pointer").bind("click",function(e){ - var target = e.target || e.srcElement, - ind2 =$(target,$t.rows).closest("tr.jqgrow")[0].id, - pos = $t.p._index[ind2], - isLeaf = $t.p.treeReader.leaf_field, - expanded = $t.p.treeReader.expanded_field; - if(!$t.p.data[pos][isLeaf]){ - if($t.p.data[pos][expanded]){ - $($t).jqGrid("collapseRow",$t.p.data[pos]); - $($t).jqGrid("collapseNode",$t.p.data[pos]); - } else { - $($t).jqGrid("expandRow",$t.p.data[pos]); - $($t).jqGrid("expandNode",$t.p.data[pos]); - } - } - $($t).jqGrid("setSelection",ind2); - return false; - }); - } - }); - }, - setTreeGrid : function() { - return this.each(function (){ - var $t = this, i=0, pico; - if(!$t.p.treeGrid) { return; } - if(!$t.p.treedatatype ) { $.extend($t.p,{treedatatype: $t.p.datatype}); } - $t.p.subGrid = false; $t.p.altRows =false; - $t.p.pgbuttons = false; $t.p.pginput = false; - $t.p.multiselect = false; $t.p.rowList = []; - pico = 'ui-icon-triangle-1-' + ($t.p.direction=="rtl" ? 'w' : 'e'); - $t.p.treeIcons = $.extend({plus:pico,minus:'ui-icon-triangle-1-s',leaf:'ui-icon-radio-off'},$t.p.treeIcons || {}); - if($t.p.treeGridModel == 'nested') { - $t.p.treeReader = $.extend({ - level_field: "level", - left_field:"lft", - right_field: "rgt", - leaf_field: "isLeaf", - expanded_field: "expanded", - loaded: "loaded" - },$t.p.treeReader); - } else - if($t.p.treeGridModel == 'adjacency') { - $t.p.treeReader = $.extend({ - level_field: "level", - parent_id_field: "parent", - leaf_field: "isLeaf", - expanded_field: "expanded", - loaded: "loaded" - },$t.p.treeReader ); - } - for (var key in $t.p.colModel){ - if($t.p.colModel.hasOwnProperty(key)) { - if($t.p.colModel[key].name == $t.p.ExpandColumn) { - $t.p.expColInd = i; - break; - } - i++; - } - } - if(!$t.p.expColInd) { $t.p.expColInd = 0; } - $.each($t.p.treeReader,function(i,n){ - if(n){ - $t.p.colNames.push(n); - $t.p.colModel.push({name:n,width:1,hidden:true,sortable:false,resizable:false,hidedlg:true,editable:true,search:false}); - } - }); - }); - }, - expandRow: function (record){ - this.each(function(){ - var $t = this; - if(!$t.grid || !$t.p.treeGrid) { return; } - var childern = $($t).jqGrid("getNodeChildren",record), - //if ($($t).jqGrid("isVisibleNode",record)) { - expanded = $t.p.treeReader.expanded_field; - $(childern).each(function(i){ - var id = $.jgrid.getAccessor(this,$t.p.localReader.id); - $("#"+id,$t.grid.bDiv).css("display",""); - if(this[expanded]) { - $($t).jqGrid("expandRow",this); - } - }); - //} - }); - }, - collapseRow : function (record) { - this.each(function(){ - var $t = this; - if(!$t.grid || !$t.p.treeGrid) { return; } - var childern = $($t).jqGrid("getNodeChildren",record), - expanded = $t.p.treeReader.expanded_field; - $(childern).each(function(i){ - var id = $.jgrid.getAccessor(this,$t.p.localReader.id); - $("#"+id,$t.grid.bDiv).css("display","none"); - if(this[expanded]){ - $($t).jqGrid("collapseRow",this); - } - }); - }); - }, - // NS ,adjacency models - getRootNodes : function() { - var result = []; - this.each(function(){ - var $t = this; - if(!$t.grid || !$t.p.treeGrid) { return; } - switch ($t.p.treeGridModel) { - case 'nested' : - var level = $t.p.treeReader.level_field; - $($t.p.data).each(function(i){ - if(parseInt(this[level],10) === parseInt($t.p.tree_root_level,10)) { - result.push(this); - } - }); - break; - case 'adjacency' : - var parent_id = $t.p.treeReader.parent_id_field; - $($t.p.data).each(function(i){ - if(this[parent_id] === null || String(this[parent_id]).toLowerCase() == "null") { - result.push(this); - } - }); - break; - } - }); - return result; - }, - getNodeDepth : function(rc) { - var ret = null; - this.each(function(){ - if(!this.grid || !this.p.treeGrid) { return; } - var $t = this; - switch ($t.p.treeGridModel) { - case 'nested' : - var level = $t.p.treeReader.level_field; - ret = parseInt(rc[level],10) - parseInt($t.p.tree_root_level,10); - break; - case 'adjacency' : - ret = $($t).jqGrid("getNodeAncestors",rc).length; - break; - } - }); - return ret; - }, - getNodeParent : function(rc) { - var result = null; - this.each(function(){ - var $t = this; - if(!$t.grid || !$t.p.treeGrid) { return; } - switch ($t.p.treeGridModel) { - case 'nested' : - var lftc = $t.p.treeReader.left_field, - rgtc = $t.p.treeReader.right_field, - levelc = $t.p.treeReader.level_field, - lft = parseInt(rc[lftc],10), rgt = parseInt(rc[rgtc],10), level = parseInt(rc[levelc],10); - $(this.p.data).each(function(){ - if(parseInt(this[levelc],10) === level-1 && parseInt(this[lftc],10) < lft && parseInt(this[rgtc],10) > rgt) { - result = this; - return false; - } - }); - break; - case 'adjacency' : - var parent_id = $t.p.treeReader.parent_id_field, - dtid = $t.p.localReader.id; - $(this.p.data).each(function(i,val){ - if(this[dtid] == rc[parent_id] ) { - result = this; - return false; - } - }); - break; - } - }); - return result; - }, - getNodeChildren : function(rc) { - var result = []; - this.each(function(){ - var $t = this; - if(!$t.grid || !$t.p.treeGrid) { return; } - switch ($t.p.treeGridModel) { - case 'nested' : - var lftc = $t.p.treeReader.left_field, - rgtc = $t.p.treeReader.right_field, - levelc = $t.p.treeReader.level_field, - lft = parseInt(rc[lftc],10), rgt = parseInt(rc[rgtc],10), level = parseInt(rc[levelc],10); - $(this.p.data).each(function(i){ - if(parseInt(this[levelc],10) === level+1 && parseInt(this[lftc],10) > lft && parseInt(this[rgtc],10) < rgt) { - result.push(this); - } - }); - break; - case 'adjacency' : - var parent_id = $t.p.treeReader.parent_id_field, - dtid = $t.p.localReader.id; - $(this.p.data).each(function(i,val){ - if(this[parent_id] == rc[dtid]) { - result.push(this); - } - }); - break; - } - }); - return result; - }, - getFullTreeNode : function(rc) { - var result = []; - this.each(function(){ - var $t = this, len; - if(!$t.grid || !$t.p.treeGrid) { return; } - switch ($t.p.treeGridModel) { - case 'nested' : - var lftc = $t.p.treeReader.left_field, - rgtc = $t.p.treeReader.right_field, - levelc = $t.p.treeReader.level_field, - lft = parseInt(rc[lftc],10), rgt = parseInt(rc[rgtc],10), level = parseInt(rc[levelc],10); - $(this.p.data).each(function(i){ - if(parseInt(this[levelc],10) >= level && parseInt(this[lftc],10) >= lft && parseInt(this[lftc],10) <= rgt) { - result.push(this); - } - }); - break; - case 'adjacency' : - result.push(rc); - var parent_id = $t.p.treeReader.parent_id_field, - dtid = $t.p.localReader.id; - $(this.p.data).each(function(i){ - len = result.length; - for (i = 0; i < len; i++) { - if (result[i][dtid] == this[parent_id]) { - result.push(this); - break; - } - } - }); - break; - } - }); - return result; - }, - // End NS, adjacency Model - getNodeAncestors : function(rc) { - var ancestors = []; - this.each(function(){ - if(!this.grid || !this.p.treeGrid) { return; } - var parent = $(this).jqGrid("getNodeParent",rc); - while (parent) { - ancestors.push(parent); - parent = $(this).jqGrid("getNodeParent",parent); - } - }); - return ancestors; - }, - isVisibleNode : function(rc) { - var result = true; - this.each(function(){ - var $t = this; - if(!$t.grid || !$t.p.treeGrid) { return; } - var ancestors = $($t).jqGrid("getNodeAncestors",rc), - expanded = $t.p.treeReader.expanded_field; - $(ancestors).each(function(){ - result = result && this[expanded]; - if(!result) {return false;} - }); - }); - return result; - }, - isNodeLoaded : function(rc) { - var result; - this.each(function(){ - var $t = this; - if(!$t.grid || !$t.p.treeGrid) { return; } - var isLeaf = $t.p.treeReader.leaf_field; - if(rc.loaded !== undefined) { - result = rc.loaded; - } else if( rc[isLeaf] || $($t).jqGrid("getNodeChildren",rc).length > 0){ - result = true; - } else { - result = false; - } - }); - return result; - }, - expandNode : function(rc) { - return this.each(function(){ - if(!this.grid || !this.p.treeGrid) { return; } - var expanded = this.p.treeReader.expanded_field; - if(!rc[expanded]) { - var id = $.jgrid.getAccessor(rc,this.p.localReader.id); - var rc1 = $("#"+id,this.grid.bDiv)[0]; - var position = this.p._index[id]; - if( $(this).jqGrid("isNodeLoaded",this.p.data[position]) ) { - rc[expanded] = true; - $("div.treeclick",rc1).removeClass(this.p.treeIcons.plus+" tree-plus").addClass(this.p.treeIcons.minus+" tree-minus"); - } else { - rc[expanded] = true; - $("div.treeclick",rc1).removeClass(this.p.treeIcons.plus+" tree-plus").addClass(this.p.treeIcons.minus+" tree-minus"); - this.p.treeANode = rc1.rowIndex; - this.p.datatype = this.p.treedatatype; - if(this.p.treeGridModel == 'nested') { - $(this).jqGrid("setGridParam",{postData:{nodeid:id,n_left:rc.lft,n_right:rc.rgt,n_level:rc.level}}); - } else { - $(this).jqGrid("setGridParam",{postData:{nodeid:id,parentid:rc.parent_id,n_level:rc.level}}); - } - $(this).trigger("reloadGrid"); - if(this.p.treeGridModel == 'nested') { - $(this).jqGrid("setGridParam",{postData:{nodeid:'',n_left:'',n_right:'',n_level:''}}); - } else { - $(this).jqGrid("setGridParam",{postData:{nodeid:'',parentid:'',n_level:''}}); - } - } - } - }); - }, - collapseNode : function(rc) { - return this.each(function(){ - if(!this.grid || !this.p.treeGrid) { return; } - if(rc.expanded) { - rc.expanded = false; - var id = $.jgrid.getAccessor(rc,this.p.localReader.id); - var rc1 = $("#"+id,this.grid.bDiv)[0]; - $("div.treeclick",rc1).removeClass(this.p.treeIcons.minus+" tree-minus").addClass(this.p.treeIcons.plus+" tree-plus"); - } - }); - }, - SortTree : function( sortname, newDir, st, datefmt) { - return this.each(function(){ - if(!this.grid || !this.p.treeGrid) { return; } - var i, len, - rec, records = [], $t = this, query, roots, - rt = $(this).jqGrid("getRootNodes"); - // Sorting roots - query = $.jgrid.from(rt); - query.orderBy(sortname,newDir,st, datefmt); - roots = query.select(); - - // Sorting children - for (i = 0, len = roots.length; i < len; i++) { - rec = roots[i]; - records.push(rec); - $(this).jqGrid("collectChildrenSortTree",records, rec, sortname, newDir,st, datefmt); - } - $.each(records, function(index, row) { - var id = $.jgrid.getAccessor(this,$t.p.localReader.id); - $('#'+$t.p.id+ ' tbody tr:eq('+index+')').after($('tr#'+id,$t.grid.bDiv)); - }); - query = null; roots=null;records=null; - }); - }, - collectChildrenSortTree : function(records, rec, sortname, newDir,st, datefmt) { - return this.each(function(){ - if(!this.grid || !this.p.treeGrid) { return; } - var i, len, - child, ch, query, children; - ch = $(this).jqGrid("getNodeChildren",rec); - query = $.jgrid.from(ch); - query.orderBy(sortname, newDir, st, datefmt); - children = query.select(); - for (i = 0, len = children.length; i < len; i++) { - child = children[i]; - records.push(child); - $(this).jqGrid("collectChildrenSortTree",records, child, sortname, newDir, st, datefmt); - } - }); - }, - // experimental - setTreeRow : function(rowid, data) { - var success=false; - this.each(function(){ - var t = this; - if(!t.grid || !t.p.treeGrid) { return; } - success = $(t).jqGrid("setRowData",rowid,data); - }); - return success; - }, - delTreeNode : function (rowid) { - return this.each(function () { - var $t = this; - if(!$t.grid || !$t.p.treeGrid) { return; } - var rc = $($t).jqGrid("getInd",rowid,true); - if (rc) { - var dr = $($t).jqGrid("getNodeChildren",rc); - if(dr.length>0){ - for (var i=0;i عدد التسجيلات (colModel)!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0,00'}, - currency : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0,00'}, - date : { - dayNames: [ - "الأحد", "الإثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", - "الأحد", "الإثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت" - ], - monthNames: [ - "جانفي", "فيفري", "مارس", "أفريل", "ماي", "جوان", "جويلية", "أوت", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر", - "جانفي", "فيفري", "مارس", "أفريل", "ماي", "جوان", "جويلية", "أوت", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر" - ], - AmPm : ["صباحا","مساءا","صباحا","مساءا"], - S: function (j) {return j == 1 ? 'er' : 'e';}, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-bg.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-bg.js deleted file mode 100644 index 15038269091..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-bg.js +++ /dev/null @@ -1,132 +0,0 @@ -;(function($){ -/** - * jqGrid Bulgarian Translation - * Tony Tomov tony@trirand.com - * http://trirand.com/blog/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "{0} - {1} от {2}", - emptyrecords: "Няма запис(и)", - loadtext: "Зареждам...", - pgtext : "Стр. {0} от {1}" - }, - search : { - caption: "Търсене...", - Find: "Намери", - Reset: "Изчисти", - odata : ['равно', 'различно', 'по-малко', 'по-малко или=','по-голямо','по-голямо или =', 'започва с','не започва с','се намира в','не се намира в','завършва с','не завършава с','съдържа', 'не съдържа' ], - groupOps: [ { op: "AND", text: " И " }, { op: "OR", text: "ИЛИ" } ], - matchText: " включи", - rulesText: " клауза" - }, - edit : { - addCaption: "Нов Запис", - editCaption: "Редакция Запис", - bSubmit: "Запиши", - bCancel: "Изход", - bClose: "Затвори", - saveData: "Данните са променени! Да съхраня ли промените?", - bYes : "Да", - bNo : "Не", - bExit : "Отказ", - msg: { - required:"Полето е задължително", - number:"Въведете валидно число!", - minValue:"стойността трябва да е по-голяма или равна от", - maxValue:"стойността трябва да е по-малка или равна от", - email: "не е валиден ел. адрес", - integer: "Въведете валидно цяло число", - date: "Въведете валидна дата", - url: "e невалиден URL. Изискава се префикс('http://' или 'https://')", - nodefined : " е недефинирана!", - novalue : " изисква връщане на стойност!", - customarray : "Потреб. Функция трябва да върне масив!", - customfcheck : "Потребителска функция е задължителна при този тип елемент!" - } - }, - view : { - caption: "Преглед запис", - bClose: "Затвори" - }, - del : { - caption: "Изтриване", - msg: "Да изтрия ли избраният запис?", - bSubmit: "Изтрий", - bCancel: "Отказ" - }, - nav : { - edittext: " ", - edittitle: "Редакция избран запис", - addtext:" ", - addtitle: "Добавяне нов запис", - deltext: " ", - deltitle: "Изтриване избран запис", - searchtext: " ", - searchtitle: "Търсене запис(и)", - refreshtext: "", - refreshtitle: "Обнови таблица", - alertcap: "Предупреждение", - alerttext: "Моля, изберете запис", - viewtext: "", - viewtitle: "Преглед избран запис" - }, - col : { - caption: "Избери колони", - bSubmit: "Ок", - bCancel: "Изход" - }, - errors : { - errcap : "Грешка", - nourl : "Няма посочен url адрес", - norecords: "Няма запис за обработка", - model : "Модела не съответства на имената!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0.00'}, - currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:" лв.", defaultValue: '0.00'}, - date : { - dayNames: [ - "Нед", "Пон", "Вт", "Ср", "Чет", "Пет", "Съб", - "Неделя", "Понеделник", "Вторник", "Сряда", "Четвъртък", "Петък", "Събота" - ], - monthNames: [ - "Яну", "Фев", "Мар", "Апр", "Май", "Юни", "Юли", "Авг", "Сеп", "Окт", "Нов", "Дек", - "Януари", "Февруари", "Март", "Април", "Май", "Юни", "Юли", "Август", "Септември", "Октомври", "Ноември", "Декември" - ], - AmPm : ["","","",""], - S: function (j) { - if(j==7 || j==8 || j== 27 || j== 28) { - return 'ми'; - } - return ['ви', 'ри', 'ти'][Math.min((j - 1) % 10, 2)]; - }, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-bg1251.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-bg1251.js deleted file mode 100644 index 935ce938a21..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-bg1251.js +++ /dev/null @@ -1,132 +0,0 @@ -;(function($){ -/** - * jqGrid Bulgarian Translation - * Tony Tomov tony@trirand.com - * http://trirand.com/blog/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "{0} - {1} îò {2}", - emptyrecords: "Íÿìà çàïèñ(è)", - loadtext: "Çàðåæäàì...", - pgtext : "Ñòð. {0} îò {1}" - }, - search : { - caption: "Òúðñåíå...", - Find: "Íàìåðè", - Reset: "Èç÷èñòè", - odata : ['ðàâíî', 'ðàçëè÷íî', 'ïî-ìàëêî', 'ïî-ìàëêî èëè=','ïî-ãîëÿìî','ïî-ãîëÿìî èëè =', 'çàïî÷âà ñ','íå çàïî÷âà ñ','ñå íàìèðà â','íå ñå íàìèðà â','çàâúðøâà ñ','íå çàâúðøàâà ñ','ñúäúðæà', 'íå ñúäúðæà' ], - groupOps: [ { op: "AND", text: " È " }, { op: "OR", text: "ÈËÈ" } ], - matchText: " âêëþ÷è", - rulesText: " êëàóçà" - }, - edit : { - addCaption: "Íîâ Çàïèñ", - editCaption: "Ðåäàêöèÿ Çàïèñ", - bSubmit: "Çàïèøè", - bCancel: "Èçõîä", - bClose: "Çàòâîðè", - saveData: "Äàííèòå ñà ïðîìåíåíè! Äà ñúõðàíÿ ëè ïðîìåíèòå?", - bYes : "Äà", - bNo : "Íå", - bExit : "Îòêàç", - msg: { - required:"Ïîëåòî å çàäúëæèòåëíî", - number:"Âúâåäåòå âàëèäíî ÷èñëî!", - minValue:"ñòîéíîñòòà òðÿáâà äà å ïî-ãîëÿìà èëè ðàâíà îò", - maxValue:"ñòîéíîñòòà òðÿáâà äà å ïî-ìàëêà èëè ðàâíà îò", - email: "íå å âàëèäåí åë. àäðåñ", - integer: "Âúâåäåòå âàëèäíî öÿëî ÷èñëî", - date: "Âúâåäåòå âàëèäíà äàòà", - url: "e íåâàëèäåí URL. Èçèñêàâà ñå ïðåôèêñ('http://' èëè 'https://')", - nodefined : " å íåäåôèíèðàíà!", - novalue : " èçèñêâà âðúùàíå íà ñòîéíîñò!", - customarray : "Ïîòðåá. Ôóíêöèÿ òðÿáâà äà âúðíå ìàñèâ!", - customfcheck : "Ïîòðåáèòåëñêà ôóíêöèÿ å çàäúëæèòåëíà ïðè òîçè òèï åëåìåíò!" - } - }, - view : { - caption: "Ïðåãëåä çàïèñ", - bClose: "Çàòâîðè" - }, - del : { - caption: "Èçòðèâàíå", - msg: "Äà èçòðèÿ ëè èçáðàíèÿò çàïèñ?", - bSubmit: "Èçòðèé", - bCancel: "Îòêàç" - }, - nav : { - edittext: " ", - edittitle: "Ðåäàêöèÿ èçáðàí çàïèñ", - addtext:" ", - addtitle: "Äîáàâÿíå íîâ çàïèñ", - deltext: " ", - deltitle: "Èçòðèâàíå èçáðàí çàïèñ", - searchtext: " ", - searchtitle: "Òúðñåíå çàïèñ(è)", - refreshtext: "", - refreshtitle: "Îáíîâè òàáëèöà", - alertcap: "Ïðåäóïðåæäåíèå", - alerttext: "Ìîëÿ, èçáåðåòå çàïèñ", - viewtext: "", - viewtitle: "Ïðåãëåä èçáðàí çàïèñ" - }, - col : { - caption: "Èçáîð êîëîíè", - bSubmit: "Îê", - bCancel: "Èçõîä" - }, - errors : { - errcap : "Ãðåøêà", - nourl : "Íÿìà ïîñî÷åí url àäðåñ", - norecords: "Íÿìà çàïèñ çà îáðàáîòêà", - model : "Ìîäåëà íå ñúîòâåòñòâà íà èìåíàòà!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0.00'}, - currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:" ëâ.", defaultValue: '0.00'}, - date : { - dayNames: [ - "Íåä", "Ïîí", "Âò", "Ñð", "×åò", "Ïåò", "Ñúá", - "Íåäåëÿ", "Ïîíåäåëíèê", "Âòîðíèê", "Ñðÿäà", "×åòâúðòúê", "Ïåòúê", "Ñúáîòà" - ], - monthNames: [ - "ßíó", "Ôåâ", "Ìàð", "Àïð", "Ìàé", "Þíè", "Þëè", "Àâã", "Ñåï", "Îêò", "Íîâ", "Äåê", - "ßíóàðè", "Ôåâðóàðè", "Ìàðò", "Àïðèë", "Ìàé", "Þíè", "Þëè", "Àâãóñò", "Ñåïòåìâðè", "Îêòîìâðè", "Íîåìâðè", "Äåêåìâðè" - ], - AmPm : ["","","",""], - S: function (j) { - if(j==7 || j==8 || j== 27 || j== 28) { - return 'ìè'; - } - return ['âè', 'ðè', 'òè'][Math.min((j - 1) % 10, 2)]; - }, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-cat.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-cat.js deleted file mode 100644 index a0ea13c69e4..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-cat.js +++ /dev/null @@ -1,128 +0,0 @@ -;(function($){ -/** - * jqGrid Catalan Translation - * Traducció jqGrid en Catatà per Faserline, S.L. - * http://www.faserline.com - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "Mostrant {0} - {1} de {2}", - emptyrecords: "Sense registres que mostrar", - loadtext: "Carregant...", - pgtext : "Pàgina {0} de {1}" - }, - search : { - caption: "Cerca...", - Find: "Cercar", - Reset: "Buidar", - odata : ['equal', 'not equal', 'less', 'less or equal','greater','greater or equal', 'begins with','does not begin with','is in','is not in','ends with','does not end with','contains','does not contain'], - groupOps: [ { op: "AND", text: "tot" }, { op: "OR", text: "qualsevol" } ], - matchText: " match", - rulesText: " rules" - }, - edit : { - addCaption: "Afegir registre", - editCaption: "Modificar registre", - bSubmit: "Guardar", - bCancel: "Cancelar", - bClose: "Tancar", - saveData: "Les dades han canviat. Guardar canvis?", - bYes : "Yes", - bNo : "No", - bExit : "Cancel", - msg: { - required:"Camp obligatori", - number:"Introdueixi un nombre", - minValue:"El valor ha de ser major o igual que ", - maxValue:"El valor ha de ser menor o igual a ", - email: "no és una direcció de correu vàlida", - integer: "Introdueixi un valor enter", - date: "Introdueixi una data correcta ", - url: "no és una URL vàlida. Prefix requerit ('http://' or 'https://')", - nodefined : " is not defined!", - novalue : " return value is required!", - customarray : "Custom function should return array!", - customfcheck : "Custom function should be present in case of custom checking!" - } - }, - view : { - caption: "Veure registre", - bClose: "Tancar" - }, - del : { - caption: "Eliminar", - msg: "¿Desitja eliminar els registres seleccionats?", - bSubmit: "Eliminar", - bCancel: "Cancelar" - }, - nav : { - edittext: " ", - edittitle: "Modificar fila seleccionada", - addtext:" ", - addtitle: "Agregar nova fila", - deltext: " ", - deltitle: "Eliminar fila seleccionada", - searchtext: " ", - searchtitle: "Cercar informació", - refreshtext: "", - refreshtitle: "Refrescar taula", - alertcap: "Avís", - alerttext: "Seleccioni una fila", - viewtext: " ", - viewtitle: "Veure fila seleccionada" - }, -// setcolumns module - col : { - caption: "Mostrar/ocultar columnes", - bSubmit: "Enviar", - bCancel: "Cancelar" - }, - errors : { - errcap : "Error", - nourl : "No s'ha especificat una URL", - norecords: "No hi ha dades per processar", - model : "Les columnes de noms són diferents de les columnes del model" - }, - formatter : { - integer : {thousandsSeparator: ".", defaultValue: '0'}, - number : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, defaultValue: '0,00'}, - currency : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0,00'}, - date : { - dayNames: [ - "Dg", "Dl", "Dt", "Dc", "Dj", "Dv", "Ds", - "Diumenge", "Dilluns", "Dimarts", "Dimecres", "Dijous", "Divendres", "Dissabte" - ], - monthNames: [ - "Gen", "Febr", "Març", "Abr", "Maig", "Juny", "Jul", "Ag", "Set", "Oct", "Nov", "Des", - "Gener", "Febrer", "Març", "Abril", "Maig", "Juny", "Juliol", "Agost", "Setembre", "Octubre", "Novembre", "Desembre" - ], - AmPm : ["am","pm","AM","PM"], - S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, - srcformat: 'Y-m-d', - newformat: 'd-m-Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: 'show', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-cn.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-cn.js deleted file mode 100644 index d5d2513dbbf..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-cn.js +++ /dev/null @@ -1,132 +0,0 @@ -;(function($){ -/** - * jqGrid Chinese Translation for v3.6 - * waiting 2010.01.18 - * http://waiting.javaeye.com/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * - * update 2010.05.04 - * add double u3000 SPACE for search:odata to fix SEARCH box display err when narrow width from only use of eq/ne/cn/in/lt/gt operator under IE6/7 -**/ -$.jgrid = { - defaults : { - recordtext: "{0} - {1}\u3000共 {2} 条", // 共字前是全角空格 - emptyrecords: "无数据显示", - loadtext: "读取中...", - pgtext : " {0} 共 {1} 页" - }, - search : { - caption: "搜索...", - Find: "查找", - Reset: "重置", - odata : ['等于\u3000\u3000', '不等\u3000\u3000', '小于\u3000\u3000', '小于等于','大于\u3000\u3000','大于等于', - '开始于','不开始于','属于\u3000\u3000','不属于','结束于','不结束于','包含\u3000\u3000','不包含'], - groupOps: [ { op: "AND", text: "所有" }, { op: "OR", text: "任一" } ], - matchText: " 匹配", - rulesText: " 规则" - }, - edit : { - addCaption: "添加记录", - editCaption: "编辑记录", - bSubmit: "提交", - bCancel: "取消", - bClose: "关闭", - saveData: "数据已改变,是否保存?", - bYes : "是", - bNo : "否", - bExit : "取消", - msg: { - required:"此字段必需", - number:"请输入有效数字", - minValue:"输值必须大于等于 ", - maxValue:"输值必须小于等于 ", - email: "这不是有效的e-mail地址", - integer: "请输入有效整数", - date: "请输入有效时间", - url: "无效网址。前缀必须为 ('http://' 或 'https://')", - nodefined : " 未定义!", - novalue : " 需要返回值!", - customarray : "自定义函数需要返回数组!", - customfcheck : "Custom function should be present in case of custom checking!" - - } - }, - view : { - caption: "查看记录", - bClose: "关闭" - }, - del : { - caption: "删除", - msg: "删除所选记录?", - bSubmit: "删除", - bCancel: "取消" - }, - nav : { - edittext: "", - edittitle: "编辑所选记录", - addtext:"", - addtitle: "添加新记录", - deltext: "", - deltitle: "删除所选记录", - searchtext: "", - searchtitle: "查找", - refreshtext: "", - refreshtitle: "刷新表格", - alertcap: "注意", - alerttext: "请选择记录", - viewtext: "", - viewtitle: "查看所选记录" - }, - col : { - caption: "选择列", - bSubmit: "确定", - bCancel: "取消" - }, - errors : { - errcap : "错误", - nourl : "没有设置url", - norecords: "没有要处理的记录", - model : "colNames 和 colModel 长度不等!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0.00'}, - currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0.00'}, - date : { - dayNames: [ - "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat", - "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" - ], - monthNames: [ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", - "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" - ], - AmPm : ["am","pm","AM","PM"], - S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, - srcformat: 'Y-m-d', - newformat: 'm-d-Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "Y/j/n", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-cs.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-cs.js deleted file mode 100644 index 81bf13baf01..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-cs.js +++ /dev/null @@ -1,128 +0,0 @@ -;(function($){ -/** - * jqGrid Czech Translation - * Pavel Jirak pavel.jirak@jipas.cz - * doplnil Thomas Wagner xwagne01@stud.fit.vutbr.cz - * http://trirand.com/blog/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "Zobrazeno {0} - {1} z {2} záznamů", - emptyrecords: "Nenalezeny žádné záznamy", - loadtext: "Načítám...", - pgtext : "Strana {0} z {1}" - }, - search : { - caption: "Vyhledávám...", - Find: "Hledat", - Reset: "Reset", - odata : ['rovno', 'nerovono', 'menší', 'menší nebo rovno','větší', 'větší nebo rovno', 'začíná s', 'nezačíná s', 'je v', 'není v', 'končí s', 'nekončí s', 'obahuje', 'neobsahuje'], - groupOps: [ { op: "AND", text: "všech" }, { op: "OR", text: "některého z" } ], - matchText: " hledat podle", - rulesText: " pravidel" - }, - edit : { - addCaption: "Přidat záznam", - editCaption: "Editace záznamu", - bSubmit: "Uložit", - bCancel: "Storno", - bClose: "Zavřít", - saveData: "Data byla změněna! Uložit změny?", - bYes : "Ano", - bNo : "Ne", - bExit : "Zrušit", - msg: { - required:"Pole je vyžadováno", - number:"Prosím, vložte validní číslo", - minValue:"hodnota musí být větší než nebo rovná ", - maxValue:"hodnota musí být menší než nebo rovná ", - email: "není validní e-mail", - integer: "Prosím, vložte celé číslo", - date: "Prosím, vložte validní datum", - url: "není platnou URL. Vyžadován prefix ('http://' or 'https://')", - nodefined : " není definován!", - novalue : " je vyžadována návratová hodnota!", - customarray : "Custom function mělá vrátit pole!", - customfcheck : "Custom function by měla být přítomna v případě custom checking!" - } - }, - view : { - caption: "Zobrazit záznam", - bClose: "Zavřít" - }, - del : { - caption: "Smazat", - msg: "Smazat vybraný(é) záznam(y)?", - bSubmit: "Smazat", - bCancel: "Storno" - }, - nav : { - edittext: " ", - edittitle: "Editovat vybraný řádek", - addtext:" ", - addtitle: "Přidat nový řádek", - deltext: " ", - deltitle: "Smazat vybraný záznam ", - searchtext: " ", - searchtitle: "Najít záznamy", - refreshtext: "", - refreshtitle: "Obnovit tabulku", - alertcap: "Varování", - alerttext: "Prosím, vyberte řádek", - viewtext: "", - viewtitle: "Zobrazit vybraný řádek" - }, - col : { - caption: "Zobrazit/Skrýt sloupce", - bSubmit: "Uložit", - bCancel: "Storno" - }, - errors : { - errcap : "Chyba", - nourl : "Není nastavena url", - norecords: "Žádné záznamy ke zpracování", - model : "Délka colNames <> colModel!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0.00'}, - currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0.00'}, - date : { - dayNames: [ - "Ne", "Po", "Út", "St", "Čt", "Pá", "So", - "Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota" - ], - monthNames: [ - "Led", "Úno", "Bře", "Dub", "Kvě", "Čer", "Čvc", "Srp", "Zář", "Říj", "Lis", "Pro", - "Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec" - ], - AmPm : ["do","od","DO","OD"], - S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-da.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-da.js deleted file mode 100644 index fba251db849..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-da.js +++ /dev/null @@ -1,128 +0,0 @@ -;(function($){ -/** - * jqGrid Danish Translation - * Aesiras A/S - * http://www.aesiras.dk - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "Vis {0} - {1} of {2}", - emptyrecords: "Ingen linjer fundet", - loadtext: "Henter...", - pgtext : "Side {0} af {1}" - }, - search : { - caption: "Søg...", - Find: "Find", - Reset: "Nulstil", - odata : ['lig', 'forskellige fra', 'mindre', 'mindre eller lig','større','større eller lig', 'begynder med','begynder ikke med','findes i','findes ikke i','ender med','ender ikke med','indeholder','indeholder ikke'], - groupOps: [ { op: "AND", text: "all" }, { op: "OR", text: "any" } ], - matchText: " lig", - rulesText: " regler" - }, - edit : { - addCaption: "Tilføj", - editCaption: "Ret", - bSubmit: "Send", - bCancel: "Annuller", - bClose: "Luk", - saveData: "Data er ændret. Gem data?", - bYes : "Ja", - bNo : "Nej", - bExit : "Fortryd", - msg: { - required:"Felt er nødvendigt", - number:"Indtast venligst et validt tal", - minValue:"værdi skal være større end eller lig med", - maxValue:"værdi skal være mindre end eller lig med", - email: "er ikke en gyldig email", - integer: "Indtast venligst et gyldigt heltal", - date: "Indtast venligst en gyldig datoværdi", - url: "er ugyldig URL. Prefix mangler ('http://' or 'https://')", - nodefined : " er ikke defineret!", - novalue : " returværdi kræves!", - customarray : "Custom function should return array!", - customfcheck : "Custom function should be present in case of custom checking!" - } - }, - view : { - caption: "Vis linje", - bClose: "Luk" - }, - del : { - caption: "Slet", - msg: "Slet valgte linje(r)?", - bSubmit: "Slet", - bCancel: "Fortryd" - }, - nav : { - edittext: " ", - edittitle: "Rediger valgte linje", - addtext:" ", - addtitle: "Tilføj ny linje", - deltext: " ", - deltitle: "Slet valgte linje", - searchtext: " ", - searchtitle: "Find linjer", - refreshtext: "", - refreshtitle: "Indlæs igen", - alertcap: "Advarsel", - alerttext: "Vælg venligst linje", - viewtext: "", - viewtitle: "Vis valgte linje" - }, - col : { - caption: "Vis/skjul kolonner", - bSubmit: "Opdatere", - bCancel: "Fortryd" - }, - errors : { - errcap : "Fejl", - nourl : "Ingen url valgt", - norecords: "Ingen linjer at behandle", - model : "colNames og colModel har ikke samme længde!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0,00'}, - currency : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0,00'}, - date : { - dayNames: [ - "Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør", - "Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag" - ], - monthNames: [ - "Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec", - "Januar", "Februar", "Marts", "April", "Maj", "Juni", "Juli", "August", "September", "Oktober", "November", "December" - ], - AmPm : ["","","",""], - S: function (j) {return '.'}, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "j/n/Y", - LongDate: "l d. F Y", - FullDateTime: "l d F Y G:i:s", - MonthDay: "d. F", - ShortTime: "G:i", - LongTime: "G:i:s", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -// DA -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-de.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-de.js deleted file mode 100644 index 39474eedc87..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-de.js +++ /dev/null @@ -1,133 +0,0 @@ -;(function($){ -/** - * jqGrid German Translation - * Version 1.0.0 (developed for jQuery Grid 3.3.1) - * Olaf Klöppel opensource@blue-hit.de - * http://blue-hit.de/ - * - * Updated for jqGrid 3.8 - * Andreas Flack - * http://www.contentcontrol-berlin.de - * - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "Zeige {0} - {1} von {2}", - emptyrecords: "Keine Datensätze vorhanden", - loadtext: "Lädt...", - pgtext : "Seite {0} von {1}" - }, - search : { - caption: "Suche...", - Find: "Suchen", - Reset: "Zurücksetzen", - odata : ['gleich', 'ungleich', 'kleiner', 'kleiner gleich','größer','größer gleich', 'beginnt mit','beginnt nicht mit','ist in','ist nicht in','endet mit','endet nicht mit','enthält','enthält nicht'], - groupOps: [ { op: "AND", text: "alle" }, { op: "OR", text: "mindestens eine" } ], - matchText: " erfülle", - rulesText: " Bedingung(en)" - }, - edit : { - addCaption: "Datensatz hinzufügen", - editCaption: "Datensatz bearbeiten", - bSubmit: "Speichern", - bCancel: "Abbrechen", - bClose: "Schließen", - saveData: "Daten wurden geändert! Änderungen speichern?", - bYes : "ja", - bNo : "nein", - bExit : "abbrechen", - msg: { - required:"Feld ist erforderlich", - number: "Bitte geben Sie eine Zahl ein", - minValue:"Wert muss größer oder gleich sein, als ", - maxValue:"Wert muss kleiner oder gleich sein, als ", - email: "ist keine gültige E-Mail-Adresse", - integer: "Bitte geben Sie eine Ganzzahl ein", - date: "Bitte geben Sie ein gültiges Datum ein", - url: "ist keine gültige URL. Präfix muss eingegeben werden ('http://' oder 'https://')", - nodefined : " ist nicht definiert!", - novalue : " Rückgabewert ist erforderlich!", - customarray : "Benutzerdefinierte Funktion sollte ein Array zurückgeben!", - customfcheck : "Benutzerdefinierte Funktion sollte im Falle der benutzerdefinierten Überprüfung vorhanden sein!" - } - }, - view : { - caption: "Datensatz anzeigen", - bClose: "Schließen" - }, - del : { - caption: "Löschen", - msg: "Ausgewählte Datensätze löschen?", - bSubmit: "Löschen", - bCancel: "Abbrechen" - }, - nav : { - edittext: " ", - edittitle: "Ausgewählte Zeile editieren", - addtext:" ", - addtitle: "Neue Zeile einfügen", - deltext: " ", - deltitle: "Ausgewählte Zeile löschen", - searchtext: " ", - searchtitle: "Datensatz suchen", - refreshtext: "", - refreshtitle: "Tabelle neu laden", - alertcap: "Warnung", - alerttext: "Bitte Zeile auswählen", - viewtext: "", - viewtitle: "Ausgewählte Zeile anzeigen" - }, - col : { - caption: "Spalten auswählen", - bSubmit: "Speichern", - bCancel: "Abbrechen" - }, - errors : { - errcap : "Fehler", - nourl : "Keine URL angegeben", - norecords: "Keine Datensätze zu bearbeiten", - model : "colNames und colModel sind unterschiedlich lang!" - }, - formatter : { - integer : {thousandsSeparator: ".", defaultValue: '0'}, - number : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, defaultValue: '0,00'}, - currency : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, prefix: "", suffix:" €", defaultValue: '0,00'}, - date : { - dayNames: [ - "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa", - "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag" - ], - monthNames: [ - "Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez", - "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember" - ], - AmPm : ["am","pm","AM","PM"], - S: function (j) {return 'ter'}, - srcformat: 'Y-m-d', - newformat: 'd.m.Y', - masks : { - ISO8601Long: "Y-m-d H:i:s", - ISO8601Short: "Y-m-d", - ShortDate: "j.n.Y", - LongDate: "l, j. F Y", - FullDateTime: "l, d. F Y G:i:s", - MonthDay: "d. F", - ShortTime: "G:i", - LongTime: "G:i:s", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); \ No newline at end of file diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-el.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-el.js deleted file mode 100644 index 5e49ddbdb4a..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-el.js +++ /dev/null @@ -1,126 +0,0 @@ -;(function($){ -/** - * jqGrid Greek (el) Translation - * Alex Cicovic - * http://www.alexcicovic.com - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "View {0} - {1} of {2}", - emptyrecords: "No records to view", - loadtext: "Φόρτωση...", - pgtext : "Page {0} of {1}" - }, - search : { - caption: "Αναζήτηση...", - Find: "Εύρεση", - Reset: "Επαναφορά", - odata : ['equal', 'not equal', 'less', 'less or equal','greater','greater or equal', 'begins with','does not begin with','is in','is not in','ends with','does not end with','contains','does not contain'], - groupOps: [ { op: "AND", text: "all" }, { op: "OR", text: "any" } ], - matchText: " match", - rulesText: " rules" - }, - edit : { - addCaption: "Εισαγωγή Εγγραφής", - editCaption: "Επεξεργασία Εγγραφής", - bSubmit: "Καταχώρηση", - bCancel: "Άκυρο", - bClose: "Κλείσιμο", - saveData: "Data has been changed! Save changes?", - bYes : "Yes", - bNo : "No", - bExit : "Cancel", - msg: { - required:"Το πεδίο είναι απαραίτητο", - number:"Το πεδίο δέχεται μόνο αριθμούς", - minValue:"Η τιμή πρέπει να είναι μεγαλύτερη ή ίση του ", - maxValue:"Η τιμή πρέπει να είναι μικρότερη ή ίση του ", - email: "Η διεύθυνση e-mail δεν είναι έγκυρη", - integer: "Το πεδίο δέχεται μόνο ακέραιους αριθμούς", - url: "is not a valid URL. Prefix required ('http://' or 'https://')", - nodefined : " is not defined!", - novalue : " return value is required!", - customarray : "Custom function should return array!", - customfcheck : "Custom function should be present in case of custom checking!" - } - }, - view : { - caption: "View Record", - bClose: "Close" - }, - del : { - caption: "Διαγραφή", - msg: "Διαγραφή των επιλεγμένων εγγραφών;", - bSubmit: "Ναι", - bCancel: "Άκυρο" - }, - nav : { - edittext: " ", - edittitle: "Επεξεργασία επιλεγμένης εγγραφής", - addtext:" ", - addtitle: "Εισαγωγή νέας εγγραφής", - deltext: " ", - deltitle: "Διαγραφή επιλεγμένης εγγραφής", - searchtext: " ", - searchtitle: "Εύρεση Εγγραφών", - refreshtext: "", - refreshtitle: "Ανανέωση Πίνακα", - alertcap: "Προσοχή", - alerttext: "Δεν έχετε επιλέξει εγγραφή", - viewtext: "", - viewtitle: "View selected row" - }, - col : { - caption: "Εμφάνιση / Απόκρυψη Στηλών", - bSubmit: "ΟΚ", - bCancel: "Άκυρο" - }, - errors : { - errcap : "Σφάλμα", - nourl : "Δεν έχει δοθεί διεύθυνση χειρισμού για τη συγκεκριμένη ενέργεια", - norecords: "Δεν υπάρχουν εγγραφές προς επεξεργασία", - model : "Άνισος αριθμός πεδίων colNames/colModel!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0.00'}, - currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0.00'}, - date : { - dayNames: [ - "Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ", - "Κυριακή", "Δευτέρα", "Τρίτη", "Τετάρτη", "Πέμπτη", "Παρασκευή", "Σάββατο" - ], - monthNames: [ - "Ιαν", "Φεβ", "Μαρ", "Απρ", "Μαι", "Ιουν", "Ιουλ", "Αυγ", "Σεπ", "Οκτ", "Νοε", "Δεκ", - "Ιανουάριος", "Φεβρουάριος", "Μάρτιος", "Απρίλιος", "Μάιος", "Ιούνιος", "Ιούλιος", "Αύγουστος", "Σεπτέμβριος", "Οκτώβριος", "Νοέμβριος", "Δεκέμβριος" - ], - AmPm : ["πμ","μμ","ΠΜ","ΜΜ"], - S: function (j) {return j == 1 || j > 1 ? ['η'][Math.min((j - 1) % 10, 3)] : ''}, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-en.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-en.js deleted file mode 100644 index 19f50a3207d..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-en.js +++ /dev/null @@ -1,128 +0,0 @@ -;(function($){ -/** - * jqGrid English Translation - * Tony Tomov tony@trirand.com - * http://trirand.com/blog/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "View {0} - {1} of {2}", - emptyrecords: "No records to view", - loadtext: "Loading...", - pgtext : "Page {0} of {1}" - }, - search : { - caption: "Search...", - Find: "Find", - Reset: "Reset", - odata : ['equal', 'not equal', 'less', 'less or equal','greater','greater or equal', 'begins with','does not begin with','is in','is not in','ends with','does not end with','contains','does not contain'], - groupOps: [ { op: "AND", text: "all" }, { op: "OR", text: "any" } ], - matchText: " match", - rulesText: " rules" - }, - edit : { - addCaption: "Add Record", - editCaption: "Edit Record", - bSubmit: "Submit", - bCancel: "Cancel", - bClose: "Close", - saveData: "Data has been changed! Save changes?", - bYes : "Yes", - bNo : "No", - bExit : "Cancel", - msg: { - required:"Field is required", - number:"Please, enter valid number", - minValue:"value must be greater than or equal to ", - maxValue:"value must be less than or equal to", - email: "is not a valid e-mail", - integer: "Please, enter valid integer value", - date: "Please, enter valid date value", - url: "is not a valid URL. Prefix required ('http://' or 'https://')", - nodefined : " is not defined!", - novalue : " return value is required!", - customarray : "Custom function should return array!", - customfcheck : "Custom function should be present in case of custom checking!" - - } - }, - view : { - caption: "View Record", - bClose: "Close" - }, - del : { - caption: "Delete", - msg: "Delete selected record(s)?", - bSubmit: "Delete", - bCancel: "Cancel" - }, - nav : { - edittext: "", - edittitle: "Edit selected row", - addtext:"", - addtitle: "Add new row", - deltext: "", - deltitle: "Delete selected row", - searchtext: "", - searchtitle: "Find records", - refreshtext: "", - refreshtitle: "Reload Grid", - alertcap: "Warning", - alerttext: "Please, select row", - viewtext: "", - viewtitle: "View selected row" - }, - col : { - caption: "Select columns", - bSubmit: "Ok", - bCancel: "Cancel" - }, - errors : { - errcap : "Error", - nourl : "No url is set", - norecords: "No records to process", - model : "Length of colNames <> colModel!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0.00'}, - currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0.00'}, - date : { - dayNames: [ - "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat", - "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" - ], - monthNames: [ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", - "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" - ], - AmPm : ["am","pm","AM","PM"], - S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-es.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-es.js deleted file mode 100644 index 9cf5753e4fe..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-es.js +++ /dev/null @@ -1,128 +0,0 @@ -;(function($){ -/** - * jqGrid Spanish Translation - * Traduccion jqGrid en Español por Yamil Bracho - * Traduccion corregida y ampliada por Faserline, S.L. - * http://www.faserline.com - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "Mostrando {0} - {1} de {2}", - emptyrecords: "Sin registros que mostrar", - loadtext: "Cargando...", - pgtext : "Página {0} de {1}" - }, - search : { - caption: "Búsqueda...", - Find: "Buscar", - Reset: "Limpiar", - odata : ['igual ', 'no igual a', 'menor que', 'menor o igual que','mayor que','mayor o igual a', 'empiece por','no empiece por','está en','no está en','termina por','no termina por','contiene','no contiene'], - groupOps: [ { op: "AND", text: "todo" }, { op: "OR", text: "cualquier" } ], - matchText: " match", - rulesText: " reglas" - }, - edit : { - addCaption: "Agregar registro", - editCaption: "Modificar registro", - bSubmit: "Guardar", - bCancel: "Cancelar", - bClose: "Cerrar", - saveData: "Se han modificado los datos, ¿guardar cambios?", - bYes : "Si", - bNo : "No", - bExit : "Cancelar", - msg: { - required:"Campo obligatorio", - number:"Introduzca un número", - minValue:"El valor debe ser mayor o igual a ", - maxValue:"El valor debe ser menor o igual a ", - email: "no es una dirección de correo válida", - integer: "Introduzca un valor entero", - date: "Introduza una fecha correcta ", - url: "no es una URL válida. Prefijo requerido ('http://' or 'https://')", - nodefined : " no está definido.", - novalue : " valor de retorno es requerido.", - customarray : "La función personalizada debe devolver un array.", - customfcheck : "La función personalizada debe estar presente en el caso de validación personalizada." - } - }, - view : { - caption: "Consultar registro", - bClose: "Cerrar" - }, - del : { - caption: "Eliminar", - msg: "¿Desea eliminar los registros seleccionados?", - bSubmit: "Eliminar", - bCancel: "Cancelar" - }, - nav : { - edittext: " ", - edittitle: "Modificar fila seleccionada", - addtext:" ", - addtitle: "Agregar nueva fila", - deltext: " ", - deltitle: "Eliminar fila seleccionada", - searchtext: " ", - searchtitle: "Buscar información", - refreshtext: "", - refreshtitle: "Recargar datos", - alertcap: "Aviso", - alerttext: "Seleccione una fila", - viewtext: "", - viewtitle: "Ver fila seleccionada" - }, - col : { - caption: "Mostrar/ocultar columnas", - bSubmit: "Enviar", - bCancel: "Cancelar" - }, - errors : { - errcap : "Error", - nourl : "No se ha especificado una URL", - norecords: "No hay datos para procesar", - model : "Las columnas de nombres son diferentes de las columnas de modelo" - }, - formatter : { - integer : {thousandsSeparator: ".", defaultValue: '0'}, - number : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, defaultValue: '0,00'}, - currency : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0,00'}, - date : { - dayNames: [ - "Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa", - "Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "Viernes", "Sabado" - ], - monthNames: [ - "Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic", - "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" - ], - AmPm : ["am","pm","AM","PM"], - S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, - srcformat: 'Y-m-d', - newformat: 'd-m-Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-fa.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-fa.js deleted file mode 100644 index 3c233de6b31..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-fa.js +++ /dev/null @@ -1,145 +0,0 @@ -;(function ($) { -/** - * jqGrid Persian Translation - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ - $.jgrid = { - defaults: { - recordtext: "نمابش {0} - {1} از {2}", - emptyrecords: "رکوردی یافت نشد", - loadtext: "بارگزاري...", - pgtext: "صفحه {0} از {1}" - }, - search: { - caption: "جستجو...", - Find: "يافته ها", - Reset: "از نو", - odata: ['برابر', 'نا برابر', 'به', 'کوچکتر', 'از', 'بزرگتر', 'شروع با', 'شروع نشود با', 'نباشد', 'عضو این نباشد', 'اتمام با', 'تمام نشود با', 'حاوی', 'نباشد حاوی'], - groupOps: [{ - op: "AND", - text: "کل" - }, - { - op: "OR", - text: "مجموع" - }], - matchText: " حاوی", - rulesText: " اطلاعات" - }, - edit: { - addCaption: "اضافه کردن رکورد", - editCaption: "ويرايش رکورد", - bSubmit: "ثبت", - bCancel: "انصراف", - bClose: "بستن", - saveData: "دیتا تعییر کرد! ذخیره شود؟", - bYes: "بله", - bNo: "خیر", - bExit: "انصراف", - msg: { - required: "فيلدها بايد ختما پر شوند", - number: "لطفا عدد وعتبر وارد کنيد", - minValue: "مقدار وارد شده بايد بزرگتر يا مساوي با", - maxValue: "مقدار وارد شده بايد کوچکتر يا مساوي", - email: "پست الکترونيک وارد شده معتبر نيست", - integer: "لطفا يک عدد صحيح وارد کنيد", - date: "لطفا يک تاريخ معتبر وارد کنيد", - url: "این آدرس صحیح نمی باشد. پیشوند نیاز است ('http://' یا 'https://')", - nodefined: " تعریف نشده!", - novalue: " مقدار برگشتی اجباری است!", - customarray: "تابع شما باید مقدار آرایه داشته باشد!", - customfcheck: "برای داشتن متد دلخواه شما باید سطون با چکینگ دلخواه داشته باشید!" - } - }, - view: { - caption: "نمایش رکورد", - bClose: "بستن" - }, - del: { - caption: "حذف", - msg: "از حذف گزينه هاي انتخاب شده مطمئن هستيد؟", - bSubmit: "حذف", - bCancel: "ابطال" - }, - nav: { - edittext: " ", - edittitle: "ويرايش رديف هاي انتخاب شده", - addtext: " ", - addtitle: "افزودن رديف جديد", - deltext: " ", - deltitle: "حذف ردبف هاي انتخاب شده", - searchtext: " ", - searchtitle: "جستجوي رديف", - refreshtext: "", - refreshtitle: "بازيابي مجدد صفحه", - alertcap: "اخطار", - alerttext: "لطفا يک رديف انتخاب کنيد", - viewtext: "", - viewtitle: "نمایش رکورد های انتخاب شده" - }, - col: { - caption: "نمايش/عدم نمايش ستون", - bSubmit: "ثبت", - bCancel: "انصراف" - }, - errors: { - errcap: "خطا", - nourl: "هيچ آدرسي تنظيم نشده است", - norecords: "هيچ رکوردي براي پردازش موجود نيست", - model: "طول نام ستون ها محالف ستون هاي مدل مي باشد!" - }, - formatter: { - integer: { - thousandsSeparator: " ", - defaultValue: "0" - }, - number: { - decimalSeparator: ".", - thousandsSeparator: " ", - decimalPlaces: 2, - defaultValue: "0.00" - }, - currency: { - decimalSeparator: ".", - thousandsSeparator: " ", - decimalPlaces: 2, - prefix: "", - suffix: "", - defaultValue: "0" - }, - date: { - dayNames: ["يک", "دو", "سه", "چهار", "پنج", "جمع", "شنب", "يکشنبه", "دوشنبه", "سه شنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه"], - monthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "ژانويه", "فوريه", "مارس", "آوريل", "مه", "ژوئن", "ژوئيه", "اوت", "سپتامبر", "اکتبر", "نوامبر", "December"], - AmPm: ["ب.ظ", "ب.ظ", "ق.ظ", "ق.ظ"], - S: function (b) { - return b < 11 || b > 13 ? ["st", "nd", "rd", "th"][Math.min((b - 1) % 10, 3)] : "th" - }, - srcformat: "Y-m-d", - newformat: "d/m/Y", - masks: { - ISO8601Long: "Y-m-d H:i:s", - ISO8601Short: "Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit: false - }, - baseLinkUrl: "", - showAction: "نمايش", - target: "", - checkbox: { - disabled: true - }, - idName: "id" - } - } -})(jQuery); \ No newline at end of file diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-fi.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-fi.js deleted file mode 100644 index f6d9175e1e4..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-fi.js +++ /dev/null @@ -1,128 +0,0 @@ -;(function($){ -/** - * jqGrid (fi) Finnish Translation - * Jukka Inkeri awot.fi 2010-05-19 Version - * http://awot.fi - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults: { - recordtext: "Rivit {0} - {1} / {2}", - emptyrecords: "Ei näytettäviä", - loadtext: "Haetaan...", - pgtext: "Sivu {0} / {1}" - }, - search: { - caption: "Etsi...", - Find: "Etsi", - Reset: "Tyhjää", - odata: ['=', '<>', '<', '<=','>','>=', 'alkaa','ei ala','joukossa','ei joukossa','loppuu','ei lopu','sisältää','ei sisällä'], - groupOps: [ { op: "AND", text: "kaikki" }, { op: "OR", text: "mikä tahansa" } ], - matchText: "  täytä ehdot:", - rulesText: "" - }, - edit: { - addCaption: "Uusi rivi", - editCaption: "Muokkaa riviä", - bSubmit: "OK", - bCancel: "Peru", - bClose: "Sulje", - saveData: "Tietoja muutettu! Tallennetaanko?", - bYes: "K", - bNo: "E", - bExit: "Peru", - msg: { - required: "pakollinen", - number: "Anna kelvollinen nro", - minValue: "arvo oltava >= ", - maxValue: "arvo oltava <= ", - email: "virheellinen sposti ", - integer: "Anna kelvollinen kokonaisluku", - date: "Anna kelvollinen pvm", - url: "Ei ole sopiva linkki(URL). Alku oltava ('http://' tai 'https://')", - nodefined: " ei ole määritelty!", - novalue: " paluuarvo vaaditaan!", - customarray: "Custom function should return array!", - customfcheck: "Custom function should be present in case of custom checking!" - } - }, - view: { - caption: "Näytä rivi", - bClose: "Sulje" - }, - del: { - caption: "Poista", - msg: "Poista valitut rivit?", - bSubmit: "Poista", - bCancel: "Peru" - }, - nav: { - edittext: " ", - edittitle: "Muokkaa valittu rivi", - addtext: " ", - addtitle: "Uusi rivi", - deltext: " ", - deltitle: "Poista valittu rivi", - searchtext: " ", - searchtitle: "Etsi tietoja", - refreshtext: "", - refreshtitle: "Lataa uudelleen", - alertcap: "Varoitus", - alerttext: "Valitse rivi", - viewtext: "", - viewtitle: "Näyta valitut rivit" - }, - col: { - caption: "Näyta/Piilota sarakkeet", - bSubmit: "OK", - bCancel: "Peru" - }, - errors : { - errcap: "Virhe", - nourl: "url asettamatta", - norecords: "Ei muokattavia tietoja", - model: "Pituus colNames <> colModel!" - }, - formatter: { - integer: {thousandsSeparator: "", defaultValue: '0'}, - number: {decimalSeparator:",", thousandsSeparator: "", decimalPlaces: 2, defaultValue: '0,00'}, - currency: {decimalSeparator:",", thousandsSeparator: "", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0,00'}, - date: { - dayNames: [ - "Su", "Ma", "Ti", "Ke", "To", "Pe", "La", - "Sunnuntai", "Maanantai", "Tiistai", "Keskiviikko", "Torstai", "Perjantai", "Lauantai" - ], - monthNames: [ - "Tam", "Hel", "Maa", "Huh", "Tou", "Kes", "Hei", "Elo", "Syy", "Lok", "Mar", "Jou", - "Tammikuu", "Helmikuu", "Maaliskuu", "Huhtikuu", "Toukokuu", "Kesäkuu", "Heinäkuu", "Elokuu", "Syyskuu", "Lokakuu", "Marraskuu", "Joulukuu" - ], - AmPm: ["am","pm","AM","PM"], - S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks: { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "d.m.Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox: {disabled:true}, - idName: 'id' - } -}; -// FI -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-fr.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-fr.js deleted file mode 100644 index a7d22abe7fd..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-fr.js +++ /dev/null @@ -1,126 +0,0 @@ -;(function($){ -/** - * jqGrid French Translation - * Tony Tomov tony@trirand.com - * http://trirand.com/blog/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "Enregistrements {0} - {1} sur {2}", - emptyrecords: "Aucun enregistrement à afficher", - loadtext: "Chargement...", - pgtext : "Page {0} sur {1}" - }, - search : { - caption: "Recherche...", - Find: "Chercher", - Reset: "Annuler", - odata : ['égal', 'différent', 'inférieur', 'inférieur ou égal','supérieur','supérieur ou égal', 'commence par','ne commence pas par','est dans',"n'est pas dans",'finit par','ne finit pas par','contient','ne contient pas'], - groupOps: [ { op: "AND", text: "tous" }, { op: "OR", text: "aucun" } ], - matchText: " correspondance", - rulesText: " règles" - }, - edit : { - addCaption: "Ajouter", - editCaption: "Editer", - bSubmit: "Valider", - bCancel: "Annuler", - bClose: "Fermer", - saveData: "Les données ont changé ! Enregistrer les modifications ?", - bYes: "Oui", - bNo: "Non", - bExit: "Annuler", - msg: { - required: "Champ obligatoire", - number: "Saisissez un nombre correct", - minValue: "La valeur doit être supérieure ou égale à", - maxValue: "La valeur doit être inférieure ou égale à", - email: "n'est pas un email correct", - integer: "Saisissez un entier correct", - url: "n'est pas une adresse correcte. Préfixe requis ('http://' or 'https://')", - nodefined : " n'est pas défini!", - novalue : " la valeur de retour est requise!", - customarray : "Une fonction personnalisée devrait retourner un tableau (array)!", - customfcheck : "Une fonction personnalisée devrait être présente dans le cas d'une vérification personnalisée!" - } - }, - view : { - caption: "Voir les enregistrement", - bClose: "Fermer" - }, - del : { - caption: "Supprimer", - msg: "Supprimer les enregistrements sélectionnés ?", - bSubmit: "Supprimer", - bCancel: "Annuler" - }, - nav : { - edittext: " ", - edittitle: "Editer la ligne sélectionnée", - addtext:" ", - addtitle: "Ajouter une ligne", - deltext: " ", - deltitle: "Supprimer la ligne sélectionnée", - searchtext: " ", - searchtitle: "Chercher un enregistrement", - refreshtext: "", - refreshtitle: "Recharger le tableau", - alertcap: "Avertissement", - alerttext: "Veuillez sélectionner une ligne", - viewtext: "", - viewtitle: "Afficher la ligne sélectionnée" - }, - col : { - caption: "Afficher/Masquer les colonnes", - bSubmit: "Valider", - bCancel: "Annuler" - }, - errors : { - errcap : "Erreur", - nourl : "Aucune adresse n'est paramétrée", - norecords: "Aucun enregistrement à traiter", - model : "Nombre de titres (colNames) <> Nombre de données (colModel)!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0,00'}, - currency : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0,00'}, - date : { - dayNames: [ - "Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", - "Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi" - ], - monthNames: [ - "Jan", "Fév", "Mar", "Avr", "Mai", "Jui", "Jul", "Aou", "Sep", "Oct", "Nov", "Déc", - "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Aout", "Septembre", "Octobre", "Novembre", "Décembre" - ], - AmPm : ["am","pm","AM","PM"], - S: function (j) {return j == 1 ? 'er' : 'e';}, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-gl.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-gl.js deleted file mode 100644 index 7b7f5a666f8..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-gl.js +++ /dev/null @@ -1,126 +0,0 @@ -;(function($){ -/** - * jqGrid Galician Translation - * Translated by Jorge Barreiro - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "Amosando {0} - {1} de {2}", - emptyrecords: "Sen rexistros que amosar", - loadtext: "Cargando...", - pgtext : "Páxina {0} de {1}" - }, - search : { - caption: "Búsqueda...", - Find: "Buscar", - Reset: "Limpar", - odata : ['igual ', 'diferente a', 'menor que', 'menor ou igual que','maior que','maior ou igual a', 'empece por','non empece por','está en','non está en','termina por','non termina por','contén','non contén'], - groupOps: [ { op: "AND", text: "todo" }, { op: "OR", text: "calquera" } ], - matchText: " match", - rulesText: " regras" - }, - edit : { - addCaption: "Engadir rexistro", - editCaption: "Modificar rexistro", - bSubmit: "Gardar", - bCancel: "Cancelar", - bClose: "Pechar", - saveData: "Modificáronse os datos, quere gardar os cambios?", - bYes : "Si", - bNo : "Non", - bExit : "Cancelar", - msg: { - required:"Campo obrigatorio", - number:"Introduza un número", - minValue:"O valor debe ser maior ou igual a ", - maxValue:"O valor debe ser menor ou igual a ", - email: "non é un enderezo de correo válido", - integer: "Introduza un valor enteiro", - date: "Introduza unha data correcta ", - url: "non é unha URL válida. Prefixo requerido ('http://' ou 'https://')", - nodefined : " non está definido.", - novalue : " o valor de retorno é obrigatorio.", - customarray : "A función persoalizada debe devolver un array.", - customfcheck : "A función persoalizada debe estar presente no caso de ter validación persoalizada." - } - }, - view : { - caption: "Consultar rexistro", - bClose: "Pechar" - }, - del : { - caption: "Eliminar", - msg: "Desexa eliminar os rexistros seleccionados?", - bSubmit: "Eliminar", - bCancel: "Cancelar" - }, - nav : { - edittext: " ", - edittitle: "Modificar a fila seleccionada", - addtext:" ", - addtitle: "Engadir unha nova fila", - deltext: " ", - deltitle: "Eliminar a fila seleccionada", - searchtext: " ", - searchtitle: "Buscar información", - refreshtext: "", - refreshtitle: "Recargar datos", - alertcap: "Aviso", - alerttext: "Seleccione unha fila", - viewtext: "", - viewtitle: "Ver fila seleccionada" - }, - col : { - caption: "Mostrar/ocultar columnas", - bSubmit: "Enviar", - bCancel: "Cancelar" - }, - errors : { - errcap : "Erro", - nourl : "Non especificou unha URL", - norecords: "Non hai datos para procesar", - model : "As columnas de nomes son diferentes das columnas de modelo" - }, - formatter : { - integer : {thousandsSeparator: ".", defaultValue: '0'}, - number : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, defaultValue: '0,00'}, - currency : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0,00'}, - date : { - dayNames: [ - "Do", "Lu", "Ma", "Me", "Xo", "Ve", "Sa", - "Domingo", "Luns", "Martes", "Mércoles", "Xoves", "Vernes", "Sábado" - ], - monthNames: [ - "Xan", "Feb", "Mar", "Abr", "Mai", "Xuñ", "Xul", "Ago", "Set", "Out", "Nov", "Dec", - "Xaneiro", "Febreiro", "Marzo", "Abril", "Maio", "Xuño", "Xullo", "Agosto", "Setembro", "Outubro", "Novembro", "Decembro" - ], - AmPm : ["am","pm","AM","PM"], - S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, - srcformat: 'Y-m-d', - newformat: 'd-m-Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-he.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-he.js deleted file mode 100644 index 677bb802605..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-he.js +++ /dev/null @@ -1,127 +0,0 @@ -;(function($){ -/** - * jqGrid Hebrew Translation - * Shuki Shukrun shukrun.shuki@gmail.com - * http://trirand.com/blog/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "מציג {0} - {1} מתוך {2}", - emptyrecords: "אין רשומות להציג", - loadtext: "טוען...", - pgtext : "דף {0} מתוך {1}" - }, - search : { - caption: "מחפש...", - Find: "חפש", - Reset: "התחל", - odata : ['שווה', 'לא שווה', 'קטן', 'קטן או שווה','גדול','גדול או שווה', 'מתחיל ב','לא מתחיל ב','נמצא ב','לא נמצא ב','מסתיים ב','לא מסתיים ב','מכיל','לא מכיל'], - groupOps: [ { op: "AND", text: "הכל" }, { op: "OR", text: "אחד מ" } ], - matchText: " תואם", - rulesText: " חוקים" - }, - edit : { - addCaption: "הוסף רשומה", - editCaption: "ערוך רשומה", - bSubmit: "שלח", - bCancel: "בטל", - bClose: "סגור", - saveData: "נתונים השתנו! לשמור?", - bYes : "כן", - bNo : "לא", - bExit : "בטל", - msg: { - required:"שדה חובה", - number:"אנא, הכנס מספר תקין", - minValue:"ערך צריך להיות גדול או שווה ל ", - maxValue:"ערך צריך להיות קטן או שווה ל ", - email: "היא לא כתובת איימל תקינה", - integer: "אנא, הכנס מספר שלם", - date: "אנא, הכנס תאריך תקין", - url: "הכתובת אינה תקינה. דרושה תחילית ('http://' או 'https://')", - nodefined : " is not defined!", - novalue : " return value is required!", - customarray : "Custom function should return array!", - customfcheck : "Custom function should be present in case of custom checking!" - } - }, - view : { - caption: "הצג רשומה", - bClose: "סגור" - }, - del : { - caption: "מחק", - msg: "האם למחוק את הרשומה/ות המסומנות?", - bSubmit: "מחק", - bCancel: "בטל" - }, - nav : { - edittext: "", - edittitle: "ערוך שורה מסומנת", - addtext:"", - addtitle: "הוסף שורה חדשה", - deltext: "", - deltitle: "מחק שורה מסומנת", - searchtext: "", - searchtitle: "חפש רשומות", - refreshtext: "", - refreshtitle: "טען גריד מחדש", - alertcap: "אזהרה", - alerttext: "אנא, בחר שורה", - viewtext: "", - viewtitle: "הצג שורה מסומנת" - }, - col : { - caption: "הצג/הסתר עמודות", - bSubmit: "שלח", - bCancel: "בטל" - }, - errors : { - errcap : "שגיאה", - nourl : "לא הוגדרה כתובת url", - norecords: "אין רשומות לעבד", - model : "אורך של colNames <> colModel!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0.00'}, - currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0.00'}, - date : { - dayNames: [ - "א", "ב", "ג", "ד", "ה", "ו", "ש", - "ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת" - ], - monthNames: [ - "ינו", "פבר", "מרץ", "אפר", "מאי", "יונ", "יול", "אוג", "ספט", "אוק", "נוב", "דצמ", - "ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר" - ], - AmPm : ["לפני הצהרים","אחר הצהרים","לפני הצהרים","אחר הצהרים"], - S: function (j) {return j < 11 || j > 13 ? ['', '', '', ''][Math.min((j - 1) % 10, 3)] : ''}, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-hu.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-hu.js deleted file mode 100644 index fc5f96a563e..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-hu.js +++ /dev/null @@ -1,129 +0,0 @@ -;(function($){ -/** - * jqGrid Hungarian Translation - * Őrszigety Ádám udx6bs@freemail.hu - * http://trirand.com/blog/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ - -$.jgrid = { - defaults : { - recordtext: "Oldal {0} - {1} / {2}", - emptyrecords: "Nincs találat", - loadtext: "Betöltés...", - pgtext : "Oldal {0} / {1}" - }, - search : { - caption: "Keresés...", - Find: "Keres", - Reset: "Alapértelmezett", - odata : ['egyenlő', 'nem egyenlő', 'kevesebb', 'kevesebb vagy egyenlő','nagyobb','nagyobb vagy egyenlő', 'ezzel kezdődik','nem ezzel kezdődik','tartalmaz','nem tartalmaz','végződik','nem végződik','tartalmaz','nem tartalmaz'], - groupOps: [ { op: "AND", text: "all" }, { op: "OR", text: "any" } ], - matchText: " match", - rulesText: " rules" - }, - edit : { - addCaption: "Új tétel", - editCaption: "Tétel szerkesztése", - bSubmit: "Mentés", - bCancel: "Mégse", - bClose: "Bezárás", - saveData: "A tétel megváltozott! Tétel mentése?", - bYes : "Igen", - bNo : "Nem", - bExit : "Mégse", - msg: { - required:"Kötelező mező", - number:"Kérjük, adjon meg egy helyes számot", - minValue:"Nagyobb vagy egyenlőnek kell lenni mint ", - maxValue:"Kisebb vagy egyenlőnek kell lennie mint", - email: "hibás emailcím", - integer: "Kérjük adjon meg egy helyes egész számot", - date: "Kérjük adjon meg egy helyes dátumot", - url: "nem helyes cím. Előtag kötelező ('http://' vagy 'https://')", - nodefined : " nem definiált!", - novalue : " visszatérési érték kötelező!!", - customarray : "Custom function should return array!", - customfcheck : "Custom function should be present in case of custom checking!" - - } - }, - view : { - caption: "Tétel megtekintése", - bClose: "Bezárás" - }, - del : { - caption: "Törlés", - msg: "Kiválaztott tétel(ek) törlése?", - bSubmit: "Törlés", - bCancel: "Mégse" - }, - nav : { - edittext: "", - edittitle: "Tétel szerkesztése", - addtext:"", - addtitle: "Új tétel hozzáadása", - deltext: "", - deltitle: "Tétel törlése", - searchtext: "", - searchtitle: "Keresés", - refreshtext: "", - refreshtitle: "Frissítés", - alertcap: "Figyelmeztetés", - alerttext: "Kérem válasszon tételt.", - viewtext: "", - viewtitle: "Tétel megtekintése" - }, - col : { - caption: "Oszlopok kiválasztása", - bSubmit: "Ok", - bCancel: "Mégse" - }, - errors : { - errcap : "Hiba", - nourl : "Nincs URL beállítva", - norecords: "Nincs feldolgozásra váró tétel", - model : "colNames és colModel hossza nem egyenlő!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0,00'}, - currency : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0,00'}, - date : { - dayNames: [ - "Va", "Hé", "Ke", "Sze", "Csü", "Pé", "Szo", - "Vasárnap", "Hétfő", "Kedd", "Szerda", "Csütörtök", "Péntek", "Szombat" - ], - monthNames: [ - "Jan", "Feb", "Már", "Ápr", "Máj", "Jún", "Júl", "Aug", "Szep", "Okt", "Nov", "Dec", - "Január", "Február", "Március", "Áprili", "Május", "Június", "Július", "Augusztus", "Szeptember", "Október", "November", "December" - ], - AmPm : ["de","du","DE","DU"], - S: function (j) {return '.-ik';}, - srcformat: 'Y-m-d', - newformat: 'Y/m/d', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "Y/j/n", - LongDate: "Y. F hó d., l", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "a g:i", - LongTime: "a g:i:s", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "Y, F" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-is.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-is.js deleted file mode 100644 index 2f4a8ad96fe..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-is.js +++ /dev/null @@ -1,126 +0,0 @@ -;(function($){ -/** - * jqGrid Icelandic Translation - * jtm@hi.is Univercity of Iceland - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "View {0} - {1} of {2}", - emptyrecords: "No records to view", - loadtext: "Hleður...", - pgtext : "Page {0} of {1}" - }, - search : { - caption: "Leita...", - Find: "Leita", - Reset: "Endursetja", - odata : ['equal', 'not equal', 'less', 'less or equal','greater','greater or equal', 'begins with','does not begin with','is in','is not in','ends with','does not end with','contains','does not contain'], - groupOps: [ { op: "AND", text: "all" }, { op: "OR", text: "any" } ], - matchText: " match", - rulesText: " rules" - }, - edit : { - addCaption: "Add Record", - editCaption: "Edit Record", - bSubmit: "Vista", - bCancel: "Hætta við", - bClose: "Loka", - saveData: "Data has been changed! Save changes?", - bYes : "Yes", - bNo : "No", - bExit : "Cancel", - msg: { - required:"Reitur er nauðsynlegur", - number:"Vinsamlega settu inn tölu", - minValue:"gildi verður að vera meira en eða jafnt og ", - maxValue:"gildi verður að vera minna en eða jafnt og ", - email: "er ekki löglegt email", - integer: "Vinsamlega settu inn tölu", - date: "Please, enter valid date value", - url: "is not a valid URL. Prefix required ('http://' or 'https://')", - nodefined : " is not defined!", - novalue : " return value is required!", - customarray : "Custom function should return array!", - customfcheck : "Custom function should be present in case of custom checking!" - } - }, - view : { - caption: "View Record", - bClose: "Close" - }, - del : { - caption: "Eyða", - msg: "Eyða völdum færslum ?", - bSubmit: "Eyða", - bCancel: "Hætta við" - }, - nav : { - edittext: " ", - edittitle: "Breyta færslu", - addtext:" ", - addtitle: "Ný færsla", - deltext: " ", - deltitle: "Eyða færslu", - searchtext: " ", - searchtitle: "Leita", - refreshtext: "", - refreshtitle: "Endurhlaða", - alertcap: "Viðvörun", - alerttext: "Vinsamlega veldu færslu", - viewtext: "", - viewtitle: "View selected row" - }, - col : { - caption: "Sýna / fela dálka", - bSubmit: "Vista", - bCancel: "Hætta við" - }, - errors : { - errcap : "Villa", - nourl : "Vantar slóð", - norecords: "Engar færslur valdar", - model : "Length of colNames <> colModel!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0.00'}, - currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0.00'}, - date : { - dayNames: [ - "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat", - "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" - ], - monthNames: [ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", - "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" - ], - AmPm : ["am","pm","AM","PM"], - S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-it.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-it.js deleted file mode 100644 index fec00456e51..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-it.js +++ /dev/null @@ -1 +0,0 @@ -(function(a){a.jgrid={defaults:{recordtext:"Visualizzati {0} - {1} di {2}",emptyrecords:"Nessun record da visualizzare",loadtext:"Caricamento...",pgtext:"Pagina {0} di {1}"},search:{caption:"Ricerca...",Find:"Cerca",Reset:"Pulisci",odata:["uguale","diverso","minore","minore o uguale","maggiore","maggiore o uguale","inizia con","non inizia con","in","non in","termina con","non termina con","contiene","non contiene"],groupOps:[{op:"AND",text:"tutto"},{op:"OR",text:"almeno uno"}],matchText:" corrisponde",rulesText:" regole"},edit:{addCaption:"Aggiungi Record",editCaption:"Modifica Record",bSubmit:"Invia",bCancel:"Chiudi",bClose:"Chiudi",saveData:"Alcuni dati modificati! Salvare i cambiamenti?",bYes:"Si",bNo:"No",bExit:"Esci",msg:{required:"Campo richiesto",number:"Per favore, inserisci un valore valido",minValue:"il valore deve essere maggiore o uguale a ",maxValue:"il valore deve essere minore o uguale a",email:"e-mail non corretta",integer:"Per favore, inserisci un numero intero valido",date:"Per favore, inserisci una data valida",url:"URL non valido. Prefisso richiesto ('http://' or 'https://')",nodefined:" non è definito!",novalue:" valore di ritorno richiesto!",customarray:"La function custon deve tornare un array!",customfcheck:"La function custom deve esistere per il custom checking!"}},view:{caption:"Visualizzazione Record",bClose:"Chiudi"},del:{caption:"Cancella",msg:"Cancellare record selezionato/i?",bSubmit:"Cancella",bCancel:"Annulla"},nav:{edittext:" ",edittitle:"Modifica record selezionato",addtext:" ",addtitle:"Aggiungi nuovo record",deltext:" ",deltitle:"Cancella record selezionato",searchtext:" ",searchtitle:"Ricerca record",refreshtext:"",refreshtitle:"Aggiorna griglia",alertcap:"Attenzione",alerttext:"Per favore, seleziona un record",viewtext:"",viewtitle:"Visualizza riga selezionata"},col:{caption:"Mostra/Nascondi Colonne",bSubmit:"Invia",bCancel:"Annulla"},errors:{errcap:"Errore",nourl:"Url non settata",norecords:"Nessun record da elaborare",model:"Lunghezza di colNames <> colModel!"},formatter:{integer:{thousandsSeparator:" ",defaultValue:"0"},number:{decimalSeparator:",",thousandsSeparator:" ",decimalPlaces:2,defaultValue:"0,00"},currency:{decimalSeparator:",",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:"",defaultValue:"0,00"},date:{dayNames:["Dom","Lun","Mar","Mer","Gio","Ven","Sab","Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"],monthNames:["Gen","Feb","Mar","Apr","Mag","Gui","Lug","Ago","Set","Ott","Nov","Dic","Genneio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Movembre","Dicembre"],AmPm:["am","pm","AM","PM"],S:function(b){return b<11||b>13?["st","nd","rd","th"][Math.min((b-1)%10,3)]:"th"},srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n/j/Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"",target:"",checkbox:{disabled:true},idName:"id"}}})(jQuery); \ No newline at end of file diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-ja.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-ja.js deleted file mode 100644 index 8a9961d8ca4..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-ja.js +++ /dev/null @@ -1,155 +0,0 @@ -;(function($){ -/** - * jqGrid Japanese Translation - * OKADA Yoshitada okada.dev@sth.jp - * http://trirand.com/blog/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "{2} \u4EF6\u4E2D {0} - {1} \u3092\u8868\u793A ", - emptyrecords: "\u8868\u793A\u3059\u308B\u30EC\u30B3\u30FC\u30C9\u304C\u3042\u308A\u307E\u305B\u3093", - loadtext: "\u8aad\u307f\u8fbc\u307f\u4e2d...", - pgtext : "{1} \u30DA\u30FC\u30B8\u4E2D {0} \u30DA\u30FC\u30B8\u76EE " - }, - search : { - caption: "\u691c\u7d22...", - Find: "\u691c\u7d22", - Reset: "\u30ea\u30bb\u30c3\u30c8", - odata: ["\u6B21\u306B\u7B49\u3057\u3044", "\u6B21\u306B\u7B49\u3057\u304F\u306A\u3044", - "\u6B21\u3088\u308A\u5C0F\u3055\u3044", "\u6B21\u306B\u7B49\u3057\u3044\u304B\u5C0F\u3055\u3044", - "\u6B21\u3088\u308A\u5927\u304D\u3044", "\u6B21\u306B\u7B49\u3057\u3044\u304B\u5927\u304D\u3044", - "\u6B21\u3067\u59CB\u307E\u308B", "\u6B21\u3067\u59CB\u307E\u3089\u306A\u3044", - "\u6B21\u306B\u542B\u307E\u308C\u308B", "\u6B21\u306B\u542B\u307E\u308C\u306A\u3044", - "\u6B21\u3067\u7D42\u308F\u308B", "\u6B21\u3067\u7D42\u308F\u3089\u306A\u3044", - "\u6B21\u3092\u542B\u3080", "\u6B21\u3092\u542B\u307E\u306A\u3044"], - groupOps: [{ - op: "AND", - text: "\u3059\u3079\u3066\u306E" - }, - { - op: "OR", - text: "\u3044\u305A\u308C\u304B\u306E" - }], - matchText: " \u6B21\u306E", - rulesText: " \u6761\u4EF6\u3092\u6E80\u305F\u3059" - }, - edit : { - addCaption: "\u30ec\u30b3\u30fc\u30c9\u8ffd\u52a0", - editCaption: "\u30ec\u30b3\u30fc\u30c9\u7de8\u96c6", - bSubmit: "\u9001\u4fe1", - bCancel: "\u30ad\u30e3\u30f3\u30bb\u30eb", - bClose: "\u9589\u3058\u308b", - saveData: "\u30C7\u30FC\u30BF\u304C\u5909\u66F4\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u4FDD\u5B58\u3057\u307E\u3059\u304B\uFF1F", - bYes: "\u306F\u3044", - bNo: "\u3044\u3044\u3048", - bExit: "\u30AD\u30E3\u30F3\u30BB\u30EB", - msg: { - required:"\u3053\u306e\u9805\u76ee\u306f\u5fc5\u9808\u3067\u3059\u3002", - number:"\u6b63\u3057\u3044\u6570\u5024\u3092\u5165\u529b\u3057\u3066\u4e0b\u3055\u3044\u3002", - minValue:"\u6b21\u306e\u5024\u4ee5\u4e0a\u3067\u5165\u529b\u3057\u3066\u4e0b\u3055\u3044\u3002", - maxValue:"\u6b21\u306e\u5024\u4ee5\u4e0b\u3067\u5165\u529b\u3057\u3066\u4e0b\u3055\u3044\u3002", - email: "e-mail\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002", - integer: "\u6b63\u3057\u3044\u6574\u6570\u5024\u3092\u5165\u529b\u3057\u3066\u4e0b\u3055\u3044\u3002", - date: "\u6b63\u3057\u3044\u5024\u3092\u5165\u529b\u3057\u3066\u4e0b\u3055\u3044\u3002", - url: "\u306F\u6709\u52B9\u306AURL\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002\20\u30D7\u30EC\u30D5\u30A3\u30C3\u30AF\u30B9\u304C\u5FC5\u8981\u3067\u3059\u3002 ('http://' \u307E\u305F\u306F 'https://')", - nodefined: " \u304C\u5B9A\u7FA9\u3055\u308C\u3066\u3044\u307E\u305B\u3093", - novalue: " \u623B\u308A\u5024\u304C\u5FC5\u8981\u3067\u3059", - customarray: "\u30AB\u30B9\u30BF\u30E0\u95A2\u6570\u306F\u914D\u5217\u3092\u8FD4\u3059\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059", - customfcheck: "\u30AB\u30B9\u30BF\u30E0\u691C\u8A3C\u306B\u306F\u30AB\u30B9\u30BF\u30E0\u95A2\u6570\u304C\u5FC5\u8981\u3067\u3059" - } - }, - view : { - caption: "\u30EC\u30B3\u30FC\u30C9\u3092\u8868\u793A", - bClose: "\u9589\u3058\u308B" - }, - del : { - caption: "\u524a\u9664", - msg: "\u9078\u629e\u3057\u305f\u30ec\u30b3\u30fc\u30c9\u3092\u524a\u9664\u3057\u307e\u3059\u304b\uff1f", - bSubmit: "\u524a\u9664", - bCancel: "\u30ad\u30e3\u30f3\u30bb\u30eb" - }, - nav : { - edittext: " ", - edittitle: "\u9078\u629e\u3057\u305f\u884c\u3092\u7de8\u96c6", - addtext:" ", - addtitle: "\u884c\u3092\u65b0\u898f\u8ffd\u52a0", - deltext: " ", - deltitle: "\u9078\u629e\u3057\u305f\u884c\u3092\u524a\u9664", - searchtext: " ", - searchtitle: "\u30ec\u30b3\u30fc\u30c9\u691c\u7d22", - refreshtext: "", - refreshtitle: "\u30b0\u30ea\u30c3\u30c9\u3092\u30ea\u30ed\u30fc\u30c9", - alertcap: "\u8b66\u544a", - alerttext: "\u884c\u3092\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044\u3002", - viewtext: "", - viewtitle: "\u9078\u629E\u3057\u305F\u884C\u3092\u8868\u793A" - }, - col : { - caption: "\u5217\u3092\u8868\u793a\uff0f\u96a0\u3059", - bSubmit: "\u9001\u4fe1", - bCancel: "\u30ad\u30e3\u30f3\u30bb\u30eb" - }, - errors : { - errcap : "\u30a8\u30e9\u30fc", - nourl : "URL\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002", - norecords: "\u51e6\u7406\u5bfe\u8c61\u306e\u30ec\u30b3\u30fc\u30c9\u304c\u3042\u308a\u307e\u305b\u3093\u3002", - model : "colNames\u306e\u9577\u3055\u304ccolModel\u3068\u4e00\u81f4\u3057\u307e\u305b\u3093\u3002" - }, - formatter : { - integer: { - thousandsSeparator: ",", - defaultValue: '0' - }, - number: { - decimalSeparator: ".", - thousandsSeparator: ",", - decimalPlaces: 2, - defaultValue: '0.00' - }, - currency: { - decimalSeparator: ".", - thousandsSeparator: ",", - decimalPlaces: 0, - prefix: "", - suffix: "", - defaultValue: '0' - }, - date : { - dayNames: [ - "\u65e5", "\u6708", "\u706b", "\u6c34", "\u6728", "\u91d1", "\u571f", - "\u65e5", "\u6708", "\u706b", "\u6c34", "\u6728", "\u91d1", "\u571f" - ], - monthNames: [ - "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", - "1\u6708", "2\u6708", "3\u6708", "4\u6708", "5\u6708", "6\u6708", "7\u6708", "8\u6708", "9\u6708", "10\u6708", "11\u6708", "12\u6708" - ], - AmPm : ["am","pm","AM","PM"], - S: "\u756a\u76ee", - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-nl.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-nl.js deleted file mode 100644 index a6227acf5c9..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-nl.js +++ /dev/null @@ -1,149 +0,0 @@ -(function(a) { - a.jgrid = - { - defaults: - { - recordtext: "regels {0} - {1} van {2}", - emptyrecords: "Geen data gevonden.", - loadtext: "laden...", - pgtext: "pagina {0} van {1}" - }, - search: - { - caption: "Zoeken...", - Find: "Zoek", - Reset: "Herstellen", - odata: ["gelijk aan", "niet gelijk aan", "kleiner dan", "kleiner dan of gelijk aan", "groter dan", "groter dan of gelijk aan", "begint met", "begint niet met", "is in", "is niet in", "eindigd met", "eindigd niet met", "bevat", "bevat niet"], - groupOps: [{ op: "AND", text: "alle" }, { op: "OR", text: "een van de"}], - matchText: " match", - rulesText: " regels" - }, - edit: - { - addCaption: "Nieuw", - editCaption: "Bewerken", - bSubmit: "Opslaan", - bCancel: "Annuleren", - bClose: "Sluiten", - saveData: "Er is data aangepast! Wijzigingen opslaan?", - bYes: "Ja", - bNo: "Nee", - bExit: "Sluiten", - msg: - { - required: "Veld is verplicht", - number: "Voer a.u.b. geldig nummer in", - minValue: "Waarde moet groter of gelijk zijn aan ", - maxValue: "Waarde moet kleiner of gelijks zijn aan", - email: "is geen geldig e-mailadres", - integer: "Voer a.u.b. een geldig getal in", - date: "Voer a.u.b. een geldige waarde in", - url: "is geen geldige URL. Prefix is verplicht ('http://' or 'https://')", - nodefined : " is not defined!", - novalue : " return value is required!", - customarray : "Custom function should return array!", - customfcheck : "Custom function should be present in case of custom checking!" - } - }, - view: - { - caption: "Tonen", - bClose: "Sluiten" - }, - del: - { - caption: "Verwijderen", - msg: "Verwijder geselecteerde regel(s)?", - bSubmit: "Verwijderen", - bCancel: "Annuleren" - }, - nav: - { - edittext: "", - edittitle: "Bewerken", - addtext: "", - addtitle: "Nieuw", - deltext: "", - deltitle: "Verwijderen", - searchtext: "", - searchtitle: "Zoeken", - refreshtext: "", - refreshtitle: "Vernieuwen", - alertcap: "Waarschuwing", - alerttext: "Selecteer a.u.b. een regel", - viewtext: "", - viewtitle: "Openen" - }, - col: - { - caption: "Tonen/verbergen kolommen", - bSubmit: "OK", - bCancel: "Annuleren" - }, - errors: - { - errcap: "Fout", - nourl: "Er is geen URL gedefinieerd", - norecords: "Geen data om te verwerken", - model: "Lengte van 'colNames' is niet gelijk aan 'colModel'!" - }, - formatter: - { - integer: - { - thousandsSeparator: ".", - defaultValue: "0" - }, - number: - { - decimalSeparator: ",", - thousandsSeparator: ".", - decimalPlaces: 2, - defaultValue: "0.00" - }, - currency: - { - decimalSeparator: ",", - thousandsSeparator: ".", - decimalPlaces: 2, - prefix: "EUR ", - suffix: "", - defaultValue: "0.00" - }, - date: - { - dayNames: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag"], - monthNames: ["Jan", "Feb", "Maa", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "October", "November", "December"], - AmPm: ["am", "pm", "AM", "PM"], - S: function(b) { - return b < 11 || b > 13 ? ["st", "nd", "rd", "th"][Math.min((b - 1) % 10, 3)] : "th" - }, - srcformat: "Y-m-d", - newformat: "d/m/Y", - masks: - { - ISO8601Long: "Y-m-d H:i:s", - ISO8601Short: "Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l d F Y G:i:s", - MonthDay: "d F", - ShortTime: "G:i", - LongTime: "G:i:s", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit: false - }, - baseLinkUrl: "", - showAction: "", - target: "", - checkbox: - { - disabled: true - }, - idName: "id" - } - } -})(jQuery); \ No newline at end of file diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-no.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-no.js deleted file mode 100644 index a70ef6d790a..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-no.js +++ /dev/null @@ -1 +0,0 @@ -(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"Rad {0} - {1}, totalt {2}",loadtext:"Laster...",pgtext:"Side {0} av {1}"};a.jgrid.search={caption:"Søk...",Find:"Finn",Reset:"Nullstill",odata:["lik","forskjellig fra","mindre enn","mindre eller lik","større enn"," større eller lik","starter med","slutter med","inneholder"]};a.jgrid.edit={addCaption:"Ny rad",editCaption:"Rediger",bSubmit:"Send",bCancel:"Avbryt",bClose:"Lukk",processData:"Laster...",msg:{required:"Felt er obligatorisk",number:"Legg inn et gyldig tall",minValue:"verdi må være større enn eller lik",maxValue:"verdi må være mindre enn eller lik",email:"er ikke en gyldig e-post adresse",integer:"Legg inn et gyldig heltall",date:"Legg inn en gyldig dato",url:"er ikke en gyldig URL. Prefiks påkrevd ('http://' eller 'https://')",nodefined:" er ikke definert!",novalue:" returverdi er påkrevd!",customarray:"Tilpasset funksjon må returnere en tabell!",customfcheck:"Tilpasset funksjon må eksistere!"}};a.jgrid.view={caption:"Åpne post",bClose:"Lukk"};a.jgrid.del={caption:"Slett",msg:"Slett valgte rad(er)?",bSubmit:"Slett",bCancel:"Avbryt",processData:"Behandler..."};a.jgrid.nav={edittext:" ",edittitle:"Rediger valgte rad(er)",addtext:" ",addtitle:"Legg til ny rad",deltext:" ",deltitle:"Slett valgte rad(er)",searchtext:" ",searchtitle:"Søk",refreshtext:"",refreshtitle:"Oppdater tabell",alertcap:"Advarsel",alerttext:"Velg rad",viewtext:" ",viewtitle:"Åpne valgt rad"};a.jgrid.col={caption:"Vis/skjul kolonner",bSubmit:"Utfør",bCancel:"Avbryt"};a.jgrid.errors={errcap:"Feil",nourl:"Ingen url er satt",norecords:"Ingen poster å behandle",model:"colNames og colModel har forskjellig lengde!"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:",",thousandsSeparator:" ",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:",",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["sø.","ma.","ti.","on.","to.","fr.","lø.","Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],monthNames:["jan.","feb.","mars","april","mai","juni","juli","aug.","sep.","okt.","nov.","des.","januar","februar","mars","april","mai","juni","juli","august","september","oktober","november","desember"],AmPm:["","","",""],S:function(b){return"."},srcformat:"Y-m-d H:i:s",newformat:"Y-m-d H:i:s",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"j.n.Y",LongDate:"l j. F Y",FullDateTime:"l j. F Y kl. G.i.s",MonthDay:"j. F",ShortTime:"H:i",LongTime:"H:i:s",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show",addParam:"",checkbox:{disabled:true}}})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-pl.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-pl.js deleted file mode 100644 index 53757b99c87..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-pl.js +++ /dev/null @@ -1,127 +0,0 @@ -;(function($){ -/** - * jqGrid Polish Translation - * Łukasz Schab - * http://FreeTree.pl - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "Pokaż {0} - {1} z {2}", - emptyrecords: "Brak rekordów do pokazania", - loadtext: "\u0142adowanie...", - pgtext : "Strona {0} z {1}" - }, - search : { - caption: "Wyszukiwanie...", - Find: "Szukaj", - Reset: "Czyść", - odata : ['dok\u0142adnie', 'różne od', 'mniejsze od', 'mniejsze lub równe','większe od','większe lub równe', 'zaczyna się od','nie zaczyna się od','zawiera','nie zawiera','kończy się na','nie kończy się na','zawiera','nie zawiera'], - groupOps: [ { op: "ORAZ", text: "wszystkie" }, { op: "LUB", text: "każdy" } ], - matchText: " pasuje", - rulesText: " regu\u0142y" - }, - edit : { - addCaption: "Dodaj rekord", - editCaption: "Edytuj rekord", - bSubmit: "Zapisz", - bCancel: "Anuluj", - bClose: "Zamknij", - saveData: "Dane zosta\u0142y zmienione! Zapisać zmiany?", - bYes : "Tak", - bNo : "Nie", - bExit : "Anuluj", - msg: { - required:"Pole jest wymagane", - number:"Proszę wpisać poprawną liczbę", - minValue:"wartość musi być większa lub równa", - maxValue:"wartość musi być mniejsza od", - email: "nie jest adresem e-mail", - integer: "Proszę wpisać poprawną liczbę", - date: "Proszę podaj poprawną datę", - url: "jest niew\u0142aściwym adresem URL. Pamiętaj o prefiksie ('http://' lub 'https://')", - nodefined : " is not defined!", - novalue : " return value is required!", - customarray : "Custom function should return array!", - customfcheck : "Custom function should be present in case of custom checking!" - } - }, - view : { - caption: "Pokaż rekord", - bClose: "Zamknij" - }, - del : { - caption: "Usuwanie", - msg: "Czy usunąć wybrany rekord(y)?", - bSubmit: "Usuń", - bCancel: "Anuluj" - }, - nav : { - edittext: " ", - edittitle: "Edytuj wybrany wiersz", - addtext:" ", - addtitle: "Dodaj nowy wiersz", - deltext: " ", - deltitle: "Usuń wybrany wiersz", - searchtext: " ", - searchtitle: "Wyszukaj rekord", - refreshtext: "", - refreshtitle: "Prze\u0142aduj", - alertcap: "Uwaga", - alerttext: "Proszę wybrać wiersz", - viewtext: "", - viewtitle: "View selected row" - }, - col : { - caption: "Pokaż/Ukryj kolumny", - bSubmit: "Zatwierdź", - bCancel: "Anuluj" - }, - errors : { - errcap : "B\u0142ąd", - nourl : "Brak adresu url", - norecords: "Brak danych", - model : "D\u0142ugość colNames <> colModel!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0.00'}, - currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0.00'}, - date : { - dayNames: [ - "Nie", "Pon", "Wt", "Śr", "Cz", "Pi", "So", - "Niedziela", "Poniedzia\u0142ek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota" - ], - monthNames: [ - "Sty", "Lu", "Mar", "Kwie", "Maj", "Cze", "Lip", "Sie", "Wrz", "Paź", "Lis", "Gru", - "Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień" - ], - AmPm : ["am","pm","AM","PM"], - S: function (j) {return j < 11 || j > 13 ? ['', '', '', ''][Math.min((j - 1) % 10, 3)] : ''}, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); \ No newline at end of file diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-pt-br.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-pt-br.js deleted file mode 100644 index 897f5735b08..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-pt-br.js +++ /dev/null @@ -1,127 +0,0 @@ -;(function($){ -/** - * jqGrid Brazilian-Portuguese Translation - * Sergio Righi sergio.righi@gmail.com - * http://curve.com.br - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "Ver {0} - {1} of {2}", - emptyrecords: "Nenhum registro para visualizar", - loadtext: "Carregando...", - pgtext : "Página {0} de {1}" - }, - search : { - caption: "Procurar...", - Find: "Procurar", - Reset: "Resetar", - odata : ['equal', 'not equal', 'less', 'less or equal','greater','greater or equal', 'begins with','does not begin with','is in','is not in','ends with','does not end with','contains','does not contain'], - groupOps: [ { op: "AND", text: "all" }, { op: "OR", text: "any" } ], - matchText: " iguala", - rulesText: " regras" - }, - edit : { - addCaption: "Incluir", - editCaption: "Alterar", - bSubmit: "Enviar", - bCancel: "Cancelar", - bClose: "Fechar", - saveData: "Os dados foram alterados! Salvar alterações?", - bYes : "Sim", - bNo : "Não", - bExit : "Cancelar", - msg: { - required:"Campo obrigatório", - number:"Por favor, informe um número válido", - minValue:"valor deve ser igual ou maior que ", - maxValue:"valor deve ser menor ou igual a", - email: "este e-mail não é válido", - integer: "Por favor, informe um valor inteiro", - date: "Por favor, informe uma data válida", - url: "não é uma URL válida. Prefixo obrigatório ('http://' or 'https://')", - nodefined : " não está definido!", - novalue : " um valor de retorno é obrigatório!", - customarray : "Função customizada deve retornar um array!", - customfcheck : "Função customizada deve estar presente em caso de validação customizada!" - } - }, - view : { - caption: "Ver Registro", - bClose: "Fechar" - }, - del : { - caption: "Apagar", - msg: "Apagar registros selecionado(s)?", - bSubmit: "Apagar", - bCancel: "Cancelar" - }, - nav : { - edittext: " ", - edittitle: "Alterar registro selecionado", - addtext:" ", - addtitle: "Incluir novo registro", - deltext: " ", - deltitle: "Apagar registro selecionado", - searchtext: " ", - searchtitle: "Procurar registros", - refreshtext: "", - refreshtitle: "Recarrgando Tabela", - alertcap: "Aviso", - alerttext: "Por favor, selecione um registro", - viewtext: "", - viewtitle: "Ver linha selecionada" - }, - col : { - caption: "Mostrar/Esconder Colunas", - bSubmit: "Enviar", - bCancel: "Cancelar" - }, - errors : { - errcap : "Erro", - nourl : "Nenhuma URL defenida", - norecords: "Sem registros para exibir", - model : "Comprimento de colNames <> colModel!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0,00'}, - currency : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, prefix: "R$ ", suffix:"", defaultValue: '0,00'}, - date : { - dayNames: [ - "Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", - "Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado" - ], - monthNames: [ - "Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez", - "Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro" - ], - AmPm : ["am","pm","AM","PM"], - S: function (j) {return j < 11 || j > 13 ? ['º', 'º', 'º', 'º'][Math.min((j - 1) % 10, 3)] : 'º'}, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-pt.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-pt.js deleted file mode 100644 index c150c228447..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-pt.js +++ /dev/null @@ -1,125 +0,0 @@ -;(function($){ -/** - * jqGrid Portuguese Translation -* Tradução da jqGrid em Portugues por Frederico Carvalho, http://www.eyeviewdesign.pt - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "View {0} - {1} of {2}", - emptyrecords: "No records to view", - loadtext: "A carregar...", - pgtext : "Page {0} of {1}" - }, - search : { - caption: "Busca...", - Find: "Procurar", - Reset: "Limpar", - odata : ['equal', 'not equal', 'less', 'less or equal','greater','greater or equal', 'begins with','does not begin with','is in','is not in','ends with','does not end with','contains','does not contain'], - groupOps: [ { op: "AND", text: "all" }, { op: "OR", text: "any" } ], - matchText: " match", - rulesText: " rules" - }, - edit : { - addCaption: "Adicionar Registo", - editCaption: "Modificar Registo", - bSubmit: "Submeter", - bCancel: "Cancelar", - bClose: "Fechar", - saveData: "Data has been changed! Save changes?", - bYes : "Yes", - bNo : "No", - bExit : "Cancel", - msg: { - required:"Campo obrigatório", - number:"Por favor, introduza um numero", - minValue:"O valor deve ser maior ou igual que", - maxValue:"O valor deve ser menor ou igual a", - email: "Não é um endereço de email válido", - integer: "Por favor, introduza um numero inteiro", - url: "is not a valid URL. Prefix required ('http://' or 'https://')", - nodefined : " is not defined!", - novalue : " return value is required!", - customarray : "Custom function should return array!", - customfcheck : "Custom function should be present in case of custom checking!" - } - }, - view : { - caption: "View Record", - bClose: "Close" - }, - del : { - caption: "Eliminar", - msg: "Deseja eliminar o(s) registo(s) seleccionado(s)?", - bSubmit: "Eliminar", - bCancel: "Cancelar" - }, - nav : { - edittext: " ", - edittitle: "Modificar registo seleccionado", - addtext:" ", - addtitle: "Adicionar novo registo", - deltext: " ", - deltitle: "Eliminar registo seleccionado", - searchtext: " ", - searchtitle: "Procurar", - refreshtext: "", - refreshtitle: "Actualizar", - alertcap: "Aviso", - alerttext: "Por favor, seleccione um registo", - viewtext: "", - viewtitle: "View selected row" - }, - col : { - caption: "Mostrar/Ocultar Colunas", - bSubmit: "Enviar", - bCancel: "Cancelar" - }, - errors : { - errcap : "Erro", - nourl : "Não especificou um url", - norecords: "Não existem dados para processar", - model : "Tamanho do colNames <> colModel!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0.00'}, - currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0.00'}, - date : { - dayNames: [ - "Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab", - "Domingo", "Segunda-Feira", "Terça-Feira", "Quarta-Feira", "Quinta-Feira", "Sexta-Feira", "Sábado" - ], - monthNames: [ - "Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez", - "Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro" - ], - AmPm : ["am","pm","AM","PM"], - S: function (j) {return j < 11 || j > 13 ? ['º', 'º', 'º', 'º'][Math.min((j - 1) % 10, 3)] : 'º'}, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-ro.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-ro.js deleted file mode 100644 index eb5ae836401..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-ro.js +++ /dev/null @@ -1,139 +0,0 @@ -;(function($){ -/** - * jqGrid Romanian Translation - * Alexandru Emil Lupu contact@alecslupu.ro - * http://www.alecslupu.ro/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "Vizualizare {0} - {1} din {2}", - emptyrecords: "Nu există înregistrări de vizualizat", - loadtext: "Încărcare...", - pgtext : "Pagina {0} din {1}" - }, - search : { - caption: "Caută...", - Find: "Caută", - Reset: "Resetare", - odata : ['egal', 'diferit', 'mai mic', 'mai mic sau egal','mai mare','mai mare sau egal', 'începe cu','nu începe cu','se găsește în','nu se găsește în','se termină cu','nu se termină cu','conține',''], - groupOps: [ { op: "AND", text: "toate" }, { op: "OR", text: "oricare" } ], - matchText: " găsite", - rulesText: " reguli" - }, - edit : { - addCaption: "Adăugare înregistrare", - editCaption: "Modificare înregistrare", - bSubmit: "Salvează", - bCancel: "Anulare", - bClose: "Închide", - saveData: "Informațiile au fost modificate! Salvați modificările?", - bYes : "Da", - bNo : "Nu", - bExit : "Anulare", - msg: { - required:"Câmpul este obligatoriu", - number:"Vă rugăm introduceți un număr valid", - minValue:"valoarea trebuie sa fie mai mare sau egală cu", - maxValue:"valoarea trebuie sa fie mai mică sau egală cu", - email: "nu este o adresă de e-mail validă", - integer: "Vă rugăm introduceți un număr valid", - date: "Vă rugăm să introduceți o dată validă", - url: "Nu este un URL valid. Prefixul este necesar('http://' or 'https://')", - nodefined : " is not defined!", - novalue : " return value is required!", - customarray : "Custom function should return array!", - customfcheck : "Custom function should be present in case of custom checking!" - } - }, - view : { - caption: "Vizualizare înregistrare", - bClose: "Închidere" - }, - del : { - caption: "Ștegere", - msg: "Ștergeți înregistrarea (înregistrările) selectate?", - bSubmit: "Șterge", - bCancel: "Anulare" - }, - nav : { - edittext: "", - edittitle: "Modifică rândul selectat", - addtext:"", - addtitle: "Adaugă rând nou", - deltext: "", - deltitle: "Șterge rândul selectat", - searchtext: "", - searchtitle: "Căutare înregistrări", - refreshtext: "", - refreshtitle: "Reîncarcare Grid", - alertcap: "Avertisment", - alerttext: "Vă rugăm să selectați un rând", - viewtext: "", - viewtitle: "Vizualizează rândul selectat" - }, - col : { - caption: "Arată/Ascunde coloanele", - bSubmit: "Salvează", - bCancel: "Anulare" - }, - errors : { - errcap : "Eroare", - nourl : "Niciun url nu este setat", - norecords: "Nu sunt înregistrări de procesat", - model : "Lungimea colNames <> colModel!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0,00'}, - currency : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0,00'}, - date : { - dayNames: [ - "Dum", "Lun", "Mar", "Mie", "Joi", "Vin", "Sâm", - "Duminică", "Luni", "Marți", "Miercuri", "Joi", "Vineri", "Sâmbătă" - ], - monthNames: [ - "Ian", "Feb", "Mar", "Apr", "Mai", "Iun", "Iul", "Aug", "Sep", "Oct", "Noi", "Dec", - "Ianuarie", "Februarie", "Martie", "Aprilie", "Mai", "Iunie", "Iulie", "August", "Septembrie", "Octombrie", "Noiembrie", "Decembrie" - ], - AmPm : ["am","pm","AM","PM"], - /* - Here is a problem in romanian: - M / F - 1st = primul / prima - 2nd = Al doilea / A doua - 3rd = Al treilea / A treia - 4th = Al patrulea/ A patra - 5th = Al cincilea / A cincea - 6th = Al șaselea / A șasea - 7th = Al șaptelea / A șaptea - .... - */ - S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-ru.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-ru.js deleted file mode 100644 index 357b0ff1aee..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-ru.js +++ /dev/null @@ -1,127 +0,0 @@ -;(function($){ -/** - * jqGrid Russian Translation v1.0 02.07.2009 (based on translation by Alexey Kanaev v1.1 21.01.2009, http://softcore.com.ru) - * Sergey Dyagovchenko - * http://d.sumy.ua - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "Просмотр {0} - {1} из {2}", - emptyrecords: "Нет записей для просмотра", - loadtext: "Загрузка...", - pgtext : "Стр. {0} из {1}" - }, - search : { - caption: "Поиск...", - Find: "Найти", - Reset: "Сброс", - odata : ['равно', 'не равно', 'меньше', 'меньше или равно','больше','больше или равно', 'начинается с','не начинается с','находится в','не находится в','заканчивается на','не заканчивается на','содержит','не содержит'], - groupOps: [ { op: "AND", text: "все" }, { op: "OR", text: "любой" } ], - matchText: " совпадает", - rulesText: " правила" - }, - edit : { - addCaption: "Добавить запись", - editCaption: "Редактировать запись", - bSubmit: "Сохранить", - bCancel: "Отмена", - bClose: "Закрыть", - saveData: "Данные были измененны! Сохранить изменения?", - bYes : "Да", - bNo : "Нет", - bExit : "Отмена", - msg: { - required:"Поле является обязательным", - number:"Пожалуйста, введите правильное число", - minValue:"значение должно быть больше либо равно", - maxValue:"значение должно быть меньше либо равно", - email: "некорректное значение e-mail", - integer: "Пожалуйста, введите целое число", - date: "Пожалуйста, введите правильную дату", - url: "неверная ссылка. Необходимо ввести префикс ('http://' or 'https://')", - nodefined : " is not defined!", - novalue : " return value is required!", - customarray : "Custom function should return array!", - customfcheck : "Custom function should be present in case of custom checking!" - } - }, - view : { - caption: "Просмотр записи", - bClose: "Закрыть" - }, - del : { - caption: "Удалить", - msg: "Удалить выбранную запись(и)?", - bSubmit: "Удалить", - bCancel: "Отмена" - }, - nav : { - edittext: " ", - edittitle: "Редактировать выбранную запись", - addtext:" ", - addtitle: "Добавить новую запись", - deltext: " ", - deltitle: "Удалить выбранную запись", - searchtext: " ", - searchtitle: "Найти записи", - refreshtext: "", - refreshtitle: "Обновить таблицу", - alertcap: "Внимание", - alerttext: "Пожалуйста, выберите запись", - viewtext: "", - viewtitle: "Просмотреть выбранную запись" - }, - col : { - caption: "Показать/скрыть столбцы", - bSubmit: "Сохранить", - bCancel: "Отмена" - }, - errors : { - errcap : "Ошибка", - nourl : "URL не установлен", - norecords: "Нет записей для обработки", - model : "Число полей не соответствует числу столбцов таблицы!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0,00'}, - currency : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0,00'}, - date : { - dayNames: [ - "Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб", - "Воскресение", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота" - ], - monthNames: [ - "Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек", - "Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь" - ], - AmPm : ["am","pm","AM","PM"], - S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, - srcformat: 'Y-m-d', - newformat: 'd.m.Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n.j.Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y G:i:s", - MonthDay: "F d", - ShortTime: "G:i", - LongTime: "G:i:s", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-sk.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-sk.js deleted file mode 100644 index 605382b19ef..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-sk.js +++ /dev/null @@ -1,127 +0,0 @@ -;(function($){ -/** - * jqGrid Slovak Translation - * Milan Cibulka - * http://trirand.com/blog/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "Zobrazených {0} - {1} z {2} záznamov", - emptyrecords: "Neboli nájdené žiadne záznamy", - loadtext: "Načítám...", - pgtext : "Strana {0} z {1}" - }, - search : { - caption: "Vyhľadávam...", - Find: "Hľadať", - Reset: "Reset", - odata : ['rovná sa', 'nerovná sa', 'menšie', 'menšie alebo rovnajúce sa','väčšie', 'väčšie alebo rovnajúce sa', 'začína s', 'nezačína s', 'je v', 'nie je v', 'končí s', 'nekončí s', 'obahuje', 'neobsahuje'], - groupOps: [ { op: "AND", text: "všetkých" }, { op: "OR", text: "niektorého z" } ], - matchText: " hľadať podla", - rulesText: " pravidiel" - }, - edit : { - addCaption: "Pridať záznam", - editCaption: "Editácia záznamov", - bSubmit: "Uložiť", - bCancel: "Storno", - bClose: "Zavrieť", - saveData: "Údaje boli zmenené! Uložiť zmeny?", - bYes : "Ano", - bNo : "Nie", - bExit : "Zrušiť", - msg: { - required:"Pole je požadované", - number:"Prosím, vložte valídne číslo", - minValue:"hodnota musí býť väčšia ako alebo rovná ", - maxValue:"hodnota musí býť menšia ako alebo rovná ", - email: "nie je valídny e-mail", - integer: "Prosím, vložte celé číslo", - date: "Prosím, vložte valídny dátum", - url: "nie je platnou URL. Požadovaný prefix ('http://' alebo 'https://')", - nodefined : " nie je definovaný!", - novalue : " je vyžadovaná návratová hodnota!", - customarray : "Custom function mala vrátiť pole!", - customfcheck : "Custom function by mala byť prítomná v prípade custom checking!" - } - }, - view : { - caption: "Zobraziť záznam", - bClose: "Zavrieť" - }, - del : { - caption: "Zmazať", - msg: "Zmazať vybraný(é) záznam(y)?", - bSubmit: "Zmazať", - bCancel: "Storno" - }, - nav : { - edittext: " ", - edittitle: "Editovať vybraný riadok", - addtext:" ", - addtitle: "Pridať nový riadek", - deltext: " ", - deltitle: "Zmazať vybraný záznam ", - searchtext: " ", - searchtitle: "Nájsť záznamy", - refreshtext: "", - refreshtitle: "Obnoviť tabuľku", - alertcap: "Varovanie", - alerttext: "Prosím, vyberte riadok", - viewtext: "", - viewtitle: "Zobraziť vybraný riadok" - }, - col : { - caption: "Zobrazit/Skrýť stĺpce", - bSubmit: "Uložiť", - bCancel: "Storno" - }, - errors : { - errcap : "Chyba", - nourl : "Nie je nastavená url", - norecords: "Žiadne záznamy k spracovaniu", - model : "Dĺžka colNames <> colModel!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0.00'}, - currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0.00'}, - date : { - dayNames: [ - "Ne", "Po", "Ut", "St", "Št", "Pi", "So", - "Nedela", "Pondelok", "Utorok", "Streda", "Štvrtok", "Piatek", "Sobota" - ], - monthNames: [ - "Jan", "Feb", "Mar", "Apr", "Máj", "Jún", "Júl", "Aug", "Sep", "Okt", "Nov", "Dec", - "Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Október", "November", "December" - ], - AmPm : ["do","od","DO","OD"], - S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-sr.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-sr.js deleted file mode 100644 index 305b17e2b53..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-sr.js +++ /dev/null @@ -1,128 +0,0 @@ -;(function($){ -/** - * jqGrid Serbian Translation - * Александар Миловац(Aleksandar Milovac) aleksandar.milovac@gmail.com - * http://trirand.com/blog/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "Преглед {0} - {1} од {2}", - emptyrecords: "Не постоји ниједан запис", - loadtext: "Учитавање...", - pgtext : "Страна {0} од {1}" - }, - search : { - caption: "Тражење...", - Find: "Тражи", - Reset: "Ресетуј", - odata : ['једнако', 'није једнако', 'мање', 'мање или једнако','веће','веће или једнако', 'почиње са','не почиње са','је у','није у','завршава са','не завршава са','садржи','не садржи'], - groupOps: [ { op: "И", text: "сви" }, { op: "ИЛИ", text: "сваки" } ], - matchText: " match", - rulesText: " правила" - }, - edit : { - addCaption: "Додај запис", - editCaption: "Измени запис", - bSubmit: "Пошаљи", - bCancel: "Одустани", - bClose: "Затвори", - saveData: "Податак је измењен! Сачувај измене?", - bYes : "Да", - bNo : "Не", - bExit : "Одустани", - msg: { - required:"Поље је обавезно", - number:"Молим, унесите исправан број", - minValue:"вредност мора бити већа од или једнака са ", - maxValue:"вредност мора бити мања од или једнака са", - email: "није исправна имејл адреса", - integer: "Молим, унесите исправну целобројну вредност ", - date: "Молим, унесите исправан датум", - url: "није исправан УРЛ. Потребан је префикс ('http://' or 'https://')", - nodefined : " није дефинисан!", - novalue : " захтевана је повратна вредност!", - customarray : "Custom function should return array!", - customfcheck : "Custom function should be present in case of custom checking!" - - } - }, - view : { - caption: "Погледај запис", - bClose: "Затвори" - }, - del : { - caption: "Избриши", - msg: "Избриши изабран(е) запис(е)?", - bSubmit: "Ибриши", - bCancel: "Одбаци" - }, - nav : { - edittext: "", - edittitle: "Измени изабрани ред", - addtext:"", - addtitle: "Додај нови ред", - deltext: "", - deltitle: "Избриши изабран ред", - searchtext: "", - searchtitle: "Нађи записе", - refreshtext: "", - refreshtitle: "Поново учитај податке", - alertcap: "Упозорење", - alerttext: "Молим, изаберите ред", - viewtext: "", - viewtitle: "Погледај изабрани ред" - }, - col : { - caption: "Изабери колоне", - bSubmit: "ОК", - bCancel: "Одбаци" - }, - errors : { - errcap : "Грешка", - nourl : "Није постављен URL", - norecords: "Нема записа за обраду", - model : "Дужина модела colNames <> colModel!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0.00'}, - currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0.00'}, - date : { - dayNames: [ - "Нед", "Пон", "Уто", "Сре", "Чет", "Пет", "Суб", - "Недеља", "Понедељак", "Уторак", "Среда", "Четвртак", "Петак", "Субота" - ], - monthNames: [ - "Јан", "Феб", "Мар", "Апр", "Мај", "Јун", "Јул", "Авг", "Сеп", "Окт", "Нов", "Дец", - "Јануар", "Фебруар", "Март", "Април", "Мај", "Јун", "Јул", "Август", "Септембар", "Октобар", "Новембар", "Децембар" - ], - AmPm : ["am","pm","AM","PM"], - S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-sv.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-sv.js deleted file mode 100644 index fc9fcf40902..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-sv.js +++ /dev/null @@ -1,127 +0,0 @@ -;(function($){ -/** - * jqGrid Swedish Translation - * Harald Normann harald.normann@wts.se, harald.normann@gmail.com - * http://www.worldteamsoftware.com - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "Visar {0} - {1} av {2}", - emptyrecords: "Det finns inga poster att visa", - loadtext: "Laddar...", - pgtext : "Sida {0} av {1}" - }, - search : { - caption: "Sök Poster - Ange sökvillkor", - Find: "Sök", - Reset: "Nollställ Villkor", - odata : ['lika', 'ej lika', 'mindre', 'mindre eller lika','större','större eller lika', 'börjar med','börjar inte med','tillhör','tillhör inte','slutar med','slutar inte med','innehåller','innehåller inte'], - groupOps: [ { op: "AND", text: "alla" }, { op: "OR", text: "eller" } ], - matchText: " träff", - rulesText: " regler" - }, - edit : { - addCaption: "Ny Post", - editCaption: "Redigera Post", - bSubmit: "Spara", - bCancel: "Avbryt", - bClose: "Stäng", - saveData: "Data har ändrats! Spara förändringar?", - bYes : "Ja", - bNo : "Nej", - bExit : "Avbryt", - msg: { - required:"Fältet är obligatoriskt", - number:"Välj korrekt nummer", - minValue:"värdet måste vara större än eller lika med", - maxValue:"värdet måste vara mindre än eller lika med", - email: "är inte korrekt e-post adress", - integer: "Var god ange korrekt heltal", - date: "Var god ange korrekt datum", - url: "är inte en korrekt URL. Prefix måste anges ('http://' or 'https://')", - nodefined : " är inte definierad!", - novalue : " returvärde måste anges!", - customarray : "Custom funktion måste returnera en vektor!", - customfcheck : "Custom funktion måste finnas om Custom kontroll sker!" - } - }, - view : { - caption: "Visa Post", - bClose: "Stäng" - }, - del : { - caption: "Radera", - msg: "Radera markerad(e) post(er)?", - bSubmit: "Radera", - bCancel: "Avbryt" - }, - nav : { - edittext: "", - edittitle: "Redigera markerad rad", - addtext:"", - addtitle: "Skapa ny post", - deltext: "", - deltitle: "Radera markerad rad", - searchtext: "", - searchtitle: "Sök poster", - refreshtext: "", - refreshtitle: "Uppdatera data", - alertcap: "Varning", - alerttext: "Ingen rad är markerad", - viewtext: "", - viewtitle: "Visa markerad rad" - }, - col : { - caption: "Välj Kolumner", - bSubmit: "OK", - bCancel: "Avbryt" - }, - errors : { - errcap : "Fel", - nourl : "URL saknas", - norecords: "Det finns inga poster att bearbeta", - model : "Antal colNames <> colModel!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0,00'}, - currency : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"Kr", defaultValue: '0,00'}, - date : { - dayNames: [ - "Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör", - "Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag" - ], - monthNames: [ - "Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec", - "Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December" - ], - AmPm : ["fm","em","FM","EM"], - S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, - srcformat: 'Y-m-d', - newformat: 'Y-m-d', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-tr.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-tr.js deleted file mode 100644 index 6ccde274a2b..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-tr.js +++ /dev/null @@ -1,126 +0,0 @@ -;(function($){ -/** - * jqGrid Turkish Translation - * Erhan Gündoğan (erhan@trposta.net) - * http://blog.zakkum.com - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "{0}-{1} listeleniyor. Toplam:{2}", - emptyrecords: "Kayıt bulunamadı", - loadtext: "Yükleniyor...", - pgtext : "{0}/{1}. Sayfa" - }, - search : { - caption: "Arama...", - Find: "Bul", - Reset: "Temizle", - odata : ['eşit', 'eşit değil', 'daha az', 'daha az veya eşit', 'daha fazla', 'daha fazla veya eşit', 'ile başlayan', 'ile başlamayan', 'içinde', 'içinde değil', 'ile biten', 'ile bitmeyen', 'içeren', 'içermeyen'], - groupOps: [ { op: "VE", text: "tüm" }, { op: "VEYA", text: "herhangi" } ], - matchText: " uyan", - rulesText: " kurallar" - }, - edit : { - addCaption: "Kayıt Ekle", - editCaption: "Kayıt Düzenle", - bSubmit: "Gönder", - bCancel: "İptal", - bClose: "Kapat", - saveData: "Veriler değişti! Kayıt edilsin mi?", - bYes : "Evet", - bNo : "Hayıt", - bExit : "İptal", - msg: { - required:"Alan gerekli", - number:"Lütfen bir numara giriniz", - minValue:"girilen değer daha büyük ya da buna eşit olmalıdır", - maxValue:"girilen değer daha küçük ya da buna eşit olmalıdır", - email: "geçerli bir e-posta adresi değildir", - integer: "Lütfen bir tamsayı giriniz", - url: "Geçerli bir URL değil. ('http://' or 'https://') ön eki gerekli.", - nodefined : " is not defined!", - novalue : " return value is required!", - customarray : "Custom function should return array!", - customfcheck : "Custom function should be present in case of custom checking!" - } - }, - view : { - caption: "Kayıt Görüntüle", - bClose: "Kapat" - }, - del : { - caption: "Sil", - msg: "Seçilen kayıtlar silinsin mi?", - bSubmit: "Sil", - bCancel: "İptal" - }, - nav : { - edittext: " ", - edittitle: "Seçili satırı düzenle", - addtext:" ", - addtitle: "Yeni satır ekle", - deltext: " ", - deltitle: "Seçili satırı sil", - searchtext: " ", - searchtitle: "Kayıtları bul", - refreshtext: "", - refreshtitle: "Tabloyu yenile", - alertcap: "Uyarı", - alerttext: "Lütfen bir satır seçiniz", - viewtext: "", - viewtitle: "Seçilen satırı görüntüle" - }, - col : { - caption: "Sütunları göster/gizle", - bSubmit: "Gönder", - bCancel: "İptal" - }, - errors : { - errcap : "Hata", - nourl : "Bir url yapılandırılmamış", - norecords: "İşlem yapılacak bir kayıt yok", - model : "colNames uzunluğu <> colModel!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0.00'}, - currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0.00'}, - date : { - dayNames: [ - "Paz", "Pts", "Sal", "Çar", "Per", "Cum", "Cts", - "Pazar", "Pazartesi", "Salı", "Çarşamba", "Perşembe", "Cuma", "Cumartesi" - ], - monthNames: [ - "Oca", "Şub", "Mar", "Nis", "May", "Haz", "Tem", "Ağu", "Eyl", "Eki", "Kas", "Ara", - "Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık" - ], - AmPm : ["am","pm","AM","PM"], - S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, - srcformat: 'Y-m-d', - newformat: 'd/m/Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n/j/Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y g:i:s A", - MonthDay: "F d", - ShortTime: "g:i A", - LongTime: "g:i:s A", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-ua.js b/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-ua.js deleted file mode 100644 index ccb085c181d..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/i18n/grid.locale-ua.js +++ /dev/null @@ -1,127 +0,0 @@ -;(function($){ -/** - * jqGrid Ukrainian Translation v1.0 02.07.2009 - * Sergey Dyagovchenko - * http://d.sumy.ua - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html -**/ -$.jgrid = { - defaults : { - recordtext: "Перегляд {0} - {1} з {2}", - emptyrecords: "Немає записів для перегляду", - loadtext: "Завантаження...", - pgtext : "Стор. {0} з {1}" - }, - search : { - caption: "Пошук...", - Find: "Знайти", - Reset: "Скидання", - odata : ['рівно', 'не рівно', 'менше', 'менше або рівне','більше','більше або рівне', 'починається з','не починається з','знаходиться в','не знаходиться в','закінчується на','не закінчується на','містить','не містить'], - groupOps: [ { op: "AND", text: "все" }, { op: "OR", text: "будь-який" } ], - matchText: " збігається", - rulesText: " правила" - }, - edit : { - addCaption: "Додати запис", - editCaption: "Змінити запис", - bSubmit: "Зберегти", - bCancel: "Відміна", - bClose: "Закрити", - saveData: "До данних були внесені зміни! Зберегти зміни?", - bYes : "Так", - bNo : "Ні", - bExit : "Відміна", - msg: { - required:"Поле є обов'язковим", - number:"Будь ласка, введіть правильне число", - minValue:"значення повинне бути більше або дорівнює", - maxValue:"значення повинно бути менше або дорівнює", - email: "некоректна адреса електронної пошти", - integer: "Будь ласка, введення дійсне ціле значення", - date: "Будь ласка, введення дійсне значення дати", - url: "не дійсний URL. Необхідна приставка ('http://' or 'https://')", - nodefined : " is not defined!", - novalue : " return value is required!", - customarray : "Custom function should return array!", - customfcheck : "Custom function should be present in case of custom checking!" - } - }, - view : { - caption: "Переглянути запис", - bClose: "Закрити" - }, - del : { - caption: "Видалити", - msg: "Видалити обраний запис(и)?", - bSubmit: "Видалити", - bCancel: "Відміна" - }, - nav : { - edittext: " ", - edittitle: "Змінити вибраний запис", - addtext:" ", - addtitle: "Додати новий запис", - deltext: " ", - deltitle: "Видалити вибраний запис", - searchtext: " ", - searchtitle: "Знайти записи", - refreshtext: "", - refreshtitle: "Оновити таблицю", - alertcap: "Попередження", - alerttext: "Будь ласка, виберіть запис", - viewtext: "", - viewtitle: "Переглянути обраний запис" - }, - col : { - caption: "Показати/Приховати стовпці", - bSubmit: "Зберегти", - bCancel: "Відміна" - }, - errors : { - errcap : "Помилка", - nourl : "URL не задан", - norecords: "Немає записів для обробки", - model : "Число полів не відповідає числу стовпців таблиці!" - }, - formatter : { - integer : {thousandsSeparator: " ", defaultValue: '0'}, - number : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: '0,00'}, - currency : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0,00'}, - date : { - dayNames: [ - "Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб", - "Неділя", "Понеділок", "Вівторок", "Середа", "Четвер", "П'ятниця", "Субота" - ], - monthNames: [ - "Січ", "Лют", "Бер", "Кві", "Тра", "Чер", "Лип", "Сер", "Вер", "Жов", "Лис", "Гру", - "Січень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "Вересень", "Жовтень", "Листопад", "Грудень" - ], - AmPm : ["am","pm","AM","PM"], - S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, - srcformat: 'Y-m-d', - newformat: 'd.m.Y', - masks : { - ISO8601Long:"Y-m-d H:i:s", - ISO8601Short:"Y-m-d", - ShortDate: "n.j.Y", - LongDate: "l, F d, Y", - FullDateTime: "l, F d, Y G:i:s", - MonthDay: "F d", - ShortTime: "G:i", - LongTime: "G:i:s", - SortableDateTime: "Y-m-d\\TH:i:s", - UniversalSortableDateTime: "Y-m-d H:i:sO", - YearMonth: "F, Y" - }, - reformatAfterEdit : false - }, - baseLinkUrl: '', - showAction: '', - target: '', - checkbox : {disabled:true}, - idName : 'id' - } -}; -})(jQuery); diff --git a/addons/base/static/lib/jquery.jqGrid/js/jqDnR.js b/addons/base/static/lib/jquery.jqGrid/js/jqDnR.js deleted file mode 100644 index 60fe2a96d0a..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/jqDnR.js +++ /dev/null @@ -1,69 +0,0 @@ -/* - * jqDnR - Minimalistic Drag'n'Resize for jQuery. - * - * Copyright (c) 2007 Brice Burgess , http://www.iceburg.net - * Licensed under the MIT License: - * http://www.opensource.org/licenses/mit-license.php - * - * $Version: 2007.08.19 +r2 - */ - -(function($){ -$.fn.jqDrag=function(h){return i(this,h,'d');}; -$.fn.jqResize=function(h,ar){return i(this,h,'r',ar);}; -$.jqDnR={ - dnr:{}, - e:0, - drag:function(v){ - if(M.k == 'd')E.css({left:M.X+v.pageX-M.pX,top:M.Y+v.pageY-M.pY}); - else { - E.css({width:Math.max(v.pageX-M.pX+M.W,0),height:Math.max(v.pageY-M.pY+M.H,0)}); - if(M1){E1.css({width:Math.max(v.pageX-M1.pX+M1.W,0),height:Math.max(v.pageY-M1.pY+M1.H,0)});} - } - return false; - }, - stop:function(){ - //E.css('opacity',M.o); - $(document).unbind('mousemove',J.drag).unbind('mouseup',J.stop); - } -}; -var J=$.jqDnR,M=J.dnr,E=J.e,E1, -i=function(e,h,k,aR){ - return e.each(function(){ - h=(h)?$(h,e):e; - h.bind('mousedown',{e:e,k:k},function(v){ - var d=v.data,p={};E=d.e;E1 = aR ? $(aR) : false; - // attempt utilization of dimensions plugin to fix IE issues - if(E.css('position') != 'relative'){try{E.position(p);}catch(e){}} - M={ - X:p.left||f('left')||0, - Y:p.top||f('top')||0, - W:f('width')||E[0].scrollWidth||0, - H:f('height')||E[0].scrollHeight||0, - pX:v.pageX, - pY:v.pageY, - k:d.k - //o:E.css('opacity') - }; - // also resize - if(E1 && d.k != 'd'){ - M1={ - X:p.left||f1('left')||0, - Y:p.top||f1('top')||0, - W:E1[0].offsetWidth||f1('width')||0, - H:E1[0].offsetHeight||f1('height')||0, - pX:v.pageX, - pY:v.pageY, - k:d.k - }; - } else {M1 = false;} - //E.css({opacity:0.8}); - try {$("input.hasDatepicker",E[0]).datepicker('hide');}catch (dpe){} - $(document).mousemove($.jqDnR.drag).mouseup($.jqDnR.stop); - return false; - }); - }); -}, -f=function(k){return parseInt(E.css(k))||false;}; -f1=function(k){ return parseInt(E1.css(k))||false;}; -})(jQuery); \ No newline at end of file diff --git a/addons/base/static/lib/jquery.jqGrid/js/jqModal.js b/addons/base/static/lib/jquery.jqGrid/js/jqModal.js deleted file mode 100644 index d1e7cda78c9..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/jqModal.js +++ /dev/null @@ -1,69 +0,0 @@ -/* - * jqModal - Minimalist Modaling with jQuery - * (http://dev.iceburg.net/jquery/jqmodal/) - * - * Copyright (c) 2007,2008 Brice Burgess - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * - * $Version: 07/06/2008 +r13 - */ -(function($) { -$.fn.jqm=function(o){ -var p={ -overlay: 50, -closeoverlay : true, -overlayClass: 'jqmOverlay', -closeClass: 'jqmClose', -trigger: '.jqModal', -ajax: F, -ajaxText: '', -target: F, -modal: F, -toTop: F, -onShow: F, -onHide: F, -onLoad: F -}; -return this.each(function(){if(this._jqm)return H[this._jqm].c=$.extend({},H[this._jqm].c,o);s++;this._jqm=s; -H[s]={c:$.extend(p,$.jqm.params,o),a:F,w:$(this).addClass('jqmID'+s),s:s}; -if(p.trigger)$(this).jqmAddTrigger(p.trigger); -});}; - -$.fn.jqmAddClose=function(e){return hs(this,e,'jqmHide');}; -$.fn.jqmAddTrigger=function(e){return hs(this,e,'jqmShow');}; -$.fn.jqmShow=function(t){return this.each(function(){$.jqm.open(this._jqm,t);});}; -$.fn.jqmHide=function(t){return this.each(function(){$.jqm.close(this._jqm,t)});}; - -$.jqm = { -hash:{}, -open:function(s,t){var h=H[s],c=h.c,cc='.'+c.closeClass,z=(parseInt(h.w.css('z-index')));z=(z>0)?z:3000;var o=$('
').css({height:'100%',width:'100%',position:'fixed',left:0,top:0,'z-index':z-1,opacity:c.overlay/100});if(h.a)return F;h.t=t;h.a=true;h.w.css('z-index',z); - if(c.modal) {if(!A[0])setTimeout(function(){L('bind');},1);A.push(s);} - else if(c.overlay > 0) {if(c.closeoverlay) h.w.jqmAddClose(o);} - else o=F; - - h.o=(o)?o.addClass(c.overlayClass).prependTo('body'):F; - if(ie6){$('html,body').css({height:'100%',width:'100%'});if(o){o=o.css({position:'absolute'})[0];for(var y in {Top:1,Left:1})o.style.setExpression(y.toLowerCase(),"(_=(document.documentElement.scroll"+y+" || document.body.scroll"+y+"))+'px'");}} - - if(c.ajax) {var r=c.target||h.w,u=c.ajax;r=(typeof r == 'string')?$(r,h.w):$(r);u=(u.substr(0,1) == '@')?$(t).attr(u.substring(1)):u; - r.html(c.ajaxText).load(u,function(){if(c.onLoad)c.onLoad.call(this,h);if(cc)h.w.jqmAddClose($(cc,h.w));e(h);});} - else if(cc)h.w.jqmAddClose($(cc,h.w)); - - if(c.toTop&&h.o)h.w.before('').insertAfter(h.o); - (c.onShow)?c.onShow(h):h.w.show();e(h);return F; -}, -close:function(s){var h=H[s];if(!h.a)return F;h.a=F; - if(A[0]){A.pop();if(!A[0])L('unbind');} - if(h.c.toTop&&h.o)$('#jqmP'+h.w[0]._jqm).after(h.w).remove(); - if(h.c.onHide)h.c.onHide(h);else{h.w.hide();if(h.o)h.o.remove();} return F; -}, -params:{}}; -var s=0,H=$.jqm.hash,A=[],ie6=$.browser.msie&&($.browser.version == "6.0"),F=false, -e=function(h){var i=$('').css({opacity:0});if(ie6)if(h.o)h.o.html('

').prepend(i);else if(!$('iframe.jqm',h.w)[0])h.w.prepend(i); f(h);}, -f=function(h){try{$(':input:visible',h.w)[0].focus();}catch(_){}}, -L=function(t){$(document)[t]("keypress",m)[t]("keydown",m)[t]("mousedown",m);}, -m=function(e){var h=H[A[A.length-1]],r=(!$(e.target).parents('.jqmID'+h.s)[0]);if(r)f(h);return !r;}, -hs=function(w,t,c){return w.each(function(){var s=this._jqm;$(t).each(function() { - if(!this[c]){this[c]=[];$(this).click(function(){for(var i in {jqmShow:1,jqmHide:1})for(var s in this[i])if(H[this[i][s]])H[this[i][s]].w[i](this);return F;});}this[c].push(s);});});}; -})(jQuery); \ No newline at end of file diff --git a/addons/base/static/lib/jquery.jqGrid/js/jquery.fmatter.js b/addons/base/static/lib/jquery.jqGrid/js/jquery.fmatter.js deleted file mode 100644 index 38314ce57eb..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/js/jquery.fmatter.js +++ /dev/null @@ -1,568 +0,0 @@ -/* -** - * formatter for values but most of the values if for jqGrid - * Some of this was inspired and based on how YUI does the table datagrid but in jQuery fashion - * we are trying to keep it as light as possible - * Joshua Burnett josh@9ci.com - * http://www.greenbill.com - * - * Changes from Tony Tomov tony@trirand.com - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl-2.0.html - * -**/ - -;(function($) { - $.fmatter = {}; - //opts can be id:row id for the row, rowdata:the data for the row, colmodel:the column model for this column - //example {id:1234,} - $.extend($.fmatter,{ - isBoolean : function(o) { - return typeof o === 'boolean'; - }, - isObject : function(o) { - return (o && (typeof o === 'object' || $.isFunction(o))) || false; - }, - isString : function(o) { - return typeof o === 'string'; - }, - isNumber : function(o) { - return typeof o === 'number' && isFinite(o); - }, - isNull : function(o) { - return o === null; - }, - isUndefined : function(o) { - return typeof o === 'undefined'; - }, - isValue : function (o) { - return (this.isObject(o) || this.isString(o) || this.isNumber(o) || this.isBoolean(o)); - }, - isEmpty : function(o) { - if(!this.isString(o) && this.isValue(o)) { - return false; - }else if (!this.isValue(o)){ - return true; - } - o = $.trim(o).replace(/\ \;/ig,'').replace(/\ \;/ig,''); - return o===""; - } - }); - $.fn.fmatter = function(formatType, cellval, opts, rwd, act) { - // build main options before element iteration - var v=cellval; - opts = $.extend({}, $.jgrid.formatter, opts); - - if ($.fn.fmatter[formatType]){ - v = $.fn.fmatter[formatType](cellval, opts, rwd, act); - } - return v; - }; - $.fmatter.util = { - // Taken from YAHOO utils - NumberFormat : function(nData,opts) { - if(!$.fmatter.isNumber(nData)) { - nData *= 1; - } - if($.fmatter.isNumber(nData)) { - var bNegative = (nData < 0); - var sOutput = nData + ""; - var sDecimalSeparator = (opts.decimalSeparator) ? opts.decimalSeparator : "."; - var nDotIndex; - if($.fmatter.isNumber(opts.decimalPlaces)) { - // Round to the correct decimal place - var nDecimalPlaces = opts.decimalPlaces; - var nDecimal = Math.pow(10, nDecimalPlaces); - sOutput = Math.round(nData*nDecimal)/nDecimal + ""; - nDotIndex = sOutput.lastIndexOf("."); - if(nDecimalPlaces > 0) { - // Add the decimal separator - if(nDotIndex < 0) { - sOutput += sDecimalSeparator; - nDotIndex = sOutput.length-1; - } - // Replace the "." - else if(sDecimalSeparator !== "."){ - sOutput = sOutput.replace(".",sDecimalSeparator); - } - // Add missing zeros - while((sOutput.length - 1 - nDotIndex) < nDecimalPlaces) { - sOutput += "0"; - } - } - } - if(opts.thousandsSeparator) { - var sThousandsSeparator = opts.thousandsSeparator; - nDotIndex = sOutput.lastIndexOf(sDecimalSeparator); - nDotIndex = (nDotIndex > -1) ? nDotIndex : sOutput.length; - var sNewOutput = sOutput.substring(nDotIndex); - var nCount = -1; - for (var i=nDotIndex; i>0; i--) { - nCount++; - if ((nCount%3 === 0) && (i !== nDotIndex) && (!bNegative || (i > 1))) { - sNewOutput = sThousandsSeparator + sNewOutput; - } - sNewOutput = sOutput.charAt(i-1) + sNewOutput; - } - sOutput = sNewOutput; - } - // Prepend prefix - sOutput = (opts.prefix) ? opts.prefix + sOutput : sOutput; - // Append suffix - sOutput = (opts.suffix) ? sOutput + opts.suffix : sOutput; - return sOutput; - - } else { - return nData; - } - }, - // Tony Tomov - // PHP implementation. Sorry not all options are supported. - // Feel free to add them if you want - DateFormat : function (format, date, newformat, opts) { - var token = /\\.|[dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU]/g, - timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, - timezoneClip = /[^-+\dA-Z]/g, - msDateRegExp = new RegExp("^\/Date\\((([-+])?[0-9]+)(([-+])([0-9]{2})([0-9]{2}))?\\)\/$"), - msMatch = ((typeof date === 'string') ? date.match(msDateRegExp): null), - pad = function (value, length) { - value = String(value); - length = parseInt(length,10) || 2; - while (value.length < length) { value = '0' + value; } - return value; - }, - ts = {m : 1, d : 1, y : 1970, h : 0, i : 0, s : 0, u:0}, - timestamp=0, dM, k,hl, - dateFormat=["i18n"]; - // Internationalization strings - dateFormat.i18n = { - dayNames: opts.dayNames, - monthNames: opts.monthNames - }; - if( format in opts.masks ) { format = opts.masks[format]; } - if(date.constructor === Number) { - //Unix timestamp - if(String(format).toLowerCase() == "u") { - date = date*1000; - } - timestamp = new Date(date); - } else if(date.constructor === Date) { - timestamp = date; - // Microsoft date format support - } else if( msMatch !== null ) { - timestamp = new Date(parseInt(msMatch[1], 10)); - if (msMatch[3]) { - var offset = Number(msMatch[5]) * 60 + Number(msMatch[6]); - offset *= ((msMatch[4] == '-') ? 1 : -1); - offset -= timestamp.getTimezoneOffset(); - timestamp.setTime(Number(Number(timestamp) + (offset * 60 * 1000))); - } - } else { - date = String(date).split(/[\\\/:_;.,\t\T\s-]/); - format = format.split(/[\\\/:_;.,\t\T\s-]/); - // parsing for month names - for(k=0,hl=format.length;k 11){date[k] = dM+1-12;} - } - if(date[k]) { - ts[format[k].toLowerCase()] = parseInt(date[k],10); - } - } - if(ts.f) {ts.m = ts.f;} - if( ts.m === 0 && ts.y === 0 && ts.d === 0) { - return " " ; - } - ts.m = parseInt(ts.m,10)-1; - var ty = ts.y; - if (ty >= 70 && ty <= 99) {ts.y = 1900+ts.y;} - else if (ty >=0 && ty <=69) {ts.y= 2000+ts.y;} - timestamp = new Date(ts.y, ts.m, ts.d, ts.h, ts.i, ts.s, ts.u); - } - - if( newformat in opts.masks ) { - newformat = opts.masks[newformat]; - } else if ( !newformat ) { - newformat = 'Y-m-d'; - } - var - G = timestamp.getHours(), - i = timestamp.getMinutes(), - j = timestamp.getDate(), - n = timestamp.getMonth() + 1, - o = timestamp.getTimezoneOffset(), - s = timestamp.getSeconds(), - u = timestamp.getMilliseconds(), - w = timestamp.getDay(), - Y = timestamp.getFullYear(), - N = (w + 6) % 7 + 1, - z = (new Date(Y, n - 1, j) - new Date(Y, 0, 1)) / 86400000, - flags = { - // Day - d: pad(j), - D: dateFormat.i18n.dayNames[w], - j: j, - l: dateFormat.i18n.dayNames[w + 7], - N: N, - S: opts.S(j), - //j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th', - w: w, - z: z, - // Week - W: N < 5 ? Math.floor((z + N - 1) / 7) + 1 : Math.floor((z + N - 1) / 7) || ((new Date(Y - 1, 0, 1).getDay() + 6) % 7 < 4 ? 53 : 52), - // Month - F: dateFormat.i18n.monthNames[n - 1 + 12], - m: pad(n), - M: dateFormat.i18n.monthNames[n - 1], - n: n, - t: '?', - // Year - L: '?', - o: '?', - Y: Y, - y: String(Y).substring(2), - // Time - a: G < 12 ? opts.AmPm[0] : opts.AmPm[1], - A: G < 12 ? opts.AmPm[2] : opts.AmPm[3], - B: '?', - g: G % 12 || 12, - G: G, - h: pad(G % 12 || 12), - H: pad(G), - i: pad(i), - s: pad(s), - u: u, - // Timezone - e: '?', - I: '?', - O: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), - P: '?', - T: (String(timestamp).match(timezone) || [""]).pop().replace(timezoneClip, ""), - Z: '?', - // Full Date/Time - c: '?', - r: '?', - U: Math.floor(timestamp / 1000) - }; - return newformat.replace(token, function ($0) { - return $0 in flags ? flags[$0] : $0.substring(1); - }); - } - }; - $.fn.fmatter.defaultFormat = function(cellval, opts) { - return ($.fmatter.isValue(cellval) && cellval!=="" ) ? cellval : opts.defaultValue ? opts.defaultValue : " "; - }; - $.fn.fmatter.email = function(cellval, opts) { - if(!$.fmatter.isEmpty(cellval)) { - return "" + cellval + ""; - }else { - return $.fn.fmatter.defaultFormat(cellval,opts ); - } - }; - $.fn.fmatter.checkbox =function(cval, opts) { - var op = $.extend({},opts.checkbox), ds; - if(!$.fmatter.isUndefined(opts.colModel.formatoptions)) { - op = $.extend({},op,opts.colModel.formatoptions); - } - if(op.disabled===true) {ds = "disabled=\"disabled\"";} else {ds="";} - if($.fmatter.isEmpty(cval) || $.fmatter.isUndefined(cval) ) {cval = $.fn.fmatter.defaultFormat(cval,op);} - cval=cval+"";cval=cval.toLowerCase(); - var bchk = cval.search(/(false|0|no|off)/i)<0 ? " checked='checked' " : ""; - return ""; - }; - $.fn.fmatter.link = function(cellval, opts) { - var op = {target:opts.target}; - var target = ""; - if(!$.fmatter.isUndefined(opts.colModel.formatoptions)) { - op = $.extend({},op,opts.colModel.formatoptions); - } - if(op.target) {target = 'target=' + op.target;} - if(!$.fmatter.isEmpty(cellval)) { - return "" + cellval + ""; - }else { - return $.fn.fmatter.defaultFormat(cellval,opts); - } - }; - $.fn.fmatter.showlink = function(cellval, opts) { - var op = {baseLinkUrl: opts.baseLinkUrl,showAction:opts.showAction, addParam: opts.addParam || "", target: opts.target, idName: opts.idName}, - target = "", idUrl; - if(!$.fmatter.isUndefined(opts.colModel.formatoptions)) { - op = $.extend({},op,opts.colModel.formatoptions); - } - if(op.target) {target = 'target=' + op.target;} - idUrl = op.baseLinkUrl+op.showAction + '?'+ op.idName+'='+opts.rowId+op.addParam; - if($.fmatter.isString(cellval) || $.fmatter.isNumber(cellval)) { //add this one even if its blank string - return "" + cellval + ""; - }else { - return $.fn.fmatter.defaultFormat(cellval,opts); - } - }; - $.fn.fmatter.integer = function(cellval, opts) { - var op = $.extend({},opts.integer); - if(!$.fmatter.isUndefined(opts.colModel.formatoptions)) { - op = $.extend({},op,opts.colModel.formatoptions); - } - if($.fmatter.isEmpty(cellval)) { - return op.defaultValue; - } - return $.fmatter.util.NumberFormat(cellval,op); - }; - $.fn.fmatter.number = function (cellval, opts) { - var op = $.extend({},opts.number); - if(!$.fmatter.isUndefined(opts.colModel.formatoptions)) { - op = $.extend({},op,opts.colModel.formatoptions); - } - if($.fmatter.isEmpty(cellval)) { - return op.defaultValue; - } - return $.fmatter.util.NumberFormat(cellval,op); - }; - $.fn.fmatter.currency = function (cellval, opts) { - var op = $.extend({},opts.currency); - if(!$.fmatter.isUndefined(opts.colModel.formatoptions)) { - op = $.extend({},op,opts.colModel.formatoptions); - } - if($.fmatter.isEmpty(cellval)) { - return op.defaultValue; - } - return $.fmatter.util.NumberFormat(cellval,op); - }; - $.fn.fmatter.date = function (cellval, opts, rwd, act) { - var op = $.extend({},opts.date); - if(!$.fmatter.isUndefined(opts.colModel.formatoptions)) { - op = $.extend({},op,opts.colModel.formatoptions); - } - if(!op.reformatAfterEdit && act=='edit'){ - return $.fn.fmatter.defaultFormat(cellval, opts); - } else if(!$.fmatter.isEmpty(cellval)) { - return $.fmatter.util.DateFormat(op.srcformat,cellval,op.newformat,op); - } else { - return $.fn.fmatter.defaultFormat(cellval, opts); - } - }; - $.fn.fmatter.select = function (cellval,opts, rwd, act) { - // jqGrid specific - cellval = cellval + ""; - var oSelect = false, ret=[]; - if(!$.fmatter.isUndefined(opts.colModel.formatoptions)){ - oSelect= opts.colModel.formatoptions.value; - } else if(!$.fmatter.isUndefined(opts.colModel.editoptions)){ - oSelect= opts.colModel.editoptions.value; - } - if (oSelect) { - var msl = opts.colModel.editoptions.multiple === true ? true : false, - scell = [], sv; - if(msl) {scell = cellval.split(",");scell = $.map(scell,function(n){return $.trim(n);});} - if ($.fmatter.isString(oSelect)) { - // mybe here we can use some caching with care ???? - var so = oSelect.split(";"), j=0; - for(var i=0; i 2 ) { - sv[1] = jQuery.map(sv,function(n,i){if(i>0) {return n;}}).join(":"); - } - if(msl) { - if(jQuery.inArray(sv[0],scell)>-1) { - ret[j] = sv[1]; - j++; - } - } else if($.trim(sv[0])==$.trim(cellval)) { - ret[0] = sv[1]; - break; - } - } - } else if($.fmatter.isObject(oSelect)) { - // this is quicker - if(msl) { - ret = jQuery.map(scell, function(n, i){ - return oSelect[n]; - }); - } else { - ret[0] = oSelect[cellval] || ""; - } - } - } - cellval = ret.join(", "); - return cellval === "" ? $.fn.fmatter.defaultFormat(cellval,opts) : cellval; - }; - $.fn.fmatter.rowactions = function(rid,gid,act,pos) { - var op ={ - keys:false, - editbutton:true, - delbutton:true, - onEdit : null, - onSuccess: null, - afterSave:null, - onError: null, - afterRestore: null, - extraparam: {oper:'edit'}, - url: null, - delOptions: {} - }, - cm = $('#'+gid)[0].p.colModel[pos]; - if(!$.fmatter.isUndefined(cm.formatoptions)) { - op = $.extend(op,cm.formatoptions); - } - var saverow = function( rowid) { - if(op.afterSave) op.afterSave(rowid); - $("tr#"+rid+" div.ui-inline-edit, "+"tr#"+rid+" div.ui-inline-del","#"+gid).show(); - $("tr#"+rid+" div.ui-inline-save, "+"tr#"+rid+" div.ui-inline-cancel","#"+gid).hide(); - }, - restorerow = function( rowid) { - if(op.afterRestore) op.afterRestore(rowid); - $("tr#"+rid+" div.ui-inline-edit, "+"tr#"+rid+" div.ui-inline-del","#"+gid).show(); - $("tr#"+rid+" div.ui-inline-save, "+"tr#"+rid+" div.ui-inline-cancel","#"+gid).hide(); - }; - - switch(act) - { - case 'edit': - $('#'+gid).jqGrid('editRow',rid, op.keys, op.onEdit, op.onSuccess, op.url, op.extraparam, saverow, op.onError,restorerow); - $("tr#"+rid+" div.ui-inline-edit, "+"tr#"+rid+" div.ui-inline-del","#"+gid).hide(); - $("tr#"+rid+" div.ui-inline-save, "+"tr#"+rid+" div.ui-inline-cancel","#"+gid).show(); - break; - case 'save': - $('#'+gid).jqGrid('saveRow',rid, op.onSuccess,op.url, op.extraparam, saverow, op.onError,restorerow); - $("tr#"+rid+" div.ui-inline-edit, "+"tr#"+rid+" div.ui-inline-del","#"+gid).show(); - $("tr#"+rid+" div.ui-inline-save, "+"tr#"+rid+" div.ui-inline-cancel","#"+gid).hide(); - break; - case 'cancel' : - $('#'+gid).jqGrid('restoreRow',rid, restorerow); - $("tr#"+rid+" div.ui-inline-edit, "+"tr#"+rid+" div.ui-inline-del","#"+gid).show(); - $("tr#"+rid+" div.ui-inline-save, "+"tr#"+rid+" div.ui-inline-cancel","#"+gid).hide(); - break; - case 'del': - $('#'+gid).jqGrid('delGridRow',rid, op.delOptions); - break; - } - }; - $.fn.fmatter.actions = function(cellval,opts, rwd) { - var op ={keys:false, editbutton:true, delbutton:true}; - if(!$.fmatter.isUndefined(opts.colModel.formatoptions)) { - op = $.extend(op,opts.colModel.formatoptions); - } - var rowid = opts.rowId, str="",ocl; - if(typeof(rowid) =='undefined' || $.fmatter.isEmpty(rowid)) {return "";} - if(op.editbutton){ - ocl = "onclick=$.fn.fmatter.rowactions('"+rowid+"','"+opts.gid+"','edit',"+opts.pos+");"; - str =str+ "

"; - } - if(op.delbutton) { - ocl = "onclick=$.fn.fmatter.rowactions('"+rowid+"','"+opts.gid+"','del',"+opts.pos+");"; - str = str+"
"; - } - ocl = "onclick=$.fn.fmatter.rowactions('"+rowid+"','"+opts.gid+"','save',"+opts.pos+");"; - str = str+""; - ocl = "onclick=$.fn.fmatter.rowactions('"+rowid+"','"+opts.gid+"','cancel',"+opts.pos+");"; - str = str+"
"; - return str; - }; - $.unformat = function (cellval,options,pos,cnt) { - // specific for jqGrid only - var ret, formatType = options.colModel.formatter, - op =options.colModel.formatoptions || {}, sep, - re = /([\.\*\_\'\(\)\{\}\+\?\\])/g, - unformatFunc = options.colModel.unformat||($.fn.fmatter[formatType] && $.fn.fmatter[formatType].unformat); - if(typeof unformatFunc !== 'undefined' && $.isFunction(unformatFunc) ) { - ret = unformatFunc($(cellval).text(), options, cellval); - } else if(!$.fmatter.isUndefined(formatType) && $.fmatter.isString(formatType) ) { - var opts = $.jgrid.formatter || {}, stripTag; - switch(formatType) { - case 'integer' : - op = $.extend({},opts.integer,op); - sep = op.thousandsSeparator.replace(re,"\\$1"); - stripTag = new RegExp(sep, "g"); - ret = $(cellval).text().replace(stripTag,''); - break; - case 'number' : - op = $.extend({},opts.number,op); - sep = op.thousandsSeparator.replace(re,"\\$1"); - stripTag = new RegExp(sep, "g"); - ret = $(cellval).text().replace(stripTag,"").replace(op.decimalSeparator,'.'); - break; - case 'currency': - op = $.extend({},opts.currency,op); - sep = op.thousandsSeparator.replace(re,"\\$1"); - stripTag = new RegExp(sep, "g"); - ret = $(cellval).text().replace(stripTag,'').replace(op.decimalSeparator,'.').replace(op.prefix,'').replace(op.suffix,''); - break; - case 'checkbox': - var cbv = (options.colModel.editoptions) ? options.colModel.editoptions.value.split(":") : ["Yes","No"]; - ret = $('input',cellval).attr("checked") ? cbv[0] : cbv[1]; - break; - case 'select' : - ret = $.unformat.select(cellval,options,pos,cnt); - break; - case 'actions': - return ""; - default: - ret= $(cellval).text(); - } - } - return ret ? ret : cnt===true ? $(cellval).text() : $.jgrid.htmlDecode($(cellval).html()); - }; - $.unformat.select = function (cellval,options,pos,cnt) { - // Spacial case when we have local data and perform a sort - // cnt is set to true only in sortDataArray - var ret = []; - var cell = $(cellval).text(); - if(cnt===true) {return cell;} - var op = $.extend({},options.colModel.editoptions); - if(op.value){ - var oSelect = op.value, - msl = op.multiple === true ? true : false, - scell = [], sv; - if(msl) {scell = cell.split(",");scell = $.map(scell,function(n){return $.trim(n);});} - if ($.fmatter.isString(oSelect)) { - var so = oSelect.split(";"), j=0; - for(var i=0; i 2 ) { - sv[1] = jQuery.map(sv,function(n,i){if(i>0) {return n;}}).join(":"); - } - if(msl) { - if(jQuery.inArray(sv[1],scell)>-1) { - ret[j] = sv[0]; - j++; - } - } else if($.trim(sv[1])==$.trim(cell)) { - ret[0] = sv[0]; - break; - } - } - } else if($.fmatter.isObject(oSelect) || $.isArray(oSelect) ){ - if(!msl) {scell[0] = cell;} - ret = jQuery.map(scell, function(n){ - var rv; - $.each(oSelect, function(i,val){ - if (val == n) { - rv = i; - return false; - } - }); - if( typeof(rv) != 'undefined' ) {return rv;} - }); - } - return ret.join(", "); - } else { - return cell || ""; - } - }; - $.unformat.date = function (cellval, opts) { - var op = $.jgrid.formatter.date || {}; - if(!$.fmatter.isUndefined(opts.formatoptions)) { - op = $.extend({},op,opts.formatoptions); - } - if(!$.fmatter.isEmpty(cellval)) { - return $.fmatter.util.DateFormat(op.newformat,cellval,op.srcformat,op); - } else { - return $.fn.fmatter.defaultFormat(cellval, opts); - } - }; -})(jQuery); \ No newline at end of file diff --git a/addons/base/static/lib/jquery.jqGrid/plugins/grid.addons.js.js b/addons/base/static/lib/jquery.jqGrid/plugins/grid.addons.js.js deleted file mode 100644 index ecb3ece98ca..00000000000 --- a/addons/base/static/lib/jquery.jqGrid/plugins/grid.addons.js.js +++ /dev/null @@ -1,704 +0,0 @@ -(function($){ -/* - * jqGrid methods without support. Use as you wish - * Tony Tomov tony@trirand.com - * http://trirand.com/blog/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl-2.0.html - * - * This list of deprecated methods. - * If you instead want to use them, please include this file after the grid main file. - * Some methods will be then overwritten. - * - */ -/*global jQuery, $ */ - -$.jgrid.extend({ -// This is the ols search Filter method used in navigator. - searchGrid : function (p) { - p = $.extend({ - recreateFilter: false, - drag: true, - sField:'searchField', - sValue:'searchString', - sOper: 'searchOper', - sFilter: 'filters', - loadDefaults: true, // this options activates loading of default filters from grid's postData for Multipe Search only. - beforeShowSearch: null, - afterShowSearch : null, - onInitializeSearch: null, - closeAfterSearch : false, - closeAfterReset: false, - closeOnEscape : false, - multipleSearch : false, - cloneSearchRowOnAdd: true, - // translation - // if you want to change or remove the order change it in sopt - // ['bw','eq','ne','lt','le','gt','ge','ew','cn'] - sopt: null, - // Note: stringResult is intentionally declared "undefined by default". - // you are velcome to define stringResult expressly in the options you pass to searchGrid() - // stringResult is a "safeguard" measure to insure we post sensible data when communicated as form-encoded - // see http://github.com/tonytomov/jqGrid/issues/#issue/36 - // - // If this value is not expressly defined in the incoming options, - // lower in the code we will infer the value based on value of multipleSearch - stringResult: undefined, - onClose : null, - // useDataProxy allows ADD, EDIT and DEL code to bypass calling $.ajax - // directly when grid's 'dataProxy' property (grid.p.dataProxy) is a function. - // Used for "editGridRow" and "delGridRow" below and automatically flipped to TRUE - // when ajax setting's 'url' (grid's 'editurl') property is undefined. - // When 'useDataProxy' is true, instead of calling $.ajax.call(gridDOMobj, o, i) we call - // gridDOMobj.p.dataProxy.call(gridDOMobj, o, i) - // - // Behavior is extremely similar to when 'datatype' is a function, but arguments are slightly different. - // Normally the following is fed to datatype.call(a, b, c): - // a = Pointer to grid's table DOM element, b = grid.p.postdata, c = "load_"+grid's ID - // In cases of "edit" and "del" the following is fed: - // a = Pointer to grid's table DOM element (same), - // b = extended Ajax Options including postdata in "data" property. (different object type) - // c = "set_"+grid's ID in case of "edit" and "del_"+grid's ID in case of "del" (same type, different content) - // The major difference is that complete ajax options object, with attached "complete" and "error" - // callback functions is fed instead of only post data. - // This allows you to emulate a $.ajax call (including calling "complete"/"error"), - // while retrieving the data locally in the browser. - useDataProxy: false, - overlay : true - }, $.jgrid.search, p || {}); - return this.each(function() { - var $t = this; - if(!$t.grid) {return;} - var fid = "fbox_"+$t.p.id, - showFrm = true; - function applyDefaultFilters(gridDOMobj, filterSettings) { - /* - gridDOMobj = ointer to grid DOM object ( $(#list)[0] ) - What we need from gridDOMobj: - gridDOMobj.SearchFilter is the pointer to the Search box, once it's created. - gridDOMobj.p.postData - dictionary of post settings. These can be overriden at grid creation to - contain default filter settings. We will parse these and will populate the search with defaults. - filterSettings - same settings object you (would) pass to $().jqGrid('searchGrid', filterSettings); - */ - - // Pulling default filter settings out of postData property of grid's properties.: - var defaultFilters = gridDOMobj.p.postData[filterSettings.sFilter]; - // example of what we might get: {"groupOp":"and","rules":[{"field":"amount","op":"eq","data":"100"}]} - // suppose we have imported this with grid import, the this is a string. - if(typeof(defaultFilters) == "string") { - defaultFilters = $.jgrid.parse(defaultFilters); - } - if (defaultFilters) { - if (defaultFilters.groupOp) { - gridDOMobj.SearchFilter.setGroupOp(defaultFilters.groupOp); - } - if (defaultFilters.rules) { - var f, i = 0, li = defaultFilters.rules.length, success = false; - for (; i < li; i++) { - f = defaultFilters.rules[i]; - // we are not trying to counter all issues with filter declaration here. Just the basics to avoid lookup exceptions. - if (f.field !== undefined && f.op !== undefined && f.data !== undefined) { - success = gridDOMobj.SearchFilter.setFilter({ - 'sfref':gridDOMobj.SearchFilter.$.find(".sf:last"), - 'filter':$.extend({},f) - }); - if (success) { gridDOMobj.SearchFilter.add(); } - } - } - } - } - } // end of applyDefaultFilters - function hideFilter(selector) { - if(p.onClose){ - var fclm = p.onClose(selector); - if(typeof fclm == 'boolean' && !fclm) { return; } - } - selector.hide(); - if(p.overlay === true) { - $(".jqgrid-overlay:first","#gbox_"+$t.p.id).hide(); - } - } - function showFilter(){ - var fl = $(".ui-searchFilter").length; - if(fl > 1) { - var zI = $("#"+fid).css("zIndex"); - $("#"+fid).css({zIndex:parseInt(zI,10)+fl}); - } - $("#"+fid).show(); - if(p.overlay === true) { - $(".jqgrid-overlay:first","#gbox_"+$t.p.id).show(); - } - try{$(':input:visible',"#"+fid)[0].focus();}catch(_){} - } - function searchFilters(filters) { - var hasFilters = (filters !== undefined), - grid = $("#"+$t.p.id), - sdata={}; - if(p.multipleSearch===false) { - sdata[p.sField] = filters.rules[0].field; - sdata[p.sValue] = filters.rules[0].data; - sdata[p.sOper] = filters.rules[0].op; - if(sdata.hasOwnProperty(p.sFilter) ) { - delete sdata[p.sFilter]; - } - } else { - sdata[p.sFilter] = filters; - $.each([p.sField, p.sValue, p.sOper], function(i, n){ - if(sdata.hasOwnProperty(n)) { delete sdata[n];} - }); - } - grid[0].p.search = hasFilters; - $.extend(grid[0].p.postData,sdata); - grid.trigger("reloadGrid",[{page:1}]); - if(p.closeAfterSearch) { hideFilter($("#"+fid)); } - } - function resetFilters(op) { - var reload = op && op.hasOwnProperty("reload") ? op.reload : true, - grid = $("#"+$t.p.id), - sdata={}; - grid[0].p.search = false; - if(p.multipleSearch===false) { - sdata[p.sField] = sdata[p.sValue] = sdata[p.sOper] = ""; - } else { - sdata[p.sFilter] = ""; - } - $.extend(grid[0].p.postData,sdata); - if(reload) { - grid.trigger("reloadGrid",[{page:1}]); - } - if(p.closeAfterReset) { hideFilter($("#"+fid)); } - } - if($.fn.searchFilter) { - if(p.recreateFilter===true) {$("#"+fid).remove();} - if( $("#"+fid).html() !== null ) { - if ( $.isFunction(p.beforeShowSearch) ) { - showFrm = p.beforeShowSearch($("#"+fid)); - if(typeof(showFrm) == "undefined") { - showFrm = true; - } - } - if(showFrm === false) { return; } - showFilter(); - if( $.isFunction(p.afterShowSearch) ) { p.afterShowSearch($("#"+fid)); } - } else { - var fields = [], - colNames = $("#"+$t.p.id).jqGrid("getGridParam","colNames"), - colModel = $("#"+$t.p.id).jqGrid("getGridParam","colModel"), - stempl = ['eq','ne','lt','le','gt','ge','bw','bn','in','ni','ew','en','cn','nc'], - j,pos,k,oprtr=[]; - if (p.sopt !==null) { - k=0; - for(j=0;j
"+K.innerHTML+"
";W.childNodes[0].innerHTML=this.templates.year_month(H);var Y=this.date.week_start(H);var J=this._reset_month_scale(W.childNodes[2],H,Y);var P=W.childNodes[2].firstChild.rows;for(var S=P.length;S<6;S++){P[0].parentNode.appendChild(P[0].cloneNode(true));for(var O=0;O11?\"pm\":\"am\")+\""; + case "%A": return "\"+(date.getHours()>11?\"PM\":\"AM\")+\""; + case "%s": return "\"+scheduler.date.to_fixed(date.getSeconds())+\""; + case "%W": return "\"+scheduler.date.to_fixed(scheduler.date.getISOWeek(date))+\""; + default: return a; + } + }) + if (utc) format=format.replace(/date\.get/g,"date.getUTC"); + return new Function("date","return \""+format+"\";"); + }, + str_to_date:function(format,utc){ + var splt="var temp=date.split(/[^0-9a-zA-Z]+/g);"; + var mask=format.match(/%[a-zA-Z]/g); + for (var i=0; i50?1900:2000);"; + break; + case "%g": + case "%G": + case "%h": + case "%H": + splt+="set[3]=temp["+i+"]||0;"; + break; + case "%i": + splt+="set[4]=temp["+i+"]||0;"; + break; + case "%Y": splt+="set[0]=temp["+i+"]||0;"; + break; + case "%a": + case "%A": splt+="set[3]=set[3]%12+((temp["+i+"]||'').toLowerCase()=='am'?0:12);"; + break; + case "%s": splt+="set[5]=temp["+i+"]||0;"; + break; + } + } + var code ="set[0],set[1],set[2],set[3],set[4],set[5]"; + if (utc) code =" Date.UTC("+code+")"; + return new Function("date","var set=[0,0,1,0,0,0]; "+splt+" return new Date("+code+");"); + }, + + getISOWeek: function(ndate) { + if(!ndate) return false; + var nday = ndate.getDay(); + if (nday == 0) { + nday = 7; + } + var first_thursday = new Date(ndate.valueOf()); + first_thursday.setDate(ndate.getDate() + (4 - nday)); + var year_number = first_thursday.getFullYear(); // year of the first Thursday + var ordinal_date = Math.floor( (first_thursday.getTime() - new Date(year_number, 0, 1).getTime()) / 86400000); //ordinal date of the first Thursday - 1 (so not really ordinal date) + var week_number = 1 + Math.floor( ordinal_date / 7); + return week_number; + }, + + getUTCISOWeek: function(ndate){ + return this.getISOWeek(ndate); + } +} diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/clear.css b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/clear.css new file mode 100644 index 00000000000..728af2d65bd --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/clear.css @@ -0,0 +1,106 @@ +.dhx_cal_ltext{ + text-align:left; +} +.dhx_agenda_line { + overflow:hidden; + white-space:nowrap; +} +.dhx_cal_light select{ + width:auto; +} + +.dhx_custom_button { + width:120px !important; +} + +.dhx_cal_ltext{ + text-align:left; +} +.dhx_form_repeat{ + text-align:left; + width:100%; +} + +.dhx_cal_lsection { + text-align:left; +} +.dhx_month_head{ + font-size:8pt; +} +.dhx_expand_icon { + position:absolute; top:0px; right:2px; + background-image:url(./imgs/colapce-expand-icon.gif); + width:18px; height:18px; + cursor:pointer; + background-position:0px 18px; + z-index:16; +} + +div.dhx_cal_container table tr td { + border-width:0 !important; + padding:0 !important; +} + +.dhx_cal_container table { + border-collapse:separate !important; + margin:0 0 !important; +} + +.dhx_cal_container{ + z-index:999; +} + +div.dhx_cal_event_clear, div.dhx_cal_event{ + line-height:100%; +} + +.dhx_cal_ltext textarea { + -moz-box-shadow:none; + border-width:0; + padding:0; + background:transparent none repeat scroll 0 0; + -webkit-box-shadow:none; +} + +.dhx_cal_light{ + text-align:left; +} +.dhx_cal_light div, .dhx_cal_container div{ + line-height:normal; +} + +.dhx_cal_light .dhx_form_repeat div,.dhx_cal_light .dhx_form_repeat{ + line-height:24px; +} + + +/* anti-joomla */ +div.dhx_cal_navline div, .dhx_scale_bar, .dhx_scale_hour, .dhx_title{ + text-align:center !important; +} +#whitebox div .dhx_month_head { + text-align:right; +} +#whitebox div .dhx_cal_event_line, #whitebox div .dhx_body{ + text-align:left; +} +div.dhx_cal_container, div.dhx_cal_lsection{ + line-height:1em; +} +div.dhx_cal_container, div.dhx_cal_lsection{ + line-height:normal; +} +.dhx_cal_header .dhx_agenda_line div, .dhx_year_month{ + text-align:center !important; +} +.dhx_tooltip{ + text-align:left; +} + + +.dhx_cal_data table{ + border-width:0px !important; +} +.dhx_cal_data table tr td{ + border-top-width:0px !important; +} diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/config.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/config.js new file mode 100644 index 00000000000..d9e5685a132 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/config.js @@ -0,0 +1,105 @@ +/* +%e Day of the month without leading zeros (01..31) +%d Day of the month, 2 digits with leading zeros (01..31) +%j Day of the year, 3 digits with leading zeros (001..366) +%a A textual representation of a day, two letters +%W A full textual representation of the day of the week + +%c Numeric representation of a month, without leading zeros (0..12) +%m Numeric representation of a month, with leading zeros (00..12) +%b A short textual representation of a month, three letters (Jan..Dec) +%M A full textual representation of a month, such as January or March (January..December) + +%y A two digit representation of a year (93..03) +%Y A full numeric representation of a year, 4 digits (1993..03) +*/ + +scheduler.config={ + default_date: "%j %M %Y", + month_date: "%F %Y", + load_date: "%Y-%m-%d", + week_date: "%l", + day_date: "%D, %F %j", + hour_date: "%H:%i", + month_day : "%d", + xml_date:"%m/%d/%Y %H:%i", + api_date:"%d-%m-%Y %H:%i", + + hour_size_px:42, + time_step:5, + + start_on_monday:1, + first_hour:0, + last_hour:24, + readonly:false, + drag_resize:1, + drag_move:1, + drag_create:1, + dblclick_create:1, + edit_on_create:1, + details_on_create:0, + click_form_details:0, + + server_utc:false, + + positive_closing:false, + + icons_edit:["icon_save","icon_cancel"], + icons_select:["icon_details","icon_edit","icon_delete"], + + lightbox:{ + sections:[ {name:"description", height:200, map_to:"text", type:"textarea" , focus:true}, + {name:"time", height:72, type:"time", map_to:"auto"} ] + } +}; +scheduler.templates={} +scheduler.init_templates=function(){ + var d=scheduler.date.date_to_str; + var c=scheduler.config; + var f = function(a,b){ + for (var c in b) + if (!a[c]) a[c]=b[c]; + } + f(scheduler.templates,{ + day_date:d(c.default_date), + month_date:d(c.month_date), + week_date:function(d1,d2){ + return scheduler.templates.day_date(d1)+" – "+scheduler.templates.day_date(scheduler.date.add(d2,-1,"day")); + }, + day_scale_date:d(c.default_date), + month_scale_date:d(c.week_date), + week_scale_date:d(c.day_date), + hour_scale:d(c.hour_date), + time_picker:d(c.hour_date), + event_date:d(c.hour_date), + month_day:d(c.month_day), + xml_date:scheduler.date.str_to_date(c.xml_date,c.server_utc), + load_format:d(c.load_date,c.server_utc), + xml_format:d(c.xml_date,c.server_utc), + api_date:scheduler.date.str_to_date(c.api_date), + event_header:function(start,end,ev){ + return scheduler.templates.event_date(start)+" - "+scheduler.templates.event_date(end); + }, + event_text:function(start,end,ev){ + return ev.text; + }, + event_class:function(start,end,ev){ + return ""; + }, + month_date_class:function(d){ + return ""; + }, + week_date_class:function(d){ + return ""; + }, + event_bar_date:function(start,end,ev){ + return scheduler.templates.event_date(start)+" "; + }, + event_bar_text:function(start,end,ev){ + return ev.text; + } + }); + this.callEvent("onTemplatesReady",[]) +} + + diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/connector.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/connector.js new file mode 100644 index 00000000000..45afbf6d089 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/connector.js @@ -0,0 +1,137 @@ +/* + dhx_sort[index]=direction + dhx_filter[index]=mask +*/ +if (window.dhtmlXGridObject){ + dhtmlXGridObject.prototype._init_point_connector=dhtmlXGridObject.prototype._init_point; + dhtmlXGridObject.prototype._init_point=function(){ + var clear_url=function(url){ + url=url.replace(/(\?|\&)connector[^\f]*/g,""); + return url+(url.indexOf("?")!=-1?"&":"?")+"connector=true"+(mygrid.hdr.rows.length > 0 ? "&dhx_no_header=1":""); + }; + var combine_urls=function(url){ + return clear_url(url)+(this._connector_sorting||"")+(this._connector_filter||""); + }; + var sorting_url=function(url,ind,dir){ + this._connector_sorting="&dhx_sort["+ind+"]="+dir; + return combine_urls.call(this,url); + }; + var filtering_url=function(url,inds,vals){ + for (var i=0; i-1) + _isChrome=true; + +if ((navigator.userAgent.indexOf('Safari') != -1)||(navigator.userAgent.indexOf('Konqueror') != -1)){ + var _KHTMLrv = parseFloat(navigator.userAgent.substr(navigator.userAgent.indexOf('Safari')+7, 5)); + + if (_KHTMLrv > 525){ //mimic FF behavior for Safari 3.1+ + _isFF=true; + var _FFrv = 1.9; + } else + _isKHTML=true; +} else if (navigator.userAgent.indexOf('Opera') != -1){ + _isOpera=true; + _OperaRv=parseFloat(navigator.userAgent.substr(navigator.userAgent.indexOf('Opera')+6, 3)); +} + + +else if (navigator.appName.indexOf("Microsoft") != -1){ + _isIE=true; + if (navigator.appVersion.indexOf("MSIE 8.0")!= -1 && document.compatMode != "BackCompat") _isIE=8; +} else { + _isFF=true; + var _FFrv = parseFloat(navigator.userAgent.split("rv:")[1]) +} + + +//multibrowser Xpath processor +dtmlXMLLoaderObject.prototype.doXPath=function(xpathExp, docObj, namespace, result_type){ + if (_isKHTML || (!_isIE && !window.XPathResult)) + return this.doXPathOpera(xpathExp, docObj); + + if (_isIE){ //IE + if (!docObj) + if (!this.xmlDoc.nodeName) + docObj=this.xmlDoc.responseXML + else + docObj=this.xmlDoc; + + if (!docObj) + dhtmlxError.throwError("LoadXML", "Incorrect XML", [ + (docObj||this.xmlDoc), + this.mainObject + ]); + + if (namespace != null) + docObj.setProperty("SelectionNamespaces", "xmlns:xsl='"+namespace+"'"); // + + if (result_type == 'single'){ + return docObj.selectSingleNode(xpathExp); + } + else { + return docObj.selectNodes(xpathExp)||new Array(0); + } + } else { //Mozilla + var nodeObj = docObj; + + if (!docObj){ + if (!this.xmlDoc.nodeName){ + docObj=this.xmlDoc.responseXML + } + else { + docObj=this.xmlDoc; + } + } + + if (!docObj) + dhtmlxError.throwError("LoadXML", "Incorrect XML", [ + (docObj||this.xmlDoc), + this.mainObject + ]); + + if (docObj.nodeName.indexOf("document") != -1){ + nodeObj=docObj; + } + else { + nodeObj=docObj; + docObj=docObj.ownerDocument; + } + var retType = XPathResult.ANY_TYPE; + + if (result_type == 'single') + retType=XPathResult.FIRST_ORDERED_NODE_TYPE + var rowsCol = new Array(); + var col = docObj.evaluate(xpathExp, nodeObj, function(pref){ + return namespace + }, retType, null); + + if (retType == XPathResult.FIRST_ORDERED_NODE_TYPE){ + return col.singleNodeValue; + } + var thisColMemb = col.iterateNext(); + + while (thisColMemb){ + rowsCol[rowsCol.length]=thisColMemb; + thisColMemb=col.iterateNext(); + } + return rowsCol; + } +} + +function _dhtmlxError(type, name, params){ + if (!this.catches) + this.catches=new Array(); + + return this; +} + +_dhtmlxError.prototype.catchError=function(type, func_name){ + this.catches[type]=func_name; +} +_dhtmlxError.prototype.throwError=function(type, name, params){ + if (this.catches[type]) + return this.catches[type](type, name, params); + + if (this.catches["ALL"]) + return this.catches["ALL"](type, name, params); + + alert("Error type: "+arguments[0]+"\nDescription: "+arguments[1]); + return null; +} + +window.dhtmlxError=new _dhtmlxError(); + + +//opera fake, while 9.0 not released +//multibrowser Xpath processor +dtmlXMLLoaderObject.prototype.doXPathOpera=function(xpathExp, docObj){ + //this is fake for Opera + var z = xpathExp.replace(/[\/]+/gi, "/").split('/'); + var obj = null; + var i = 1; + + if (!z.length) + return []; + + if (z[0] == ".") + obj=[docObj]; else if (z[0] == ""){ + obj=(this.xmlDoc.responseXML||this.xmlDoc).getElementsByTagName(z[i].replace(/\[[^\]]*\]/g, "")); + i++; + } else + return []; + + for (i; i < z.length; i++)obj=this._getAllNamedChilds(obj, z[i]); + + if (z[i-1].indexOf("[") != -1) + obj=this._filterXPath(obj, z[i-1]); + return obj; +} + +dtmlXMLLoaderObject.prototype._filterXPath=function(a, b){ + var c = new Array(); + var b = b.replace(/[^\[]*\[\@/g, "").replace(/[\[\]\@]*/g, ""); + + for (var i = 0; i < a.length; i++) + if (a[i].getAttribute(b)) + c[c.length]=a[i]; + + return c; +} +dtmlXMLLoaderObject.prototype._getAllNamedChilds=function(a, b){ + var c = new Array(); + + if (_isKHTML) + b=b.toUpperCase(); + + for (var i = 0; i < a.length; i++)for (var j = 0; j < a[i].childNodes.length; j++){ + if (_isKHTML){ + if (a[i].childNodes[j].tagName&&a[i].childNodes[j].tagName.toUpperCase() == b) + c[c.length]=a[i].childNodes[j]; + } + + else if (a[i].childNodes[j].tagName == b) + c[c.length]=a[i].childNodes[j]; + } + + return c; +} + +function dhtmlXHeir(a, b){ + for (var c in b) + if (typeof (b[c]) == "function") + a[c]=b[c]; + return a; +} + +function dhtmlxEvent(el, event, handler){ + if (el.addEventListener) + el.addEventListener(event, handler, false); + + else if (el.attachEvent) + el.attachEvent("on"+event, handler); +} + +//============= XSL Extension =================================== + +dtmlXMLLoaderObject.prototype.xslDoc=null; +dtmlXMLLoaderObject.prototype.setXSLParamValue=function(paramName, paramValue, xslDoc){ + if (!xslDoc) + xslDoc=this.xslDoc + + if (xslDoc.responseXML) + xslDoc=xslDoc.responseXML; + var item = + this.doXPath("/xsl:stylesheet/xsl:variable[@name='"+paramName+"']", xslDoc, + "http:/\/www.w3.org/1999/XSL/Transform", "single"); + + if (item != null) + item.firstChild.nodeValue=paramValue +} +dtmlXMLLoaderObject.prototype.doXSLTransToObject=function(xslDoc, xmlDoc){ + if (!xslDoc) + xslDoc=this.xslDoc; + + if (xslDoc.responseXML) + xslDoc=xslDoc.responseXML + + if (!xmlDoc) + xmlDoc=this.xmlDoc; + + if (xmlDoc.responseXML) + xmlDoc=xmlDoc.responseXML + + //MOzilla + if (!_isIE){ + if (!this.XSLProcessor){ + this.XSLProcessor=new XSLTProcessor(); + this.XSLProcessor.importStylesheet(xslDoc); + } + var result = this.XSLProcessor.transformToDocument(xmlDoc); + } else { + var result = new ActiveXObject("Msxml2.DOMDocument.3.0"); + try{ + xmlDoc.transformNodeToObject(xslDoc, result); + }catch(e){ + result = xmlDoc.transformNode(xslDoc); + } + } + return result; +} + +dtmlXMLLoaderObject.prototype.doXSLTransToString=function(xslDoc, xmlDoc){ + var res = this.doXSLTransToObject(xslDoc, xmlDoc); + if(typeof(res)=="string") + return res; + return this.doSerialization(res); +} + +dtmlXMLLoaderObject.prototype.doSerialization=function(xmlDoc){ + if (!xmlDoc) + xmlDoc=this.xmlDoc; + if (xmlDoc.responseXML) + xmlDoc=xmlDoc.responseXML + if (!_isIE){ + var xmlSerializer = new XMLSerializer(); + return xmlSerializer.serializeToString(xmlDoc); + } else + return xmlDoc.xml; +} + +/** +* @desc: +* @type: private +*/ +dhtmlxEventable=function(obj){ + obj.dhx_SeverCatcherPath=""; + obj.attachEvent=function(name, catcher, callObj){ + name='ev_'+name.toLowerCase(); + if (!this[name]) + this[name]=new this.eventCatcher(callObj||this); + + return(name+':'+this[name].addEvent(catcher)); //return ID (event name & event ID) + } + obj.callEvent=function(name, arg0){ + name='ev_'+name.toLowerCase(); + if (this[name]) + return this[name].apply(this, arg0); + return true; + } + obj.checkEvent=function(name){ + return (!!this['ev_'+name.toLowerCase()]) + } + obj.eventCatcher=function(obj){ + var dhx_catch = []; + var z = function(){ + var res = true; + for (var i = 0; i < dhx_catch.length; i++){ + if (dhx_catch[i] != null){ + var zr = dhx_catch[i].apply(obj, arguments); + res=res&&zr; + } + } + return res; + } + z.addEvent=function(ev){ + if (typeof (ev) != "function") + ev=eval(ev); + if (ev) + return dhx_catch.push(ev)-1; + return false; + } + z.removeEvent=function(id){ + dhx_catch[id]=null; + } + return z; + } + obj.detachEvent=function(id){ + if (id != false){ + var list = id.split(':'); //get EventName and ID + this[list[0]].removeEvent(list[1]); //remove event + } + } +} diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/dhtmlxdataprocessor.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/dhtmlxdataprocessor.js new file mode 100644 index 00000000000..8dfc1cb0dd1 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/dhtmlxdataprocessor.js @@ -0,0 +1,581 @@ +/** + * @desc: constructor, data processor object + * @param: serverProcessorURL - url used for update + * @type: public + */ +function dataProcessor(serverProcessorURL){ + this.serverProcessor = serverProcessorURL; + this.action_param="!nativeeditor_status"; + + this.object = null; + this.updatedRows = []; //ids of updated rows + + this.autoUpdate = true; + this.updateMode = "cell"; + this._tMode="GET"; + this.post_delim = "_"; + + this._waitMode=0; + this._in_progress={};//? + this._invalid={}; + this.mandatoryFields=[]; + this.messages=[]; + + this.styles={ + updated:"font-weight:bold;", + inserted:"font-weight:bold;", + deleted:"text-decoration : line-through;", + invalid:"background-color:FFE0E0;", + invalid_cell:"border-bottom:2px solid red;", + error:"color:red;", + clear:"font-weight:normal;text-decoration:none;" + }; + + this.enableUTFencoding(true); + dhtmlxEventable(this); + + return this; + } + +dataProcessor.prototype={ + /** + * @desc: select GET or POST transaction model + * @param: mode - GET/POST + * @param: total - true/false - send records row by row or all at once (for grid only) + * @type: public + */ + setTransactionMode:function(mode,total){ + this._tMode=mode; + this._tSend=total; + }, + escape:function(data){ + if (this._utf) + return encodeURIComponent(data); + else + return escape(data); + }, + /** + * @desc: allows to set escaping mode + * @param: true - utf based escaping, simple - use current page encoding + * @type: public + */ + enableUTFencoding:function(mode){ + this._utf=convertStringToBoolean(mode); + }, + /** + * @desc: allows to define, which column may trigger update + * @param: val - array or list of true/false values + * @type: public + */ + setDataColumns:function(val){ + this._columns=(typeof val == "string")?val.split(","):val; + }, + /** + * @desc: get state of updating + * @returns: true - all in sync with server, false - some items not updated yet. + * @type: public + */ + getSyncState:function(){ + return !this.updatedRows.length; + }, + /** + * @desc: enable/disable named field for data syncing, will use column ids for grid + * @param: mode - true/false + * @type: public + */ + enableDataNames:function(mode){ + this._endnm=convertStringToBoolean(mode); + }, + /** + * @desc: enable/disable mode , when only changed fields and row id send to the server side, instead of all fields in default mode + * @param: mode - true/false + * @type: public + */ + enablePartialDataSend:function(mode){ + this._changed=convertStringToBoolean(mode); + }, + /** + * @desc: set if rows should be send to server automaticaly + * @param: mode - "row" - based on row selection changed, "cell" - based on cell editing finished, "off" - manual data sending + * @type: public + */ + setUpdateMode:function(mode,dnd){ + this.autoUpdate = (mode=="cell"); + this.updateMode = mode; + this.dnd=dnd; + }, + ignore:function(code,master){ + this._silent_mode=true; + code.call(master||window); + this._silent_mode=false; + }, + /** + * @desc: mark row as updated/normal. check mandatory fields,initiate autoupdate (if turned on) + * @param: rowId - id of row to set update-status for + * @param: state - true for "updated", false for "not updated" + * @param: mode - update mode name + * @type: public + */ + setUpdated:function(rowId,state,mode){ + if (this._silent_mode) return; + var ind=this.findRow(rowId); + + mode=mode||"updated"; + var existing = this.obj.getUserData(rowId,this.action_param); + if (existing && mode == "updated") mode=existing; + if (state){ + this.set_invalid(rowId,false); //clear previous error flag + this.updatedRows[ind]=rowId; + this.obj.setUserData(rowId,this.action_param,mode); + if (this._in_progress[rowId]) + this._in_progress[rowId]="wait"; + } else{ + if (!this.is_invalid(rowId)){ + this.updatedRows.splice(ind,1); + this.obj.setUserData(rowId,this.action_param,""); + } + } + + //clear changed flag + if (!state) + this._clearUpdateFlag(rowId); + + this.markRow(rowId,state,mode); + if (state && this.autoUpdate) this.sendData(rowId); + }, + _clearUpdateFlag:function(id){}, + markRow:function(id,state,mode){ + var str=""; + var invalid=this.is_invalid(id); + if (invalid){ + str=this.styles[invalid]; + state=true; + } + if (this.callEvent("onRowMark",[id,state,mode,invalid])){ + //default logic + str=this.styles[state?mode:"clear"]+str; + + this.obj[this._methods[0]](id,str); + + if (invalid && invalid.details){ + str+=this.styles[invalid+"_cell"]; + for (var i=0; i < invalid.details.length; i++) + if (invalid.details[i]) + this.obj[this._methods[1]](id,i,str); + } + } + }, + getState:function(id){ + return this.obj.getUserData(id,this.action_param); + }, + is_invalid:function(id){ + return this._invalid[id]; + }, + set_invalid:function(id,mode,details){ + if (details) mode={value:mode, details:details, toString:function(){ return this.value.toString(); }}; + this._invalid[id]=mode; + }, + /** + * @desc: check mandatory fields and varify values of cells, initiate update (if specified) + * @param: rowId - id of row to set update-status for + * @type: public + */ + checkBeforeUpdate:function(rowId){ + return true; + }, + /** + * @desc: send row(s) values to server + * @param: rowId - id of row which data to send. If not specified, then all "updated" rows will be send + * @type: public + */ + sendData:function(rowId){ + if (this._waitMode && (this.obj.mytype=="tree" || this.obj._h2)) return; + if (this.obj.editStop) this.obj.editStop(); + + + if(typeof rowId == "undefined" || this._tSend) return this.sendAllData(); + if (this._in_progress[rowId]) return false; + + this.messages=[]; + if (!this.checkBeforeUpdate(rowId) && this.callEvent("onValidatationError",[rowId,this.messages])) return false; + this._beforeSendData(this._getRowData(rowId),rowId); + }, + _beforeSendData:function(data,rowId){ + if (!this.callEvent("onBeforeUpdate",[rowId,this.getState(rowId),data])) return false; + this._sendData(data,rowId); + }, + serialize:function(data, id){ + if (typeof data == "string") + return data; + if (typeof id != "undefined") + return this.serialize_one(data,""); + else{ + var stack = []; + var keys = []; + for (var key in data) + if (data.hasOwnProperty(key)){ + stack.push(this.serialize_one(data[key],key+this.post_delim)); + keys.push(key); + } + stack.push("ids="+this.escape(keys.join(","))); + return stack.join("&"); + } + }, + serialize_one:function(data, pref){ + if (typeof data == "string") + return data; + var stack = []; + for (var key in data) + if (data.hasOwnProperty(key)) + stack.push(this.escape((pref||"")+key)+"="+this.escape(data[key])); + return stack.join("&"); + }, + _sendData:function(a1,rowId){ + if (!a1) return; //nothing to send + if (!this.callEvent("onBeforeDataSending",rowId?[rowId,this.getState(rowId),a1]:[null, null, a1])) return false; + + if (rowId) + this._in_progress[rowId]=(new Date()).valueOf(); + var a2=new dtmlXMLLoaderObject(this.afterUpdate,this,true); + + var a3 = this.serverProcessor+(this._user?(getUrlSymbol(this.serverProcessor)+["dhx_user="+this._user,"dhx_version="+this.obj.getUserData(0,"version")].join("&")):""); + + if (this._tMode!="POST") + a2.loadXML(a3+((a3.indexOf("?")!=-1)?"&":"?")+this.serialize(a1,rowId)); + else + a2.loadXML(a3,true,this.serialize(a1,rowId)); + + this._waitMode++; + }, + sendAllData:function(){ + if (!this.updatedRows.length) return; + + this.messages=[]; var valid=true; + for (var i=0; i[close] [clear]  DataProcessor
 Current state
 Log:
"; + if (document.body) document.body.insertBefore(c,document.body.firstChild); + else dhtmlxEvent(window,"load",function(){ + document.body.insertBefore(c,document.body.firstChild); + }) + dhtmlxEvent(window,"dblclick",function(){ + c.style.display=''; + }) + return c; +} + +dataProcessor.prototype._error=function(data){ + this._log(""+data+""); +} +dataProcessor.prototype._log=function(data){ + var div=document.createElement("DIV"); + div.innerHTML = data; + var parent=this._console.childNodes[2]; + parent.appendChild(div); + parent.scrollTop=parent.scrollHeight; + + if (window.console && window.console.log) + window.console.log("DataProcessor :: "+data.replace(" "," ").replace("","").replace("","")); + +} +dataProcessor.prototype._updateStat=function(data){ + var data=[" Current state"]; + for(var i=0;i")+"
Current mode: "+this.updateMode; +} +dataProcessor.prototype.xml_analize=function(xml){ + if (_isFF){ + if (!xml.xmlDoc.responseXML) + this._error("Not an XML, probably incorrect content type specified ( must be text/xml ), or some text output was started before XML data"); + else if (xml.xmlDoc.responseXML.firstChild.tagName=="parsererror") + this._error(xml.xmlDoc.responseXML.firstChild.textContent); + else return true; + } else if (_isIE){ + if (xml.xmlDoc.responseXML.parseError.errorCode) + this._error("XML error : "+xml.xmlDoc.responseXML.parseError.reason); + else if (!xml.xmlDoc.responseXML.documentElement) + this._error("Not an XML, probably incorrect content type specified ( must be text/xml ), or some text output was started before XML data"); + else return true; + } + return false; +} + +dataProcessor.wrap=function(name,before,after){ + var d=dataProcessor.prototype; + if (!d._wrap) d._wrap={}; + d._wrap[name]=d[name]; + d[name]=function(){ + if (before) before.apply(this,arguments); + var res=d._wrap[name].apply(this,arguments); + if (after) after.apply(this,[arguments,res]); + return res; + } +}; + +dataProcessor.wrap("setUpdated",function(rowId,state,mode){ + this._log(" row "+rowId+" "+(state?"marked":"unmarked")+" ["+(mode||"updated")+","+(this.is_invalid(rowId)||"valid")+"]"); +},function(){ + this._updateStat(); +}); + + + +dataProcessor.wrap("sendData",function(rowId){ + if (rowId){ + this._log(" Initiating data sending for "+rowId+""); + if (this.obj.mytype=="tree"){ + if (!this.obj._idpull[rowId]) + this._log(" Error! item with such ID not exists "+rowId+""); + } else { + if (!this.obj.rowsAr[rowId]) + this._log(" Error! row with such ID not exists "+rowId+""); + } + } +},function(){ + +}); + +dataProcessor.wrap("sendAllData",function(){ + this._log(" Initiating data sending for all rows "); +},function(){ + +}); +dataProcessor.logSingle=function(data,id){ + var tdata = {}; + if (id) + tdata[id] = data; + else + tdata = data; + + var url = []; + for (var key in tdata) { + url.push("
"+key+""); + var suburl = []; + + for (var ikey in tdata[key]) + suburl.push(ikey+" = "+tdata[key][ikey]); + + url.push(suburl.join("
")); + url.push("
"); + } + return url.join(""); +} +dataProcessor.wrap("_sendData",function(data,rowId){ + if (rowId) + this._log(" Sending in one-by-one mode, current ID = "+rowId); + else + this._log(" Sending all data at once"); + this._log(" Server url: "+this.serverProcessor+" parameters"); + var url = []; + this._log("
"+dataProcessor.logSingle(data,rowId)+"
"); +},function(){ + +}); + + +dataProcessor.wrap("afterUpdate",function(that,b,c,d,xml){ + that._log(" Server response received details
"+(xml.xmlDoc.responseText||"").replace(/\&/g,"&").replace(//g,">")+"
"); + if (!that.xml_analize(xml)) return; + var atag=xml.doXPath("//data/action"); + if (!atag){ + that._log(" No actions found"); + var atag=xml.getXMLTopNode("data"); + if (!atag) that._log(" XML not valid"); + else that._log(" Incorrect content type - need to be text/xml"); + } +},function(){ + +}); + +dataProcessor.wrap("afterUpdateCallback",function(sid,tid,action){ + if (this.obj.mytype=="tree"){ + if (!this.obj._idpull[sid]) this._log("Incorrect SID, item with such ID not exists in grid"); + } else { + if (!this.obj.rowsAr[sid]) this._log("Incorrect SID, row with such ID not exists in grid"); + } + this._log(" Action: "+action+" SID:"+sid+" TID:"+tid); +},function(){ + +}); + + + + + + diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/event.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/event.js new file mode 100644 index 00000000000..202a6e5fcb9 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/event.js @@ -0,0 +1,545 @@ +scheduler.uid=function(){ + if (!this._seed) this._seed=(new Date).valueOf(); + return this._seed++; +}; +scheduler._events={}; +scheduler.clearAll=function(){ + this._events={}; + this._loaded={}; + this.clear_view(); +}; +scheduler.addEvent=function(start_date,end_date,text,id,extra_data){ + var ev=start_date; + if (arguments.length!=1){ + ev=extra_data||{}; + ev.start_date=start_date; + ev.end_date=end_date; + ev.text=text; + ev.id=id; + }; + ev.id = ev.id||scheduler.uid(); + ev.text = ev.text||""; + + if (typeof ev.start_date == "string") ev.start_date=this.templates.api_date(ev.start_date); + if (typeof ev.end_date == "string") ev.end_date=this.templates.api_date(ev.end_date); + ev._timed=this.is_one_day_event(ev); + + var is_new=!this._events[ev.id]; + this._events[ev.id]=ev; + this.event_updated(ev); + if (!this._loading) + this.callEvent(is_new?"onEventAdded":"onEventChanged",[ev.id,ev]); +}; +scheduler.deleteEvent=function(id,silent){ + var ev=this._events[id]; + if (!silent && !this.callEvent("onBeforeEventDelete",[id,ev])) return; + + if (ev){ + delete this._events[id]; + this.unselect(id); + this.event_updated(ev); + } +}; +scheduler.getEvent=function(id){ + return this._events[id]; +}; +scheduler.setEvent=function(id,hash){ + this._events[id]=hash; +}; +scheduler.for_rendered=function(id,method){ + for (var i=this._rendered.length-1; i>=0; i--) + if (this._rendered[i].getAttribute("event_id")==id) + method(this._rendered[i],i); +}; +scheduler.changeEventId=function(id,new_id){ + if (id == new_id) return; + var ev=this._events[id]; + if (ev){ + ev.id=new_id; + this._events[new_id]=ev; + delete this._events[id]; + } + this.for_rendered(id,function(r){ + r.setAttribute("event_id",new_id); + }); + if (this._select_id==id) this._select_id=new_id; + if (this._edit_id==id) this._edit_id=new_id; + this.callEvent("onEventIdChange",[id,new_id]); +}; + +(function(){ + var attrs=["text","Text","start_date","StartDate","end_date","EndDate"]; + var create_getter=function(name){ + return function(id){ return (scheduler.getEvent(id))[name]; }; + }; + var create_setter=function(name){ + return function(id,value){ + var ev=scheduler.getEvent(id); ev[name]=value; + ev._changed=true; + ev._timed=this.is_one_day_event(ev); + scheduler.event_updated(ev,true); + }; + }; + for (var i=0; i this._colsS.height-22){ // 22 - height of cell's header + //we have overflow, update heights + var cells = evl.rows[i].cells; + for (var j=0; j < cells.length; j++) { + cells[j].childNodes[1].style.height = h[i]*hb+"px"; + } + h[i]=(h[i-1]||0)+cells[0].offsetHeight; + } + h[i]=(h[i-1]||0)+evl.rows[i].cells[0].offsetHeight; + } + h.unshift(0); + if (evl.parentNode.offsetHeightb.start_date?1:-1; }); + var days=[]; //events by weeks + var evs_originals = []; + for (var i=0; i < evs.length; i++) { + var ev=evs[i]; + + //check scale overflow + var sh = ev.start_date.getHours(); + var eh = ev.end_date.getHours(); + + ev._sday=this._get_event_sday(ev); + if (!days[ev._sday]) days[ev._sday]=[]; + + if (!hold){ + ev._inner=false; + var stack=days[ev._sday]; + while (stack.length && stack[stack.length-1].end_date<=ev.start_date) + stack.splice(stack.length-1,1); + if (stack.length) stack[stack.length-1]._inner=true; + ev._sorder=stack.length; stack.push(ev); + if (stack.length>(stack.max_count||0)) stack.max_count=stack.length; + } + + if (sh < this.config.first_hour || eh >= this.config.last_hour){ + evs_originals.push(ev); + evs[i]=ev=this._copy_event(ev); + if (sh < this.config.first_hour){ + ev.start_date.setHours(this.config.first_hour); + ev.start_date.setMinutes(0); + } + if (eh >= this.config.last_hour){ + ev.end_date.setMinutes(0); + ev.end_date.setHours(this.config.last_hour); + } + if (ev.start_date>ev.end_date || sh==this.config.last_hour) { + evs.splice(i,1); i--; continue; + } + } + + } + if (!hold){ + for (var i=0; i < evs.length; i++) + evs[i]._count=days[evs[i]._sday].max_count; + for (var i=0; i < evs_originals.length; i++) + evs_originals[i]._count=days[evs_originals[i]._sday].max_count; + } + + return evs; +}; +scheduler._time_order=function(evs){ + evs.sort(function(a,b){ + if (a.start_date.valueOf()==b.start_date.valueOf()){ + if (a._timed && !b._timed) return 1; + if (!a._timed && b._timed) return -1; + return 0; + } + return a.start_date>b.start_date?1:-1; + }); +}; +scheduler._pre_render_events_table=function(evs,hold){ // max - max height of week slot + this._time_order(evs); + + var out=[]; + var weeks=[[],[],[],[],[],[],[]]; //events by weeks + var max = this._colsS.heights; + var start_date; + var cols = this._cols.length; + + for (var i=0; i < evs.length; i++) { + var ev=evs[i]; + var sd = (start_date||ev.start_date); + var ed = ev.end_date; + //trim events which are crossing through current view + if (sdthis._max_date) ed=this._max_date; + + var locate_s = this.locate_holder_day(sd,false,ev); + ev._sday=locate_s%cols; + var locate_e = this.locate_holder_day(ed,true,ev)||cols; + ev._eday=(locate_e%cols)||cols; //cols used to fill full week, when event end on monday + ev._length=locate_e-locate_s; + + //3600000 - compensate 1 hour during winter|summer time shift + ev._sweek=Math.floor((this._correct_shift(sd.valueOf(),1)-this._min_date.valueOf())/(60*60*1000*24*cols)); + + //current slot + var stack=weeks[ev._sweek]; + //check order position + var stack_line; + + for (stack_line=0; stack_line"; + if (this._quirks7) d2.firstChild.style.height=height-12+"px"; //IEFIX + this._editor=d2.firstChild; + this._editor.onkeypress=function(e){ + if ((e||event).shiftKey) return true; + var code=(e||event).keyCode; + if (code==scheduler.keys.edit_save) scheduler.editStop(true); + if (code==scheduler.keys.edit_cancel) scheduler.editStop(false); + }; + this._editor.onselectstart=function(e){ return (e||event).cancelBubble=true; }; + d2.firstChild.focus(); + //IE and opera can add x-scroll during focusing + this._els["dhx_cal_data"][0].scrollLeft=0; + d2.firstChild.select(); + } + + if (this._select_id==ev.id){ + //d.style.zIndex = 1; //fix overlapping issue + var icons=this.config["icons_"+((this._edit_id==ev.id)?"edit":"select")]; + var icons_str=""; + for (var i=0; i"; + var obj = this._render_v_bar(ev.id,left-menu+1,top,menu,icons.length*20+26,"","
",icons_str,true); + obj.style.left=left-menu+1; + this._els["dhx_cal_data"][0].appendChild(obj); + this._rendered.push(obj); + } +}; +scheduler._render_v_bar=function(id,x,y,w,h,style,contentA,contentB,bottom){ + var d=document.createElement("DIV"); + + var ev = this.getEvent(id); + var cs = "dhx_cal_event"; + var cse = scheduler.templates.event_class(ev.start_date,ev.end_date,ev); + if (cse) cs=cs+" "+cse; + + var html='
'; + html+='
 
'; + html+='
'+contentA+'
'; + html+='
'+contentB+'
'; + html+='
'; + + d.innerHTML=html; + return d.firstChild; +}; +scheduler.locate_holder=function(day){ + if (this._mode=="day") return this._els["dhx_cal_data"][0].firstChild; //dirty + return this._els["dhx_cal_data"][0].childNodes[day]; +}; +scheduler.locate_holder_day=function(date,past){ + var day = Math.floor((this._correct_shift(date,1)-this._min_date)/(60*60*24*1000)); + //when locating end data of event , we need to use next day if time part was defined + if (past && this.date.time_part(date)) day++; + return day; +}; +scheduler.render_event_bar=function(ev){ + var parent=this._els["dhx_cal_data"][0]; + + var x=this._colsS[ev._sday]; + var x2=this._colsS[ev._eday]; + if (x2==x) x2=this._colsS[ev._eday+1]; + var hb = this.xy.bar_height; + + var y=this._colsS.heights[ev._sweek]+(this._colsS.height?(this.xy.month_scale_height+2):2)+ev._sorder*hb; + + var d=document.createElement("DIV"); + var cs = ev._timed?"dhx_cal_event_clear":"dhx_cal_event_line"; + var cse = scheduler.templates.event_class(ev.start_date,ev.end_date,ev); + if (cse) cs=cs+" "+cse; + + var html='
'; + + if (ev._timed) + html+=scheduler.templates.event_bar_date(ev.start_date,ev.end_date,ev); + html+=scheduler.templates.event_bar_text(ev.start_date,ev.end_date,ev)+'
'; + html+=''; + + d.innerHTML=html; + + this._rendered.push(d.firstChild); + parent.appendChild(d.firstChild); +}; + +scheduler._locate_event=function(node){ + var id=null; + while (node && !id && node.getAttribute){ + id=node.getAttribute("event_id"); + node=node.parentNode; + } + return id; +}; + + +scheduler.edit=function(id){ + if (this._edit_id==id) return; + this.editStop(false,id); + this._edit_id=id; + this.updateEvent(id); +}; +scheduler.editStop=function(mode,id){ + if (id && this._edit_id==id) return; + var ev=this.getEvent(this._edit_id); + if (ev){ + if (mode) ev.text=this._editor.value; + this._edit_id=null; + this._editor=null; + this.updateEvent(ev.id); + this._edit_stop_event(ev,mode); + } +}; +scheduler._edit_stop_event=function(ev,mode){ + if (this._new_event){ + if (!mode) this.deleteEvent(ev.id,true); + else this.callEvent("onEventAdded",[ev.id,ev]); + this._new_event=null; + } else + if (mode) this.callEvent("onEventChanged",[ev.id,ev]); +}; + +scheduler.getEvents = function(from,to){ + var result = []; + for (var a in this._events){ + var ev = this._events[a]; + if (ev && ev.start_datefrom) + result.push(ev); + } + return result; +}; \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext.css b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext.css new file mode 100644 index 00000000000..402c5b38271 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext.css @@ -0,0 +1,317 @@ +.dhx_expand_icon { + position:absolute; top:0px; right:0px; + background-image:url(../codebase/imgs/colapce-expand-icon.gif); + width:18px; height:18px; + cursor:pointer; + background-position:0px 18px; + z-index:16; +} +.dhx_agenda_area{ + width:100%; + height:100%; + overflow-y:auto; + background-image:url(../codebase/imgs/databg.png); +} +.dhx_agenda_line{ + height:21px; + clear:both; + overflow:hidden; +} +.dhx_agenda_line div{ + float:left; + width:188px; + border-right:1px dotted #8894A3; + text-align:center; + line-height:21px; + overflow:hidden; +} +.dhx_agenda_area .dhx_agenda_line div{ + border-right:0px dotted #8894A3; +} +.dhx_v_border{ + position:absolute; left:186px; top:0px; + border-right:1px dotted #8894A3; + width:1px; + height:100%; +} +.dhx_agenda_line .dhx_event_icon{ + width:20px; + border-width:0px; + background:url(../codebase/imgs/icon.png) no-repeat; + background-position: 5px 4px; + cursor:pointer; +} +.dhx_agenda_line span{ + padding-left:5px; + line-height:21px; +} + + +.dhx_year_body{ + border-left:1px dotted #586A7E; +} +.dhx_year_week{ + height:20px; + position:relative; +} +.dhx_scale_bar_last{ + border-right:1px dotted #586A7E; +} +.dhx_year_month{ + height:18px; + padding-top:3px; + border:1px dotted #586A7E; + text-align:center; + vertical-align:middle; +} +.dhx_year_body .dhx_before .dhx_month_head, .dhx_year_body .dhx_after .dhx_month_head, .dhx_year_body .dhx_before .dhx_month_head a, .dhx_year_body .dhx_after .dhx_month_head a{ + color:#E2E3E6 !important; +} +.dhx_year_body .dhx_month_body{ + height:0px; + overflow:hidden; +} +.dhx_month_head.dhx_year_event{ + background-color:#FFE763; +} +.dhx_year_body .dhx_before .dhx_month_head, .dhx_year_body .dhx_after .dhx_month_head{ + cursor: default; +} +.dhx_tooltip{ + border:1px solid #BBBBBB; + background-image:url(../codebase/imgs/databg.png); + position:absolute; + z-index:9998; + width:300px; + height:auto; + font-family:Tahoma; + font-size:8pt; + overflow:hidden; +} + +.dhx_tooltip_line{ + line-height:20px; + height:20px; + overflow:hidden; +} + +.dhx_tooltip_line .dhx_event_icon{ + width:20px; height:20px; + padding-right:10px; + float:left; + border-width:0px; + position:relative; + background:url(../codebase/imgs/icon.png) no-repeat; + background-position: 5px 4px; + cursor:pointer; +} + +.dhx_tooltip_date{ + float:left; + width:auto; + padding-left:5px; + text-align:center; +} + +.dhx_text_disabled{ + color:#887A2E; + font-family:Tahoma; + font-size:8pt; +} + +.dhx_mini_calendar{ + -moz-box-shadow:5px 5px 5px #888; /*Doesn't work in IE*/ + -khtml-box-shadow: 5px 5px 5px #888; +} + +.dhx_mini_calendar .dhx_month_head{ + cursor:pointer; +} +.dhx_mini_calendar .dhx_calendar_click{ + background-color: #C2D5FC; +} +.dhx_cal_navline div.dhx_minical_icon{ + width:18px; + height:18px; + left:190px; + top:1px; + cursor:pointer; + background-image:url(../imgs/calendar.gif); +} + + + +.dhx_matrix_cell, .dhx_matrix_scell{ + overflow:hidden; + text-align:center; + vertical-align:middle; + border-bottom:1px dotted #8894A3; + border-right:1px dotted #8894A3; +} +.dhx_matrix_cell{ + background-color:white; +} +.dhx_matrix_cell div, .dhx_matrix_scell div{ + overflow:hidden; + text-align:center; + width:100%; + height:auto; +} + +.dhx_cal_lsection .dhx_readonly{ + font-size:9pt; + font-size:8pt; + padding:2px; + color:#887A2E; +} + +/* Tree view */ +.dhx_matrix_scell.folder, .dhx_data_table.folder .dhx_matrix_cell{ + background-color: #969394; + cursor: pointer; +} +.dhx_matrix_scell .dhx_scell_level0{ + padding-left: 5px; +} +.dhx_matrix_scell .dhx_scell_level1{ + padding-left: 20px; +} +.dhx_matrix_scell .dhx_scell_level2{ + padding-left: 35px; +} + +.dhx_matrix_scell.folder{ + font-weight: bold; + text-align: left; +} + +.dhx_matrix_scell.folder .dhx_scell_expand{ + float: left; + width: 10px; + padding-right:3px; +} +.dhx_matrix_scell.folder .dhx_scell_name{ + float: left; + width: auto; +} +.dhx_matrix_scell.item .dhx_scell_name{ + padding-left:15px; + text-align: left; +} +.dhx_section_timeline, .dhx_section_timeline2{ + overflow: hidden; + padding: 2px 0 2px 10px; +} +.dhx_section_timeline select, .dhx_section_timeline2 select{ + width: 552px; +} +/* Tree view end*/ + +/* Map view */ +.dhx_map_area{ + width:100%; + height:100%; + overflow-y: auto; + overflow-x: hidden; + background-image:url(../codebase/imgs/databg.png); +} +.dhx_map_line .dhx_event_icon{ + width:20px; + border-width:0px; + background:url(../codebase/imgs/icon.png) no-repeat; + background-position: 5px 4px; + cursor:pointer; +} +.dhx_map_line{ + height:21px; + clear:both; + overflow:hidden; +} +.dhx_map { + position:absolute; +} +.dhx_map_line div{ + float:left; + border-right:1px dotted #8894A3; + text-align:center; + line-height:21px; + overflow:hidden; +} +.dhx_map_line .headline_description{ + float:left; + + border-right:1px dotted #8894A3; + text-align:center; + line-height:21px; + overflow:hidden; +} +.dhx_map_line .dhx_map_description{ + float:left; + border-right: 0px dotted #8894A3; + text-align:center; + line-height:21px; + overflow:hidden; +} +.dhx_map_line .line_description{ + float:left; + border-right:1px dotted #8894A3; + text-align:left; + padding-left:5px; + line-height:21px; + overflow:hidden; +} +.dhx_map_line.highlight{ + background-color: #C4C5CC; +} +.dhx_map_area .dhx_map_line div{ + border-right:0px dotted #8894A3; +} +/* Map view end */ + +/* dhtmlXTooltip start */ +.dhtmlXTooltip.tooltip{ + -moz-box-shadow:3px 3px 3px #888888; + -khtml-box-shadow:3px 3px 3px #888888; + + background-color:white; + border-left:1px dotted #887A2E; + border-top:1px dotted #887A2E; + color:#887A2E; + cursor:default; + padding:10px; + position:absolute; + z-index:500; +} +/* dhtmlXTooltip end */ + +/* Lightbox checkbox section */ +.dhx_cal_checkbox label { + padding-left: 5px; +} +/* Lightbox checkbox section end */ + + +/* Lightbox radiobuttons section */ +.dhx_cal_light .radio { + padding: 2px 0px 2px 10px; +} +.dhx_cal_light .radio input, .dhx_cal_light .radio label{ + line-height: 15px; +} +.dhx_cal_light .radio input { + vertical-align: middle; + margin: 0px; + padding: 0px; +} +.dhx_cal_light .radio label { + vertical-align: middle; + padding-right: 10px; +} +/* Lightbox radiobuttons section end */ + + +/* Lightbox dhtmlx combo section */ +.dhx_cal_light .combo { + padding: 4px; +} +/* Lightbox dhtmlx combo section end */ diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_active_links.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_active_links.js new file mode 100644 index 00000000000..79ebce494bb --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_active_links.js @@ -0,0 +1,21 @@ +scheduler.attachEvent("onTemplatesReady",function(){ + var s_d = scheduler.date.str_to_date(scheduler.config.api_date); + var d_s = scheduler.date.date_to_str(scheduler.config.api_date); + + var month_x = scheduler.templates.month_day; + scheduler.templates.month_day=function(date){ + return ""+month_x(date)+""; + } + var week_x = scheduler.templates.week_scale_date; + scheduler.templates.week_scale_date=function(date){ + return ""+week_x(date)+""; + } + + + dhtmlxEvent(this._obj,"click",function(e){ + var start = e.target || event.srcElement; + var to = start.getAttribute("jump_to"); + if (to) + scheduler.setCurrentView(s_d(to),"day"); + }) +}) \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_agenda_view.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_agenda_view.js new file mode 100644 index 00000000000..6fcdd5cc106 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_agenda_view.js @@ -0,0 +1,93 @@ +scheduler.date.add_agenda = function(date){ + return (new Date(date.valueOf())); +} + +scheduler.dblclick_dhx_agenda_area=function(){ + if (!this.config.readonly && this.config.dblclick_create) + this.addEventNow(); +} +scheduler.templates.agenda_time = function(start,end,ev){ + if (ev._timed) + return this.day_date(ev.start_date, ev.end_date, ev)+" "+this.event_date(start); + else + return scheduler.templates.day_date(start)+" – "+scheduler.templates.day_date(end); +} +scheduler.templates.agenda_text = function(ev){ + return ev.text; +} +scheduler.date.agenda_start=function(d){ return d; }; + +scheduler.attachEvent("onTemplatesReady",function(){ + + + + scheduler.attachEvent("onSchedulerResize",function(){ + if (this._mode == "agenda"){ + this.agenda_view(true); + return false; + } + return true; + }); + + + var old = scheduler.render_data; + scheduler.render_data=function(evs){ + if (this._mode == "agenda") + fill_agenda_tab(); + else + return old.apply(this,arguments); + } + + + function set_full_view(mode){ + if (mode){ + var l = scheduler.locale.labels; + scheduler._els["dhx_cal_header"][0].innerHTML="
"+l.date+"
"+l.description+"
"; + scheduler._table_view=true; + scheduler.set_sizes(); + } + } + + function fill_agenda_tab(){ + //get current date + var date = scheduler._date; + //select events for which data need to be printed + + var events = scheduler.get_visible_events(); + events.sort(function(a,b){ return a.start_date>b.start_date?1:-1}); + + //generate html for the view + var html="
"; + for (var i=0; i
"+scheduler.templates.agenda_time(events[i].start_date, events[i].end_date,events[i])+"
"; + html+="
 
"; + html+=""+scheduler.templates.agenda_text(events[i])+"
"; + } + html+="
"; + + //render html + scheduler._els["dhx_cal_data"][0].scrollTop = 0; //fix flickering in FF + scheduler._els["dhx_cal_data"][0].innerHTML = html; + + var t=scheduler._els["dhx_cal_data"][0].firstChild.childNodes; + scheduler._els["dhx_cal_date"][0].innerHTML=""; + + scheduler._rendered=[]; + for (var i=0; i < t.length-1; i++) + scheduler._rendered[i]=t[i] + + } + + scheduler.agenda_view=function(mode){ + scheduler._min_date = scheduler.config.agenda_start||(new Date()); + scheduler._max_date = scheduler.config.agenda_end||(new Date(9999,1,1)); + scheduler._table_view = true; + set_full_view(mode); + if (mode){ + //agenda tab activated + fill_agenda_tab(); + } else { + //agenda tab de-activated + } + } +}) \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_collision.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_collision.js new file mode 100644 index 00000000000..d2582a05926 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_collision.js @@ -0,0 +1,100 @@ +(function(){ + +var temp_section,temp_time; +var before; + +scheduler.config.collision_limit = 1; +scheduler.attachEvent("onBeforeDrag",function(id){ + var pr = scheduler._props?scheduler._props[this._mode]:null; + var matrix = scheduler.matrix?scheduler.matrix[this._mode]:null; + var checked_mode = pr||matrix; + if(pr) + var map_to = checked_mode.map_to; + if(matrix) + var map_to = checked_mode.y_property; + + if ((checked_mode) && id){ + temp_section = this.getEvent(id)[map_to]; + temp_time = this.getEvent(id).start_date; + } + return true; +}); +scheduler.attachEvent("onBeforeLightbox",function(id){ + var ev = scheduler.getEvent(id); + before = [ev.start_date, ev.end_date]; + return true; +}); +scheduler.attachEvent("onEventChanged",function(id){ + if (!id) return true; + var ev = scheduler.getEvent(id); + if (!collision_check(ev)){ + if (!before) return false; + ev.start_date = before[0]; + ev.end_date = before[1]; + ev._timed=this.is_one_day_event(ev); + }; + return true; +}); +scheduler.attachEvent("onBeforeEventChanged",function(ev,e,is_new){ + return collision_check(ev); +}); +scheduler.attachEvent("onEventSave",function(id, edited_ev){ + //var ev = scheduler.getEvent(id); + if(edited_ev.rec_type) + scheduler._roll_back_dates(edited_ev); + + return collision_check(edited_ev); +}); + + +function collision_check(ev){ + var evs = []; + + if (ev.rec_type) { + var evs_dates = scheduler.getRecDates(ev); + for(var k=0; k scheduler.config.collision_limit) { + scheduler._drag_event.start_date = temp_time; + ev[map_to] = temp_section; + single = false; + } + } + else { + if (evs.length > scheduler.config.collision_limit) + single = false; + } + + if (!single) return !scheduler.callEvent("onEventCollision",[ev,evs]); + return single; + +}; + +})(); \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_cookie.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_cookie.js new file mode 100644 index 00000000000..0df4852ccdc --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_cookie.js @@ -0,0 +1,36 @@ +(function(){ + function setCookie(name,cookie_param,value) { + var str = name + "=" + value + (cookie_param?("; "+cookie_param):""); + document.cookie = str; + } + function getCookie(name) { + var search = name + "="; + if (document.cookie.length > 0) { + var offset = document.cookie.indexOf(search); + if (offset != -1) { + offset += search.length; + var end = document.cookie.indexOf(";", offset); + if (end == -1) + end = document.cookie.length; + return document.cookie.substring(offset, end); + } + } + return ""; + } + var first = true; + scheduler.attachEvent("onBeforeViewChange",function(om,od,m,d){ + if (first){ + first = false; + var data=getCookie("scheduler_settings"); + if (data){ + data = data.split("@"); + data[0] = this.templates.xml_date(data[0]); + this.setCurrentView(data[0],data[1]); + return false; + } + } + var text = this.templates.xml_format(d||od)+"@"+(m||om); + setCookie("scheduler_settings","expires=Sun, 31 Jan 9999 22:00:00 GMT",text); + return true; + }); +})(); \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_editors.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_editors.js new file mode 100644 index 00000000000..8c64d13eddc --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_editors.js @@ -0,0 +1,95 @@ +scheduler.form_blocks['combo']={ + render:function(sns) { + var res = ''; + res += "
"; + return res; + }, + set_value:function(node,value,ev,config){ + if(node._combo) { + node._combo.destructor(); + } + window.dhx_globalImgPath = config.image_path||'/'; + node._combo = new dhtmlXCombo(node, config.name, node.offsetWidth-8); + node._combo.enableFilteringMode(!!config.filtering, config.script_path||null, !!config.cache); + + if (!config.script_path) { // script-side filtration is used + var all_options = []; + for (var i = 0; i < config.options.length; i++) { + var single_option = []; + single_option.push(config.options[i].key); + single_option.push(config.options[i].label); + all_options.push(single_option); + } + node._combo.addOption(all_options); + if (ev[config.map_to]) { + var index = node._combo.getIndexByValue(ev[config.map_to]); + node._combo.selectOption(index); + } + } else { // server-side filtration is used + node._combo.setComboValue(ev[config.map_to]||null); + } + }, + get_value:function(node,ev,config){ + var selected_id = node._combo.getSelectedValue(); // value = key + return selected_id; + }, + focus:function(node){ + } +}; + +scheduler.form_blocks['radio']={ + render:function(sns) { + var res = ''; + res += "
"; + for (var i=0; i"; + if(sns.vertical) + res += "
"; + } + res += "
"; + + return res; + }, + set_value:function(node,value,ev,config){ + var radiobuttons = node.getElementsByTagName('input'); + for (var i = 0; i < radiobuttons.length; i++) { + radiobuttons[i].checked = false; + if (radiobuttons[i].value == ev[config.map_to]) { + radiobuttons[i].checked = true; + } + } + }, + get_value:function(node,ev,config){ + var radiobuttons = node.getElementsByTagName('input'); + for(var i=0; i"; + + }, + get_value:function(node,ev,config){ + var checkbox = node.previousSibling.getElementsByTagName('input')[0]; // moved to the header + return (checkbox.checked)?(config.checked_value||true):(config.unchecked_value||false); + }, + focus:function(node){ + } +}; \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_expand.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_expand.js new file mode 100644 index 00000000000..9224bef1af5 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_expand.js @@ -0,0 +1,54 @@ +scheduler.expand = function(){ + var t = scheduler._obj; + do { + t._position = t.style.position||""; + t.style.position = "static"; + } while ((t = t.parentNode) && t.style ); + t = scheduler._obj; + t.style.position="absolute"; + t._width = t.style.width; + t._height = t.style.height; + t.style.width = t.style.height = "100%"; + t.style.top = t.style.left = "0px"; + + var top =document.body; + top.scrollTop = 0; + + top = top.parentNode; + if (top) + top.scrollTop = 0; + document.body._overflow=document.body.style.overflow||""; + document.body.style.overflow = "hidden"; + scheduler._maximize() +} + +scheduler.collapse = function(){ + var t = scheduler._obj; + do { + t.style.position = t._position; + } while ((t = t.parentNode) && t.style ); + t = scheduler._obj; + t.style.width = t._width; + t.style.height = t._height; + document.body.style.overflow=document.body._overflow; + scheduler._maximize() +} + +scheduler.attachEvent("onTemplatesReady",function(){ + var t = document.createElement("DIV"); + t.className="dhx_expand_icon"; + scheduler.toggleIcon = t; + scheduler._obj.appendChild(t); + t.onclick = function(){ + if (!scheduler.expanded) + scheduler.expand(); + else + scheduler.collapse(); + } +}); +scheduler._maximize = function(){ + this.expanded = !this.expanded; + this.toggleIcon.style.backgroundPosition="0px "+(this._expand?"0":"18")+"px"; + if (scheduler.callEvent("onSchedulerResize",[])) + scheduler.update_view(); +} diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_html_templates.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_html_templates.js new file mode 100644 index 00000000000..d75582b438c --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_html_templates.js @@ -0,0 +1,15 @@ +scheduler.attachEvent("onTemplatesReady",function(){ + var els = document.body.getElementsByTagName("DIV"); + for (var i=0; i < els.length; i++) { + var cs = els[i].className||""; + cs = cs.split(":"); + if (cs.length == 2 && cs[0] == "template"){ + var code = "return \""+(els[i].innerHTML||"").replace(/\"/g,"\\\"").replace(/[\n\r]+/g,"")+"\";"; + code = unescape(code).replace(/\{event\.([a-z]+)\}/g,function(all,mask){ + return '"+ev.'+mask+'+"'; + }); + scheduler.templates[cs[1]]=Function("start","end","ev",code); + els[i].style.display='none'; + } + }; +}) \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_key_nav.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_key_nav.js new file mode 100644 index 00000000000..cc00f3d3698 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_key_nav.js @@ -0,0 +1,32 @@ +//Initial idea and implementation by Steve MC +(function (){ + +var lightboxopen = false; + +scheduler.attachEvent("onBeforeLightbox",function(){ lightboxopen = true; return true; }); +scheduler.attachEvent("onAfterLightbox",function(){ lightboxopen = false; return true; }); + +dhtmlxEvent(document,(_isOpera?"keypress":"keydown"),function(e){ + e=e||event; + if (!lightboxopen){ + + if (e.keyCode == 37 || e.keyCode == 39) { // Left-Arrow + e.cancelBubble = true; + + var next = scheduler.date.add(scheduler._date,(e.keyCode == 37 ? -1 : 1 ),scheduler._mode); + scheduler.setCurrentView(next); + return true; + } else if (e.ctrlKey && e.keyCode == 67){ + scheduler._copy_id = scheduler._select_id; + } else if (e.ctrlKey && e.keyCode == 86){ + var ev = scheduler.getEvent(scheduler._copy_id); + if (ev){ + var new_ev = scheduler._copy_event(ev); + new_ev.id = scheduler.uid(); + scheduler.addEvent(new_ev); + } + } + } +}); + +})(); \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_limit.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_limit.js new file mode 100644 index 00000000000..4a8ad2fed6d --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_limit.js @@ -0,0 +1,78 @@ +scheduler.config.limit_start = new Date(-3999,0,0); +scheduler.config.limit_end = new Date( 3999,0,0); +scheduler.config.limit_view = false; + +(function(){ + var before = null; + + scheduler.attachEvent("onBeforeViewChange",function(om,od,nm,nd){ + nd = nd||od; nm = nm||om; + if (scheduler.config.limit_view){ + if (nd.valueOf()>scheduler.config.limit_end.valueOf() || this.date.add(nd,1,nm)<=scheduler.config.limit_start.valueOf()){ + setTimeout(function(){ + scheduler.setCurrentView(scheduler._date, nm); + },1); + return false; + } + } + return true; + }); + var blocker = function(ev){ + var c = scheduler.config; + var res = (ev.start_date.valueOf() >= c.limit_start.valueOf() && ev.end_date.valueOf() <= c.limit_end.valueOf()); + if (!res) { + scheduler._drag_id = null; + scheduler._drag_mode = null; + scheduler.callEvent("onLimitViolation",[ev.id, ev]); + } + return res; + }; + + scheduler.attachEvent("onBeforeDrag",function(id){ + if (!id) return true; + return blocker(scheduler.getEvent(id)); + }); + scheduler.attachEvent("onClick", function (event_id, native_event_object){ + return blocker(scheduler.getEvent(event_id)); + }); + scheduler.attachEvent("onBeforeLightbox",function(id){ + var ev = scheduler.getEvent(id); + before = [ev.start_date, ev.end_date]; + return blocker(ev); + }); + scheduler.attachEvent("onEventAdded",function(id){ + if (!id) return true; + var ev = scheduler.getEvent(id); + if (!blocker(ev)){ + if (ev.start_date < scheduler.config.limit_start) { + ev.start_date = new Date(scheduler.config.limit_start); + } + if (ev.end_date > scheduler.config.limit_end) { + ev.end_date = new Date(scheduler.config.limit_end); + // as end date was changed need to recheck if event occuring during one day + ev._timed = this.is_one_day_event(ev); + } + // in case if both start and end date were specified < scheduler.config.limit_star + if (ev.start_date > ev.end_date) { + ev.end_date = this.date.add(ev.start_date, (this.config.event_duration||this.config.time_step), "minute"); + } + } + return true; + }); + scheduler.attachEvent("onEventChanged",function(id){ + if (!id) return true; + var ev = scheduler.getEvent(id); + if (!blocker(ev)){ + if (!before) return false; + ev.start_date = before[0]; + ev.end_date = before[1]; + ev._timed=this.is_one_day_event(ev); + }; + return true; + }); + scheduler.attachEvent("onBeforeEventChanged",function(ev, native_object, is_new){ + return blocker(ev); + }); + +})(); + diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_map_view.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_map_view.js new file mode 100644 index 00000000000..05845b9c468 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_map_view.js @@ -0,0 +1,396 @@ + + +scheduler.xy.map_date_width = 188; // date column width +scheduler.xy.map_description_width = 400; // description column width + +scheduler.config.map_resolve_event_location = true; // if events in database doesn't have lat and lng values there will be an attempt to resolve them on event loading, useful for migration +scheduler.config.map_resolve_user_location = true; // if user will be promted to share his location to display it on the map + +scheduler.config.map_initial_position = new google.maps.LatLng(48.724, 8.215); // inital position of the map +scheduler.config.map_error_position = new google.maps.LatLng(15, 15); // this position will be displayed in case if event doesn't have corresponding coordinates + +scheduler.config.map_infowindow_max_width = 300; + +scheduler.config.map_type = google.maps.MapTypeId.ROADMAP; + +scheduler.config.map_zoom_after_resolve = 15; + +scheduler.locale.labels.marker_geo_success = "It seems you are here."; +scheduler.locale.labels.marker_geo_fail = "Sorry, could not get your current position using geolocation."; + +scheduler.templates.marker_date=scheduler.date.date_to_str("%Y-%m-%d %H:%i"); // date for map's infowindow will be formated following way + +scheduler.templates.marker_text=function(start, end, ev){ + return "
"+ev.text+"

"+(ev.event_location||'')+"

"+scheduler.templates.marker_date(start)+" - "+scheduler.templates.marker_date(end)+"
"; +}; +scheduler.dblclick_dhx_map_area=function(){ + if (!this.config.readonly && this.config.dblclick_create) + this.addEventNow(); +}; +scheduler.templates.map_time = function(start,end,ev){ + if (ev._timed) + return this.day_date(ev.start_date, ev.end_date, ev)+" "+this.event_date(start); + else + return scheduler.templates.day_date(start)+" – "+scheduler.templates.day_date(end); +}; +scheduler.templates.map_text = function(ev){ + return ev.text; +}; +scheduler.date.map_start=function(d){ return d; }; + + +scheduler.attachEvent("onTemplatesReady",function(){ + + function _append_map() { + _isPositionSet = false; // if user actual (geolocation) position was set on the map + + var gmap = document.createElement('div'); + gmap.className='dhx_map'; + gmap.id='dhx_gmap'; + gmap.style.dispay = "none"; + + node = document.getElementById('scheduler_here'); + + node.appendChild(gmap); + + scheduler._els.dhx_gmap = []; + scheduler._els.dhx_gmap.push(gmap); + + _setMapSize('dhx_gmap'); + + var mapOptions = { + zoom: scheduler.config.map_inital_zoom || 10, + center: scheduler.config.map_initial_position, + mapTypeId: scheduler.config.map_type||google.maps.MapTypeId.ROADMAP + }; + map = new google.maps.Map(document.getElementById('dhx_gmap'), mapOptions); + map.disableDefaultUI = false; + map.disableDoubleClickZoom = true; + + google.maps.event.addListener(map, "dblclick", function(event) { + if (!scheduler.config.readonly && scheduler.config.dblclick_create) { + point = event.latLng; + geocoder.geocode( + { 'latLng': point }, + function(results, status) { + if (status == google.maps.GeocoderStatus.OK) { + point = results[0].geometry.location; + scheduler.addEventNow({ + lat: point.lat(), + lng: point.lng(), + event_location: results[0].formatted_address + }); + } + } + ); + } + }); + + var infoWindowOptions = { + content: '' + }; + + if (scheduler.config.map_infowindow_max_width) { + infoWindowOptions.maxWidth = scheduler.config.map_infowindow_max_width; + } + + scheduler.map = { + _points: [], + _markers: [], + _infowindow: new google.maps.InfoWindow(infoWindowOptions), + _infowindows_content: [], + _initialization_count: -1 + }; + + geocoder = new google.maps.Geocoder(); + + if(scheduler.config.map_resolve_user_location) { + if(navigator.geolocation) { + if(!_isPositionSet) { + navigator.geolocation.getCurrentPosition(function(position) { + var _userLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude); + map.setCenter(_userLocation); + map.setZoom(scheduler.config.map_zoom_after_resolve||10); + scheduler.map._infowindow.setContent(scheduler.locale.labels.marker_geo_success); + scheduler.map._infowindow.position = map.getCenter(); + scheduler.map._infowindow.open(map); + + _isPositionSet = true; + }, + function() { + scheduler.map._infowindow.setContent(scheduler.locale.labels.marker_geo_fail); + scheduler.map._infowindow.setPosition(map.getCenter()); + scheduler.map._infowindow.open(map); + _isPositionSet = true; + }); + } + } + } + google.maps.event.addListener(map, "resize", function(event) { + gmap.style.zIndex='5'; + map.setZoom( map.getZoom() ); + }); + google.maps.event.addListener(map, "tilesloaded", function(event) { + gmap.style.zIndex='5'; + }); + } + _append_map(); + + scheduler.attachEvent("onSchedulerResize",function(){ + if (this._mode == "map"){ + this.map_view(true); + } + }); + + var old = scheduler.render_data; + scheduler.render_data=function(evs,hold){ + if (this._mode == "map") { + fill_map_tab(); + var events = scheduler.get_visible_events(); + for(var i=0; i
"+l.date+"
"+l.description+"
"; + scheduler._table_view=true; + scheduler.set_sizes(); + } + } + + function fill_map_tab(){ + //get current date + var date = scheduler._date; + //select events for which data need to be printed + var events = scheduler.get_visible_events(); + events.sort(function(a,b){ return a.start_date>b.start_date?1:-1; }); + + //generate html for the view + var html="
"; + for (var i=0; i
"+scheduler.templates.map_time(events[i].start_date, events[i].end_date,events[i])+"
"; + html+="
 
"; + html+="
"+scheduler.templates.map_text(events[i])+"
"; // -25 = icon size 20 and padding 5 + } + html+="
"; + + //render html + scheduler._els["dhx_cal_data"][0].scrollTop = 0; //fix flickering in FF + scheduler._els["dhx_cal_data"][0].innerHTML = html; + scheduler._els["dhx_cal_data"][0].style.width = (scheduler.xy.map_date_width + scheduler.xy.map_description_width + 1) + 'px'; + + var t=scheduler._els["dhx_cal_data"][0].firstChild.childNodes; + scheduler._els["dhx_cal_date"][0].innerHTML=""; + + scheduler._rendered=[]; + for (var i=0; i < t.length-2; i++) { + scheduler._rendered[i]=t[i]; + } + + } + + function _setMapSize(elem_id) { //input - map's div id + var map = document.getElementById(elem_id); + map.style.height = (scheduler._y - scheduler.xy.nav_height) + 'px'; + map.style.width = (scheduler._x - scheduler.xy.map_date_width - scheduler.xy.map_description_width - 1) + 'px'; + map.style.marginLeft = (scheduler.xy.map_date_width + scheduler.xy.map_description_width + 1) + 'px'; + map.style.marginTop = (scheduler.xy.nav_height + 2) + 'px'; + } + + scheduler.map_view=function(mode){ + scheduler.map._initialization_count++; + var gmap = scheduler._els.dhx_gmap[0]; + + scheduler._els.dhx_cal_data[0].style.width = (scheduler.xy.map_date_width + scheduler.xy.map_description_width + 1) + 'px'; + + scheduler._min_date = scheduler.config.map_start||(new Date()); + scheduler._max_date = scheduler.config.map_end||(new Date(9999,1,1)); + scheduler._table_view = true; + set_full_view(mode); + + if (mode){ //map tab activated + fill_map_tab(); + gmap.style.display = 'block'; + + // need to resize block everytime window is resized + _setMapSize('dhx_gmap'); + + var events = scheduler.get_visible_events(); + for(var i=0; ipos.x){ //index of section + break; + } + } + + summ = 0; + for (yind; yind < this._colsS.heights.length; yind++) { + summ+=this._colsS.heights[yind]; + if (summ>pos.y) + break; + } + + pos.fields={}; + pos.fields[obj.y_property] = ev[obj.y_property] = obj.y_unit[yind].key; + + pos.x = yind/10000000; //force rendering when section changes + + if (this._drag_mode == "new-size" && ev.start_date*1==this._drag_start*1) { + xind++; + } + + + if(xind >= obj._trace_x.length) { // if our event is at the end of the view + var end_date = scheduler.date.add(obj._trace_x[obj._trace_x.length-1], obj.x_step, obj.x_unit); + } else { + var end_date = obj._trace_x[xind]; + } + + pos.y = Math.round((end_date-this._min_date)/(1000*60*this.config.time_step)); + pos.custom = true; + pos.shift = step_diff; + + return pos; + }; + } +}; + +scheduler.render_timeline_event = function(ev, stack, attach){ + + var x_start = _getX(ev, false, this._step); + var x_end = _getX(ev, true, this._step); + + var hb = scheduler.xy.bar_height; + var y = 2+stack*hb; + + + var cs = scheduler.templates.event_class(ev.start_date,ev.end_date,ev); + cs = "dhx_cal_event_line "+(cs||""); + + var html='
'+scheduler.templates.event_bar_text(ev.start_date,ev.end_date,ev)+'
'; + + if (!attach) + return html; + else { + var d = document.createElement("DIV"); + d.innerHTML = html; + + var ind = this.order[ev[this.y_property]]; + var parent = scheduler._els["dhx_cal_data"][0].firstChild.rows[ind].cells[1].firstChild; + + scheduler._rendered.push(d.firstChild); + parent.appendChild(d.firstChild); + } + +}; + +function trace_events(){ + //minimize event set + var evs = scheduler.getEvents(scheduler._min_date, scheduler._max_date); + var matrix =[]; + for (var i=0; i < this.y_unit.length; i++) + matrix[i]=[]; + + + //next code defines row for undefined key + //most possible it is an artifact of incorrect configuration + if (!matrix[y]) + matrix[y]=[]; + + for (var i=0; i < evs.length; i++) { + var y = this.order[evs[i][this.y_property]]; + var x = 0; + while (this._trace_x[x+1] && evs[i].start_date>=this._trace_x[x+1]) x++; + while (this._trace_x[x] && evs[i].end_date>this._trace_x[x]) { + if (!matrix[y][x]) matrix[y][x]=[]; + matrix[y][x].push(evs[i]); + x++; + } + } + return matrix; +} + +// function used to get X (both start and end) coordinates for timeline bar view +function _getX(ev, isEndPoint, step) { + var x = 0; + var date = (isEndPoint) ? ev.end_date : ev.start_date; + if(date.valueOf()>scheduler._max_date.valueOf()) + date = scheduler._max_date; + var delta = date - scheduler._min_date_timeline; + if (delta<0) { + column_offset = 0; + } else { + var index = Math.round( delta/(step*scheduler._cols[0]) ); // results varies ~0.9 - ~24.17, e.g. that way we get 1 and 24 + if(index>scheduler._cols.length) // if columns really small it's possible to get incorrect index + index = scheduler._cols.length; + for (var k=0; k"+stats.td_content+""; + + if (this.render == "cell"){ + for (var j=0; j < scheduler._cols.length; j++) { + html+="
"+scheduler.templates[this.name+"_cell_value"](evs[i][j])+"
"; + } + } else { + //section 2 + html+="
"; + + if (evs[i]){ + evs[i].sort(function(a,b){ return a.start_date>b.start_date?1:-1; }); + var stack=[]; + for (var j=0; j ev.start_date) + stack_pointer++; + stack[stack_pointer]=ev; + //render line + + html+=scheduler.render_timeline_event.call(this, ev, stack_pointer); + } + } + //section 3 + html+=""; + for (var j=0; j < scheduler._cols.length; j++) + html+=""; + html+="
"; + html+="
"; + } + html+=""; + } + html += ""; + this._matrix = evs; + d.scrollTop = 0; //fix flickering in FF + d.innerHTML = html; + + scheduler._rendered = []; + var divs = document.getElementsByTagName("DIV"); + for (var i=0; i < divs.length; i++) + if (divs[i].getAttribute("event_id")) + scheduler._rendered.push(divs[i]); + + for (var i=0; i < d.firstChild.rows.length; i++) + heights.push(d.firstChild.rows[i].offsetHeight); + +} +function x_scale(h){ + h.innerHTML = "
"; h=h.firstChild; + + scheduler._cols=[]; //store for data section + scheduler._colsS={height:0}; + this._trace_x =[]; + + scheduler._min_date_timeline = scheduler._min_date; + + var start = scheduler._min_date; + var summ = scheduler._x-this.dx-18; //border delta + + var left = this.dx; + + for (var i=0; ib.start_date?1:-1; }); + + if (scheduler._tooltip){ + if (scheduler._tooltip.date == mark) return; + scheduler._tooltip.innerHTML=""; + } else { + var t = scheduler._tooltip = document.createElement("DIV"); + t.className = "dhx_tooltip"; + document.body.appendChild(t); + t.onclick = scheduler._click.dhx_cal_data; + } + + var html = ""; + + for (var i=0; i"; + html+="
"+(evs[i]._timed?scheduler.templates.event_date(evs[i].start_date):"")+"
"; + html+="
 
"; + html+=scheduler.templates[obj.name+"_tooltip"](evs[i].start_date, evs[i].end_date,evs[i])+"
"; + } + + scheduler._tooltip.style.display=""; + scheduler._tooltip.style.top = "0px"; + + if (document.body.offsetWidth-offset.left-scheduler._tooltip.offsetWidth < 0) + scheduler._tooltip.style.left = offset.left-scheduler._tooltip.offsetWidth+"px"; + else + scheduler._tooltip.style.left = offset.left+pos.src.offsetWidth+"px"; + + scheduler._tooltip.date = mark; + scheduler._tooltip.innerHTML = html; + + if (document.body.offsetHeight-offset.top-scheduler._tooltip.offsetHeight < 0) + scheduler._tooltip.style.top= offset.top-scheduler._tooltip.offsetHeight+pos.src.offsetHeight+"px"; + else + scheduler._tooltip.style.top= offset.top+"px"; +} + +function _init_matrix_tooltip(){ + dhtmlxEvent(scheduler._els["dhx_cal_data"][0], "mouseover", function(e){ + var obj = scheduler.matrix[scheduler._mode]; + if (obj){ + var pos = scheduler._locate_cell_timeline(e); + var e = e || event; + var src = e.target||e.srcElement; + if (pos) + return showToolTip(obj,pos,getOffset(pos.src)); + } + hideToolTip(); + }); + _init_matrix_tooltip=function(){}; +} + +scheduler.renderMatrix = function(mode){ + var start_date = scheduler.date[this.name+"_start"](scheduler._date); + scheduler._min_date = scheduler.date.add(start_date, this.x_start*this.x_step, this.x_unit); + scheduler._max_date = scheduler.date.add(scheduler._min_date, this.x_size*this.x_step, this.x_unit); + scheduler._table_view = true; + set_full_view.call(this,mode); +}; + +function html_index(el) { + var p = el.parentNode.childNodes; + for (var i=0; i < p.length; i++) + if (p[i] == el) return i; + return -1; +} +function locate_hcell(e){ + e = e||event; + var trg = e.target?e.target:e.srcElement; + while (trg && trg.tagName != "DIV") + trg=trg.parentNode; + if (trg && trg.tagName == "DIV"){ + var cs = trg.className.split(" ")[0]; + if (cs == "dhx_scale_bar") + return { x:html_index(trg), y:-1, src:trg, scale:true }; + } +} +scheduler._locate_cell_timeline = function(e){ + e = e||event; + var trg = e.target?e.target:e.srcElement; + while (trg && trg.tagName != "TD") + trg=trg.parentNode; + if (trg && trg.tagName == "TD"){ + var cs = trg.className.split(" ")[0]; + if (cs == "dhx_matrix_cell") { + + if(scheduler._isRender("cell")) { + return { x:trg.cellIndex-1, y:trg.parentNode.rowIndex, src:trg }; + } else { // probably desired path for all modes except cell + var trscell = trg.parentNode; // moving out from current td + while(trscell && trscell.tagName != "TD") { + trscell=trscell.parentNode; + } + return { x:trg.cellIndex, y:trscell.parentNode.rowIndex, src:trg }; + } + } + else if (cs == "dhx_matrix_scell") + return { x:-1, y:trg.parentNode.rowIndex, src:trg, scale:true }; + } + return false; +}; + +var old_click = scheduler._click.dhx_cal_data; +scheduler._click.dhx_cal_data = function(e){ + var ret = old_click.apply(this,arguments); + var obj = scheduler.matrix[scheduler._mode]; + if (obj){ + var pos = scheduler._locate_cell_timeline(e); + if (pos){ + if (pos.scale) + scheduler.callEvent("onYScaleClick",[pos.y, obj.y_unit[pos.y], e||event]); + else + scheduler.callEvent("onCellClick",[pos.x, pos.y, obj._trace_x[pos.x], (((obj._matrix[pos.y]||{})[pos.x])||[]), e||event]); + } + } + return ret; +}; + +scheduler.dblclick_dhx_matrix_cell = function(e){ + var obj = scheduler.matrix[scheduler._mode]; + if (obj){ + var pos = scheduler._locate_cell_timeline(e); + if (pos){ + if (pos.scale) + scheduler.callEvent("onYScaleDblClick",[pos.y, obj.y_unit[pos.y], e||event]); + else + scheduler.callEvent("onCellDblClick",[pos.x, pos.y, obj._trace_x[pos.x], (((obj._matrix[pos.y]||{})[pos.x])||[]), e||event]); + } + } +}; +scheduler.dblclick_dhx_matrix_scell = function(e){ + return scheduler.dblclick_dhx_matrix_cell(e); +}; + +scheduler._isRender = function(mode){ + return (scheduler.matrix[scheduler._mode] && scheduler.matrix[scheduler._mode].render == mode); +}; + +scheduler.attachEvent("onCellDblClick", function (x, y, a, b, event){ + if (this.config.readonly|| (event.type == "dblclick" && !this.config.dblclick_create)) return; + + var obj = scheduler.matrix[scheduler._mode]; + var event_options = {}; + event_options['start_date'] = obj._trace_x[x]; + event_options['end_date'] = (obj._trace_x[x+1]) ? obj._trace_x[x+1] : scheduler.date.add(obj._trace_x[x], obj.x_step, obj.x_unit); + event_options[scheduler.matrix[scheduler._mode].y_property] = obj.y_unit[y].key; + scheduler.addEventNow(event_options, null, event); +}); + +scheduler.attachEvent("onBeforeDrag", function (event_id, mode, native_event_object){ + if(scheduler._isRender("cell")) { + return false; + } + return true; +}); + +})(); \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_minical.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_minical.js new file mode 100644 index 00000000000..d978ec53bb8 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_minical.js @@ -0,0 +1,378 @@ +scheduler.templates.calendar_month = scheduler.date.date_to_str("%F %Y"); +scheduler.templates.calendar_scale_date = scheduler.date.date_to_str("%D"); +scheduler.templates.calendar_date = scheduler.date.date_to_str("%d"); + + +scheduler.renderCalendar=function(obj, _prev){ + var cal = null; + var date = obj.date||(new Date()); + if (typeof date == "string") + date = this.templates.api_date(date); + + if (!_prev){ + var cont = obj.container; + var pos = obj.position; + + + if (typeof cont == "string") + cont = document.getElementById(cont); + + if (typeof pos == "string") + pos = document.getElementById(pos); + if (pos && (typeof pos.left == "undefined")){ + var tpos = getOffset(pos); + pos = { + top:tpos.top + pos.offsetHeight, + left:tpos.left + }; + }; + if (!cont) + cont = scheduler._get_def_cont(pos); + + cal = this._render_calendar(cont,date,obj); + cal.onclick = function(e){ + e = e||event; + var src = e.target||e.srcElement; + + if (src.className.indexOf("dhx_month_head")!=-1){ + var pname = src.parentNode.className; + if (pname.indexOf("dhx_after")==-1 && pname.indexOf("dhx_before")==-1) { + var newdate = scheduler.templates.xml_date(this.getAttribute("date")); + newdate.setDate(parseInt(src.innerHTML,10)); + scheduler.unmarkCalendar(this); + scheduler.markCalendar(this,newdate,"dhx_calendar_click"); + this._last_date=newdate; + if (this.conf.handler) this.conf.handler.call(scheduler, newdate, this); + } + } + }; + } else { + cal = this._render_calendar(_prev.parentNode, date, obj, _prev); + scheduler.unmarkCalendar(cal); + } + + + var start = scheduler.date.month_start(date); + var end = scheduler.date.add(start,1,"month"); + var evs = this.getEvents(start,end); + for (var i=0; i < evs.length; i++){ + var ev = evs[i]; + var d = ev.start_date; + if (d.valueOf()=end.valueOf()) + break; + } + } + + + + cal.conf = obj; + return cal; +}; +scheduler._get_def_cont = function(pos){ + if (!this._def_count){ + this._def_count = document.createElement("DIV"); + this._def_count.style.cssText = "position:absolute;z-index:10100;width:251px; height:175px;"; + this._def_count.onclick = function(e){ (e||event).cancelBubble = true; }; + document.body.appendChild(this._def_count); + } + + this._def_count.style.left = pos.left+"px"; + this._def_count.style.top = pos.top+"px"; + this._def_count._created = new Date(); + + return this._def_count; +}; +scheduler._locateCalendar=function(cal,date){ + var table=cal.childNodes[2].childNodes[0]; + if (typeof date == "string") + date = scheduler.templates.api_date(date); + + var d = cal.week_start+date.getDate()-1; + return table.rows[Math.floor(d/7)].cells[d%7].firstChild; +}; +scheduler.markCalendar=function(cal,date,css){ + this._locateCalendar(cal,date).className+=" "+css; +}; +scheduler.unmarkCalendar=function(cal,date,css){ + date=date||cal._last_date; + css=css||"dhx_calendar_click"; + if (!date) return; + var el = this._locateCalendar(cal,date); + el.className= (el.className||"").replace(RegExp(css,"g")); +}; +scheduler._week_template=function(width){ + var summ = (width || 250); + var left = 0; + + var week_template = document.createElement("div"); + var dummy_date = this.date.week_start(new Date()); + for (var i=0; i<7; i++){ + this._cols[i]=Math.floor(summ/(7-i)); + this._render_x_header(i,left,dummy_date,week_template); + dummy_date = this.date.add(dummy_date,1,"day"); + summ-=this._cols[i]; + left+=this._cols[i]; + } + week_template.lastChild.className+=" dhx_scale_bar_last"; + return week_template; +}; +scheduler.updateCalendar=function(obj,sd){ + obj.conf.date = sd; + this.renderCalendar(obj.conf, obj); +}; +scheduler._mini_cal_arrows = [" ", " "]; +scheduler._render_calendar=function(obj,sd,conf, previous){ + /*store*/ + var ts = scheduler.templates; + var temp = this._cols; this._cols=[]; + var temp2 = this._mode; this._mode = "calendar"; + var temp3 = this._colsS; this._colsS = {height:0}; + var temp4 = new Date(this._min_date); + var temp5 = new Date(this._max_date); + var temp6 = new Date(scheduler._date); + var temp7 = ts.month_day; ts.month_day=ts.calendar_date; + + + sd = this.date.month_start(sd); + var week_template = this._week_template(obj.offsetWidth-1); + + var d; + if (previous) + d = previous; + else { + var d = document.createElement("DIV"); + d.className="dhx_cal_container dhx_mini_calendar"; + } + d.setAttribute("date",this.templates.xml_format(sd)); + d.innerHTML="
"+week_template.innerHTML+"
"; + + d.childNodes[0].innerHTML=this.templates.calendar_month(sd); + if (conf.navigation){ + var arrow = document.createElement("DIV"); + arrow.className = "dhx_cal_prev_button"; + arrow.style.cssText="left:1px;top:2px;position:absolute;"; + arrow.innerHTML = this._mini_cal_arrows[0]; + d.firstChild.appendChild(arrow); + arrow.onclick=function(){ + scheduler.updateCalendar(d, scheduler.date.add(d._date, -1, "month")); + }; + + arrow = document.createElement("DIV"); + arrow.className = "dhx_cal_next_button"; + arrow.style.cssText="left:auto; right:1px;top:2px;position:absolute;"; + arrow.innerHTML = this._mini_cal_arrows[1]; + d.firstChild.appendChild(arrow); + arrow.onclick=function(){ + scheduler.updateCalendar(d, scheduler.date.add(d._date, 1, "month")); + }; + d._date = new Date(sd); + } + + d.week_start = (sd.getDay()-(this.config.start_on_monday?1:0)+7)%7; + + var dd = this.date.week_start(sd); + this._reset_month_scale(d.childNodes[2],sd,dd); + + var r=d.childNodes[2].firstChild.rows; + for (var k=r.length; k<6; k++) { + r[0].parentNode.appendChild(r[0].cloneNode(true)); + for (var ri=0; ri < r[k].childNodes.length; ri++) { + r[k].childNodes[ri].className = "dhx_after"; + }; + } + + if (!previous) + obj.appendChild(d); + + /*restore*/ this._cols=temp; this._mode = temp2; this._colsS = temp3; this._min_date=temp4; this._max_date=temp5; scheduler._date = temp6; ts.month_day=temp7; + return d; +}; +scheduler.destroyCalendar=function(cal,force){ + if (!cal && this._def_count && this._def_count.firstChild){ + if (force || (new Date()).valueOf() - this._def_count._created.valueOf() > 500) + cal = this._def_count.firstChild; + } + if (!cal) return; + cal.onclick=null; + cal.innerHTML=""; + if (cal.parentNode) + cal.parentNode.removeChild(cal); + if (this._def_count) + this._def_count.style.top = "-1000px"; +}; +scheduler.isCalendarVisible=function(){ + if (this._def_count && parseInt(this._def_count.style.top,10) > 0 ) + return this._def_count; + return false; +}; +scheduler.attachEvent("onTemplatesReady",function(){ + dhtmlxEvent(document.body, "click", function(){ scheduler.destroyCalendar(); }); +}); + +scheduler.templates.calendar_time = scheduler.date.date_to_str("%d-%m-%Y"); + +scheduler.form_blocks.calendar_time={ + render:function(){ + var html = ""; + + var cfg = scheduler.config; + var dt = this.date.date_part(new Date()); + if (cfg.first_hour) + dt.setHours(cfg.first_hour); + + html+=" "; + + var full_day = scheduler.config.full_day; + + return "
"+html+"  –  "+html+"
"; + }, + set_value:function(node,value,ev){ + + var inputs=node.getElementsByTagName("input"); + var selects=node.getElementsByTagName("select"); + + var _init_once = function(inp,date,number){ + inp.onclick = function(){ + scheduler.destroyCalendar(null, true); + scheduler.renderCalendar({ + position:inp, + date:new Date(this._date), + navigation:true, + handler:function(new_date){ + inp.value = scheduler.templates.calendar_time(new_date); + inp._date = new Date(new_date); + scheduler.destroyCalendar(); + if(scheduler.config.event_duration && number == 0) { //first element = start date + _update_minical_select(); + } + } + }); + }; + }; + + if(scheduler.config.full_day) { + if (!node._full_day){ + node.previousSibling.innerHTML+="
"; + node._full_day=true; + } + var input=node.previousSibling.getElementsByTagName("input")[0]; + + var isFulldayEvent = (scheduler.date.time_part(ev.start_date)==0 && scheduler.date.time_part(ev.end_date)==0 && ev.end_date.valueOf()-ev.start_date.valueOf() < 2*24*60*60*1000); + input.checked = isFulldayEvent; + for(var i in selects) + selects[i].disabled=input.checked; + for(var i=0; i0) + continue; + scheduler.markCalendar(calendar, dateNew, "dhx_calendar_click"); + dateNew = scheduler.date.add(dateNew,1,"day"); + } + } + } + return true; + }; + + scheduler.attachEvent("onViewChange", action); + scheduler.attachEvent("onXLE", action); + scheduler.attachEvent("onEventAdded", action); + scheduler.attachEvent("onEventChanged", action); + scheduler.attachEvent("onAfterEventDelete", action); + action(); +}; \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_monthheight.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_monthheight.js new file mode 100644 index 00000000000..52060ffdde4 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_monthheight.js @@ -0,0 +1,27 @@ +scheduler.attachEvent("onTemplatesReady",function(){ + scheduler.xy.scroll_width = 0; + + var old = scheduler.render_view_data; + scheduler.render_view_data=function(){ + var data = this._els["dhx_cal_data"][0]; + data.firstChild._h_fix = true; + + old.apply(scheduler,arguments); + + + + var height = parseInt(data.style.height); + data.style.height="1px"; + data.style.height=data.scrollHeight+"px"; + + this._obj.style.height = this._obj.clientHeight + data.scrollHeight - height + "px"; + } + + var old_s=scheduler._reset_month_scale; + scheduler._reset_month_scale=function(a,b,c){ + var dummy = {clientHeight:100}; + old_s.apply(scheduler,[dummy,b,c]); + a.innerHTML = dummy.innerHTML; + } + +}); \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_multiselect.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_multiselect.js new file mode 100644 index 00000000000..98b14168996 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_multiselect.js @@ -0,0 +1,63 @@ +scheduler.form_blocks["multiselect"]={ + render:function(sns) { + var _result = "
"; + for (var i=0; i"+sns.options[i].label+""; + if(convertStringToBoolean(sns.vertical)) _result += '
'; + } + _result += "
"; + return _result; + }, + set_value:function(node,value,ev,config){ + + var _children = node.getElementsByTagName('input'); + for(var i=0;i<_children.length;i++) { + _children[i].checked = false; //unchecking all inputs on the form + } + + function _mark_inputs(ids) { // ids = [ 0: undefined, 1: undefined, 2: true ... ] + var _children = node.getElementsByTagName('input'); + for(var i=0;i<_children.length; i++) { + _children[i].checked = !! ids[_children[i].value]; + } + } + + if(!scheduler._new_event) { // if it is a new event - new to get saved options + var _ids = []; + if(ev[config.map_to]) { + var results = ev[config.map_to].split(','); + for(var i=0;i"; + dx = xh[0].offsetWidth; + return xml; + } + function de_day(node,n){ + var x = parseInt(node.style.left); + + for (var dx=0; dx < scheduler._cols.length; dx++){ + x-=scheduler._cols[dx]; + if (x<0) return dx; + } + return n; + } + function de_week(node,n){ + var y = parseInt(node.style.top); + for (var dy=0; dy < scheduler._colsS.heights.length; dy++) + if (scheduler._colsS.heights[dy]>y) return dy; + return n; + } + function xml_month(yh){ + var xml=""; + var r = yh.firstChild.rows; + for (var i = 0; i < r.length; i++) { + var days = []; + for (var j = 0; j < r[i].cells.length; j++){ + /* var dd = r[i].cells[j]; + var css = dd.className; + + if (css!=" " && css!="dhx_now ") + days.push(""); + else*/ + days.push(r[i].cells[j].firstChild.innerHTML); + } + + xml += "\n"; + dy = yh.firstChild.rows[0].cells[0].offsetHeight; + } + return xml; + } + function xml_top(profile) { + var xml = ""; + + if (scheduler._mode == "agenda"){ + var xh = scheduler._els.dhx_cal_header[0].childNodes[0].childNodes; + + xml+=""+xh[0].innerHTML+""+xh[1].innerHTML+"" + } else if (scheduler._mode == "year"){ + var xh = scheduler._els.dhx_cal_data[0].childNodes; + for (var i=0; i < xh.length; i++) { + xml+=""; + xml+=xml_month_scale(xh[i].childNodes[1].childNodes); + xml+=xml_month(xh[i].childNodes[2]); + xml+=""; + }; + } else { + xml += ""; + var xh = scheduler._els.dhx_cal_header[0].childNodes; + xml+=xml_month_scale(xh); + xml += ""; + + var yh = scheduler._els.dhx_cal_data[0]; + if (yh.firstChild.tagName == "TABLE") { + xml += xml_month(yh); + } else { + yh = yh.childNodes[yh.childNodes.length - 1]; + while (yh.className.indexOf("dhx_scale_holder") == -1) + yh = yh.previousSibling; + yh = yh.childNodes; + + xml += ""; + for (var i = 0; i < yh.length; i++) + xml += "\n"; + xml += ""; + dy = yh[0].offsetHeight; + } + } + + xml += ""; + return xml; + } + function get_style(node, style){ + return (window.getComputedStyle?(window.getComputedStyle(node, null)[style]):(node.currentStyle?node.currentStyle[style]:null))||""; + } + function xml_body() { + var xml = ""; + var evs = scheduler._rendered; + + if (scheduler._mode == "agenda"){ + for (var i=0; i < evs.length; i++) + xml+=""+evs[i].childNodes[0].innerHTML+""+evs[i].childNodes[2].innerHTML+""; + } else if (scheduler._mode == "year"){ + var evs = scheduler.get_visible_events(); + for (var i=0; i < evs.length; i++) { + var d = evs[i].start_date; + if (d.valueOf()"; + scheduler._mark_year_date(d); + d = scheduler.date.add(d,1,"day"); + if (d.valueOf()>=scheduler._max_date.valueOf()) + break; + } + } + } else { + for (var i = 0; i < evs.length; i++) { + var zx = x_norm(evs[i].style.left); + var zy = y_norm(evs[i].style.top); + var zdx = x_norm(evs[i].style.width); + var zdy = y_norm(evs[i].style.height); + var e_type = evs[i].className.split(" ")[0].replace("dhx_cal_", ""); + var dets = scheduler.getEvent(evs[i].getAttribute("event_id")) + var day = dets._sday; + var week = dets._sweek; + if (scheduler._mode != "month") { + if (parseInt(evs[i].style.left) <= 26) { + zx = 2; + zdx += x_norm(evs[i].style.left)-1; + } + if (evs[i].parentNode == scheduler._els.dhx_cal_data[0]) continue; + zx += x_norm(evs[i].parentNode.style.left); + zx -= x_norm(51); + } else { + zdy = parseInt(evs[i].offsetHeight); + zy = parseInt(evs[i].style.top) - 22; + + day = de_day(evs[i],day); + week = de_week(evs[i],week); + } + + xml += "\n"; + + + if (e_type == "event") { + xml += "
"; + var text_color = colors?get_style(evs[i].childNodes[2],"color"):""; + var bg_color = colors?get_style(evs[i].childNodes[2],"backgroundColor"):""; + xml += ""; + } else { + var text_color = colors?get_style(evs[i],"color"):""; + var bg_color = colors?get_style(evs[i],"backgroundColor"):""; + xml += ""; + } + xml += "
"; + } + } + return xml; + } + function xml_end(){ + var xml = "
"; + return xml; + } + + var uid = (new Date()).valueOf(); + var d=document.createElement("div"); + d.style.display="none"; + document.body.appendChild(d); + + d.innerHTML = '
'; + document.getElementById(uid).firstChild.value = xml_top(mode).replace("\u2013", "-") + xml_body() + xml_end(); + document.getElementById(uid).submit(); + d.parentNode.removeChild(d);grid = null; +} \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_readonly.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_readonly.js new file mode 100644 index 00000000000..b11c4fe8048 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_readonly.js @@ -0,0 +1,100 @@ +scheduler.attachEvent("onTemplatesReady",function(){ + scheduler.attachEvent("onBeforeLightbox",function(id){ + if (this.config.readonly_form || this.getEvent(id).readonly) + this.config.readonly_active = true; + else { + this.config.readonly_active = false; + return true; + } + + for (var i=0; i < this.config.lightbox.sections.length; i++) { + this.config.lightbox.sections[i].focus = false; + }; + + return true; + }); + + function txt_replace(tag,d,n,text){ + var txts = d.getElementsByTagName(tag); + var txtt = n.getElementsByTagName(tag); + for (var i=txtt.length-1; i>=0; i--){ + var n = txtt[i]; + if (!text) + n.disabled = true; + else { + var t = document.createElement("SPAN"); + t.className = "dhx_text_disabled"; + t.innerHTML=text(txts[i]); + n.parentNode.insertBefore(t,n); + n.parentNode.removeChild(n); + } + } + } + + var old = scheduler._fill_lightbox; + scheduler._fill_lightbox=function(){ + var sns = this.config.lightbox.sections; + if (this.config.readonly_active){ + for (var i=0; i < sns.length; i++) { + if (sns[i].type == 'recurring') { + var s = document.getElementById(sns[i].id); + s.style.display=s.nextSibling.style.display='none'; + sns.splice(i,1); + i--; + } + }; + } + + var res = old.apply(this,arguments); + if (this.config.readonly_active){ + + var d = this._get_lightbox(); + var n = this._lightbox_r = d.cloneNode(true); + + txt_replace("textarea",d,n,function(a){ return a.value; }); + txt_replace("input",d,n,false); + txt_replace("select",d,n,function(a){ return a.options[Math.max((a.selectedIndex||0),0)].text; }); + + n.removeChild(n.childNodes[2]); + n.removeChild(n.childNodes[3]); + + d.parentNode.insertBefore(n,d); + + olds.call(this,n); + this._lightbox = n; + this.setLightboxSize(); + this._lightbox = null; + n.onclick=function(e){ + var src=e?e.target:event.srcElement; + if (!src.className) src=src.previousSibling; + if (src && src.className) + switch(src.className){ + case "dhx_cancel_btn": + scheduler.callEvent("onEventCancel",[scheduler._lightbox_id]); + scheduler._edit_stop_event(scheduler.getEvent(scheduler._lightbox_id),false); + scheduler.hide_lightbox(); + break; + } + }; + } + return res; + }; + + var olds = scheduler.showCover; + scheduler.showCover=function(){ + if (!this.config.readonly_active) + olds.apply(this,arguments); + }; + + var hold = scheduler.hide_lightbox; + scheduler.hide_lightbox=function(){ + if (this._lightbox_r){ + this._lightbox_r.parentNode.removeChild(this._lightbox_r); + this._lightbox_r = null; + } + + return hold.apply(this,arguments); + }; + + +}); \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_serialize.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_serialize.js new file mode 100644 index 00000000000..879ab661c62 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_serialize.js @@ -0,0 +1,66 @@ +//redefine this method, if you want to provide a custom set of attributes for serialization +scheduler.data_attributes=function(){ + var attrs = []; + var format = scheduler.templates.xml_format; + for (var a in this._events){ + var ev = this._events[a]; + for (var name in ev) + if (name.substr(0,1) !="_") + attrs.push([name,((name == "start_date" || name == "end_date")?format:null)]); + break; + } + return attrs; +} + +scheduler.toXML = function(header){ + var xml = []; + var attrs = this.data_attributes(); + + + for (var a in this._events){ + var ev = this._events[a]; + if (ev.id.toString().indexOf("#")!=-1) continue; + xml.push(""); + for (var i=0; i < attrs.length; i++) + xml.push("<"+attrs[i][0]+">"); + + xml.push(""); + } + return (header||"")+""+xml.join("\n")+""; +}; + +scheduler.toJSON = function(){ + var json = []; + var attrs = this.data_attributes(); + for (var a in this._events){ + var ev = this._events[a]; + if (ev.id.toString().indexOf("#")!=-1) continue; + var ev = this._events[a]; + var line =[]; + for (var i=0; i < attrs.length; i++) + line.push(' '+attrs[i][0]+':"'+((attrs[i][1]?attrs[i][1](ev[attrs[i][0]]):ev[attrs[i][0]])||"").toString().replace(/\n/g,"")+'" '); + json.push("{"+line.join(",")+"}"); + } + return "["+json.join(",\n")+"]"; +}; + + +scheduler.toICal = function(header){ + var start = "BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//dhtmlXScheduler//NONSGML v2.2//EN\nDESCRIPTION:"; + var end = "END:VCALENDAR"; + var format = scheduler.date.date_to_str("%Y%m%dT%H%i%s"); + + var ical = []; + for (var a in this._events){ + var ev = this._events[a]; + if (ev.id.toString().indexOf("#")!=-1) continue; + + + ical.push("BEGIN:VEVENT"); + ical.push("DTSTART:"+format(ev.start_date)); + ical.push("DTEND:"+format(ev.end_date)); + ical.push("SUMMARY:"+ev.text); + ical.push("END:VEVENT"); + } + return start+(header||"")+"\n"+ical.join("\n")+"\n"+end; +}; \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_tooltip.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_tooltip.js new file mode 100644 index 00000000000..2146c8f9414 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_tooltip.js @@ -0,0 +1,133 @@ +window.dhtmlXTooltip={version:0.1}; + +dhtmlXTooltip.config = { + className: 'dhtmlXTooltip tooltip', + timeout_to_display: 50, + delta_x: 15, + delta_y: -20 +}; + +dhtmlXTooltip.tooltip = document.createElement('div'); +dhtmlXTooltip.tooltip.className = dhtmlXTooltip.config.className; + +dhtmlXTooltip.show = function(event, text) { //browser event, text to display + dhtmlXTooltip.tooltip.className = dhtmlXTooltip.config.className; + var pos=this.position(event); + + var target = event.target||event.srcElement; + if (this.isTooltip(target)) {return;} // if we are over tooltip -- do nothing, just return (so tooltip won't move) + + var actual_x = pos.x+dhtmlXTooltip.config.delta_x||0; + var actual_y = pos.y-dhtmlXTooltip.config.delta_y||0; + + this.tooltip.style.visibility = "hidden"; + + if(this.tooltip.style.removeAttribute) { + this.tooltip.style.removeAttribute("right"); + this.tooltip.style.removeAttribute("bottom"); + } else { + this.tooltip.style.removeProperty("right"); + this.tooltip.style.removeProperty("bottom"); + } + + this.tooltip.style.left = "0px"; + this.tooltip.style.top = "0px"; + + this.tooltip.innerHTML = text; + scheduler._obj.appendChild(this.tooltip); + + var tooltip_width = this.tooltip.offsetWidth; + var tooltip_height = this.tooltip.offsetHeight; + + if (document.body.offsetWidth - actual_x - tooltip_width < 0) { // tooltip is out of the right page bound + if(this.tooltip.style.removeAttribute) + this.tooltip.style.removeAttribute("left"); + else + this.tooltip.style.removeProperty("left"); + this.tooltip.style.right = (document.body.offsetWidth - actual_x + 2 * dhtmlXTooltip.config.delta_x||0) + "px"; + } else { + if (actual_x < 0) { // tooltips is out of the left page bound + this.tooltip.style.left = (pos.x + Math.abs(dhtmlXTooltip.config.delta_x||0)) + "px"; + } else { // normal situation + this.tooltip.style.left = actual_x + "px"; + } + } + + if (document.body.offsetHeight - actual_y - tooltip_height < 0) { // tooltip is below bottom of the page + if(this.tooltip.style.removeAttribute) + this.tooltip.style.removeAttribute("top"); + else + this.tooltip.style.removeProperty("top"); + this.tooltip.style.bottom = (document.body.offsetHeight - actual_y - 2 * dhtmlXTooltip.config.delta_y||0) + "px"; + } else { + if (actual_y < 0) { // tooltip is higher then top of the page + this.tooltip.style.top = (pos.y + Math.abs(dhtmlXTooltip.config.delta_y||0)) + "px"; + } + else { // normal situation + this.tooltip.style.top = actual_y + "px"; + } + } + + this.tooltip.style.visibility = "visible"; +}; + +dhtmlXTooltip.hide = function() { + if(this.tooltip.parentNode) { + this.tooltip.parentNode.removeChild(this.tooltip); + } +}; +dhtmlXTooltip.delay = function(method, object, params, delay) { + if(this.tooltip._timeout_id) { + window.clearTimeout(this.tooltip._timeout_id); + } + this.tooltip._timeout_id = setTimeout(function(){ + var ret = method.apply(object,params); + method = obj = params = null; + return ret; + },delay||this.config.timeout_to_display); +}; + +dhtmlXTooltip.isTooltip = function(node){ + var res = false; + while (node && !res) { + res = (node.className == this.tooltip.className); + node=node.parentNode; + } + return res; +}; + +dhtmlXTooltip.position = function(ev) { + var ev = ev || window.event; + if(ev.pageX || ev.pageY) //FF, KHTML + return {x:ev.pageX, y:ev.pageY}; + //IE + var d = ((dhtmlx._isIE)&&(document.compatMode != "BackCompat"))?document.documentElement:document.body; + return { + x:ev.clientX + d.scrollLeft - d.clientLeft, + y:ev.clientY + d.scrollTop - d.clientTop + }; +}; + +scheduler.attachEvent("onMouseMove", function(event_id, e){ // (scheduler event_id, browser event) + var ev = e||window.event; + var target = ev.target||ev.srcElement; + + if (event_id || dhtmlXTooltip.isTooltip(target)) { // if we are over event or tooltip + var event = scheduler.getEvent(event_id) || scheduler.getEvent(dhtmlXTooltip.tooltip.event_id); + dhtmlXTooltip.tooltip.event_id = event.id; + var text = scheduler.templates.tooltip_text(event.start_date, event.end_date, event); + + if (_isIE) { //make a copy of event, will be used in timed call + var evt = document.createEventObject(ev); + } + + dhtmlXTooltip.delay(dhtmlXTooltip.show, dhtmlXTooltip, [ evt||ev , text]); // showing tooltip + } else { + dhtmlXTooltip.delay(dhtmlXTooltip.hide, dhtmlXTooltip, []); + } +}); + +/* Could be redifined */ +scheduler.templates.tooltip_text = function(start,end,event) { + return "Event: "+event.text+"
Start date: "+scheduler.templates.tooltip_date_format(start)+"
End date: "+scheduler.templates.tooltip_date_format(end); +}; \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_touch.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_touch.js new file mode 100644 index 00000000000..9dde6fd89b4 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_touch.js @@ -0,0 +1,411 @@ +TouchScroll=function(node, nontouch, scroll, compat){ + this.debug = !!nontouch; + this.compat = !!compat; + this.rough = !!scroll; + + + this.axisX = this.axisY = true; + + if (typeof node!= "object") + node = document.getElementById(node); + + this._init(); + node.addEventListener("touchstart",this,false); + node.addEventListener("webkitTransitionEnd",this,false); + if (this.debug) + node.addEventListener("mousedown",this,false); + + + this.node = node; + for (var i=0; i < node.childNodes.length; i++) + if (node.childNodes[i].nodeType == 1){ + this.area = node.childNodes[i]; + break; + } + + if (window.getComputedStyle(this.node).position == "static") + this.node.style.position = "relative" + this.area.style.cssText += "-webkit-transition: -webkit-transform; -webkit-user-select:none; -webkit-transform-style:preserve-3d;"; + this.scrolls={}; +}; + +TouchScroll.prototype = { + refresh:function(){ + this.node.style.webkitTransformStyle="flat"; + this.node.style.webkitTransformStyle="preserve-3d"; + }, + scrollTo:function(x,y,speed){ + this.set_matrix({e:x,f:y}, (speed||0)); + }, + onscroll:function(x,y){}, + handleEvent:function(ev){ + return this["ev_"+ev.type](ev); + }, + get_matrix:function(node){ + return new WebKitCSSMatrix(window.getComputedStyle(node||this.area).webkitTransform); + }, + set_matrix:function(value,speed,node){ + (node||this.area).style.webkitTransform = "translate("+Math.round(value.e)+"px,"+Math.round(value.f)+"px)"; + (node||this.area).style.webkitTransitionDuration= speed; + }, + ev_touchstart:function(ev){ + this.ev_mousedown(ev.touches[0]); + ev.preventDefault(); + return false; + }, + ev_mousedown:function(ev){ + var touch = ev; + + this.x = touch.pageX; + this.y = touch.pageY; + this.dx = this.node.offsetWidth; + this.dy = this.node.offsetHeight; + this.mx = this.area.scrollWidth; + this.my = this.area.scrollHeight; + this.target = touch.target; + + if (!this.rough){ + var temp = this.get_matrix(); + this.target_x = temp.e; + this.target_y = temp.f; + if (!this.scroll && this.compat){ + temp.e = this.node.scrollLeft*-1; + temp.f = this.node.scrollTop*-1; + this.node.scrollTop = this.node.scrollLeft = 0; + } + + this.set_matrix(temp,0); + this._correct_scroll(this.target_x, this.target_y); + } + this.scroll_x = this.scroll_y = this.scroll = false; + + + this._init_events(); + }, + ev_touchend:function(){ + return this.ev_mouseup(); + }, + ev_mouseup:function(){ + this._deinit_events(); + if (!this.scroll){ + this._remove_scroll(); + var ev = document.createEvent("MouseEvent"); + ev.initMouseEvent("click",true, true); + this.target.dispatchEvent(ev); + } + this.target = null; + }, + ev_webkitTransitionEnd:function(){ + if (this.target || !this.scroll) return; + + this._remove_scroll(); + var temp = this.get_matrix(); + this.node.firstChild._scrollTop = -1*temp.f; + + if (this.compat && (temp.e||temp.f)){ + var y = temp.f; var x = temp.e; + temp.e = temp.f = 0; + this.set_matrix(temp,0); + + this.node.scrollTop = -1*y; + this.node.scrollLeft = -1*x; + } + + this.scroll = false; + }, + ev_touchmove:function(ev){ + return this.ev_mousemove(ev.touches[0]); + }, + ev_mousemove:function(ev){ + if (!this.target) return; + var touch = ev; + + var dx = (touch.pageX - this.x)*(this.axisX?5:0);//Math.min(3,this.mx/this.dx); + var dy = (touch.pageY - this.y)*(this.axisY?5:0);//Math.min(3,this.my/this.dy); + + if (Math.abs(dx)<10 && Math.abs(dy)<10) return; + + if (Math.abs(dx)>50) + this.scroll_x=true; + if (Math.abs(dy)>50) + this.scroll_y=true; + + + if (this.scroll_x || this.scroll_y){ + this.x = touch.pageX; this.y = touch.pageY; + this.scroll = true; + var temp = this.get_matrix(); + dx = dx + (this.target_x - temp.e); + dy = dy + (this.target_y - temp.f); + + var speed = "2000ms"; + var fast = "500ms"; + this.target_x = dx+temp.e; + this.target_y = dy+temp.f; + + if (this.target_x > 0) { + this.target_x = 0; + speed = fast; + } + if (this.target_y > 0) { + this.target_y = 0; + speed = fast; + } + if (this.mx - this.dx + this.target_x < 0){ + this.target_x = - this.mx + this.dx; + speed = fast; + } + if (this.my - this.dy + this.target_y < 0){ + this.target_y = - this.my + this.dy; + speed = fast; + } + + + this.set_matrix({e:this.target_x,f:this.target_y},speed); + this._add_scroll(temp.e, temp.f); + this._correct_scroll(this.target_x, this.target_y, speed); + this.onscroll(this.target_x, this.target_y); + } + return false; + }, + _correct_scroll:function(x,y,speed){ + if (this.scrolls.x){ + var stemp = this.get_matrix(this.scrolls.x); + var sx = this.dx*x/this.mx; + this.set_matrix({e:-1*sx,f:0}, speed, this.scrolls.x); + } + if (this.scrolls.y){ + var stemp = this.get_matrix(this.scrolls.y); + var sy = this.dy*y/this.my; + this.set_matrix({e:0,f:-1*sy}, speed, this.scrolls.y); + } + }, + _remove_scroll:function(){ + if (this.scrolls.x) + this.scrolls.x.parentNode.removeChild(this.scrolls.x); + if (this.scrolls.y) + this.scrolls.y.parentNode.removeChild(this.scrolls.y); + this.scrolls = {}; + }, + _add_scroll:function(){ + if (this.scrolls.ready) return; + + var d; + if (this.my>5 && this.axisY){ + var h = this.dy*this.dy/this.my-1; + this.scrolls.y = d = document.createElement("DIV"); + d.className="dhx_scroll_y"; + d.style.height = h +"px"; + this.node.appendChild(d); + } + if (this.mx>5 && this.axisX){ + var h = this.dx*this.dx/this.mx; + this.scrolls.x = d = document.createElement("DIV"); + d.className="dhx_scroll_x"; + d.style.width = h +"px"; + this.node.appendChild(d); + } + + var temp = this.get_matrix(); + this._correct_scroll(temp.e, temp.f, 0); + this.scrolls.ready = true; + }, + _init_events:function(){ + document.addEventListener("touchmove",this,false); + document.addEventListener("touchend",this,false); + if (this.debug){ + document.addEventListener("mousemove",this,false); + document.addEventListener("mouseup",this,false); + } + }, + _deinit_events:function(){ + document.removeEventListener("touchmove",this,false); + document.removeEventListener("touchend",this,false); + if (this.debug){ + document.removeEventListener("mousemove",this,false); + document.removeEventListener("mouseup",this,false); + } + }, + _init:function(){ + document.styleSheets[0].insertRule(".dhx_scroll_x { width:50px;height:4px;background:rgba(0, 0, 0, 0.4);position:absolute; left:0px; bottom:3px; border:1px solid transparent; -webkit-border-radius:4px;-webkit-transition: -webkit-transform;}",0); + document.styleSheets[0].insertRule(".dhx_scroll_y { width:4px;height:50px;background:rgba(0, 0, 0, 0.4);position:absolute; top:0px; right:3px; border:1px solid transparent; -webkit-border-radius:4px;-webkit-transition: -webkit-transform;}",0); + this._init = function(){}; + } +}; + + + + + +scheduler._ipad_before_init=function(){ + scheduler._ipad_before_init=function(){}; + scheduler.xy.scroll_width = 0; + + var tabs = scheduler._els["dhx_cal_tab"]; + var right = 42; + for (var i=tabs.length-1; i >=0; i--) { + tabs[i].style.cssText+="top:4px;"; + tabs[i].style.left="auto"; + tabs[i].style.right = right+"px"; + if (i==0) + tabs[i].style.cssText+=";-webkit-border-top-left-radius: 5px; -webkit-border-bottom-left-radius: 5px;"; + if (i==tabs.length-1) + tabs[i].style.cssText+=";-webkit-border-top-right-radius: 5px; -webkit-border-bottom-right-radius: 5px;"; + + right+=100; + }; + + scheduler._els["dhx_cal_prev_button"][0].innerHTML = "<"; + scheduler._els["dhx_cal_next_button"][0].innerHTML = ">"; + var d = document.createElement("div"); + d.className = "dhx_cal_add_button"; + d.innerHTML = "+ "; + d.onclick = function(){ + var now = new Date(); + if (now > scheduler._min_date && now < scheduler._max_date) + scheduler.addEventNow(); + else + scheduler.addEventNow(scheduler._min_date.valueOf()); + } + scheduler._els["dhx_cal_navline"][0].appendChild(d); + + + this._obj.onmousedown = this._obj.onmouseup = this._obj.onmousemove = function(){}; + + var long_tap = null; + var long_tap_pos = []; + this._obj.ontouchmove=function(e){ + if (long_tap){ + var dx = Math.abs(e.touches[0].pageX - long_tap_pos[0]); + var dy = Math.abs(e.touches[0].pageY - long_tap_pos[1]); + if (dx>50 || dy>50) + long_tap = window.clearTimeout(long_tap); + } + if (scheduler.config.touch_actions) + scheduler._on_mouse_move(e.touches[0]); + } + this._obj.ontouchstart = function(e){ + if (scheduler._lightbox_id) return; + + long_tap = window.setTimeout(function(){ + scheduler._on_dbl_click(e.touches[0],(e.target.className?e.target:e.target.parentNode)); + },400); + long_tap_pos = [e.touches[0].pageX, e.touches[0].pageY]; + if (scheduler.config.touch_actions) + scheduler._on_mouse_down(e.touches[0]); + } + this._obj.ontouchend = function(e){ + if (long_tap) + long_tap = window.clearTimeout(long_tap); + if (scheduler.config.touch_actions) + scheduler._on_mouse_up(e.touches[0]); + } +} +scheduler._ipad_init=function(){ + var d = document.createElement("DIV"); + var data = scheduler._els["dhx_cal_data"][0]; + d.appendChild(data); + d.style.cssText = "overflow:hidden; width:100%; overflow:hidden;position:relative;"; + this._obj.appendChild(d); + + data.style.overflowY = "hidden"; + + var scroll = new TouchScroll(d); + scroll.axisX = false; + scheduler._ipad_init = function(){ + data.parentNode.style.height = data.style.height; + data.parentNode.style.top = data.style.top; + data.style.height = data.scrollHeight+"px"; + data.style.top = "0px"; + + if (Math.abs(data.parentNode.offsetHeight - data.offsetHeight)<5){ + scroll.axisY=false; + scroll.scrollTo(0,0,0); + } else + scroll.axisY=true; + + scroll.refresh(); + }; + + scheduler.attachEvent("onSchedulerResize", function(){ + setTimeout(function(){ + scheduler._ipad_init(); + }); + return true; + }) + + scheduler._ipad_init(); +}; + +scheduler.attachEvent("onViewChange",function(){ + scheduler._ipad_init(); +}); +scheduler.attachEvent("onBeforeViewChange",function(){ + scheduler._ipad_before_init(); + return true; +}); + +scheduler.showCover=function(box){ + this.show_cover(); + if (box){ + box.style.display="block"; + var pos = getOffset(this._obj); + box.style.top = box.offsetHeight*-1+"px"; + box.style.left = Math.round(pos.left+(this._obj.offsetWidth-box.offsetWidth)/2)+"px"; + } + + var node =this._get_lightbox(); + node.style.webkitTransform = "translate(0px,"+(box.offsetHeight+41)+"px)"; + node.style.webkitTransitionDuration = "500ms"; +}; + +scheduler.hideCover=function(box){ + if (box){ + box.style.webkitTransform = "translate(0px,"+(box.offsetHeight+41)*-1+"px)"; + box.style.webkitTransitionDuration = "500ms"; + } + this.hide_cover(); +} + +scheduler.config.lightbox.sections[0].height = 100; +if (scheduler.form_blocks.calendar_time){ + scheduler.config.lightbox.sections[1].type = "calendar_time"; + scheduler._mini_cal_arrows = ["<", ">"]; +} + +scheduler.xy.menu_width = 0; +scheduler.attachEvent("onClick", function(){ + return false; +}); + +scheduler.locale.labels.new_event=""; + +scheduler._mouse_coords=function(ev){ + var pos; + var b=document.body; + var d = document.documentElement; + if(ev.pageX || ev.pageY) + pos={x:ev.pageX, y:ev.pageY}; + else pos={ + x:ev.clientX + (b.scrollLeft||d.scrollLeft||0) - b.clientLeft, + y:ev.clientY + (b.scrollTop||d.scrollTop||0) - b.clientTop + } + + //apply layout + pos.x-=getAbsoluteLeft(this._obj)+(this._table_view?0:this.xy.scale_width); + var top = + pos.y-=getAbsoluteTop(this._obj)+this.xy.nav_height+this._dy_shift+this.xy.scale_height-(this._els["dhx_cal_data"][0]._scrollTop||0); + //transform to date + if (!this._table_view){ + pos.x=Math.max(0,Math.ceil(pos.x/this._cols[0])-1); + pos.y=Math.max(0,Math.ceil(pos.y*60/(this.config.time_step*this.config.hour_size_px))-1)+this.config.first_hour*(60/this.config.time_step); + } else { + var dy=0; + for (dy=1; dy < this._colsS.heights.length; dy++) + if (this._colsS.heights[dy]>pos.y) break; + + pos.y=(Math.max(0,Math.ceil(pos.x/this._cols[0])-1)+Math.max(0,dy-1)*7)*24*60/this.config.time_step; + pos.x=0; + } + return pos; +} diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_treetimeline.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_treetimeline.js new file mode 100644 index 00000000000..9fb08261470 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ext/ext_treetimeline.js @@ -0,0 +1,275 @@ +scheduler.attachEvent("onTimelineCreated", function (obj){ + + if(obj.render == "tree") { + obj.y_unit_original = obj.y_unit; + obj.y_unit = scheduler._getArrayToDisplay(obj.y_unit_original); + + scheduler.form_blocks[obj.name]={ + render:function(sns) { + var _result = "
"; + return _result; + }, + set_value:function(node,value,ev,config){ + var options = scheduler._getArrayForSelect(scheduler.matrix[config.type].y_unit_original, config.type); + node.innerHTML = ''; + var temp_select = document.createElement('select'); + node.appendChild(temp_select); + + var select = node.getElementsByTagName('select')[0]; + + for(var i=0; i"; + table_className = (timeline.folder_events_available)?"dhx_data_table folder_events":"dhx_data_table folder"; + } else { + height = timeline.dy; + tr_className = "dhx_row_item"; + td_className = "dhx_matrix_scell item"; + div_expand = ''; + table_className = "dhx_data_table"; + } + td_content = "
"+div_expand+"
"+(scheduler.templates[timeline.name+'_scale_label'](y_unit.key, y_unit.label, timeline)||y_unit.label)+"
"; + + res = { + height: height, + style_height: style_height, + //section 1 + tr_className: tr_className, + td_className: td_className, + td_content: td_content, + //section 3 + table_className: table_className + }; + }; + return res; +}); + +var section_id_before; // section id of the event before dragging (to bring it back if user drop's event on folder without folder_events_available) + +scheduler.attachEvent("onBeforeEventChanged", function(event_object, native_event, is_new) { + if (scheduler._isRender("tree")) { // if mode's render == tree + var section = scheduler.getSection(event_object.section_id); + if (typeof section.children != 'undefined' && !scheduler.matrix[scheduler._mode].folder_events_available) { + if (!is_new) { //if old - move back + event_object[scheduler.matrix[scheduler._mode].y_property] = section_id_before; + } + return false; + } + } + return true; +}); + +scheduler.attachEvent("onBeforeDrag", function (event_id, mode, native_event_object){ + var cell = scheduler._locate_cell_timeline(native_event_object); + if(cell) { + var section_id = scheduler.matrix[scheduler._mode].y_unit[cell.y].key; + if(typeof scheduler.matrix[scheduler._mode].y_unit[cell.y].children != "undefined" && !scheduler.matrix[scheduler._mode].folder_events_available) { + return false; + } + } + if(scheduler._isRender("tree")) { + ev = scheduler.getEvent(event_id); + section_id_before = section_id||ev[scheduler.matrix[scheduler._mode].y_property]; // either event id or section_id will be available + } + return true; +}); + +scheduler._getArrayToDisplay = function(array){ // function to flatten out hierarhical array, used for tree view + var result = []; + var fillResultArray = function(array, lvl){ + var level = lvl||0; + for(var i=0; i open) +scheduler._toggleFolderDisplay(4, true) -- open section with the key 4 (doesn't matter what status was before). False - close. +scheduler._toggleFolderDisplay(4, false, true) -- close ALL sections. Key is not used in such condition. +*/ +scheduler._toggleFolderDisplay = function(key, status, all_sections){ // used for tree view + var marked; + var toggleElement = function(key, array, status, all_sections) { + for (var i=0; i" + html+="
"+(evs[i]._timed?this.templates.event_date(evs[i].start_date):"")+"
"; + html+="
 
"; + html+=this.templates.year_tooltip(evs[i].start_date, evs[i].end_date,evs[i])+"
"; + } + + this._tooltip.style.display=""; + this._tooltip.style.top = "0px"; + + + if (document.body.offsetWidth-pos.left-this._tooltip.offsetWidth < 0) + this._tooltip.style.left = pos.left-this._tooltip.offsetWidth+"px"; + else + this._tooltip.style.left = pos.left+src.offsetWidth+"px"; + + this._tooltip.date = date; + this._tooltip.innerHTML = html; + + if (document.body.offsetHeight-pos.top-this._tooltip.offsetHeight < 0) + this._tooltip.style.top= pos.top-this._tooltip.offsetHeight+src.offsetHeight+"px"; + else + this._tooltip.style.top= pos.top+"px"; +} + +scheduler._init_year_tooltip=function(){ + dhtmlxEvent(scheduler._els["dhx_cal_data"][0], "mouseover", function(e){ + if (!is_year_mode()) return; + + var e = e || event; + var src = e.target||e.srcElement; + if ((src.className||"").indexOf("dhx_year_event")!=-1) + scheduler.showToolTip(from_attr(src.getAttribute("date")),getOffset(src),e,src); + else + scheduler.hideToolTip(); + }) + this._init_year_tooltip=function(){}; +} + +scheduler.attachEvent("onSchedulerResize",function(){ + if (is_year_mode()){ + this.year_view(true); + return false; + } + return true; +}); +scheduler._get_year_cell=function(d){ + //there can be more than 1 year in view + //year can start not from January + var m = d.getMonth()+12*(d.getFullYear()-this._min_date.getFullYear())-this.week_starts._month; + var t = this._els["dhx_cal_data"][0].childNodes[m]; + var d = this.week_starts[m]+d.getDate()-1; + + + return t.childNodes[2].firstChild.rows[Math.floor(d/7)].cells[d%7].firstChild; +} + + +var marked = []; +scheduler._mark_year_date=function(d,ev){ + var c = this._get_year_cell(d); + c.className = "dhx_month_head dhx_year_event "+this.templates.event_class(ev.start_date,ev.end_date,ev); + c.setAttribute("date",to_attr(d)) + marked.push(c); +} +scheduler._unmark_year_date=function(d){ + this._get_year_cell(d).className = "dhx_month_head"; +} +scheduler._year_render_event=function(ev){ + var d = ev.start_date; + if (d.valueOf()=this._max_date.valueOf()) + return; + } +} +scheduler.year_view=function(mode){ + if (mode){ + var temp = scheduler.xy.scale_height; + scheduler.xy.scale_height = -1; + } + + scheduler._els["dhx_cal_header"][0].style.display=mode?"none":""; + scheduler.set_sizes(); + + if (mode) + scheduler.xy.scale_height = temp; + + + scheduler._table_view = mode; + if (this._load_mode && this._load()) return; + + if (mode){ + scheduler._init_year_tooltip(); + scheduler._reset_year_scale(); + scheduler.render_view_data(); + } else { + scheduler.hideToolTip(); + } +} +scheduler._reset_year_scale = function(){ + this._cols=[]; this._colsS={}; + var week_starts = []; //start day of first week in each month + var b=this._els["dhx_cal_data"][0]; + + var c = this.config; + b.scrollTop=0; //fix flickering in FF + b.innerHTML=""; + + var dx = Math.floor(parseInt(b.style.width)/c.year_x); + var dy = Math.floor((parseInt(b.style.height)-scheduler.xy.year_top)/c.year_y); + if (dy<190) { + dy = 190; + dx = Math.floor((parseInt(b.style.width)-scheduler.xy.scroll_width)/c.year_x); + } + + var summ = dx-11; + var left = 0; + var week_template = document.createElement("div"); + var dummy_date = this.date.week_start(new Date()); + for (var i=0; i<7; i++){ + this._cols[i]=Math.floor(summ/(7-i)); + this._render_x_header(i,left,dummy_date,week_template); + dummy_date = this.date.add(dummy_date,1,"day"); + summ-=this._cols[i]; + left+=this._cols[i]; + } + week_template.lastChild.className+=" dhx_scale_bar_last"; + + var sd = this.date[this._mode+"_start"](this.date.copy(this._date)); + var ssd=sd; + + for (var i=0; i
"; + d.childNodes[0].innerHTML=this.templates.year_month(sd); + + var dd = this.date.week_start(sd); + var ed = this._reset_month_scale(d.childNodes[2],sd,dd); + + var r=d.childNodes[2].firstChild.rows; + for (var k=r.length; k<6; k++) { + r[0].parentNode.appendChild(r[0].cloneNode(true)); + for (var ri=0; ri < r[k].childNodes.length; ri++) { + r[k].childNodes[ri].className = "dhx_after"; + r[k].childNodes[ri].firstChild.innerHTML = scheduler.templates.month_day(ed); + ed = scheduler.date.add(ed,1,"day"); + }; + } + + + b.appendChild(d); + + var dt = Math.round((dy-190)/2); + d.style.marginTop=dt+"px"; + this.set_xy(d,dx-10,dy-dt-10,dx*j+5,dy*i+5+scheduler.xy.year_top); + + week_starts[i*c.year_x+j] = (sd.getDay()-(this.config.start_on_monday?1:0)+7)%7; + sd = this.date.add(sd,1,"month"); + + } + this._els["dhx_cal_date"][0].innerHTML=this.templates[this._mode+"_date"](ssd,sd,this._mode); + this.week_starts = week_starts; + week_starts._month = ssd.getMonth(); + this._min_date = ssd; + this._max_date = sd; +} + +})(); diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ical.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ical.js new file mode 100644 index 00000000000..ab6fdb0101c --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/ical.js @@ -0,0 +1,65 @@ +scheduler.ical={ + parse:function(str){ + var data = str.match(RegExp(this.c_start+"[^\f]*"+this.c_end,"")); + if (!data.length) return; + + //unfolding + data[0]=data[0].replace(/[\r\n]+(?=[a-z \t])/g," "); + //drop property + data[0]=data[0].replace(/\;[^:\r\n]*/g,""); + + + var incoming=[]; + var match; + var event_r = RegExp("(?:"+this.e_start+")([^\f]*?)(?:"+this.e_end+")","g"); + while (match=event_r.exec(data)){ + var e={}; + var param; + var param_r = /[^\r\n]+[\r\n]+/g; + while (param=param_r.exec(match[1])) + this.parse_param(param.toString(),e); + if (e.uid && !e.id) e.id = e.uid; //fallback to UID, when ID is not defined + incoming.push(e); + } + return incoming; + }, + parse_param:function(str,obj){ + var d = str.indexOf(":"); + if (d==-1) return; + + var name = str.substr(0,d).toLowerCase(); + var value = str.substr(d+1).replace(/\\\,/g,",").replace(/[\r\n]+$/,""); + if (name=="summary") + name="text"; + else if (name=="dtstart"){ + name = "start_date"; + value = this.parse_date(value,0,0); + } + else if (name=="dtend"){ + name = "end_date"; + if (obj.start_date && obj.start_date.getHours()==0) + value = this.parse_date(value,24,00); + else + value = this.parse_date(value,23,59); + } + obj[name]=value; + }, + parse_date:function(value,dh,dm){ + var t = value.split("T"); + if (t[1]){ + dh=t[1].substr(0,2); + dm=t[1].substr(2,2); + } + var dy = t[0].substr(0,4); + var dn = parseInt(t[0].substr(4,2),10)-1; + var dd = t[0].substr(6,2); + if (scheduler.config.server_utc && !t[1]) { // if no hours/minutes were specified == full day event + return new Date(Date.UTC(dy,dn,dd,dh,dm)) ; + } + return new Date(dy,dn,dd,dh,dm); + }, + c_start:"BEGIN:VCALENDAR", + e_start:"BEGIN:VEVENT", + e_end:"END:VEVENT", + c_end:"END:VCALENDAR" +}; \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/layout.css b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/layout.css new file mode 100644 index 00000000000..4818d92db21 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/layout.css @@ -0,0 +1,179 @@ +.dhx_cal_container{ + background-color:#C2D5FC; + font-family:Tahoma; + font-size:8pt; + position:relative; + overflow:hidden; +} +.dhx_cal_container div{ + -moz-user-select:none; + -moz-user-select:-moz-none; +} +.dhx_cal_navline{ + height:20px; + position:absolute; + z-index:3; + width:750px; + color:#2F3A48; +} +.dhx_cal_navline div{ + position:absolute; + top:2px; + white-space:nowrap; +} +.dhx_cal_navline .dhx_cal_date{ + font-weight:600; + left:210px; +} +.dhx_cal_button .dhx_left_bg{ + width:1px; overflow:hidden; + height:17px; + z-index:20; + top:0px; +} +.dhx_cal_prev_button{ + background-image:url(imgs/buttons.png); + background-position:0px 0px; + width:29px; height:17px; + left:50px; cursor:pointer; +} +.dhx_cal_next_button{ + background-image:url(imgs/buttons.png); + background-position: -30px 0px; + width:29px; height:17px; + left:80px; cursor:pointer; +} +.dhx_cal_today_button{ + background-image:url(imgs/buttons.png); + background-position: -60px 0px; + width:75px; height:17px; + left:112px; cursor:pointer; + text-align:center; + text-decoration:underline; +} +.dhx_cal_tab{ + background-image:url(imgs/white_tab.png); + width:61px; height:19px; + text-align:center; + text-decoration:underline; + padding-top:3px; cursor:pointer; +} +.dhx_cal_tab.active{ + background-image:url(imgs/blue_tab.png); + text-decoration:none; + height:20px; + padding-top:2px; cursor:default; + font-weight:bold; +} +.dhx_cal_header{ + position:absolute; + left:10px; top:23px; + width:750px; + border-top:1px dotted #8894A3; + border-right:1px dotted #8894A3; + z-index:2; + overflow:hidden; + color:#2F3A48; +} +.dhx_cal_data{ + border-top:1px dotted #8894A3; + position:absolute; + top:44px; + width:600px; + overflow-y:auto; + overflow-x:hidden; +} +.dhx_scale_bar{ + position:absolute; + text-align:center; + background-color:#C2D5FC; + padding-top:3px; + border-left:1px dotted #586A7E; +} +.dhx_scale_holder{ + position:absolute; + border-right:1px dotted #586A7E; + background-image:url(imgs/databg.png); +} +.dhx_scale_holder_now{ + position:absolute; + border-right:1px dotted #586A7E; + background-image:url(imgs/databg_now.png); +} +.dhx_scale_hour{ + height:41px; + width:50px; + border-bottom:1px dotted #8894A3; + background-color:#C2D5FC; + text-align:center; + line-height:40px; + color:#586A7E; + overflow:hidden; +} +.dhx_month_head{ + background-color:#EBEFF4; + color:#2F3A48; + border-right:1px dotted #586A7E; + height:18px; + padding-right:5px; + padding-top:3px; + text-align:right; +} +.dhx_month_body{ + border-right:1px dotted #586A7E; + border-bottom:1px dotted #586A7E; + background-color:#FFFFFF; +} +.dhx_now .dhx_month_body{ + background-color:#E2EDFF; +} +.dhx_after .dhx_month_body, .dhx_before .dhx_month_body{ + background-color:#ECECEC; +} +.dhx_after .dhx_month_head, .dhx_before .dhx_month_head{ + background-color:#E2E3E6; + color:#94A6BB; +} +.dhx_now .dhx_month_head{ + background-color:#D1DEF4; + font-weight:bold; +} +.dhx_cal_drag{ + position:absolute; + z-index:9999; + background-color:#FFE763; + border:1px solid #B7A543; + opacity:0.5; + filter:alpha(opacity=50); +} +.dhx_loading{ + position:absolute; + width:128px; + height:15px; + background-image:url(imgs/loading.gif); + z-index:9999; +} +.dhx_multi_day_icon, .dhx_multi_day{ + position:absolute; + background-color:#E1E6FF; + background-repeat:no-repeat; + border-bottom:1px dotted #8894A3; + border-left:1px dotted #8894A3; +} +.dhx_multi_day_icon{ + background-image:url(imgs/clock_big.gif); +} +.dhx_multi_day_icon_small{ + background-image:url(imgs/clock_small.gif); +} +.dhx_multi_day_icon, .dhx_multi_day_icon_small{ + background-position: center center; + position:absolute; + background-color:#E1E6FF; + background-repeat:no-repeat; + border-bottom:1px dotted #8894A3; + border-left:1px dotted #8894A3; +} +.dhtmlxLayoutPolyContainer_dhx_skyblue .dhx_cal_container { + background-color: #d0e5ff; +} \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/lightbox.css b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/lightbox.css new file mode 100644 index 00000000000..5781bc3d3b5 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/lightbox.css @@ -0,0 +1,151 @@ + .dhx_cal_light{ + height:400px; + light:300px; + background-color:#FFE763; + + font-family:Tahoma; + font-size:8pt; + border:1px solid #B7A64B; + color:#887A2E; + + position:absolute; + z-index:10001; + + width:580px; + height:300px; + } + .dhx_mark{ + position:relative; top:3px; + background-image:url('./imgs/controls.gif'); + background-position: 0px -43px; + padding-left:10px; + } + .dhx_ie6 .dhx_mark{ + background-position: 6px -41px; + } + + .dhx_cal_light select{ + font-family:Tahoma; + font-size:8pt; + color:#887A2E; + padding:2px; + margin:0px; + } + .dhx_cal_ltitle{ + padding:2px 0px 2px 5px; + overflow:hidden; + white-space:nowrap; + } + .dhx_cal_ltitle span{ + white-space:nowrap; + } + .dhx_cal_lsection{ + background-color:#DBCF8C; + color:#FFF4B5; + font-size:18pt; + font-weight:bold; + padding:5px 0px 3px 10px; + } + .dhx_cal_ltext{ + padding:2px 0px 2px 10px; + height:130px; + height=140px; + overflow:hidden; + } + .dhx_cal_ltext textarea{ + background-color:transparent; + overflow:auto; + border:none; + color:#887A2E; + height:100%; + width:100%; + outline:none !important; + } + .dhx_time{ + font-weight:bold; + } + .dhx_cal_light .dhx_title{ + padding-left:10px; + } + .dhx_cal_larea{ + border:1px solid #DCC43E; + background-color:#FFF4B5; + overflow:hidden; + + margin-left:3px; + + width:572px; + height:1px; + } + .dhx_btn_set{ + padding:5px 10px 0px 10px; + float:left; + } + .dhx_btn_set div{ + float:left; + height:21px; + line-height:21px; + vertical-align:middle; + cursor:pointer; + } + .dhx_save_btn{ + background-image:url('./imgs/controls.gif'); + background-position:-84px 0px; + width:21px; + + } + .dhx_cancel_btn{ + background-image:url('./imgs/controls.gif'); + background-position:-63px 0px; + width:20px; + } + .dhx_delete_btn{ + background-image:url('./imgs/controls.gif'); + background-position:-42px 0px; + width:20px; + } + .dhx_cal_cover{ + width:100%; + height:100%; + position:absolute; + z-index:10000; + top:0px; + left:0px; + background-color:black; + + opacity:0.1; + filter:alpha(opacity=10); + } + .dhx_custom_button{ + padding:0px 3px 0px 3px; + color:#887A2E; + font-family:Tahoma; + font-size:8pt; + background-color:#FFE763; + font-weight:normal; + margin-right:5px; + margin-top:5px; + cursor:pointer; + } + .dhx_custom_button div{ + cursor:pointer; + float:left; + height:21px; + line-height:21px; + vertical-align:middle; + } + + .dhx_fullday_checkbox { + padding-top: 5px; + float:right; + } + + .dhx_fullday_checkbox input{ + vertical-align: middle; + } + + .dhx_fullday_checkbox label{ + font-size: 12pt; + font-weight: bold; + vertical-align: middle; + } \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/lightbox.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/lightbox.js new file mode 100644 index 00000000000..2a928a34831 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/lightbox.js @@ -0,0 +1,340 @@ +scheduler.form_blocks={ + textarea:{ + render:function(sns){ + var height=(sns.height||"130")+"px"; + return "
"; + }, + set_value:function(node,value,ev){ + node.firstChild.value=value||""; + }, + get_value:function(node,ev){ + return node.firstChild.value; + }, + focus:function(node){ + var a=node.firstChild; a.select(); a.focus(); + } + }, + select:{ + render:function(sns){ + var height=(sns.height||"23")+"px"; + var html="
"; + return html; + }, + set_value:function(node,value,ev){ + if (typeof value == "undefined") + value = (node.firstChild.options[0]||{}).value; + node.firstChild.value=value||""; + }, + get_value:function(node,ev){ + return node.firstChild.value; + }, + focus:function(node){ + var a=node.firstChild; if (a.select) a.select(); a.focus(); + } + }, + time:{ + render:function(){ + //hours + var cfg = scheduler.config; + var dt = this.date.date_part(new Date()); + var last = 24*60, first = 0; + if(scheduler.config.limit_time_select){ + last = 60*cfg.last_hour+1; + first = 60*cfg.first_hour; + dt.setHours(cfg.first_hour); + } + + var html=" "; + + return "
"+html+"  –  "+html+"
"; + + }, + set_value:function(node,value,ev){ + + var s=node.getElementsByTagName("select"); + + if(scheduler.config.full_day) { + if (!node._full_day){ + node.previousSibling.innerHTML+="
"; + node._full_day=true; + } + var input=node.previousSibling.getElementsByTagName("input")[0]; + var isFulldayEvent = (scheduler.date.time_part(ev.start_date)==0 && scheduler.date.time_part(ev.end_date)==0 && ev.end_date.valueOf()-ev.start_date.valueOf() < 2*24*60*60*1000); + input.checked = isFulldayEvent; + + for(var k in s) + s[k].disabled=input.checked; + + input.onclick = function(){ + if(input.checked) { + var start_date = new Date(ev.start_date); + var end_date = new Date(ev.end_date); + + scheduler.date.date_part(start_date); + end_date = scheduler.date.add(start_date, 1, "day") + } + for(var i in s) + s[i].disabled=input.checked; + + _fill_lightbox_select(s,0,start_date||ev.start_date); + _fill_lightbox_select(s,4,end_date||ev.end_date); + } + } + + if(scheduler.config.auto_end_date && scheduler.config.event_duration) { + function _update_lightbox_select() { + ev.start_date=new Date(s[3].value,s[2].value,s[1].value,0,s[0].value); + ev.end_date.setTime(ev.start_date.getTime() + (scheduler.config.event_duration * 60 * 1000)); + _fill_lightbox_select(s,4,ev.end_date); + } + for(var i=0; i<4; i++) { + s[i].onchange = _update_lightbox_select; + } + } + + function _fill_lightbox_select(s,i,d){ + s[i+0].value=Math.round((d.getHours()*60+d.getMinutes())/scheduler.config.time_step)*scheduler.config.time_step; + s[i+1].value=d.getDate(); + s[i+2].value=d.getMonth(); + s[i+3].value=d.getFullYear(); + } + + _fill_lightbox_select(s,0,ev.start_date); + _fill_lightbox_select(s,4,ev.end_date); + }, + get_value:function(node,ev){ + s=node.getElementsByTagName("select"); + ev.start_date=new Date(s[3].value,s[2].value,s[1].value,0,s[0].value); + ev.end_date=new Date(s[7].value,s[6].value,s[5].value,0,s[4].value); + if (ev.end_date<=ev.start_date) + ev.end_date=scheduler.date.add(ev.start_date,scheduler.config.time_step,"minute"); + }, + focus:function(node){ + node.getElementsByTagName("select")[0].focus(); + } + } +} +scheduler.showCover=function(box){ + this.show_cover(); + if (box){ + box.style.display="block"; + var pos = getOffset(this._obj); + box.style.top=Math.round(pos.top+(this._obj.offsetHeight-box.offsetHeight)/2)+"px"; + box.style.left=Math.round(pos.left+(this._obj.offsetWidth-box.offsetWidth)/2)+"px"; + } +} +scheduler.showLightbox=function(id){ + if (!id) return; + if (!this.callEvent("onBeforeLightbox",[id])) return; + var box = this._get_lightbox(); + this.showCover(box); + this._fill_lightbox(id,box); + this.callEvent("onLightbox",[id]); +} +scheduler._fill_lightbox=function(id,box){ + var ev=this.getEvent(id); + var s=box.getElementsByTagName("span"); + if (scheduler.templates.lightbox_header){ + s[1].innerHTML=""; + s[2].innerHTML=scheduler.templates.lightbox_header(ev.start_date,ev.end_date,ev); + } else { + s[1].innerHTML=this.templates.event_header(ev.start_date,ev.end_date,ev); + s[2].innerHTML=(this.templates.event_bar_text(ev.start_date,ev.end_date,ev)||"").substr(0,70); //IE6 fix + } + + + var sns = this.config.lightbox.sections; + for (var i=0; i < sns.length; i++) { + var node=document.getElementById(sns[i].id).nextSibling; + var block=this.form_blocks[sns[i].type]; + block.set_value.call(this,node,ev[sns[i].map_to],ev, sns[i]) + if (sns[i].focus) + block.focus.call(this,node); + }; + + scheduler._lightbox_id=id; +} +scheduler._lightbox_out=function(ev){ + var sns = this.config.lightbox.sections; + for (var i=0; i < sns.length; i++) { + var node=document.getElementById(sns[i].id).nextSibling; + var block=this.form_blocks[sns[i].type]; + var res=block.get_value.call(this,node,ev, sns[i]); + if (sns[i].map_to!="auto") + ev[sns[i].map_to]=res; + } + return ev; +} +scheduler._empty_lightbox=function(){ + var id=scheduler._lightbox_id; + var ev=this.getEvent(id); + var box=this._get_lightbox(); + + this._lightbox_out(ev); + + ev._timed=this.is_one_day_event(ev); + this.setEvent(ev.id,ev); + this._edit_stop_event(ev,true) + this.render_view_data(); +} +scheduler.hide_lightbox=function(id){ + this.hideCover(this._get_lightbox()); + this._lightbox_id=null; + this.callEvent("onAfterLightbox",[]); +} +scheduler.hideCover=function(box){ + if (box) box.style.display="none"; + this.hide_cover(); +} +scheduler.hide_cover=function(){ + if (this._cover) + this._cover.parentNode.removeChild(this._cover); + this._cover=null; +} +scheduler.show_cover=function(){ + this._cover=document.createElement("DIV"); + this._cover.className="dhx_cal_cover"; + document.body.appendChild(this._cover); +} +scheduler.save_lightbox=function(){ + if (this.checkEvent("onEventSave") && !this.callEvent("onEventSave",[this._lightbox_id,this._lightbox_out({ id: this._lightbox_id}), this._new_event])) + return; + this._empty_lightbox() + this.hide_lightbox(); +}; +scheduler.startLightbox = function(id, box){ + this._lightbox_id=id; + this.showCover(box); +} +scheduler.endLightbox = function(mode, box){ + this._edit_stop_event(scheduler.getEvent(this._lightbox_id),mode); + if (mode) + scheduler.render_view_data(); + this.hideCover(box); +}; +scheduler.resetLightbox = function(){ + scheduler._lightbox = null; +}; +scheduler.cancel_lightbox=function(){ + this.callEvent("onEventCancel",[this._lightbox_id, this._new_event]); + this.endLightbox(false); + this.hide_lightbox(); +}; +scheduler._init_lightbox_events=function(){ + this._get_lightbox().onclick=function(e){ + var src=e?e.target:event.srcElement; + if (!src.className) src=src.previousSibling; + if (src && src.className) + switch(src.className){ + case "dhx_save_btn": + scheduler.save_lightbox(); + break; + case "dhx_delete_btn": + var c=scheduler.locale.labels.confirm_deleting; + if (!c||confirm(c)) { + scheduler.deleteEvent(scheduler._lightbox_id); + scheduler._new_event = null; //clear flag, if it was unsaved event + scheduler.hide_lightbox(); + } + break; + case "dhx_cancel_btn": + scheduler.cancel_lightbox(); + break; + + default: + if (src.className.indexOf("dhx_custom_button_")!=-1){ + var index = src.parentNode.getAttribute("index"); + var block=scheduler.form_blocks[scheduler.config.lightbox.sections[index].type]; + var sec = src.parentNode.parentNode; + block.button_click(index,src,sec,sec.nextSibling); + } + } + }; + this._get_lightbox().onkeypress=function(e){ + switch((e||event).keyCode){ + case scheduler.keys.edit_save: + if ((e||event).shiftKey) return; + scheduler.save_lightbox(); + break; + case scheduler.keys.edit_cancel: + scheduler.cancel_lightbox(); + break; + } + } +} +scheduler.setLightboxSize=function(){ + var d = this._lightbox; + if (!d) return; + + var con = d.childNodes[1]; + con.style.height="0px"; + con.style.height=con.scrollHeight+"px"; + d.style.height=con.scrollHeight+50+"px"; + con.style.height=con.scrollHeight+"px"; //it is incredible , how ugly IE can be +} + +scheduler._get_lightbox=function(){ + if (!this._lightbox){ + var d=document.createElement("DIV"); + d.className="dhx_cal_light"; + if (/msie|MSIE 6/.test(navigator.userAgent)) + d.className+=" dhx_ie6"; + d.style.visibility="hidden"; + d.innerHTML=this._lightbox_template; + document.body.insertBefore(d,document.body.firstChild); + this._lightbox=d; + + var sns=this.config.lightbox.sections; + var html=""; + for (var i=0; i < sns.length; i++) { + var block=this.form_blocks[sns[i].type]; + if (!block) continue; //ignore incorrect blocks + sns[i].id="area_"+this.uid(); + var button = ""; + if (sns[i].button) button = "
"+this.locale.labels["button_"+sns[i].button]+"
"; + html+="
"+button+this.locale.labels["section_"+sns[i].name]+"
"+block.render.call(this,sns[i]); + }; + + + //localization + var ds=d.getElementsByTagName("div"); + ds[4].innerHTML=scheduler.locale.labels.icon_save; + ds[7].innerHTML=scheduler.locale.labels.icon_cancel; + ds[10].innerHTML=scheduler.locale.labels.icon_delete; + //sections + ds[1].innerHTML=html; + //sizes + this.setLightboxSize(); + + this._init_lightbox_events(this); + d.style.display="none"; + d.style.visibility="visible"; + } + return this._lightbox; +} +scheduler._lightbox_template="
 
 
 
 
"; \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/load.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/load.js new file mode 100644 index 00000000000..cb81b4ee2ee --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/load.js @@ -0,0 +1,184 @@ +scheduler._loaded={}; +scheduler._load=function(url,from){ + url=url||this._load_url; + url+=(url.indexOf("?")==-1?"?":"&")+"timeshift="+(new Date()).getTimezoneOffset(); + if (this.config.prevent_cache) url+="&uid="+this.uid(); + var to; + from=from||this._date; + + if (this._load_mode){ + var lf = this.templates.load_format; + + from = this.date[this._load_mode+"_start"](new Date(from.valueOf())); + while (from>this._min_date) from=this.date.add(from,-1,this._load_mode); + to = from; + + var cache_line = true; + while (tofrom && this._loaded[lf(temp_to)]); + + if (to<=from) + return false; //already loaded + dhtmlxAjax.get(url+"&from="+lf(from)+"&to="+lf(to),function(l){scheduler.on_load(l);}); + while(from


числа кожний місяць
кожен місяць

повторень

'; + diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/locale_ru.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/locale_ru.js new file mode 100644 index 00000000000..485cd795488 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/locale_ru.js @@ -0,0 +1,38 @@ +scheduler.locale={ + date:{ + month_full:["Январь", "Февраль", "Март", "Апрель", "Maй", "Июнь", "Июль", "Август", "Сентябрь", "Oктябрь", "Ноябрь", "Декабрь"], + month_short:["Янв", "Фев", "Maр", "Aпр", "Maй", "Июн", "Июл", "Aвг", "Сен", "Окт", "Ноя", "Дек"], + day_full:[ "Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота"], + day_short:["Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"] + }, + labels:{ + dhx_cal_today_button: "Сегодня", + day_tab:"День", + week_tab:"Неделя", + month_tab:"Месяц", + new_event:"Новое событие", + icon_save:"Сохранить", + icon_cancel:"Отменить", + icon_details:"Детали", + icon_edit:"Изменить", + icon_delete:"Удалить", + confirm_closing:"",//Ваши изменения будут потеряны, продолжить? + confirm_deleting:"Событие будет удалено безвозвратно, продолжить?", + section_description:"Описание", + section_time:"Период времени", + full_day:"Весь день", + + confirm_recurring:"Вы хотите изменить всю серию повторяющихся событий?", + section_recurring:"Повторение", + button_recurring:"Отключено", + button_recurring_open:"Включено", + + /*agenda view extension*/ + agenda_tab:"Список", + date:"Дата", + description:"Описание", + + /*year view extension*/ + year_tab:"Год" + } +} diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/locale_si.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/locale_si.js new file mode 100644 index 00000000000..29da1a35bc0 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/locale_si.js @@ -0,0 +1,40 @@ +scheduler.locale={ + date:{ + month_full:["Januar", "Februar", "Marec", "April", "Maj", "Junij", "Julij", "Avgust", "September", "Oktober", "November", "December"], + month_short:["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"], + day_full:["Nedelja", "Ponedeljek", "Torek", "Sreda", "Èetrtek", "Petek", "Sobota"], + day_short:["Ne", "Po", "To", "Sre", "Èe", "Pe", "So"] + }, + labels:{ + dhx_cal_today_button:"Danes", + day_tab:"Dan", + week_tab:"Teden", + month_tab:"Mesec", + new_event:"Nov dogodek", + icon_save:"Shrani", + icon_cancel:"Preklièi", + icon_details:"Podrobnosti", + icon_edit:"Uredi", + icon_delete:"Zbriši", + confirm_closing:"",//Vaše spremembe bodo izgubljene, želite nadaljevati ? + confirm_deleting:"Dogodek bo izbrisan trajno, želite nadaljevati?", + section_description:"Opis", + section_time:"Èasovno obdobje", + full_day:"Ves dan", + + /*recurring events*/ + confirm_recurring:"Ali želite urediti celoten nabor ponavljajoèih dogodkov?", + section_recurring:"Ponovi dogodek", + button_recurring:"Onemogoèi", + button_recurring_open:"Omogoèi", + + /*agenda view extension*/ + agenda_tab:"Agenda", + date:"Datum", + description:"Opis", + + /*year view extension*/ + year_tab:"Leto" + } +} + diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/locale_sv.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/locale_sv.js new file mode 100644 index 00000000000..76bf908acec --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/locale_sv.js @@ -0,0 +1,45 @@ +/* +Copyright DHTMLX LTD. http://www.dhtmlx.com +You allowed to use this component or parts of it under GPL terms +To use it on other terms please contact us at sales@dhtmlx.com +*/ + +scheduler.locale={ + date:{ + month_full:["Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December"], + month_short:["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], + day_full:["Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag"], + day_short:["Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör"] + }, + labels:{ + dhx_cal_today_button:"Idag", + day_tab:"Dag", + week_tab:"Vecka", + month_tab:"Månad", + new_event:"Ny händelse", + icon_save:"Spara", + icon_cancel:"Ångra", + icon_details:"Detajer", + icon_edit:"Ändra", + icon_delete:"Ta bort", + confirm_closing:"",//Dina förändingar kommer gå förlorade, är du säker? + confirm_deleting:"Är du säker på att du vill ta bort händelsen permanent?", + section_description:"Beskrivning", + section_time:"Tid", + full_day:"Hela dagen", + + /*recurring events*/ + confirm_recurring:"Vill du redigera hela serien med repeterande händelser?", + section_recurring:"Upprepa händelse", + button_recurring:"Inaktiverat", + button_recurring_open:"Aktiverat", + + /*agenda view extension*/ + agenda_tab:"Dagordning", + date:"Datum", + description:"Beskrivning", + + /*year view extension*/ + year_tab:"År" + } +} \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/locale_ua.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/locale_ua.js new file mode 100644 index 00000000000..a7c946159e1 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/locale_ua.js @@ -0,0 +1,40 @@ +scheduler.locale={ + date:{ + month_full:["Січень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "Вересень", "Жовтень", "Листопад", "Грудень"], + month_short:["Січ", "Лют", "Бер", "Кві", "Тра", "Чер", "Лип", "Сер", "Вер", "Жов", "Лис", "Гру"], + day_full:["Неділя", "Понеділок", "Вівторок", "Середа", "Четвер", "П'ятниця", "Субота"], + day_short:["Нед", "Пон", "Вів", "Сер", "Чет", "Птн", "Суб"] + }, + labels:{ + dhx_cal_today_button:"Сьогодні", + day_tab:"День", + week_tab:"Тиждень", + month_tab:"Місяць", + new_event:"Нова подія", + icon_save:"Зберегти", + icon_cancel:"Відміна", + icon_details:"Деталі", + icon_edit:"Редагувати", + icon_delete:"Вилучити", + confirm_closing:"",//Ваші зміни втратяться. Ви впевнені ? + confirm_deleting:"Подія вилучиться назавжди. Ви впевнені?", + section_description:"Опис", + section_time:"Часовий проміжок", + full_day:"Весь день", + + /*recurring events*/ + confirm_recurring:"Хочете редагувати весь перелік повторюваних подій?", + section_recurring:"Повторювана подія", + button_recurring:"Відключено", + button_recurring_open:"Включено", + + /*agenda view extension*/ + agenda_tab:"Перелік", + date:"Дата", + description:"Опис", + + /*year view extension*/ + year_tab:"Рік" + } +} + diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/note.css b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/note.css new file mode 100644 index 00000000000..e1ebfed7378 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/note.css @@ -0,0 +1,115 @@ +.dhx_cal_event div{ + background-color:#FFE763; + border:1px solid #B7A543; + color:#887A2E; + overflow:hidden; + width:100%; + + font-family:Tahoma; + font-size:8pt; +} +.dhx_move_denied .dhx_cal_event .dhx_header, .dhx_move_denied .dhx_cal_event .dhx_title{ + cursor:default; +} +.dhx_cal_event .dhx_header{ + height:1px; + margin-left:1px; + border-width:1px 1px 0px 1px; + cursor:pointer; +} +.dhx_cal_event .dhx_title{ + height:12px; + border-width:0px 1px 1px 1px; + border-bottom-style:dotted; + + font-size:7pt; + font-weight:bold; + text-align:center; + + background-position:right; + background-repeat:no-repeat; + cursor:pointer; +} +.dhx_cal_event .dhx_body{ + border-width:0px 1px 1px 1px; + padding:5px; +} +.dhx_resize_denied .dhx_cal_event .dhx_footer{ + cursor:default; +} +.dhx_cal_event .dhx_footer{ + height:1px; + margin-left:2px; + border-width:0px 1px 1px 1px; + cursor:s-resize; +} +.dhx_cal_event_line{ + background-color:#FFE763; + border:1px solid #B7A543; + font-family:Tahoma; + font-size:8pt; + height:13px; + padding-left:10px; + color:#887A2E; + cursor:pointer; + overflow:hidden; +} +.dhx_cal_event_clear{ + font-family:Tahoma; + font-size:8pt; + height:13px; + padding-left:2px; + color:#887A2E; + white-space:nowrap; + overflow:hidden; + cursor:pointer; +} +.dhx_in_move{ + background-color:#FFFF80; +} +div.dhx_cal_editor{ + background-color:#FFE763; + border:1px solid #B7A543; + border-top-style:dotted; + z-index:999; + position:absolute; + overflow:hidden; +} +textarea.dhx_cal_editor{ + width:100%; + height:100%; + border:0px solid black; + margin:none; + padding:none; + overflow:auto; +} +div.dhx_menu_head{ + background-image:url(imgs/controls.gif); + background-position: 0px -43px; + width:10px; height:10px; + margin-left:5px; margin-top:1px; + border:none; + cursor:default; +} +div.dhx_menu_icon{ + background-image:url(imgs/controls.gif); + width:20px; height:20px; + margin-left:-5px; margin-top:0px; + border:none; + cursor:pointer; +} +div.icon_details{ + background-position: 0px 0px; +} +div.icon_edit{ + background-position: -22px 0px; +} +div.icon_save{ + background-position: -84px -1px; +} +div.icon_cancel{ + background-position: -62px 0px; +} +div.icon_delete{ + background-position: -42px 0px; +} \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/property.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/property.js new file mode 100644 index 00000000000..ee9a59d2222 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/property.js @@ -0,0 +1,175 @@ +scheduler._props = {}; +scheduler.createUnitsView=function(name,property,list,size,step){ + if (typeof name == "object"){ + list = name.list; + property = name.property; + size = name.size||0; + step = name.step||1; + name = name.name; + } + scheduler.date[name+"_start"]= scheduler.date.day_start; + scheduler.templates[name+"_date"] = function(date){ + return scheduler.templates.day_date(date); + } + scheduler.templates[name+"_scale_date"] = function(date){ + if (!list.length) return ""; + var index = (scheduler._props[name].position||0)+Math.floor((scheduler._correct_shift(date.valueOf(),1)-scheduler._min_date.valueOf())/(60*60*24*1000)); + if (list[index].css) + return ""+list[index].label+""; + else + return list[index].label; + } + scheduler.date["add_"+name]=function(date,inc){ return scheduler.date.add(date,inc,"day"); } + scheduler.date["get_"+name+"_end"]=function(date){ return scheduler.date.add(date,size||list.length,"day"); } + + scheduler._props[name]={map_to:property, options:list, size:size, step:step, position:0 }; + + scheduler.attachEvent("onOptionsLoad",function(){ + var order = scheduler._props[name].order = {}; + for(var i=0; i= pr.size+pr.position ) + return false; + } + } + return res; + } + + scheduler._reset_scale = function(){ + var pr = scheduler._props[this._mode]; + var ret = t.apply(this,arguments); + if (pr){ + this._max_date=this.date.add(this._min_date,1,"day"); + + var d = this._els["dhx_cal_data"][0].childNodes; + for (var i=0; i < d.length; i++) + d[i].className = d[i].className.replace("_now",""); //clear now class + + if (pr.size && pr.size < pr.options.length){ + + var h = this._els["dhx_cal_header"][0]; + var arrow = document.createElement("DIV"); + if (pr.position){ + arrow.className = "dhx_cal_prev_button"; + arrow.style.cssText="left:1px;top:2px;position:absolute;" + arrow.innerHTML = " " + h.firstChild.appendChild(arrow); + arrow.onclick=function(){ + scheduler.scrollUnit(pr.step*-1); + } + } + if (pr.position+pr.sizepr.order[b[pr.map_to]]?1:-1; + }); + } else + o.apply(this,arguments); + } + + scheduler.attachEvent("onEventAdded",function(id,ev){ + if (this._loading) return true; + for (var a in scheduler._props){ + var pr = scheduler._props[a]; + if (typeof ev[pr.map_to] == "undefined") + ev[pr.map_to] = pr.options[0].key; + } + return true; + }) + scheduler.attachEvent("onEventCreated",function(id,n_ev){ + var pr = scheduler._props[this._mode]; + if (pr){ + var ev = this.getEvent(id); + this._mouse_coords(n_ev); + fix_und(pr,ev); + this.event_updated(ev); + } + return true; + }) + +})(); \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/recurring.css b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/recurring.css new file mode 100644 index 00000000000..ed4755f0892 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/recurring.css @@ -0,0 +1,111 @@ +/*IE*/ +div input.radio { margin:-4px 0 0 -4px !ie; } +div input.checkbox { margin:0 0 0 -4px !ie; } + +/*All*/ +.dhx_form_repeat, .dhx_form_repeat input { + padding:0; + margin:0; + font-family:Tahoma, Verdana; + font-size:11px; + line-height:24px; +} + +.dhx_form_repeat { + overflow:hidden; + /*height:115px;*/ + height:0px; + background-color: #FFF4B5; + /*border: 1px solid #DCC43E;*/ +} + + +.dhx_repeat_center, .dhx_repeat_left{ + height:115px; + padding:10px 0 10px 10px; + float:left; +} + +.dhx_repeat_left{ + width:95px; +} + +.dhx_repeat_center{ + width:335px; + margin-top:12px; +} + +.dhx_repeat_divider{ + float:left; + height:115px; + border-left:1px dotted #DCC43E; + /*background-color: #DCC43E;*/ + width:1px; +} + +.dhx_repeat_right { + float:right; + height:115px; + width:160px; + padding:10px 3px 10px 10px; + margin-top:7px; +} + +input.dhx_repeat_text { + height:16px; + width: 27px; + margin: 0 4px 0 4px; + line-height:18px; + padding: 0 0 0 2px; +} + +.dhx_form_repeat select { + height: 20px; + width: 87px; + padding:0 0 0 2px; + margin: 0 4px 0 4px; +} + +input.dhx_repeat_date{ + height: 18px; + width: 80px; + padding:0 0 0 2px; + margin: 0 4px 0 4px; + background-repeat:no-repeat; + background-position:64px 0; + border:1px #7f9db9 solid; + line-height:18px; +} + +input.dhx_repeat_radio { + margin-right:4px; +} + +input.dhx_repeat_checkbox { + margin:4px 4px 0 0; +} + +.dhx_repeat_days td { + padding-right:5px; +} + +.dhx_repeat_days label { + font-size:10px; +} + +.dhx_custom_button_recurring{ + background-image:url(imgs/but_repeat.gif); + background-position:-5px 20px; + width:20px; + margin-right:10px; +} +.dhx_custom_button{ + width:90px; +} +/* increase width of lightbox */ +.dhx_cal_light{ + width:640px; +} +.dhx_cal_larea{ + width:632px; +} \ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/recurring.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/recurring.js new file mode 100644 index 00000000000..938226c9fb4 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/recurring.js @@ -0,0 +1,596 @@ +scheduler.form_blocks["recurring"]={ + render:function(sns){ + return scheduler.__recurring_template; + }, + set_value:function(node,value,ev){ + var ds = {start:ev.start_date, end:ev._end_date}; + var str_date=scheduler.date.str_to_date(scheduler.config.repeat_date); + var date_str=scheduler.date.date_to_str(scheduler.config.repeat_date); + + var top = node.getElementsByTagName("FORM")[0]; + var els = []; + function register_els(inps){ + for (var i=0; icday) + return sd.setDate(sd.getDate()+list[i]*1-cday-(size?cor:cor2)); + } + this.transpose_day_week(sd,list,cor+size,null,cor); +}; +scheduler.transpose_type = function(type){ + var f = "transpose_"+type; + if (!this.date[f]) { + var str = type.split("_"); + var day = 60*60*24*1000; + var gf = "add_"+type; + var step = this.transponse_size[str[0]]*str[1]; + + if (str[0]=="day" || str[0]=="week"){ + var days = null; + if (str[4]){ + days=str[4].split(","); + if (scheduler.config.start_on_monday){ + for (var i=0; i < days.length; i++) + days[i]=(days[i]*1)||7; + days.sort(); + } + } + + + this.date[f] = function(nd,td){ + var delta = Math.floor((td.valueOf()-nd.valueOf())/(day*step)); + if (delta>0) + nd.setDate(nd.getDate()+delta*step); + if (days) + scheduler.transpose_day_week(nd,days,1,step); + }; + this.date[gf] = function(sd,inc){ + var nd = new Date(sd.valueOf()); + if (days){ + for (var count=0; count < inc; count++) + scheduler.transpose_day_week(nd,days,0,step); + } else + nd.setDate(nd.getDate()+inc*step); + + return nd; + }; + } + else if (str[0]=="month" || str[0]=="year"){ + this.date[f] = function(nd,td){ + var delta = Math.ceil(((td.getFullYear()*12+td.getMonth()*1)-(nd.getFullYear()*12+nd.getMonth()*1))/(step)); + if (delta>=0) + nd.setMonth(nd.getMonth()+delta*step); + if (str[3]) + scheduler.date.day_week(nd,str[2],str[3]); + }; + this.date[gf] = function(sd,inc){ + var nd = new Date(sd.valueOf()); + nd.setMonth(nd.getMonth()+inc*step); + if (str[3]) + scheduler.date.day_week(nd,str[2],str[3]); + return nd; + }; + } + } +}; +scheduler.repeat_date=function(ev,stack,non_render,from,to){ + from = from||this._min_date; + to = to||this._max_date; + + var td = new Date(ev.start_date.valueOf()); + if (!ev.rec_pattern && ev.rec_type) + ev.rec_pattern = ev.rec_type.split("#")[0]; + + this.transpose_type(ev.rec_pattern); + scheduler.date["transpose_"+ev.rec_pattern](td, from); + while (td0) + copy.end_date = new Date(td.valueOf()+ev.event_length*1000-shift*60*1000); + else { + copy.end_date = new Date(copy.end_date.valueOf() + shift*60*1000); + } + } + + copy._timed=this.is_one_day_event(copy); + + if (!copy._timed && !this._table_view && !this.config.multi_day) return; + stack.push(copy); + + if(!non_render){ + this._events[copy.id] = copy; + this._rec_temp.push(copy); + } + + } else + if (non_render) stack.push(ch); + + td = this.date.add(td,1,ev.rec_pattern); + } +}; + +scheduler.getRecDates = function(id, max){ + var ev = typeof id == "object" ? id : scheduler.getEvent(id); + var count = 0; + var result = []; + max = max || 1000; + + + var td = new Date(ev.start_date.valueOf()); + var from = new Date(td.valueOf()); + + if(!ev.rec_type) { + return [ { start_date: ev.start_date, end_date: ev.end_date } ]; + } + this.transpose_type(ev.rec_pattern); + scheduler.date["transpose_"+ev.rec_pattern](td, from); + + while (tdfrom){ + if (ev.rec_pattern){ + if (ev.rec_pattern=="none") continue; + var sev = []; + this.repeat_date(ev,sev,true,from,to); + for (var i=0; i < sev.length; i++) + if (!sev[i].rec_pattern && sev[i].start_datefrom) + result.push(sev[i]); + } else if (!ev.event_pid || ev.event_pid==0){ + result.push(ev); + } + } + } + return result; +}; + +scheduler.config.repeat_date="%m.%d.%Y"; +scheduler.config.lightbox.sections=[ + {name:"description", height:130, map_to:"text", type:"textarea" , focus:true}, + {name:"recurring", height:115, type:"recurring", map_to:"rec_type", button:"recurring"}, + {name:"time", height:72, type:"time", map_to:"auto"} +]; +//drop secondary attributes +scheduler._copy_dummy=function(ev){ + this.start_date=new Date(this.start_date); + this.end_date=new Date(this.end_date); + this.event_length=this.event_pid=this.rec_pattern=this.rec_type=this._timed=null; +}; diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template.html b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template.html new file mode 100644 index 00000000000..3d351383fc9 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template.html @@ -0,0 +1,57 @@ +
+
+
+
+
+
+ +
+
+
+ + +
+ day everymonth
+ everymonth
+
+ +
+
+
+
+ occurrences
+
+
+
+
+
+
\ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_cn.html b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_cn.html new file mode 100644 index 00000000000..222bb5f6e6c --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_cn.html @@ -0,0 +1,57 @@ +
+
+
+
+
+
+ +
+
+
+ + +
+ 日 每月
+ 每月
+
+ +
+
+
+
+ 次结束
+
+
+
+
+
+
\ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_de.html b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_de.html new file mode 100644 index 00000000000..ae9dbb3cabf --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_de.html @@ -0,0 +1,60 @@ +
+
+
+
+
+
+ +
+
+
+ + +
+ + Tag eines jedenMonats
+ jedenMonats
+
+ +
+
+
+
+ Ereignissen
+
+
+
+
+
+
\ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_es.html b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_es.html new file mode 100644 index 00000000000..bcfcf2e81ea --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_es.html @@ -0,0 +1,57 @@ +
+
+
+
+
+
+ +
+
+
+ + +
+ dia cada mes
+ cadames
+
+ +
+
+
+
+ occurencias
+
+
+
+
+
+
\ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_fr.html b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_fr.html new file mode 100644 index 00000000000..65313e6314b --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_fr.html @@ -0,0 +1,57 @@ +
+
+
+
+
+
+ +
+
+
+ + +
+ jour chaquemois
+ chaquemois
+
+ +
+
+
+
+ occurrences
+
+
+
+
+
+
\ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_it.html b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_it.html new file mode 100644 index 00000000000..e55c7ebc2bc --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_it.html @@ -0,0 +1,57 @@ +
+
+
+
+
+
+ +
+
+
+ + +
+ giorno ognimese
+ ognimese
+
+ +
+
+
+
+ occorenze
+
+
+
+
+
+
\ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_nl.html b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_nl.html new file mode 100644 index 00000000000..14f32c7f2ef --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_nl.html @@ -0,0 +1,65 @@ +
+
+
+
+
+
+ +
+
+
+ + +
+ dag iederemaanden
+ iederemaanden
+
+ +
+
+
+
+ keren
+
+
+
+
+
+
diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_ru.html b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_ru.html new file mode 100644 index 00000000000..6b521212eb0 --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/repeat_template_ru.html @@ -0,0 +1,57 @@ +
+
+
+
+
+
+ +
+
+
+ + +
+ числа каждый месяц
+ каждый месяц
+
+ +
+
+
+
+ повторений
+
+
+
+
+
+
\ No newline at end of file diff --git a/addons/base_calendar/static/lib/dhtmlxScheduler/sources/scheduler.js b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/scheduler.js new file mode 100644 index 00000000000..b14592a050b --- /dev/null +++ b/addons/base_calendar/static/lib/dhtmlxScheduler/sources/scheduler.js @@ -0,0 +1,642 @@ +window.dhtmlXScheduler=window.scheduler={version:2.2}; +dhtmlxEventable(scheduler); +scheduler.init=function(id,date,mode){ + date=date||(new Date()); + mode=mode||"week"; + + this._obj=(typeof id == "string")?document.getElementById(id):id; + this._els=[]; + this._scroll=true; + this._quirks=(_isIE && document.compatMode == "BackCompat"); + this._quirks7=(_isIE && navigator.appVersion.indexOf("MSIE 8")==-1); + + this.get_elements(); + this.init_templates(); + this.set_actions(); + dhtmlxEvent(window,"resize",function(){ + window.clearTimeout(scheduler._resize_timer); + scheduler._resize_timer=window.setTimeout(function(){ + if (scheduler.callEvent("onSchedulerResize",[])) + scheduler.update_view(); + }, 100); + }) + + this.set_sizes(); + this.setCurrentView(date,mode); +}; +scheduler.xy={ + nav_height:22, + min_event_height:40, + scale_width:50, + bar_height:20, + scroll_width:18, + scale_height:20, + month_scale_height:20, + menu_width:25, + margin_top:0, + margin_left:0, + editor_width:140 +}; +scheduler.keys={ + edit_save:13, + edit_cancel:27 +}; +scheduler.set_sizes=function(){ + var w = this._x = this._obj.clientWidth-this.xy.margin_left; + var h = this._y = this._obj.clientHeight-this.xy.margin_top; + + //not-table mode always has scroll - need to be fixed in future + var scale_x=this._table_view?0:(this.xy.scale_width+this.xy.scroll_width); + var scale_s=this._table_view?-1:this.xy.scale_width; + + this.set_xy(this._els["dhx_cal_navline"][0],w,this.xy.nav_height,0,0); + this.set_xy(this._els["dhx_cal_header"][0],w-scale_x,this.xy.scale_height,scale_s,this.xy.nav_height+(this._quirks?-1:1)); + //to support alter-skin, we need a way to alter height directly from css + var actual_height = this._els["dhx_cal_navline"][0].offsetHeight; + if (actual_height > 0) this.xy.nav_height = actual_height; + + var data_y=this.xy.scale_height+this.xy.nav_height+(this._quirks?-2:0); + this.set_xy(this._els["dhx_cal_data"][0],w,h-(data_y+2),0,data_y+2); +} +scheduler.set_xy=function(node,w,h,x,y){ + node.style.width=Math.max(0,w)+"px"; + node.style.height=Math.max(0,h)+"px"; + if (arguments.length>3){ + node.style.left=x+"px"; + node.style.top=y+"px"; + } +} +scheduler.get_elements=function(){ + //get all child elements as named hash + var els=this._obj.getElementsByTagName("DIV"); + for (var i=0; i < els.length; i++){ + var name=els[i].className; + if (!this._els[name]) this._els[name]=[]; + this._els[name].push(els[i]); + + //check if name need to be changed + var t=scheduler.locale.labels[els[i].getAttribute("name")||name]; + if (t) els[i].innerHTML=t; + } +} +scheduler.set_actions=function(){ + for (var a in this._els) + if (this._click[a]) + for (var i=0; i < this._els[a].length; i++) + this._els[a][i].onclick=scheduler._click[a]; + this._obj.onselectstart=function(e){ return false; } + this._obj.onmousemove=function(e){ + scheduler._on_mouse_move(e||event); + } + this._obj.onmousedown=function(e){ + scheduler._on_mouse_down(e||event); + } + this._obj.onmouseup=function(e){ + scheduler._on_mouse_up(e||event); + } + this._obj.ondblclick=function(e){ + scheduler._on_dbl_click(e||event); + } +} +scheduler.select=function(id){ + if (this._table_view || !this.getEvent(id)._timed) return; //temporary block + if (this._select_id==id) return; + this.editStop(false); + this.unselect(); + this._select_id = id; + this.updateEvent(id); +} +scheduler.unselect=function(id){ + if (id && id!=this._select_id) return; + var t=this._select_id; + this._select_id = null; + if (t) this.updateEvent(t); +} +scheduler.getState=function(){ + return { + mode: this._mode, + date: this._date, + min_date: this._min_date, + max_date: this._max_date, + editor_id: this._edit_id, + lightbox_id: this._lightbox_id + }; +} +scheduler._click={ + dhx_cal_data:function(e){ + var trg = e?e.target:event.srcElement; + var id = scheduler._locate_event(trg); + + e = e || event; + if ((id && !scheduler.callEvent("onClick",[id,e])) ||scheduler.config.readonly) return; + + if (id) { + scheduler.select(id); + var mask = trg.className; + if (mask.indexOf("_icon")!=-1) + scheduler._click.buttons[mask.split(" ")[1].replace("icon_","")](id); + } else + scheduler._close_not_saved(); + }, + dhx_cal_prev_button:function(){ + scheduler._click.dhx_cal_next_button(0,-1); + }, + dhx_cal_next_button:function(dummy,step){ + scheduler.setCurrentView(scheduler.date.add( //next line changes scheduler._date , but seems it has not side-effects + scheduler.date[scheduler._mode+"_start"](scheduler._date),(step||1),scheduler._mode)); + }, + dhx_cal_today_button:function(){ + scheduler.setCurrentView(new Date()); + }, + dhx_cal_tab:function(){ + var mode = this.getAttribute("name").split("_")[0]; + scheduler.setCurrentView(scheduler._date,mode); + }, + buttons:{ + "delete":function(id){ var c=scheduler.locale.labels.confirm_deleting; if (!c||confirm(c)) scheduler.deleteEvent(id); }, + edit:function(id){ scheduler.edit(id); }, + save:function(id){ scheduler.editStop(true); }, + details:function(id){ scheduler.showLightbox(id); }, + cancel:function(id){ scheduler.editStop(false); } + } +} + +scheduler.addEventNow=function(start,end,e){ + var base = {}; + if (typeof start == "object"){ + base = start; + start = null; + } + + var d = (this.config.event_duration||this.config.time_step)*60000; + if (!start) start = Math.round((new Date()).valueOf()/d)*d; + var start_date = new Date(start); + if (!end){ + var start_hour = this.config.first_hour; + if (start_hour > start_date.getHours()){ + start_date.setHours(start_hour); + start = start_date.valueOf(); + } + end = start+d; + } + + + base.start_date = base.start_date||start_date; + base.end_date = base.end_date||new Date(end); + base.text = base.text||this.locale.labels.new_event; + base.id = this._drag_id = this.uid(); + this._drag_mode="new-size"; + + this._loading=true; + this.addEvent(base); + this.callEvent("onEventCreated",[this._drag_id,e]); + this._loading=false; + + this._drag_event={}; //dummy , to trigger correct event updating logic + this._on_mouse_up(e); +} +scheduler._on_dbl_click=function(e,src){ + src = src||(e.target||e.srcElement); + if (this.config.readonly) return; + var name = src.className.split(" ")[0]; + switch(name){ + case "dhx_scale_holder": + case "dhx_scale_holder_now": + case "dhx_month_body": + if (!scheduler.config.dblclick_create) break; + var pos=this._mouse_coords(e); + var start=this._min_date.valueOf()+(pos.y*this.config.time_step+(this._table_view?0:pos.x)*24*60)*60000; + start = this._correct_shift(start); + this.addEventNow(start,null,e); + break; + case "dhx_body": + case "dhx_cal_event_line": + case "dhx_cal_event_clear": + var id = this._locate_event(src); + if (!this.callEvent("onDblClick",[id,e])) return; + if (this.config.details_on_dblclick || this._table_view || !this.getEvent(id)._timed) + this.showLightbox(id); + else + this.edit(id); + break; + case "": + if (src.parentNode) + return scheduler._on_dbl_click(e,src.parentNode); + default: + var t = this["dblclick_"+name]; + if (t) t.call(this,e); + break; + } +} + +scheduler._mouse_coords=function(ev){ + var pos; + var b=document.body; + var d = document.documentElement; + if(ev.pageX || ev.pageY) + pos={x:ev.pageX, y:ev.pageY}; + else pos={ + x:ev.clientX + (b.scrollLeft||d.scrollLeft||0) - b.clientLeft, + y:ev.clientY + (b.scrollTop||d.scrollTop||0) - b.clientTop + } + + //apply layout + pos.x-=getAbsoluteLeft(this._obj)+(this._table_view?0:this.xy.scale_width); + pos.y-=getAbsoluteTop(this._obj)+this.xy.nav_height+(this._dy_shift||0)+this.xy.scale_height-this._els["dhx_cal_data"][0].scrollTop; + pos.ev = ev; + + var handler = this["mouse_"+this._mode]; + if (handler) + return handler.call(this,pos); + + //transform to date + if (!this._table_view){ + pos.x=Math.max(0,Math.ceil(pos.x/this._cols[0])-1); + pos.y=Math.max(0,Math.ceil(pos.y*60/(this.config.time_step*this.config.hour_size_px))-1)+this.config.first_hour*(60/this.config.time_step); + } else { + var dy=0; + for (dy=1; dy < this._colsS.heights.length; dy++) + if (this._colsS.heights[dy]>pos.y) break; + + pos.y=(Math.max(0,Math.ceil(pos.x/this._cols[0])-1)+Math.max(0,dy-1)*7)*24*60/this.config.time_step; + pos.x=0; + } + + return pos; +} +scheduler._close_not_saved=function(){ + if (new Date().valueOf()-(scheduler._new_event||0) > 500 && scheduler._edit_id){ + var c=scheduler.locale.labels.confirm_closing; + if (!c || confirm(c)) + scheduler.editStop(scheduler.config.positive_closing); + } +} +scheduler._correct_shift=function(start, back){ + return start-=((new Date(scheduler._min_date)).getTimezoneOffset()-(new Date(start)).getTimezoneOffset())*60000*(back?-1:1); +} +scheduler._on_mouse_move=function(e){ + if (this._drag_mode){ + var pos=this._mouse_coords(e); + if (!this._drag_pos || this._drag_pos.x!=pos.x || this._drag_pos.y!=pos.y){ + + if (this._edit_id!=this._drag_id) + this._close_not_saved(); + + this._drag_pos=pos; + + if (this._drag_mode=="create"){ + this._close_not_saved(); + this._loading=true; //will be ignored by dataprocessor + + var start=this._min_date.valueOf()+(pos.y*this.config.time_step+(this._table_view?0:pos.x)*24*60)*60000; + //if (this._mode != "week" && this._mode != "day") + start = this._correct_shift(start); + + if (!this._drag_start){ + this._drag_start=start; return; + } + var end = start; + if (end==this._drag_start) return; + + this._drag_id=this.uid(); + this.addEvent(new Date(this._drag_start), new Date(end),this.locale.labels.new_event,this._drag_id, pos.fields); + + this.callEvent("onEventCreated",[this._drag_id,e]); + this._loading=false; + this._drag_mode="new-size"; + + } + + var ev=this.getEvent(this._drag_id); + var start,end; + if (this._drag_mode=="move"){ + start = this._min_date.valueOf()+(pos.y*this.config.time_step+pos.x*24*60)*60000; + if (!pos.custom && this._table_view) start+=this.date.time_part(ev.start_date)*1000; + start = this._correct_shift(start); + end = ev.end_date.valueOf()-(ev.start_date.valueOf()-start); + } else { + start = ev.start_date.valueOf(); + if (this._table_view) + end = this._min_date.valueOf()+pos.y*this.config.time_step*60000 + (pos.custom?0:24*60*60000); + else{ + end = this.date.date_part(new Date(ev.end_date)).valueOf()+pos.y*this.config.time_step*60000; + this._els["dhx_cal_data"][0].style.cursor="s-resize"; + if (this._mode == "week" || this._mode == "day") + end = this._correct_shift(end); + } + if (this._drag_mode == "new-size"){ + if (end <= this._drag_start){ + var shift = pos.shift||((this._table_view && !pos.custom)?24*60*60000:0); + start = end-shift; + end = this._drag_start+(shift||(this.config.time_step*60000)); + } else { + start = this._drag_start; + } + + } else if (end<=start) + end=start+this.config.time_step*60000; + } + var new_end = new Date(end-1); + var new_start = new Date(start); + //prevent out-of-borders situation for day|week view + if (this._table_view || (new_end.getDate()==new_start.getDate() && new_end.getHours()=ed) + cls='dhx_after'; + else if (sd.valueOf()==cd.valueOf()) + cls='dhx_now'; + html+=" class='"+cls+" "+this.templates.month_date_class(sd,cd)+"' "; + html+=">
"+this.templates.month_day(sd)+"
" + sd=this.date.add(sd,1,"day"); + } + html+=""; + h[i] = cellheight; + cellheight+=this._colsS.height; + } + html+=""; + this._max_date=sd; + + b.innerHTML=html; + return sd; +} +scheduler.getLabel = function(property, key) { + var sections = this.config.lightbox.sections; + for (var i=0; i',{'width':'100%','cellspacing': 0, 'cellpadding': 0, 'id':'cal-sidebar-option'}) + ) + for(s in sidebar) { + jQuery('#cal-sidebar-option').append( + jQuery('').append( + jQuery('').append( + jQuery('
') + .append( + jQuery('', + { + 'type': 'checkbox', + 'id':sidebar[s][0], + 'value':sidebar[s][0] + }).bind('click',function(){ + self.reload_scheduler() + }), + sidebar[s][1] + ) + .css('background-color',sidebar[s][sidebar[s].length-1]) + ) + ) + ) + } + }, + + convert_date_format: function(start_date, end_date) { + var params = {}; + params['start_date'] = start_date.getFullYear() +'-' + start_date.getMonth()+'-' + start_date.getDate()+' '+start_date.getHours()+':'+start_date.getMinutes()+':'+start_date.getSeconds(); + if(end_date) { + params['end_date'] = end_date.getFullYear() +'-' + end_date.getMonth()+'-' + end_date.getDate()+' '+end_date.getHours()+':'+end_date.getMinutes()+':'+end_date.getSeconds(); + } + return params; + }, + + edit_event: function(evt_id, evt_object) { + var dates = this.convert_date_format(evt_object.start_date, evt_object.end_date); + this.rpc( + '/base_calendar/calendarview/edit_events', + { + 'start_date': dates.start_date, + 'end_date': dates.end_date, + 'id': evt_id, + 'model': this.model, + 'info_fields': this.info_fields, + 'fields': this.fields, + 'calendar_fields': this.calendar_fields + } + ); + }, + + mini_calendar: function() { + + if(scheduler.isCalendarVisible()) { + scheduler.destroyCalendar(); + } else { + scheduler.renderCalendar({ + position:"dhx_minical_icon", + date:scheduler._date, + navigation:true, + handler:function(date,calendar){ + scheduler.setCurrentView(date); + scheduler.destroyCalendar() + } + }); + } + }, + + reload_scheduler: function() { +// self.color_field + console.log('Reload Scheduler>>>') + }, + + do_show: function () { + this.$element.show(); + }, + + do_hide: function () { + this.$element.hide(); + } +}); + +//openerp.base.Action = openerp.base.Action.extend({ +// do_action_window: function(action) { +// this._super.apply(this,arguments); +// for(var i = 0; i < action.views.length; i++) { +// if(action.views[i][1] == "calendar") { +// this.calendar_id = action.views[i][0]; +// break; +// } +// } +// // IF there is a view calender +// // if(this.calendar_id +// }, +//}); + +}; + +// DEBUG_RPC:rpc.request:('execute', 'addons-dsh-l10n_us', 1, '*', ('ir.filters', 'get_filters', u'res.partner')) +// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/base_calendar/static/src/xml/base_calendar.xml b/addons/base_calendar/static/src/xml/base_calendar.xml new file mode 100644 index 00000000000..02d67be05bb --- /dev/null +++ b/addons/base_calendar/static/src/xml/base_calendar.xml @@ -0,0 +1,33 @@ + diff --git a/addons/base_diagram/__init__.py b/addons/base_diagram/__init__.py new file mode 100644 index 00000000000..355939a4922 --- /dev/null +++ b/addons/base_diagram/__init__.py @@ -0,0 +1 @@ +import controllers \ No newline at end of file diff --git a/addons/base_diagram/__openerp__.py b/addons/base_diagram/__openerp__.py new file mode 100644 index 00000000000..92b768896f9 --- /dev/null +++ b/addons/base_diagram/__openerp__.py @@ -0,0 +1,6 @@ +{ + "name" : "OpenERP Web base Diagram", + "version" : "2.0", + "depends" : [], + 'active': False, +} diff --git a/addons/base_diagram/controllers/__init__.py b/addons/base_diagram/controllers/__init__.py new file mode 100644 index 00000000000..039d9715fab --- /dev/null +++ b/addons/base_diagram/controllers/__init__.py @@ -0,0 +1 @@ +import main \ No newline at end of file diff --git a/addons/base_diagram/controllers/main.py b/addons/base_diagram/controllers/main.py new file mode 100644 index 00000000000..2f76ead7117 --- /dev/null +++ b/addons/base_diagram/controllers/main.py @@ -0,0 +1,127 @@ +from base.controllers.main import View +import openerpweb + +class DiagramView(View): + _cp_path = "/base_diagram/diagram" + + @openerpweb.jsonrequest + def load(self, req, model, view_id): + print req + print dir(req) + fields_view = self.fields_view_get(req, model, view_id, 'diagram') + return {'fields_view': fields_view} + + @openerpweb.jsonrequest + def get_diagram_info(self, req, **kw): + id = kw['id'] + model = kw['model'] + node = kw['node'] + connector = kw['connector'] + src_node = kw['src_node'] + des_node = kw['des_node'] + + visible_node_fields = kw.get('visible_node_fields',[]) + invisible_node_fields = kw.get('invisible_node_fields',[]) + node_fields_string = kw.get('node_fields_string',[]) + connector_fields = kw.get('connector_fields',[]) + connector_fields_string = kw.get('connector_fields_string',[]) + + bgcolors = {} + shapes = {} + bgcolor = kw.get('bgcolor','') + shape = kw.get('shape','') + + if bgcolor: + for color_spec in bgcolor.split(';'): + if color_spec: + colour, color_state = color_spec.split(':') + bgcolors[colour] = color_state + + if shape: + for shape_spec in shape.split(';'): + if shape_spec: + shape_colour, shape_color_state = shape_spec.split(':') + shapes[shape_colour] = shape_color_state + + ir_view = req.session.model('ir.ui.view') + graphs = ir_view.graph_get(id, model, node, connector, src_node, des_node, False, + (140, 180), req.session.context) + + nodes = graphs['nodes'] + transitions = graphs['transitions'] + isolate_nodes = {} + + for node in graphs['blank_nodes']: + isolate_nodes[node['id']] = node + else: + y = map(lambda t: t['y'],filter(lambda x: x['y'] if x['x']==20 else None, nodes.values())) + y_max = (y and max(y)) or 120 + + connectors = {} + list_tr = [] + + for tr in transitions: + list_tr.append(tr) + connectors.setdefault(tr, { + 'id': tr, + 's_id': transitions[tr][0], + 'd_id': transitions[tr][1] + }) + connector_tr = req.session.model(connector) + connector_ids = connector_tr.search([('id', 'in', list_tr)], 0, 0, 0, req.session.context) + + data_connectors =connector_tr.read(connector_ids, connector_fields, req.session.context) + + + for tr in data_connectors: + t = connectors.get(str(tr['id'])) + t.update({ + 'source': tr[src_node][1], + 'destination': tr[des_node][1], + 'options': {} + }) + + for i, fld in enumerate(connector_fields): + t['options'][connector_fields_string[i]] = tr[fld] + + fields = req.session.model('ir.model.fields') + field_ids = fields.search([('model', '=', model), ('relation', '=', node)], 0, 0, 0, req.session.context) + field_data = fields.read(field_ids, ['relation_field'], req.session.context) + + node_act = req.session.model(node) + search_acts = node_act.search([(field_data[0]['relation_field'], '=', id)], 0, 0, 0, req.session.context) + data_acts = node_act.read(search_acts, invisible_node_fields + visible_node_fields, req.session.context) + + for act in data_acts: + n = nodes.get(str(act['id'])) + if not n: + n = isolate_nodes.get(act['id'], {}) + y_max += 140 + n.update({'x': 20, 'y': y_max}) + nodes[act['id']] = n + + n.update( + id=act['id'], + color='white', + shape='ellipse', + options={} + ) + for color, expr in bgcolors.items(): + if eval(expr, act): + n['color'] = color + + for shape, expr in shapes.items(): + if eval(expr, act): + n['shape'] = shape + + for i, fld in enumerate(visible_node_fields): + n['options'][node_fields_string[i]] = act[fld] + + #to relate m2o field of transition to corresponding o2m in activity + in_transition_field_id = fields.search([('relation', '=', connector), ('relation_field', '=', des_node), ('model', '=', node)], 0, 0, 0, req.session.context) + in_transition_field = fields.read(in_transition_field_id[0], ['name'], req.session.context)['name'] + + out_transition_field_id = fields.search([('relation', '=', connector), ('relation_field', '=', src_node), ('model', '=', node)], 0, 0, 0, req.session.context) + out_transition_field = fields.read(out_transition_field_id[0], ['name'], req.session.context)['name'] + + return dict(nodes=nodes, conn=connectors, in_transition_field=in_transition_field, out_transition_field=out_transition_field) diff --git a/addons/base_diagram/static/lib/js/Curry-1.0.1.js b/addons/base_diagram/static/lib/js/Curry-1.0.1.js new file mode 100644 index 00000000000..f5aa0f993a6 --- /dev/null +++ b/addons/base_diagram/static/lib/js/Curry-1.0.1.js @@ -0,0 +1,29 @@ +/** + * Curry - Function currying + * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com + * Licensed under BSD (http://www.opensource.org/licenses/bsd-license.php) + * Date: 10/4/2008 + * + * @author Ariel Flesler + * @version 1.0.1 + */ + +function curry( fn ){ + return function(){ + var args = curry.args(arguments), + master = arguments.callee, + self = this; + + return args.length >= fn.length ? fn.apply(self,args) : function(){ + return master.apply( self, args.concat(curry.args(arguments)) ); + }; + }; +}; + +curry.args = function( args ){ + return Array.prototype.slice.call(args); +}; + +Function.prototype.curry = function(){ + return curry(this); +}; \ No newline at end of file diff --git a/addons/base_diagram/static/lib/js/dracula_algorithms.js b/addons/base_diagram/static/lib/js/dracula_algorithms.js new file mode 100644 index 00000000000..0fbb0857fc8 --- /dev/null +++ b/addons/base_diagram/static/lib/js/dracula_algorithms.js @@ -0,0 +1,599 @@ +/* + * Various algorithms and data structures, licensed under the MIT-license. + * (c) 2010 by Johann Philipp Strathausen + * http://strathausen.eu + * + */ + + + +/* + Bellman-Ford + + Path-finding algorithm, finds the shortest paths from one node to all nodes. + + + Complexity + + O( |E| · |V| ), where E = edges and V = vertices (nodes) + + + Constraints + + Can run on graphs with negative edge weights as long as they do not have + any negative weight cycles. + + */ +function bellman_ford(g, source) { + + /* STEP 1: initialisation */ + for(var n in g.nodes) + g.nodes[n].distance = Infinity; + /* predecessors are implicitly null */ + source.distance = 0; + + step("Initially, all distances are infinite and all predecessors are null."); + + /* STEP 2: relax each edge (this is at the heart of Bellman-Ford) */ + /* repeat this for the number of nodes minus one */ + for(var i = 1; i < g.nodes.length; i++) + /* for each edge */ + for(var e in g.edges) { + var edge = g.edges[e]; + if(edge.source.distance + edge.weight < edge.target.distance) { + step("Relax edge between " + edge.source.id + " and " + edge.target.id + "."); + edge.target.distance = edge.source.distance + edge.weight; + edge.target.predecessor = edge.source; + } + //Added by Jake Stothard (Needs to be tested) + if(!edge.style.directed) { + if(edge.target.distance + edge.weight < edge.source.distance) { + g.snapShot("Relax edge between "+edge.target.id+" and "+edge.source.id+"."); + edge.source.distance = edge.target.distance + edge.weight; + edge.source.predecessor = edge.target; + } + } + } + step("Ready."); + + /* STEP 3: TODO Check for negative cycles */ + /* For now we assume here that the graph does not contain any negative + weights cycles. (this is left as an excercise to the reader[tm]) */ +} + + + +/* + Path-finding algorithm Dijkstra + + - worst-case running time is O((|E| + |V|) · log |V| ) thus better than + Bellman-Ford for sparse graphs (with less edges), but cannot handle + negative edge weights + */ +function dijkstra(g, source) { + + /* initially, all distances are infinite and all predecessors are null */ + for(var n in g.nodes) + g.nodes[n].distance = Infinity; + /* predecessors are implicitly null */ + + g.snapShot("Initially, all distances are infinite and all predecessors are null."); + + source.distance = 0; + /* set of unoptimized nodes, sorted by their distance (but a Fibonacci heap + would be better) */ + var q = new BinaryMinHeap(g.nodes, "distance"); + + /* pointer to the node in focus */ + var node; + + /* get the node with the smallest distance + as long as we have unoptimized nodes. q.min() can have O(log n). */ + while(q.min() != undefined) { + /* remove the latest */ + node = q.extractMin(); + node.optimized = true; + + /* no nodes accessible from this one, should not happen */ + if(node.distance == Infinity) + throw "Orphaned node!"; + + /* for each neighbour of node */ + for(e in node.edges) { + var other = (node == node.edges[e].target) ? node.edges[e].source : node.edges[e].target; + + if(other.optimized) + continue; + + /* look for an alternative route */ + var alt = node.distance + node.edges[e].weight; + + /* update distance and route if a better one has been found */ + if (alt < other.distance) { + + /* update distance of neighbour */ + other.distance = alt; + + /* update priority queue */ + q.heapify(); + + /* update path */ + other.predecessor = node; + g.snapShot("Enhancing node.") + } + } + } +} + + +/* All-Pairs-Shortest-Paths */ +/* Runs at worst in O(|V|³) and at best in Omega(|V|³) :-) + complexity Sigma(|V|²) */ +/* This implementation is not yet ready for general use, but works with the + Dracula graph library. */ +function floyd_warshall(g, source) { + + /* Step 1: initialising empty path matrix (second dimension is implicit) */ + var path = []; + var next = []; + var n = g.nodes.length; + + /* construct path matrix, initialize with Infinity */ + for(j in g.nodes) { + path[j] = []; + next[j] = []; + for(i in g.nodes) + path[j][i] = j == i ? 0 : Infinity; + } + + /* initialize path with edge weights */ + for(e in g.edges) + path[g.edges[e].source.id][g.edges[e].target.id] = g.edges[e].weight; + + /* Note: Usually, the initialisation is done by getting the edge weights + from a node matrix representation of the graph, not by iterating through + a list of edges as done here. */ + + /* Step 2: find best distances (the heart of Floyd-Warshall) */ + for(k in g.nodes){ + for(i in g.nodes) { + for(j in g.nodes) + if(path[i][j] > path[i][k] + path[k][j]) { + path[i][j] = path[i][k] + path[k][j]; + /* Step 2.b: remember the path */ + next[i][j] = k; + } + } + } + + /* Step 3: Path reconstruction, get shortest path */ + function getPath(i, j) { + if(path[i][j] == Infinity) + throw "There is no path."; + var intermediate = next[i][j]; + if(intermediate == undefined) + return null; + else + return getPath(i, intermediate) + .concat([intermediate]) + .concat(getPath(intermediate, j)); + } + + /* TODO use the knowledge, e.g. mark path in graph */ +} + +/* + Ford-Fulkerson + + Max-Flow-Min-Cut Algorithm finding the maximum flow through a directed + graph from source to sink. + + + Complexity + + O(E * max(f)), max(f) being the maximum flow + + + Description + + As long as there is an open path through the residual graph, send the + minimum of the residual capacities on the path. + + + Constraints + + The algorithm works only if all weights are integers. Otherwise it is + possible that the Ford–Fulkerson algorithm will not converge to the maximum + value. + + + Input + + g - Graph object + s - Source ID + t - Target (sink) ID + + + Output + + Maximum flow from Source s to Target t + + */ +/* + Edmonds-Karp + + Max-Flow-Min-Cut Algorithm finding the maximum flow through a directed + graph from source to sink. An implementation of the Ford-Fulkerson + algorithm. + + + Complexity + + O(|V|*|E|²) + + + Input + + g - Graph object (with node and edge lists, capacity is a property of edge) + s - source ID + t - sink ID + + */ +function edmonds_karp(g, s, t) { + +} + +/* + A simple binary min-heap serving as a priority queue + - takes an array as the input, with elements having a key property + - elements will look like this: + { + key: "... key property ...", + value: "... element content ..." + } + - provides insert(), min(), extractMin() and heapify() + - example usage (e.g. via the Firebug or Chromium console): + var x = {foo: 20, hui: "bla"}; + var a = new BinaryMinHeap([x,{foo:3},{foo:10},{foo:20},{foo:30},{foo:6},{foo:1},{foo:3}],"foo"); + console.log(a.extractMin()); + console.log(a.extractMin()); + x.foo = 0; // update key + a.heapify(); // call this always after having a key updated + console.log(a.extractMin()); + console.log(a.extractMin()); + - can also be used on a simple array, like [9,7,8,5] + */ +function BinaryMinHeap(array, key) { + + /* Binary tree stored in an array, no need for a complicated data structure */ + var tree = []; + + var key = key || 'key'; + + /* Calculate the index of the parent or a child */ + var parent = function(index) { return Math.floor((index - 1)/2); }; + var right = function(index) { return 2 * index + 2; }; + var left = function(index) { return 2 * index + 1; }; + + /* Helper function to swap elements with their parent + as long as the parent is bigger */ + function bubble_up(i) { + var p = parent(i); + while((p >= 0) && (tree[i][key] < tree[p][key])) { + /* swap with parent */ + tree[i] = tree.splice(p, 1, tree[i])[0]; + /* go up one level */ + i = p; + p = parent(i); + } + } + + /* Helper function to swap elements with the smaller of their children + as long as there is one */ + function bubble_down(i) { + var l = left(i); + var r = right(i); + + /* as long as there are smaller children */ + while(tree[l] && (tree[i][key] > tree[l][key]) || tree[r] && (tree[i][key] > tree[r][key])) { + + /* find smaller child */ + var child = tree[l] ? tree[r] ? tree[l][key] > tree[r][key] ? r : l : l : l; + + /* swap with smaller child with current element */ + tree[i] = tree.splice(child, 1, tree[i])[0]; + + /* go up one level */ + i = child; + l = left(i); + r = right(i); + } + } + + /* Insert a new element with respect to the heap property + 1. Insert the element at the end + 2. Bubble it up until it is smaller than its parent */ + this.insert = function(element) { + + /* make sure there's a key property */ + (element[key] == undefined) && (element = {key:element}); + + /* insert element at the end */ + tree.push(element); + + /* bubble up the element */ + bubble_up(tree.length - 1); + } + + /* Only show us the minimum */ + this.min = function() { + return tree.length == 1 ? undefined : tree[0]; + } + + /* Return and remove the minimum + 1. Take the root as the minimum that we are looking for + 2. Move the last element to the root (thereby deleting the root) + 3. Compare the new root with both of its children, swap it with the + smaller child and then check again from there (bubble down) + */ + this.extractMin = function() { + var result = this.min(); + + /* move the last element to the root or empty the tree completely */ + /* bubble down the new root if necessary */ + (tree.length == 1) && (tree = []) || (tree[0] = tree.pop()) && bubble_down(0); + + return result; + } + + /* currently unused, TODO implement */ + this.changeKey = function(index, key) { + throw "function not implemented"; + } + + this.heapify = function() { + for(var start = Math.floor((tree.length - 2) / 2); start >= 0; start--) { + bubble_down(start); + } + } + + /* insert the input elements one by one only when we don't have a key property (TODO can be done more elegant) */ + for(i in (array || [])) + this.insert(array[i]); +} + + + +/* + Quick Sort: + 1. Select some random value from the array, the median. + 2. Divide the array in three smaller arrays according to the elements + being less, equal or greater than the median. + 3. Recursively sort the array containg the elements less than the + median and the one containing elements greater than the median. + 4. Concatenate the three arrays (less, equal and greater). + 5. One or no element is always sorted. + TODO: This could be implemented more efficiently by using only one array object and several pointers. +*/ +function quickSort(arr) { + /* recursion anchor: one element is always sorted */ + if(arr.length <= 1) return arr; + /* randomly selecting some value */ + var median = arr[Math.floor(Math.random() * arr.length)]; + var arr1 = [], arr2 = [], arr3 = []; + for(var i in arr) { + arr[i] < median && arr1.push(arr[i]); + arr[i] == median && arr2.push(arr[i]); + arr[i] > median && arr3.push(arr[i]); + } + /* recursive sorting and assembling final result */ + return quickSort(arr1).concat(arr2).concat(quickSort(arr3)); +} + +/* + Selection Sort: + 1. Select the minimum and remove it from the array + 2. Sort the rest recursively + 3. Return the minimum plus the sorted rest + 4. An array with only one element is already sorted +*/ +function selectionSort(arr) { + /* recursion anchor: one element is always sorted */ + if(arr.length == 1) return arr; + var minimum = Infinity; + var index; + for(var i in arr) { + if(arr[i] < minimum) { + minimum = arr[i]; + index = i; /* remember the minimum index for later removal */ + } + } + /* remove the minimum */ + arr.splice(index, 1); + /* assemble result and sort recursively (could be easily done iteratively as well)*/ + return [minimum].concat(selectionSort(arr)); +} + +/* + Merge Sort: + 1. Cut the array in half + 2. Sort each of them recursively + 3. Merge the two sorted arrays + 4. An array with only one element is considered sorted + +*/ +function mergeSort(arr) { + /* merges two sorted arrays into one sorted array */ + function merge(a, b) { + /* result set */ + var c = []; + /* as long as there are elements in the arrays to be merged */ + while(a.length > 0 || b.length > 0){ + /* are there elements to be merged, if yes, compare them and merge */ + var n = a.length > 0 && b.length > 0 ? a[0] < b[0] ? a.shift() : b.shift() : b.length > 0 ? b.shift() : a.length > 0 ? a.shift() : null; + /* always push the smaller one onto the result set */ + n != null && c.push(n); + } + return c; + } + /* this mergeSort implementation cuts the array in half, wich should be fine with randomized arrays, but introduces the risk of a worst-case scenario */ + median = Math.floor(arr.length / 2); + var part1 = arr.slice(0, median); /* for some reason it doesn't work if inserted directly in the return statement (tried so with firefox) */ + var part2 = arr.slice(median - arr.length); + return arr.length <= 1 ? arr : merge( + mergeSort(part1), /* first half */ + mergeSort(part2) /* second half */ + ); +} + +/* Balanced Red-Black-Tree */ +function RedBlackTree(arr) { + +} + +function BTree(arr) { + +} + +function NaryTree(n, arr) { + +} + +/** + * Knuth-Morris-Pratt string matching algorithm - finds a pattern in a text. + * FIXME: Doesn't work correctly yet. + */ +function kmp(p, t) { + + /** + * PREFIX, OVERLAP or FALIURE function for KMP. Computes how many iterations + * the algorithm can skip after a mismatch. + * + * @input p - pattern (string) + * @result array of skippable iterations + */ + function prefix(p) { + /* pi contains the computed skip marks */ + var pi = [0], k = 0; + for(q = 1; q < p.length; q++) { + while(k > 0 && (p.charAt(k) != p.charAt(q))) + k = pi[k-1]; + + (p.charAt(k) == p.charAt(q)) && k++; + + pi[q] = k; + } + return pi; + } + + /* The actual KMP algorithm starts here. */ + + var pi = prefix(p), q = 0, result = []; + + for(var i = 0; i < t.length; i++) { + /* jump forward as long as the character doesn't match */ + while((q > 0) && (p.charAt(q) != t.charAt(i))) + q = pi[q]; + + (p.charAt(q) == t.charAt(i)) && q++; + + (q == p.length) && result.push(i - p.length) && (q = pi[q]); + } + + return result; +} + +/* step for algorithm visualisation */ +function step(comment, funct) { + //wait for input + //display comment (before or after waiting) +// next.wait(); + /* execute callback function */ + funct(); +} + +/** + * Curry - Function currying + * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com + * Licensed under BSD (http://www.opensource.org/licenses/bsd-license.php) + * Date: 10/4/2008 + * + * @author Ariel Flesler + * @version 1.0.1 + */ +function curry( fn ){ + return function(){ + var args = curry.args(arguments), + master = arguments.callee, + self = this; + + return args.length >= fn.length ? fn.apply(self,args) : function(){ + return master.apply( self, args.concat(curry.args(arguments)) ); + }; + }; +}; + +curry.args = function( args ){ + return Array.prototype.slice.call(args); +}; + +Function.prototype.curry = function(){ + return curry(this); +}; + +/** + * Topological Sort + * + * Sort a directed graph based on incoming edges + * + * Coded by Jake Stothard + */ +function topological_sort(g) { + //Mark nodes as "deleted" instead of actually deleting them + //That way we don't have to copy g + + for(i in g.nodes) + g.nodes[i].deleted = false; + + var ret = topological_sort_helper(g); + + //Cleanup: Remove the deleted property + for(i in g.nodes) + delete g.nodes[i].deleted + + return ret; +} +function topological_sort_helper(g) { + //Find node with no incoming edges + var node; + for(i in g.nodes) { + if(g.nodes[i].deleted) + continue; //Bad style, meh + + var incoming = false; + for(j in g.nodes[i].edges) { + if(g.nodes[i].edges[j].target == g.nodes[i] + && g.nodes[i].edges[j].source.deleted == false) { + incoming = true; + break; + } + } + if(!incoming) { + node = g.nodes[i]; + break; + } + } + + // Either unsortable or done. Either way, GTFO + if(node == undefined) + return []; + + //"Delete" node from g + node.deleted = true; + + var tail = topological_sort_helper(g); + + tail.unshift(node); + + return tail; +} diff --git a/addons/base_diagram/static/lib/js/dracula_graffle.js b/addons/base_diagram/static/lib/js/dracula_graffle.js new file mode 100644 index 00000000000..9d4fd2099e8 --- /dev/null +++ b/addons/base_diagram/static/lib/js/dracula_graffle.js @@ -0,0 +1,106 @@ +/** + * Originally grabbed from the official RaphaelJS Documentation + * http://raphaeljs.com/graffle.html + * Adopted (arrows) and commented by Philipp Strathausen http://blog.ameisenbar.de + * Licenced under the MIT licence. + */ + +/** + * Usage: + * connect two shapes + * parameters: + * source shape [or connection for redrawing], + * target shape, + * style with { fg : linecolor, bg : background color, directed: boolean } + * returns: + * connection { draw = function() } + */ +Raphael.fn.connection = function (obj1, obj2, style) { + var selfRef = this; + /* create and return new connection */ + var edge = {/* + from : obj1, + to : obj2, + style : style,*/ + draw : function() { + /* get bounding boxes of target and source */ + var bb1 = obj1.getBBox(); + var bb2 = obj2.getBBox(); + var off1 = 0; + var off2 = 0; + /* coordinates for potential connection coordinates from/to the objects */ + var p = [ + {x: bb1.x + bb1.width / 2, y: bb1.y - off1}, /* NORTH 1 */ + {x: bb1.x + bb1.width / 2, y: bb1.y + bb1.height + off1}, /* SOUTH 1 */ + {x: bb1.x - off1, y: bb1.y + bb1.height / 2}, /* WEST 1 */ + {x: bb1.x + bb1.width + off1, y: bb1.y + bb1.height / 2}, /* EAST 1 */ + {x: bb2.x + bb2.width / 2, y: bb2.y - off2}, /* NORTH 2 */ + {x: bb2.x + bb2.width / 2, y: bb2.y + bb2.height + off2}, /* SOUTH 2 */ + {x: bb2.x - off2, y: bb2.y + bb2.height / 2}, /* WEST 2 */ + {x: bb2.x + bb2.width + off2, y: bb2.y + bb2.height / 2} /* EAST 2 */ + ]; + + /* distances between objects and according coordinates connection */ + var d = {}, dis = []; + + /* + * find out the best connection coordinates by trying all possible ways + */ + /* loop the first object's connection coordinates */ + for (var i = 0; i < 4; i++) { + /* loop the seond object's connection coordinates */ + for (var j = 4; j < 8; j++) { + var dx = Math.abs(p[i].x - p[j].x), + dy = Math.abs(p[i].y - p[j].y); + if ((i == j - 4) || (((i != 3 && j != 6) || p[i].x < p[j].x) && ((i != 2 && j != 7) || p[i].x > p[j].x) && ((i != 0 && j != 5) || p[i].y > p[j].y) && ((i != 1 && j != 4) || p[i].y < p[j].y))) { + dis.push(dx + dy); + d[dis[dis.length - 1].toFixed(3)] = [i, j]; + } + } + } + var res = dis.length == 0 ? [0, 4] : d[Math.min.apply(Math, dis).toFixed(3)]; + /* bezier path */ + var x1 = p[res[0]].x, + y1 = p[res[0]].y, + x4 = p[res[1]].x, + y4 = p[res[1]].y, + dx = Math.max(Math.abs(x1 - x4) / 2, 10), + dy = Math.max(Math.abs(y1 - y4) / 2, 10), + x2 = [x1, x1, x1 - dx, x1 + dx][res[0]].toFixed(3), + y2 = [y1 - dy, y1 + dy, y1, y1][res[0]].toFixed(3), + x3 = [0, 0, 0, 0, x4, x4, x4 - dx, x4 + dx][res[1]].toFixed(3), + y3 = [0, 0, 0, 0, y1 + dy, y1 - dy, y4, y4][res[1]].toFixed(3); + /* assemble path and arrow */ + var path = ["M", x1.toFixed(3), y1.toFixed(3), "C", x2, y2, x3, y3, x4.toFixed(3), y4.toFixed(3)].join(","); + /* arrow */ + if(style && style.directed) { + /* magnitude, length of the last path vector */ + var mag = Math.sqrt((y4 - y3) * (y4 - y3) + (x4 - x3) * (x4 - x3)); + /* vector normalisation to specified length */ + var norm = function(x,l){return (-x*(l||5)/mag);}; + /* calculate array coordinates (two lines orthogonal to the path vector) */ + var arr = [ + {x:(norm(x4-x3)+norm(y4-y3)+x4).toFixed(3), y:(norm(y4-y3)+norm(x4-x3)+y4).toFixed(3)}, + {x:(norm(x4-x3)-norm(y4-y3)+x4).toFixed(3), y:(norm(y4-y3)-norm(x4-x3)+y4).toFixed(3)} + ]; + path = path + ",M"+arr[0].x+","+arr[0].y+",L"+x4+","+y4+",L"+arr[1].x+","+arr[1].y; + } + /* function to be used for moving existent path(s), e.g. animate() or attr() */ + var move = "attr"; + /* applying path(s) */ + edge.fg && edge.fg[move]({path:path}) + || (edge.fg = selfRef.path(path).attr({stroke: style && style.stroke || "#000", fill: "none"}).toBack()); + edge.bg && edge.bg[move]({path:path}) + || style && style.fill && (edge.bg = style.fill.split && selfRef.path(path).attr({stroke: style.fill.split("|")[0], fill: "none", "stroke-width": style.fill.split("|")[1] || 3}).toBack()); + /* setting label */ + style && style.label + && (edge.label && edge.label.attr({x:(x1+x4)/2, y:(y1+y4)/2}) + || (edge.label = selfRef.text((x1+x4)/2, (y1+y4)/2, style.label).attr({fill: "#000", "font-size": style["font-size"] || "12px"}))); +// && selfRef.text(x4, y4, style.label).attr({stroke: style && style.stroke || "#fff", "font-weight":"bold", "font-size":"20px"}) +// style && style.callback && style.callback(edge); + } + } + edge.draw(); + return edge; +}; +//Raphael.prototype.set.prototype.dodo=function(){console.log("works");}; diff --git a/addons/base_diagram/static/lib/js/dracula_graph.coffee b/addons/base_diagram/static/lib/js/dracula_graph.coffee new file mode 100644 index 00000000000..bb91945098d --- /dev/null +++ b/addons/base_diagram/static/lib/js/dracula_graph.coffee @@ -0,0 +1,524 @@ +### + * Dracula Graph Layout and Drawing Framework 0.0.3alpha + * (c) 2010 Philipp Strathausen , http://strathausen.eu + * + * Contributions by: + * Branched by Jake Stothard . + * + * based on the Graph JavaScript framework, version 0.0.1 + * (c) 2006 Aslak Hellesoy + * (c) 2006 Dave Hoover + * + * Ported from Graph::Layouter::Spring in + * http://search.cpan.org/~pasky/Graph-Layderer-0.02/ + * The algorithm is based on a spring-style layouter of a Java-based social + * network tracker PieSpy written by Paul Mutton Epaul@jibble.orgE. + * + * This code is freely distributable under the terms of an MIT-style license. + * For details, see the Graph web site: http://dev.buildpatternd.com/trac + * + * Links: + * + * Graph Dracula JavaScript Framework: + * http://graphdracula.net + * + * Demo of the original applet: + * http://redsquirrel.com/dave/work/webdep/ + * + * Mirrored original source code at snipplr: + * http://snipplr.com/view/1950/graph-javascript-framework-version-001/ + * + * Original usage example: + * http://ajaxian.com/archives/new-javascriptcanvas-graph-library + * +### + + +### + Edge Factory +### +AbstractEdge = -> + +AbstractEdge.prototype = + hide: -> + @connection.fg.hide() + @connection.bg && @bg.connection.hide() + +EdgeFactory = -> + @template = new AbstractEdge() + @template.style = new Object() + @template.style.directed = false + @template.weight = 1 + +EdgeFactory.prototype = + build: (source, target) -> + e = jQuery.extend true, {}, @template + e.source = source + e.target = target + e + +### + Graph +### +Graph = -> + @nodes = {} + @edges = [] + @snapshots = [] # previous graph states TODO to be implemented + @edgeFactory = new EdgeFactory() + +Graph.prototype = +### + add a node + @id the node's ID (string or number) + @content (optional, dictionary) can contain any information that is + being interpreted by the layout algorithm or the graph + representation +### + addNode: (id, content) -> + # testing if node is already existing in the graph + if @nodes[id] == undefined + @nodes[id] = new Graph.Node id, content + @nodes[id] + + addEdge: (source, target, style) -> + s = @addNode source + t = @addNode target + var edge = @edgeFactory.build s, t + jQuery.extend edge.style, style + s.edges.push edge + @edges.push edge + # NOTE: Even directed edges are added to both nodes. + t.edges.push edge + + # TODO to be implemented + # Preserve a copy of the graph state (nodes, positions, ...) + # @comment a comment describing the state + snapShot: (comment) -> + ###/* FIXME + var graph = new Graph() + graph.nodes = jQuery.extend(true, {}, @nodes) + graph.edges = jQuery.extend(true, {}, @edges) + @snapshots.push({comment: comment, graph: graph}) + */ + ### + + removeNode: (id) -> + delete @nodes[id] + for i = 0; i < @edges.length; i++ + if @edges[i].source.id == id || @edges[i].target.id == id + @edges.splice(i, 1) + i-- + +/* + * Node + */ +Graph.Node = (id, node) -> + node = node || {} + node.id = id + node.edges = [] + node.hide = -> + @hidden = true + @shape && @shape.hide() # FIXME this is representation specific code and should be elsewhere */ + for(i in @edges) + (@edges[i].source.id == id || @edges[i].target == id) && @edges[i].hide && @edges[i].hide() + + node.show = -> + @hidden = false + @shape && @shape.show() + for(i in @edges) + (@edges[i].source.id == id || @edges[i].target == id) && @edges[i].show && @edges[i].show() + + node + +Graph.Node.prototype = { } + +### + Renderer base class +### +Graph.Renderer = { } + +### + Renderer implementation using RaphaelJS +### +Graph.Renderer.Raphael = (element, graph, width, height) -> + @width = width || 400 + @height = height || 400 + var selfRef = this + @r = Raphael element, @width, @height + @radius = 40 # max dimension of a node + @graph = graph + @mouse_in = false + + # TODO default node rendering + if(!@graph.render) { + @graph.render = -> + return + } + } + + /* + * Dragging + */ + @isDrag = false + @dragger = (e) -> + @dx = e.clientX + @dy = e.clientY + selfRef.isDrag = this + @set && @set.animate "fill-opacity": .1, 200 && @set.toFront() + e.preventDefault && e.preventDefault() + + document.onmousemove = (e) { + e = e || window.event + if (selfRef.isDrag) { + var bBox = selfRef.isDrag.set.getBBox() + // TODO round the coordinates here (eg. for proper image representation) + var newX = e.clientX - selfRef.isDrag.dx + (bBox.x + bBox.width / 2) + var newY = e.clientY - selfRef.isDrag.dy + (bBox.y + bBox.height / 2) + /* prevent shapes from being dragged out of the canvas */ + var clientX = e.clientX - (newX < 20 ? newX - 20 : newX > selfRef.width - 20 ? newX - selfRef.width + 20 : 0) + var clientY = e.clientY - (newY < 20 ? newY - 20 : newY > selfRef.height - 20 ? newY - selfRef.height + 20 : 0) + selfRef.isDrag.set.translate(clientX - Math.round(selfRef.isDrag.dx), clientY - Math.round(selfRef.isDrag.dy)) + // console.log(clientX - Math.round(selfRef.isDrag.dx), clientY - Math.round(selfRef.isDrag.dy)) + for (var i in selfRef.graph.edges) { + selfRef.graph.edges[i].connection && selfRef.graph.edges[i].connection.draw() + } + //selfRef.r.safari() + selfRef.isDrag.dx = clientX + selfRef.isDrag.dy = clientY + } + } + document.onmouseup = -> + selfRef.isDrag && selfRef.isDrag.set.animate({"fill-opacity": .6}, 500) + selfRef.isDrag = false + } + @draw() +} +Graph.Renderer.Raphael.prototype = { + translate: (point) { + return [ + (point[0] - @graph.layoutMinX) * @factorX + @radius, + (point[1] - @graph.layoutMinY) * @factorY + @radius + ] + }, + + rotate: (point, length, angle) { + var dx = length * Math.cos(angle) + var dy = length * Math.sin(angle) + return [point[0]+dx, point[1]+dy] + }, + + draw: -> + @factorX = (@width - 2 * @radius) / (@graph.layoutMaxX - @graph.layoutMinX) + @factorY = (@height - 2 * @radius) / (@graph.layoutMaxY - @graph.layoutMinY) + for (i in @graph.nodes) { + @drawNode(@graph.nodes[i]) + } + for (var i = 0; i < @graph.edges.length; i++) { + @drawEdge(@graph.edges[i]) + } + }, + + drawNode: (node) { + var point = @translate([node.layoutPosX, node.layoutPosY]) + node.point = point + + /* if node has already been drawn, move the nodes */ + if(node.shape) { + var oBBox = node.shape.getBBox() + var opoint = { x: oBBox.x + oBBox.width / 2, y: oBBox.y + oBBox.height / 2} + node.shape.translate(Math.round(point[0] - opoint.x), Math.round(point[1] - opoint.y)) + @r.safari() + return node + }/* else, draw new nodes */ + + var shape + + /* if a node renderer is provided by the user, then use it + or the default render instead */ + if(!node.render) { + node.render = (r, node) { + /* the default node drawing */ + var color = Raphael.getColor() + var ellipse = r.ellipse(0, 0, 30, 20).attr({fill: color, stroke: color, "stroke-width": 2}) + /* set DOM node ID */ + ellipse.node.id = node.label || node.id + shape = r.set(). + push(ellipse). + push(r.text(0, 30, node.label || node.id)) + return shape + } + } + /* or check for an ajax representation of the nodes */ + if(node.shapes) { + // TODO ajax representation evaluation + } + + shape = node.render(@r, node).hide() + + shape.attr({"fill-opacity": .6}) + /* re-reference to the node an element belongs to, needed for dragging all elements of a node */ + shape.items.forEach((item){ item.set = shape; item.node.style.cursor = "move"; }) + shape.mousedown(@dragger) + + var box = shape.getBBox() + shape.translate(Math.round(point[0]-(box.x+box.width/2)),Math.round(point[1]-(box.y+box.height/2))) + //console.log(box,point) + node.hidden || shape.show() + node.shape = shape + }, + drawEdge: (edge) { + /* if this edge already exists the other way around and is undirected */ + if(edge.backedge) + return + if(edge.source.hidden || edge.target.hidden) { + edge.connection && edge.connection.fg.hide() | edge.connection.bg && edge.connection.bg.hide() + return + } + /* if edge already has been drawn, only refresh the edge */ + if(!edge.connection) { + edge.style && edge.style.callback && edge.style.callback(edge); // TODO move this somewhere else + edge.connection = @r.connection(edge.source.shape, edge.target.shape, edge.style) + return + } + //FIXME showing doesn't work well + edge.connection.fg.show() + edge.connection.bg && edge.connection.bg.show() + edge.connection.draw() + } +} +Graph.Layout = {} +Graph.Layout.Spring = (graph) { + @graph = graph + @iterations = 500 + @maxRepulsiveForceDistance = 6 + @k = 2 + @c = 0.01 + @maxVertexMovement = 0.5 + @layout() +} +Graph.Layout.Spring.prototype = { + layout: -> + @layoutPrepare() + for (var i = 0; i < @iterations; i++) { + @layoutIteration() + } + @layoutCalcBounds() + }, + + layoutPrepare: -> + for (i in @graph.nodes) { + var node = @graph.nodes[i] + node.layoutPosX = 0 + node.layoutPosY = 0 + node.layoutForceX = 0 + node.layoutForceY = 0 + } + + }, + + layoutCalcBounds: -> + var minx = Infinity, maxx = -Infinity, miny = Infinity, maxy = -Infinity + + for (i in @graph.nodes) { + var x = @graph.nodes[i].layoutPosX + var y = @graph.nodes[i].layoutPosY + + if(x > maxx) maxx = x + if(x < minx) minx = x + if(y > maxy) maxy = y + if(y < miny) miny = y + } + + @graph.layoutMinX = minx + @graph.layoutMaxX = maxx + @graph.layoutMinY = miny + @graph.layoutMaxY = maxy + }, + + layoutIteration: -> + // Forces on nodes due to node-node repulsions + + var prev = new Array() + for(var c in @graph.nodes) { + var node1 = @graph.nodes[c] + for (var d in prev) { + var node2 = @graph.nodes[prev[d]] + @layoutRepulsive(node1, node2) + + } + prev.push(c) + } + + // Forces on nodes due to edge attractions + for (var i = 0; i < @graph.edges.length; i++) { + var edge = @graph.edges[i] + @layoutAttractive(edge); + } + + // Move by the given force + for (i in @graph.nodes) { + var node = @graph.nodes[i] + var xmove = @c * node.layoutForceX + var ymove = @c * node.layoutForceY + + var max = @maxVertexMovement + if(xmove > max) xmove = max + if(xmove < -max) xmove = -max + if(ymove > max) ymove = max + if(ymove < -max) ymove = -max + + node.layoutPosX += xmove + node.layoutPosY += ymove + node.layoutForceX = 0 + node.layoutForceY = 0 + } + }, + + layoutRepulsive: (node1, node2) { + var dx = node2.layoutPosX - node1.layoutPosX + var dy = node2.layoutPosY - node1.layoutPosY + var d2 = dx * dx + dy * dy + if(d2 < 0.01) { + dx = 0.1 * Math.random() + 0.1 + dy = 0.1 * Math.random() + 0.1 + var d2 = dx * dx + dy * dy + } + var d = Math.sqrt(d2) + if(d < @maxRepulsiveForceDistance) { + var repulsiveForce = @k * @k / d + node2.layoutForceX += repulsiveForce * dx / d + node2.layoutForceY += repulsiveForce * dy / d + node1.layoutForceX -= repulsiveForce * dx / d + node1.layoutForceY -= repulsiveForce * dy / d + } + }, + + layoutAttractive: (edge) { + var node1 = edge.source + var node2 = edge.target + + var dx = node2.layoutPosX - node1.layoutPosX + var dy = node2.layoutPosY - node1.layoutPosY + var d2 = dx * dx + dy * dy + if(d2 < 0.01) { + dx = 0.1 * Math.random() + 0.1 + dy = 0.1 * Math.random() + 0.1 + var d2 = dx * dx + dy * dy + } + var d = Math.sqrt(d2) + if(d > @maxRepulsiveForceDistance) { + d = @maxRepulsiveForceDistance + d2 = d * d + } + var attractiveForce = (d2 - @k * @k) / @k + if(edge.attraction == undefined) edge.attraction = 1 + attractiveForce *= Math.log(edge.attraction) * 0.5 + 1 + + node2.layoutForceX -= attractiveForce * dx / d + node2.layoutForceY -= attractiveForce * dy / d + node1.layoutForceX += attractiveForce * dx / d + node1.layoutForceY += attractiveForce * dy / d + } +} + +Graph.Layout.Ordered = (graph, order) { + @graph = graph + @order = order + @layout() +} +Graph.Layout.Ordered.prototype = { + layout: -> + @layoutPrepare() + @layoutCalcBounds() + }, + + layoutPrepare: (order) { + for (i in @graph.nodes) { + var node = @graph.nodes[i] + node.layoutPosX = 0 + node.layoutPosY = 0 + } + var counter = 0 + for (i in @order) { + var node = @order[i] + node.layoutPosX = counter + node.layoutPosY = Math.random() + counter++ + } + }, + + layoutCalcBounds: -> + var minx = Infinity, maxx = -Infinity, miny = Infinity, maxy = -Infinity + + for (i in @graph.nodes) { + var x = @graph.nodes[i].layoutPosX + var y = @graph.nodes[i].layoutPosY + + if(x > maxx) maxx = x + if(x < minx) minx = x + if(y > maxy) maxy = y + if(y < miny) miny = y + } + + @graph.layoutMinX = minx + @graph.layoutMaxX = maxx + + @graph.layoutMinY = miny + @graph.layoutMaxY = maxy + } +} + +/* + * usefull JavaScript extensions, + */ + + log(a) {console.log&&console.log(a);} + +/* + * Raphael Tooltip Plugin + * - attaches an element as a tooltip to another element + * + * Usage example, adding a rectangle as a tooltip to a circle: + * + * paper.circle(100,100,10).tooltip(paper.rect(0,0,20,30)) + * + * If you want to use more shapes, you'll have to put them into a set. + * + */ +Raphael.el.tooltip = (tp) { + @tp = tp + @tp.o = {x: 0, y: 0} + @tp.hide() + @hover( + (event){ + @mousemove((event){ + @tp.translate(event.clientX - + @tp.o.x,event.clientY - @tp.o.y) + @tp.o = {x: event.clientX, y: event.clientY} + }) + @tp.show().toFront() + }, + (event){ + @tp.hide() + @unmousemove() + }) + return this +} + +/* For IE */ +if (!Array.prototype.forEach) +{ + Array.prototype.forEach = (fun /*, thisp*/) + { + var len = @length + if (typeof fun != "") + throw new TypeError() + + var thisp = arguments[1] + for (var i = 0; i < len; i++) + { + if (i in this) + fun.call(thisp, this[i], i, this) + } + } +} diff --git a/addons/base_diagram/static/lib/js/dracula_graph.js b/addons/base_diagram/static/lib/js/dracula_graph.js new file mode 100644 index 00000000000..f7069c5d2e5 --- /dev/null +++ b/addons/base_diagram/static/lib/js/dracula_graph.js @@ -0,0 +1,525 @@ +/* + * Dracula Graph Layout and Drawing Framework 0.0.3alpha + * (c) 2010 Philipp Strathausen , http://strathausen.eu + * Contributions by Jake Stothard . + * + * based on the Graph JavaScript framework, version 0.0.1 + * (c) 2006 Aslak Hellesoy + * (c) 2006 Dave Hoover + * + * Ported from Graph::Layouter::Spring in + * http://search.cpan.org/~pasky/Graph-Layderer-0.02/ + * The algorithm is based on a spring-style layouter of a Java-based social + * network tracker PieSpy written by Paul Mutton . + * + * This code is freely distributable under the MIT license. Commercial use is + * hereby granted without any cost or restriction. + * + * Links: + * + * Graph Dracula JavaScript Framework: + * http://graphdracula.net + * + /*--------------------------------------------------------------------------*/ + +/* + * Edge Factory + */ +var AbstractEdge = function() { +} +AbstractEdge.prototype = { + hide: function() { + this.connection.fg.hide(); + this.connection.bg && this.bg.connection.hide(); + } +}; +var EdgeFactory = function() { + this.template = new AbstractEdge(); + this.template.style = new Object(); + this.template.style.directed = false; + this.template.weight = 1; +}; +EdgeFactory.prototype = { + build: function(source, target) { + var e = jQuery.extend(true, {}, this.template); + e.source = source; + e.target = target; + return e; + } +}; + +/* + * Graph + */ +var Graph = function() { + this.nodes = {}; + this.edges = []; + this.snapshots = []; // previous graph states TODO to be implemented + this.edgeFactory = new EdgeFactory(); +}; +Graph.prototype = { + /* + * add a node + * @id the node's ID (string or number) + * @content (optional, dictionary) can contain any information that is + * being interpreted by the layout algorithm or the graph + * representation + */ + addNode: function(id, content) { + /* testing if node is already existing in the graph */ + if(this.nodes[id] == undefined) { + this.nodes[id] = new Graph.Node(id, content); + } + return this.nodes[id]; + }, + + addEdge: function(source, target, style) { + var s = this.addNode(source); + var t = this.addNode(target); + var edge = this.edgeFactory.build(s, t); + jQuery.extend(edge.style,style); + s.edges.push(edge); + this.edges.push(edge); + // NOTE: Even directed edges are added to both nodes. + t.edges.push(edge); + }, + + /* TODO to be implemented + * Preserve a copy of the graph state (nodes, positions, ...) + * @comment a comment describing the state + */ + snapShot: function(comment) { + /* FIXME + var graph = new Graph(); + graph.nodes = jQuery.extend(true, {}, this.nodes); + graph.edges = jQuery.extend(true, {}, this.edges); + this.snapshots.push({comment: comment, graph: graph}); + */ + }, + removeNode: function(id) { + delete this.nodes[id]; + for(var i = 0; i < this.edges.length; i++) { + if (this.edges[i].source.id == id || this.edges[i].target.id == id) { + this.edges.splice(i, 1); + i--; + } + } + } +}; + +/* + * Node + */ +Graph.Node = function(id, node){ + node = node || {}; + node.id = id; + node.edges = []; + node.hide = function() { + this.hidden = true; + this.shape && this.shape.hide(); /* FIXME this is representation specific code and should be elsewhere */ + for(i in this.edges) + (this.edges[i].source.id == id || this.edges[i].target == id) && this.edges[i].hide && this.edges[i].hide(); + }; + node.show = function() { + this.hidden = false; + this.shape && this.shape.show(); + for(i in this.edges) + (this.edges[i].source.id == id || this.edges[i].target == id) && this.edges[i].show && this.edges[i].show(); + }; + return node; +}; +Graph.Node.prototype = { +}; + +/* + * Renderer base class + */ +Graph.Renderer = {}; + +/* + * Renderer implementation using RaphaelJS + */ +Graph.Renderer.Raphael = function(element, graph, width, height) { + this.width = width || 800; + this.height = height || 800; + var selfRef = this; + this.r = Raphael(element, this.width, this.height); + this.radius = 40; /* max dimension of a node */ + this.graph = graph; + this.mouse_in = false; + + /* TODO default node rendering function */ + if(!this.graph.render) { + this.graph.render = function() { + return; + } + } + + /* + * Dragging + */ + this.isDrag = false; + this.dragger = function (e) { + this.dx = e.clientX; + this.dy = e.clientY; + selfRef.isDrag = this; + this.set && this.set.animate({"fill-opacity": .1}, 200) && this.set.toFront(); + e.preventDefault && e.preventDefault(); + }; + + var d = document.getElementById(element); + d.onmousemove = function (e) { + e = e || window.event; + if (selfRef.isDrag) { + var bBox = selfRef.isDrag.set.getBBox(); + // TODO round the coordinates here (eg. for proper image representation) + var newX = e.clientX - selfRef.isDrag.dx + (bBox.x + bBox.width / 2); + var newY = e.clientY - selfRef.isDrag.dy + (bBox.y + bBox.height / 2); + /* prevent shapes from being dragged out of the canvas */ + var clientX = e.clientX - (newX < 20 ? newX - 20 : newX > selfRef.width - 20 ? newX - selfRef.width + 20 : 0); + var clientY = e.clientY - (newY < 20 ? newY - 20 : newY > selfRef.height - 20 ? newY - selfRef.height + 20 : 0); + selfRef.isDrag.set.translate(clientX - Math.round(selfRef.isDrag.dx), clientY - Math.round(selfRef.isDrag.dy)); + // console.log(clientX - Math.round(selfRef.isDrag.dx), clientY - Math.round(selfRef.isDrag.dy)); + for (var i in selfRef.graph.edges) { + selfRef.graph.edges[i].connection && selfRef.graph.edges[i].connection.draw(); + } + //selfRef.r.safari(); + selfRef.isDrag.dx = clientX; + selfRef.isDrag.dy = clientY; + } + }; + d.onmouseup = function () { + selfRef.isDrag && selfRef.isDrag.set.animate({"fill-opacity": .6}, 500); + selfRef.isDrag = false; + }; + this.draw(); +}; +Graph.Renderer.Raphael.prototype = { + translate: function(point) { + return [ + (point[0] - this.graph.layoutMinX) * this.factorX + this.radius, + (point[1] - this.graph.layoutMinY) * this.factorY + this.radius + ]; + }, + + rotate: function(point, length, angle) { + var dx = length * Math.cos(angle); + var dy = length * Math.sin(angle); + return [point[0]+dx, point[1]+dy]; + }, + + draw: function() { + this.factorX = (this.width - 2 * this.radius) / (this.graph.layoutMaxX - this.graph.layoutMinX); + this.factorY = (this.height - 2 * this.radius) / (this.graph.layoutMaxY - this.graph.layoutMinY); + for (i in this.graph.nodes) { + this.drawNode(this.graph.nodes[i]); + } + for (var i = 0; i < this.graph.edges.length; i++) { + this.drawEdge(this.graph.edges[i]); + } + }, + + drawNode: function(node) { + var point = this.translate([node.layoutPosX, node.layoutPosY]); + node.point = point; + + /* if node has already been drawn, move the nodes */ + if(node.shape) { + var oBBox = node.shape.getBBox(); + var opoint = { x: oBBox.x + oBBox.width / 2, y: oBBox.y + oBBox.height / 2}; + node.shape.translate(Math.round(point[0] - opoint.x), Math.round(point[1] - opoint.y)); + this.r.safari(); + return node; + }/* else, draw new nodes */ + + var shape; + + /* if a node renderer function is provided by the user, then use it + or the default render function instead */ + if(!node.render) { + node.render = function(r, node) { + /* the default node drawing */ + var color = Raphael.getColor(); + var ellipse = r.ellipse(0, 0, 30, 20).attr({fill: color, stroke: color, "stroke-width": 2}); + /* set DOM node ID */ + ellipse.node.id = node.label || node.id; + shape = r.set(). + push(ellipse). + push(r.text(0, 30, node.label || node.id)); + return shape; + } + } + /* or check for an ajax representation of the nodes */ + if(node.shapes) { + // TODO ajax representation evaluation + } + + shape = node.render(this.r, node).hide(); + + shape.attr({"fill-opacity": .6}); + /* re-reference to the node an element belongs to, needed for dragging all elements of a node */ + shape.items.forEach(function(item){ item.set = shape; item.node.style.cursor = "move"; }); + shape.mousedown(this.dragger); + + var box = shape.getBBox(); + shape.translate(Math.round(point[0]-(box.x+box.width/2)),Math.round(point[1]-(box.y+box.height/2))) + //console.log(box,point); + node.hidden || shape.show(); + node.shape = shape; + }, + drawEdge: function(edge) { + /* if this edge already exists the other way around and is undirected */ + if(edge.backedge) + return; + if(edge.source.hidden || edge.target.hidden) { + edge.connection && edge.connection.fg.hide() | edge.connection.bg && edge.connection.bg.hide(); + return; + } + /* if edge already has been drawn, only refresh the edge */ + if(!edge.connection) { + edge.style && edge.style.callback && edge.style.callback(edge); // TODO move this somewhere else + edge.connection = this.r.connection(edge.source.shape, edge.target.shape, edge.style); + return; + } + //FIXME showing doesn't work well + edge.connection.fg.show(); + edge.connection.bg && edge.connection.bg.show(); + edge.connection.draw(); + } +}; +Graph.Layout = {}; +Graph.Layout.Spring = function(graph) { + this.graph = graph; + this.iterations = 500; + this.maxRepulsiveForceDistance = 6; + this.k = 2; + this.c = 0.01; + this.maxVertexMovement = 0.5; + this.layout(); +}; +Graph.Layout.Spring.prototype = { + layout: function() { + this.layoutPrepare(); + for (var i = 0; i < this.iterations; i++) { + this.layoutIteration(); + } + this.layoutCalcBounds(); + }, + + layoutPrepare: function() { + for (i in this.graph.nodes) { + var node = this.graph.nodes[i]; + node.layoutPosX = 0; + node.layoutPosY = 0; + node.layoutForceX = 0; + node.layoutForceY = 0; + } + + }, + + layoutCalcBounds: function() { + var minx = Infinity, maxx = -Infinity, miny = Infinity, maxy = -Infinity; + + for (i in this.graph.nodes) { + var x = this.graph.nodes[i].layoutPosX; + var y = this.graph.nodes[i].layoutPosY; + + if(x > maxx) maxx = x; + if(x < minx) minx = x; + if(y > maxy) maxy = y; + if(y < miny) miny = y; + } + + this.graph.layoutMinX = minx; + this.graph.layoutMaxX = maxx; + this.graph.layoutMinY = miny; + this.graph.layoutMaxY = maxy; + }, + + layoutIteration: function() { + // Forces on nodes due to node-node repulsions + + var prev = new Array(); + for(var c in this.graph.nodes) { + var node1 = this.graph.nodes[c]; + for (var d in prev) { + var node2 = this.graph.nodes[prev[d]]; + this.layoutRepulsive(node1, node2); + + } + prev.push(c); + } + + // Forces on nodes due to edge attractions + for (var i = 0; i < this.graph.edges.length; i++) { + var edge = this.graph.edges[i]; + this.layoutAttractive(edge); + } + + // Move by the given force + for (i in this.graph.nodes) { + var node = this.graph.nodes[i]; + var xmove = this.c * node.layoutForceX; + var ymove = this.c * node.layoutForceY; + + var max = this.maxVertexMovement; + if(xmove > max) xmove = max; + if(xmove < -max) xmove = -max; + if(ymove > max) ymove = max; + if(ymove < -max) ymove = -max; + + node.layoutPosX += xmove; + node.layoutPosY += ymove; + node.layoutForceX = 0; + node.layoutForceY = 0; + } + }, + + layoutRepulsive: function(node1, node2) { + var dx = node2.layoutPosX - node1.layoutPosX; + var dy = node2.layoutPosY - node1.layoutPosY; + var d2 = dx * dx + dy * dy; + if(d2 < 0.01) { + dx = 0.1 * Math.random() + 0.1; + dy = 0.1 * Math.random() + 0.1; + var d2 = dx * dx + dy * dy; + } + var d = Math.sqrt(d2); + if(d < this.maxRepulsiveForceDistance) { + var repulsiveForce = this.k * this.k / d; + node2.layoutForceX += repulsiveForce * dx / d; + node2.layoutForceY += repulsiveForce * dy / d; + node1.layoutForceX -= repulsiveForce * dx / d; + node1.layoutForceY -= repulsiveForce * dy / d; + } + }, + + layoutAttractive: function(edge) { + var node1 = edge.source; + var node2 = edge.target; + + var dx = node2.layoutPosX - node1.layoutPosX; + var dy = node2.layoutPosY - node1.layoutPosY; + var d2 = dx * dx + dy * dy; + if(d2 < 0.01) { + dx = 0.1 * Math.random() + 0.1; + dy = 0.1 * Math.random() + 0.1; + var d2 = dx * dx + dy * dy; + } + var d = Math.sqrt(d2); + if(d > this.maxRepulsiveForceDistance) { + d = this.maxRepulsiveForceDistance; + d2 = d * d; + } + var attractiveForce = (d2 - this.k * this.k) / this.k; + if(edge.attraction == undefined) edge.attraction = 1; + attractiveForce *= Math.log(edge.attraction) * 0.5 + 1; + + node2.layoutForceX -= attractiveForce * dx / d; + node2.layoutForceY -= attractiveForce * dy / d; + node1.layoutForceX += attractiveForce * dx / d; + node1.layoutForceY += attractiveForce * dy / d; + } +}; + +Graph.Layout.Ordered = function(graph, order) { + this.graph = graph; + this.order = order; + this.layout(); +}; +Graph.Layout.Ordered.prototype = { + layout: function() { + this.layoutPrepare(); + this.layoutCalcBounds(); + }, + + layoutPrepare: function(order) { + for (i in this.graph.nodes) { + var node = this.graph.nodes[i]; + node.layoutPosX = 0; + node.layoutPosY = 0; + } + var counter = 0; + for (i in this.order) { + var node = this.order[i]; + node.layoutPosX = counter; + node.layoutPosY = Math.random(); + counter++; + } + }, + + layoutCalcBounds: function() { + var minx = Infinity, maxx = -Infinity, miny = Infinity, maxy = -Infinity; + + for (i in this.graph.nodes) { + var x = this.graph.nodes[i].layoutPosX; + var y = this.graph.nodes[i].layoutPosY; + + if(x > maxx) maxx = x; + if(x < minx) minx = x; + if(y > maxy) maxy = y; + if(y < miny) miny = y; + } + + this.graph.layoutMinX = minx; + this.graph.layoutMaxX = maxx; + + this.graph.layoutMinY = miny; + this.graph.layoutMaxY = maxy; + } +}; + +/* + * usefull JavaScript extensions, + */ + +function log(a) {console.log&&console.log(a);} + +/* + * Raphael Tooltip Plugin + * - attaches an element as a tooltip to another element + * + * Usage example, adding a rectangle as a tooltip to a circle: + * + * paper.circle(100,100,10).tooltip(paper.rect(0,0,20,30)); + * + * If you want to use more shapes, you'll have to put them into a set. + * + */ +Raphael.el.tooltip = function (tp) { + this.tp = tp; + this.tp.o = {x: 0, y: 0}; + this.tp.hide(); + this.hover( + function(event){ + this.mousemove(function(event){ + this.tp.translate(event.clientX - + this.tp.o.x,event.clientY - this.tp.o.y); + this.tp.o = {x: event.clientX, y: event.clientY}; + }); + this.tp.show().toFront(); + }, + function(event){ + this.tp.hide(); + this.unmousemove(); + }); + return this; +}; + +/* For IE */ +if (!Array.prototype.forEach) +{ + Array.prototype.forEach = function(fun /*, thisp*/) + { + var len = this.length; + if (typeof fun != "function") + throw new TypeError(); + + var thisp = arguments[1]; + for (var i = 0; i < len; i++) + { + if (i in this) + fun.call(thisp, this[i], i, this); + } + }; +} diff --git a/addons/base_diagram/static/lib/js/raphael-min.js b/addons/base_diagram/static/lib/js/raphael-min.js new file mode 100644 index 00000000000..8718b5bc749 --- /dev/null +++ b/addons/base_diagram/static/lib/js/raphael-min.js @@ -0,0 +1,7 @@ +/* + * Raphael 1.3.1 - JavaScript Vector Library + * + * Copyright (c) 2008 - 2009 Dmitry Baranovskiy (http://raphaeljs.com) + * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. + */ +Raphael=(function(){var a=/[, ]+/,aO=/^(circle|rect|path|ellipse|text|image)$/,L=document,au=window,l={was:"Raphael" in au,is:au.Raphael},an=function(){if(an.is(arguments[0],"array")){var d=arguments[0],e=w[aW](an,d.splice(0,3+an.is(d[0],al))),S=e.set();for(var R=0,a0=d[m];R

";if(ag.childNodes[m]!=2){return null;}}an.svg=!(an.vml=an.type=="VML");aT[aY]=an[aY];an._id=0;an._oid=0;an.fn={};an.is=function(e,d){d=aZ.call(d);return((d=="object"||d=="undefined")&&typeof e==d)||(e==null&&d=="null")||aZ.call(aw.call(e).slice(8,-1))==d;};an.setWindow=function(d){au=d;L=au.document;};var aD=function(e){if(an.vml){var d=/^\s+|\s+$/g;aD=aj(function(R){var S;R=(R+at)[aP](d,at);try{var a0=new ActiveXObject("htmlfile");a0.write("");a0.close();S=a0.body;}catch(a2){S=createPopup().document.body;}var i=S.createTextRange();try{S.style.color=R;var a1=i.queryCommandValue("ForeColor");a1=((a1&255)<<16)|(a1&65280)|((a1&16711680)>>>16);return"#"+("000000"+a1[aA](16)).slice(-6);}catch(a2){return"none";}});}else{var E=L.createElement("i");E.title="Rapha\xebl Colour Picker";E.style.display="none";L.body[aL](E);aD=aj(function(i){E.style.color=i;return L.defaultView.getComputedStyle(E,at).getPropertyValue("color");});}return aD(e);};an.hsb2rgb=aj(function(a3,a1,a7){if(an.is(a3,"object")&&"h" in a3&&"s" in a3&&"b" in a3){a7=a3.b;a1=a3.s;a3=a3.h;}var R,S,a8;if(a7==0){return{r:0,g:0,b:0,hex:"#000"};}if(a3>1||a1>1||a7>1){a3/=255;a1/=255;a7/=255;}var a0=~~(a3*6),a4=(a3*6)-a0,E=a7*(1-a1),e=a7*(1-(a1*a4)),a9=a7*(1-(a1*(1-a4)));R=[a7,e,E,E,a9,a7,a7][a0];S=[a9,a7,a7,e,E,E,a9][a0];a8=[E,E,a9,a7,a7,e,E][a0];R*=255;S*=255;a8*=255;var a5={r:R,g:S,b:a8},d=(~~R)[aA](16),a2=(~~S)[aA](16),a6=(~~a8)[aA](16);d=d[aP](aU,"0");a2=a2[aP](aU,"0");a6=a6[aP](aU,"0");a5.hex="#"+d+a2+a6;return a5;},an);an.rgb2hsb=aj(function(d,e,a1){if(an.is(d,"object")&&"r" in d&&"g" in d&&"b" in d){a1=d.b;e=d.g;d=d.r;}if(an.is(d,"string")){var a3=an.getRGB(d);d=a3.r;e=a3.g;a1=a3.b;}if(d>1||e>1||a1>1){d/=255;e/=255;a1/=255;}var a0=g(d,e,a1),i=aI(d,e,a1),R,E,S=a0;if(i==a0){return{h:0,s:0,b:a0};}else{var a2=(a0-i);E=a2/a0;if(d==a0){R=(e-a1)/a2;}else{if(e==a0){R=2+((a1-d)/a2);}else{R=4+((d-e)/a2);}}R/=6;R<0&&R++;R>1&&R--;}return{h:R,s:E,b:S};},an);var aE=/,?([achlmqrstvxz]),?/gi;an._path2string=function(){return this.join(",")[aP](aE,"$1");};function aj(E,e,d){function i(){var R=Array[aY].slice.call(arguments,0),a0=R[az]("\u25ba"),S=i.cache=i.cache||{},a1=i.count=i.count||[];if(S[Q](a0)){return d?d(S[a0]):S[a0];}a1[m]>=1000&&delete S[a1.shift()];a1[f](a0);S[a0]=E[aW](e,R);return d?d(S[a0]):S[a0];}return i;}an.getRGB=aj(function(d){if(!d||!!((d=d+at).indexOf("-")+1)){return{r:-1,g:-1,b:-1,hex:"none",error:1};}if(d=="none"){return{r:-1,g:-1,b:-1,hex:"none"};}!(({hs:1,rg:1})[Q](d.substring(0,2))||d.charAt()=="#")&&(d=aD(d));var S,i,E,a2,a3,a0=d.match(x);if(a0){if(a0[2]){a2=G(a0[2].substring(5),16);E=G(a0[2].substring(3,5),16);i=G(a0[2].substring(1,3),16);}if(a0[3]){a2=G((a3=a0[3].charAt(3))+a3,16);E=G((a3=a0[3].charAt(2))+a3,16);i=G((a3=a0[3].charAt(1))+a3,16);}if(a0[4]){a0=a0[4][z](/\s*,\s*/);i=W(a0[0]);E=W(a0[1]);a2=W(a0[2]);}if(a0[5]){a0=a0[5][z](/\s*,\s*/);i=W(a0[0])*2.55;E=W(a0[1])*2.55;a2=W(a0[2])*2.55;}if(a0[6]){a0=a0[6][z](/\s*,\s*/);i=W(a0[0]);E=W(a0[1]);a2=W(a0[2]);return an.hsb2rgb(i,E,a2);}if(a0[7]){a0=a0[7][z](/\s*,\s*/);i=W(a0[0])*2.55;E=W(a0[1])*2.55;a2=W(a0[2])*2.55;return an.hsb2rgb(i,E,a2);}a0={r:i,g:E,b:a2};var e=(~~i)[aA](16),R=(~~E)[aA](16),a1=(~~a2)[aA](16);e=e[aP](aU,"0");R=R[aP](aU,"0");a1=a1[aP](aU,"0");a0.hex="#"+e+R+a1;return a0;}return{r:-1,g:-1,b:-1,hex:"none",error:1};},an);an.getColor=function(e){var i=this.getColor.start=this.getColor.start||{h:0,s:1,b:e||0.75},d=this.hsb2rgb(i.h,i.s,i.b);i.h+=0.075;if(i.h>1){i.h=0;i.s-=0.2;i.s<=0&&(this.getColor.start={h:0,s:1,b:i.b});}return d.hex;};an.getColor.reset=function(){delete this.start;};an.parsePathString=aj(function(d){if(!d){return null;}var i={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},e=[];if(an.is(d,"array")&&an.is(d[0],"array")){e=av(d);}if(!e[m]){(d+at)[aP](/([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig,function(R,E,a1){var a0=[],S=aZ.call(E);a1[aP](/(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig,function(a3,a2){a2&&a0[f](+a2);});while(a0[m]>=i[S]){e[f]([E][aS](a0.splice(0,i[S])));if(!i[S]){break;}}});}e[aA]=an._path2string;return e;});an.findDotsAtSegment=function(e,d,be,bc,a0,R,a2,a1,a8){var a6=1-a8,a5=aM(a6,3)*e+aM(a6,2)*3*a8*be+a6*3*a8*a8*a0+aM(a8,3)*a2,a3=aM(a6,3)*d+aM(a6,2)*3*a8*bc+a6*3*a8*a8*R+aM(a8,3)*a1,ba=e+2*a8*(be-e)+a8*a8*(a0-2*be+e),a9=d+2*a8*(bc-d)+a8*a8*(R-2*bc+d),bd=be+2*a8*(a0-be)+a8*a8*(a2-2*a0+be),bb=bc+2*a8*(R-bc)+a8*a8*(a1-2*R+bc),a7=(1-a8)*e+a8*be,a4=(1-a8)*d+a8*bc,E=(1-a8)*a0+a8*a2,i=(1-a8)*R+a8*a1,S=(90-ab.atan((ba-bd)/(a9-bb))*180/ab.PI);(ba>bd||a91){bi=ab.sqrt(by)*bi;bg=ab.sqrt(by)*bg;}var E=bi*bi,br=bg*bg,bt=(a4==S?-1:1)*ab.sqrt(ab.abs((E*br-E*bn*bn-br*bo*bo)/(E*bn*bn+br*bo*bo))),bd=bt*bi*bn/bg+(a9+a8)/2,bc=bt*-bg*bo/bi+(bE+bD)/2,a3=ab.asin(((bE-bc)/bg).toFixed(7)),a2=ab.asin(((bD-bc)/bg).toFixed(7));a3=a9a2){a3=a3-R*2;}if(!S&&a2>a3){a2=a2-R*2;}}else{a3=bb[0];a2=bb[1];bd=bb[2];bc=bb[3];}var a7=a2-a3;if(ab.abs(a7)>bf){var be=a2,bh=a8,a5=bD;a2=a3+bf*(S&&a2>a3?1:-1);a8=bd+bi*ab.cos(a2);bD=bc+bg*ab.sin(a2);bm=K(a8,bD,bi,bg,ba,0,S,bh,a5,[a2,be,bd,bc]);}a7=a2-a3;var a1=ab.cos(a3),bC=ab.sin(a3),a0=ab.cos(a2),bB=ab.sin(a2),bp=ab.tan(a7/4),bs=4/3*bi*bp,bq=4/3*bg*bp,bz=[a9,bE],bx=[a9+bs*bC,bE-bq*a1],bw=[a8+bs*bB,bD-bq*a0],bu=[a8,bD];bx[0]=2*bz[0]-bx[0];bx[1]=2*bz[1]-bx[1];if(bb){return[bx,bw,bu][aS](bm);}else{bm=[bx,bw,bu][aS](bm)[az]()[z](",");var bk=[];for(var bv=0,bl=bm[m];bv1000000000000&&(a0=0.5);ab.abs(S)>1000000000000&&(S=0.5);if(a0>0&&a0<1){e=M(i,d,R,E,a9,a8,a5,a2,a0);a6[f](e.x);a3[f](e.y);}if(S>0&&S<1){e=M(i,d,R,E,a9,a8,a5,a2,S);a6[f](e.x);a3[f](e.y);}a7=(a8-2*E+d)-(a2-2*a8+E);a4=2*(E-d)-2*(a8-E);a1=d-E;a0=(-a4+ab.sqrt(a4*a4-4*a7*a1))/2/a7;S=(-a4-ab.sqrt(a4*a4-4*a7*a1))/2/a7;ab.abs(a0)>1000000000000&&(a0=0.5);ab.abs(S)>1000000000000&&(S=0.5);if(a0>0&&a0<1){e=M(i,d,R,E,a9,a8,a5,a2,a0);a6[f](e.x);a3[f](e.y);}if(S>0&&S<1){e=M(i,d,R,E,a9,a8,a5,a2,S);a6[f](e.x);a3[f](e.y);}return{min:{x:aI[aW](0,a6),y:aI[aW](0,a3)},max:{x:g[aW](0,a6),y:g[aW](0,a3)}};}),H=aj(function(a9,a4){var R=r(a9),a5=a4&&r(a4),a6={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},d={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},a0=function(ba,bb){var i,bc;if(!ba){return["C",bb.x,bb.y,bb.x,bb.y,bb.x,bb.y];}!(ba[0] in {T:1,Q:1})&&(bb.qx=bb.qy=null);switch(ba[0]){case"M":bb.X=ba[1];bb.Y=ba[2];break;case"A":ba=["C"][aS](K[aW](0,[bb.x,bb.y][aS](ba.slice(1))));break;case"S":i=bb.x+(bb.x-(bb.bx||bb.x));bc=bb.y+(bb.y-(bb.by||bb.y));ba=["C",i,bc][aS](ba.slice(1));break;case"T":bb.qx=bb.x+(bb.x-(bb.qx||bb.x));bb.qy=bb.y+(bb.y-(bb.qy||bb.y));ba=["C"][aS](aK(bb.x,bb.y,bb.qx,bb.qy,ba[1],ba[2]));break;case"Q":bb.qx=ba[1];bb.qy=ba[2];ba=["C"][aS](aK(bb.x,bb.y,ba[1],ba[2],ba[3],ba[4]));break;case"L":ba=["C"][aS](aX(bb.x,bb.y,ba[1],ba[2]));break;case"H":ba=["C"][aS](aX(bb.x,bb.y,ba[1],bb.y));break;case"V":ba=["C"][aS](aX(bb.x,bb.y,bb.x,ba[1]));break;case"Z":ba=["C"][aS](aX(bb.x,bb.y,bb.X,bb.Y));break;}return ba;},e=function(ba,bb){if(ba[bb][m]>7){ba[bb].shift();var bc=ba[bb];while(bc[m]){ba.splice(bb++,0,["C"][aS](bc.splice(0,6)));}ba.splice(bb,1);a7=g(R[m],a5&&a5[m]||0);}},E=function(be,bd,bb,ba,bc){if(be&&bd&&be[bc][0]=="M"&&bd[bc][0]!="M"){bd.splice(bc,0,["M",ba.x,ba.y]);bb.bx=0;bb.by=0;bb.x=be[bc][1];bb.y=be[bc][2];a7=g(R[m],a5&&a5[m]||0);}};for(var a2=0,a7=g(R[m],a5&&a5[m]||0);a23){return{container:1,x:arguments[0],y:arguments[1],width:arguments[2],height:arguments[3]};}}},aG=function(d,i){var e=this;for(var E in i){if(i[Q](E)&&!(E in d)){switch(typeof i[E]){case"function":(function(R){d[E]=d===e?R:function(){return R[aW](e,arguments);};})(i[E]);break;case"object":d[E]=d[E]||{};aG.call(this,d[E],i[E]);break;default:d[E]=i[E];break;}}}},ak=function(d,e){d==e.top&&(e.top=d.prev);d==e.bottom&&(e.bottom=d.next);d.next&&(d.next.prev=d.prev);d.prev&&(d.prev.next=d.next);},Y=function(d,e){if(e.top===d){return;}ak(d,e);d.next=null;d.prev=e.top;e.top.next=d;e.top=d;},k=function(d,e){if(e.bottom===d){return;}ak(d,e);d.next=e.bottom;d.prev=null;e.bottom.prev=d;e.bottom=d;},A=function(e,d,i){ak(e,i);d==i.top&&(i.top=e);d.next&&(d.next.prev=e);e.next=d.next;e.prev=d;d.next=e;},aq=function(e,d,i){ak(e,i);d==i.bottom&&(i.bottom=e);d.prev&&(d.prev.next=e);e.prev=d.prev;d.prev=e;e.next=d;},s=function(d){return function(){throw new Error("Rapha\xebl: you are calling to method \u201c"+d+"\u201d of removed object");};},ar=/^r(?:\(([^,]+?)\s*,\s*([^\)]+?)\))?/;if(an.svg){aT[aY].svgns="http://www.w3.org/2000/svg";aT[aY].xlink="http://www.w3.org/1999/xlink";var O=function(d){return +d+(~~d===d)*0.5;},V=function(S){for(var e=0,E=S[m];e0.5)*2-1);aM(a1-0.5,2)+aM(S-0.5,2)>0.25&&(S=ab.sqrt(0.25-aM(a1-0.5,2))*ba+0.5)&&S!=0.5&&(S=S.toFixed(5)-0.00001*ba);}return at;});a7=a7[z](/\s*\-\s*/);if(a4=="linear"){var a0=a7.shift();a0=-W(a0);if(isNaN(a0)){return null;}var R=[0,0,ab.cos(a0*ab.PI/180),ab.sin(a0*ab.PI/180)],a6=1/(g(ab.abs(R[2]),ab.abs(R[3]))||1);R[2]*=a6;R[3]*=a6;if(R[2]<0){R[0]=-R[2];R[2]=0;}if(R[3]<0){R[1]=-R[3];R[3]=0;}}var a3=p(a7);if(!a3){return null;}var e=aJ(a4+"Gradient");e.id="r"+(an._id++)[aA](36);aJ(e,a4=="radial"?{fx:a1,fy:S}:{x1:R[0],y1:R[1],x2:R[2],y2:R[3]});d.defs[aL](e);for(var a2=0,a8=a3[m];a2a1.height)&&(a1.height=a0.y+a0.height-a1.y);(a0.x+a0.width-a1.x>a1.width)&&(a1.width=a0.x+a0.width-a1.x);}}E&&this.hide();return a1;};ax[aY].attr=function(){if(this.removed){return this;}if(arguments[m]==0){var R={};for(var E in this.attrs){if(this.attrs[Q](E)){R[E]=this.attrs[E];}}this._.rt.deg&&(R.rotation=this.rotate());(this._.sx!=1||this._.sy!=1)&&(R.scale=this.scale());R.gradient&&R.fill=="none"&&(R.fill=R.gradient)&&delete R.gradient;return R;}if(arguments[m]==1&&an.is(arguments[0],"string")){if(arguments[0]=="translation"){return t.call(this);}if(arguments[0]=="rotation"){return this.rotate();}if(arguments[0]=="scale"){return this.scale();}if(arguments[0]=="fill"&&this.attrs.fill=="none"&&this.attrs.gradient){return this.attrs.gradient;}return this.attrs[arguments[0]];}if(arguments[m]==1&&an.is(arguments[0],"array")){var d={};for(var e in arguments[0]){if(arguments[0][Q](e)){d[arguments[0][e]]=this.attrs[arguments[0][e]];}}return d;}if(arguments[m]==2){var S={};S[arguments[0]]=arguments[1];aa(this,S);}else{if(arguments[m]==1&&an.is(arguments[0],"object")){aa(this,arguments[0]);}}return this;};ax[aY].toFront=function(){if(this.removed){return this;}this.node.parentNode[aL](this.node);var d=this.paper;d.top!=this&&Y(this,d);return this;};ax[aY].toBack=function(){if(this.removed){return this;}if(this.node.parentNode.firstChild!=this.node){this.node.parentNode.insertBefore(this.node,this.node.parentNode.firstChild);k(this,this.paper);var d=this.paper;}return this;};ax[aY].insertAfter=function(d){if(this.removed){return this;}var e=d.node;if(e.nextSibling){e.parentNode.insertBefore(this.node,e.nextSibling);}else{e.parentNode[aL](this.node);}A(this,d,this.paper);return this;};ax[aY].insertBefore=function(d){if(this.removed){return this;}var e=d.node;e.parentNode.insertBefore(this.node,e);aq(this,d,this.paper);return this;};var P=function(e,d,S,R){d=O(d);S=O(S);var E=aJ("circle");e.canvas&&e.canvas[aL](E);var i=new ax(E,e);i.attrs={cx:d,cy:S,r:R,fill:"none",stroke:"#000"};i.type="circle";aJ(E,i.attrs);return i;};var aF=function(i,d,a1,e,S,a0){d=O(d);a1=O(a1);var R=aJ("rect");i.canvas&&i.canvas[aL](R);var E=new ax(R,i);E.attrs={x:d,y:a1,width:e,height:S,r:a0||0,rx:a0||0,ry:a0||0,fill:"none",stroke:"#000"};E.type="rect";aJ(R,E.attrs);return E;};var ai=function(e,d,a0,S,R){d=O(d);a0=O(a0);var E=aJ("ellipse");e.canvas&&e.canvas[aL](E);var i=new ax(E,e);i.attrs={cx:d,cy:a0,rx:S,ry:R,fill:"none",stroke:"#000"};i.type="ellipse";aJ(E,i.attrs);return i;};var o=function(i,a0,d,a1,e,S){var R=aJ("image");aJ(R,{x:d,y:a1,width:e,height:S,preserveAspectRatio:"none"});R.setAttributeNS(i.xlink,"href",a0);i.canvas&&i.canvas[aL](R);var E=new ax(R,i);E.attrs={x:d,y:a1,width:e,height:S,src:a0};E.type="image";return E;};var X=function(e,d,S,R){var E=aJ("text");aJ(E,{x:d,y:S,"text-anchor":"middle"});e.canvas&&e.canvas[aL](E);var i=new ax(E,e);i.attrs={x:d,y:S,"text-anchor":"middle",text:R,font:j.font,stroke:"none",fill:"#000"};i.type="text";aa(i,i.attrs);return i;};var aV=function(e,d){this.width=e||this.width;this.height=d||this.height;this.canvas[v]("width",this.width);this.canvas[v]("height",this.height);return this;};var w=function(){var E=ao[aW](null,arguments),i=E&&E.container,e=E.x,a0=E.y,R=E.width,d=E.height;if(!i){throw new Error("SVG container not found.");}var S=aJ("svg");R=R||512;d=d||342;aJ(S,{xmlns:"http://www.w3.org/2000/svg",version:1.1,width:R,height:d});if(i==1){S.style.cssText="position:absolute;left:"+e+"px;top:"+a0+"px";L.body[aL](S);}else{if(i.firstChild){i.insertBefore(S,i.firstChild);}else{i[aL](S);}}i=new aT;i.width=R;i.height=d;i.canvas=S;aG.call(i,i,an.fn);i.clear();return i;};aT[aY].clear=function(){var d=this.canvas;while(d.firstChild){d.removeChild(d.firstChild);}this.bottom=this.top=null;(this.desc=aJ("desc"))[aL](L.createTextNode("Created with Rapha\xebl"));d[aL](this.desc);d[aL](this.defs=aJ("defs"));};aT[aY].remove=function(){this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas);for(var d in this){this[d]=s(d);}};}if(an.vml){var aH=function(a8){var a5=/[ahqstv]/ig,a0=r;(a8+at).match(a5)&&(a0=H);a5=/[clmz]/g;if(a0==r&&!(a8+at).match(a5)){var e={M:"m",L:"l",C:"c",Z:"x",m:"t",l:"r",c:"v",z:"x"},R=/([clmz]),?([^clmz]*)/gi,S=/-?[^,\s-]+/g;var a4=(a8+at)[aP](R,function(a9,bb,i){var ba=[];i[aP](S,function(bc){ba[f](O(bc));});return e[bb]+ba;});return a4;}var a6=a0(a8),E,a4=[],d;for(var a2=0,a7=a6[m];a21&&(e=1);a7.opacity=e;}a8.fill&&(a7.on=true);if(a7.on==null||a8.fill=="none"){a7.on=false;}if(a7.on&&a8.fill){var i=a8.fill.match(c);if(i){a7.src=i[1];a7.type="tile";}else{a7.color=an.getRGB(a8.fill).hex;a7.src=at;a7.type="solid";if(an.getRGB(a8.fill).error&&(bd.type in {circle:1,ellipse:1}||(a8.fill+at).charAt()!="r")&&b(bd,a8.fill)){a9.fill="none";a9.gradient=a8.fill;}}}ba&&a6[aL](a7);var R=(a6.getElementsByTagName("stroke")&&a6.getElementsByTagName("stroke")[0]),bb=false;!R&&(bb=R=ah("stroke"));if((a8.stroke&&a8.stroke!="none")||a8["stroke-width"]||a8["stroke-opacity"]!=null||a8["stroke-dasharray"]||a8["stroke-miterlimit"]||a8["stroke-linejoin"]||a8["stroke-linecap"]){R.on=true;}(a8.stroke=="none"||R.on==null||a8.stroke==0||a8["stroke-width"]==0)&&(R.on=false);R.on&&a8.stroke&&(R.color=an.getRGB(a8.stroke).hex);var e=((+a9["stroke-opacity"]+1||2)-1)*((+a9.opacity+1||2)-1),a4=(W(a8["stroke-width"])||1)*0.75;e<0&&(e=0);e>1&&(e=1);a8["stroke-width"]==null&&(a4=a9["stroke-width"]);a8["stroke-width"]&&(R.weight=a4);a4&&a4<1&&(e*=a4)&&(R.weight=1);R.opacity=e;a8["stroke-linejoin"]&&(R.joinstyle=a8["stroke-linejoin"]||"miter");R.miterlimit=a8["stroke-miterlimit"]||8;a8["stroke-linecap"]&&(R.endcap=a8["stroke-linecap"]=="butt"?"flat":a8["stroke-linecap"]=="square"?"square":"round");if(a8["stroke-dasharray"]){var a5={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};R.dashstyle=a5[Q](a8["stroke-dasharray"])?a5[a8["stroke-dasharray"]]:at;}bb&&a6[aL](R);}if(bd.type=="text"){var a0=bd.paper.span.style;a9.font&&(a0.font=a9.font);a9["font-family"]&&(a0.fontFamily=a9["font-family"]);a9["font-size"]&&(a0.fontSize=a9["font-size"]);a9["font-weight"]&&(a0.fontWeight=a9["font-weight"]);a9["font-style"]&&(a0.fontStyle=a9["font-style"]);bd.node.string&&(bd.paper.span.innerHTML=(bd.node.string+at)[aP](/"));bd.W=a9.w=bd.paper.span.offsetWidth;bd.H=a9.h=bd.paper.span.offsetHeight;bd.X=a9.x;bd.Y=a9.y+O(bd.H/2);switch(a9["text-anchor"]){case"start":bd.node.style["v-text-align"]="left";bd.bbx=O(bd.W/2);break;case"end":bd.node.style["v-text-align"]="right";bd.bbx=-O(bd.W/2);break;default:bd.node.style["v-text-align"]="center";break;}}};var b=function(d,a1){d.attrs=d.attrs||{};var a2=d.attrs,a4=d.node.getElementsByTagName("fill"),S="linear",a0=".5 .5";d.attrs.gradient=a1;a1=(a1+at)[aP](ar,function(a6,a7,i){S="radial";if(a7&&i){a7=W(a7);i=W(i);aM(a7-0.5,2)+aM(i-0.5,2)>0.25&&(i=ab.sqrt(0.25-aM(a7-0.5,2))*((i>0.5)*2-1)+0.5);a0=a7+am+i;}return at;});a1=a1[z](/\s*\-\s*/);if(S=="linear"){var e=a1.shift();e=-W(e);if(isNaN(e)){return null;}}var R=p(a1);if(!R){return null;}d=d.shape||d.node;a4=a4[0]||ah("fill");if(R[m]){a4.on=true;a4.method="none";a4.type=(S=="radial")?"gradientradial":"gradient";a4.color=R[0].color;a4.color2=R[R[m]-1].color;var a5=[];for(var E=0,a3=R[m];E');};}catch(af){ah=function(d){return L.createElement("<"+d+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');};}var w=function(){var i=ao[aW](null,arguments),d=i.container,a2=i.height,a3,e=i.width,a1=i.x,a0=i.y;if(!d){throw new Error("VML container not found.");}var R=new aT,S=R.canvas=L.createElement("div"),E=S.style;e=e||512;a2=a2||342;e==+e&&(e+="px");a2==+a2&&(a2+="px");R.width=1000;R.height=1000;R.coordsize="1000 1000";R.coordorigin="0 0";R.span=L.createElement("span");R.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";S[aL](R.span);E.cssText=an.format("width:{0};height:{1};position:absolute;clip:rect(0 {0} {1} 0);overflow:hidden",e,a2);if(d==1){L.body[aL](S);E.left=a1+"px";E.top=a0+"px";}else{d.style.width=e;d.style.height=a2;if(d.firstChild){d.insertBefore(S,d.firstChild);}else{d[aL](S);}}aG.call(R,R,an.fn);return R;};aT[aY].clear=function(){this.canvas.innerHTML=at;this.span=L.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[aL](this.span);this.bottom=this.top=null;};aT[aY].remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var d in this){this[d]=s(d);}};}if((/^Apple|^Google/).test(navigator.vendor)&&!(navigator.userAgent.indexOf("Version/4.0")+1)){aT[aY].safari=function(){var d=this.rect(-99,-99,this.width+99,this.height+99);setTimeout(function(){d.remove();});};}else{aT[aY].safari=function(){};}var ae=(function(){if(L.addEventListener){return function(R,i,e,d){var E=function(S){return e.call(d,S);};R.addEventListener(i,E,false);return function(){R.removeEventListener(i,E,false);return true;};};}else{if(L.attachEvent){return function(S,E,i,e){var R=function(a0){return i.call(e,a0||au.event);};S.attachEvent("on"+E,R);var d=function(){S.detachEvent("on"+E,R);return true;};return d;};}}})();for(var ac=F[m];ac--;){(function(d){ax[aY][d]=function(e){if(an.is(e,"function")){this.events=this.events||[];this.events.push({name:d,f:e,unbind:ae(this.shape||this.node,d,e,this)});}return this;};ax[aY]["un"+d]=function(E){var i=this.events,e=i[m];while(e--){if(i[e].name==d&&i[e].f==E){i[e].unbind();i.splice(e,1);!i.length&&delete this.events;return this;}}return this;};})(F[ac]);}ax[aY].hover=function(e,d){return this.mouseover(e).mouseout(d);};ax[aY].unhover=function(e,d){return this.unmouseover(e).unmouseout(d);};aT[aY].circle=function(d,i,e){return P(this,d||0,i||0,e||0);};aT[aY].rect=function(d,R,e,i,E){return aF(this,d||0,R||0,e||0,i||0,E||0);};aT[aY].ellipse=function(d,E,i,e){return ai(this,d||0,E||0,i||0,e||0);};aT[aY].path=function(d){d&&!an.is(d,"string")&&!an.is(d[0],"array")&&(d+=at);return q(an.format[aW](an,arguments),this);};aT[aY].image=function(E,d,R,e,i){return o(this,E||"about:blank",d||0,R||0,e||0,i||0);};aT[aY].text=function(d,i,e){return X(this,d||0,i||0,e||at);};aT[aY].set=function(d){arguments[m]>1&&(d=Array[aY].splice.call(arguments,0,arguments[m]));return new T(d);};aT[aY].setSize=aV;aT[aY].top=aT[aY].bottom=null;aT[aY].raphael=an;function u(){return this.x+am+this.y;}ax[aY].scale=function(a6,a5,E,e){if(a6==null&&a5==null){return{x:this._.sx,y:this._.sy,toString:u};}a5=a5||a6;!+a5&&(a5=a6);var ba,a8,a9,a7,bm=this.attrs;if(a6!=0){var a4=this.getBBox(),a1=a4.x+a4.width/2,R=a4.y+a4.height/2,bl=a6/this._.sx,bk=a5/this._.sy;E=(+E||E==0)?E:a1;e=(+e||e==0)?e:R;var a3=~~(a6/ab.abs(a6)),a0=~~(a5/ab.abs(a5)),be=this.node.style,bo=E+(a1-E)*bl,bn=e+(R-e)*bk;switch(this.type){case"rect":case"image":var a2=bm.width*a3*bl,bd=bm.height*a0*bk;this.attr({height:bd,r:bm.r*aI(a3*bl,a0*bk),width:a2,x:bo-a2/2,y:bn-bd/2});break;case"circle":case"ellipse":this.attr({rx:bm.rx*a3*bl,ry:bm.ry*a0*bk,r:bm.r*aI(a3*bl,a0*bk),cx:bo,cy:bn});break;case"path":var bg=ad(bm.path),bh=true;for(var bj=0,bc=bg[m];bjS){if(e&&!a8.start){a6=an.findDotsAtSegment(a5,a4,E[1],E[2],E[3],E[4],E[5],E[6],(S-a3)/a1);R+=["C",a6.start.x,a6.start.y,a6.m.x,a6.m.y,a6.x,a6.y];if(a0){return R;}a8.start=R;R=["M",a6.x,a6.y+"C",a6.n.x,a6.n.y,a6.end.x,a6.end.y,E[5],E[6]][az]();a3+=a1;a5=+E[5];a4=+E[6];continue;}if(!d&&!e){a6=an.findDotsAtSegment(a5,a4,E[1],E[2],E[3],E[4],E[5],E[6],(S-a3)/a1);return{x:a6.x,y:a6.y,alpha:a6.alpha};}}a3+=a1;a5=+E[5];a4=+E[6];}R+=E;}a8.end=R;a6=d?a3:e?a8:an.findDotsAtSegment(a5,a4,E[1],E[2],E[3],E[4],E[5],E[6],1);a6.alpha&&(a6={x:a6.x,y:a6.y,alpha:a6.alpha});return a6;};},n=aj(function(E,d,a0,S,a6,a5,a4,a3){var R={x:0,y:0},a2=0;for(var a1=0;a1<1.01;a1+=0.01){var e=M(E,d,a0,S,a6,a5,a4,a3,a1);a1&&(a2+=ab.sqrt(aM(R.x-e.x,2)+aM(R.y-e.y,2)));R=e;}return a2;});var ap=aB(1),C=aB(),J=aB(0,1);ax[aY].getTotalLength=function(){if(this.type!="path"){return;}return ap(this.attrs.path);};ax[aY].getPointAtLength=function(d){if(this.type!="path"){return;}return C(this.attrs.path,d);};ax[aY].getSubpath=function(i,e){if(this.type!="path"){return;}if(ab.abs(this.getTotalLength()-e)<0.000001){return J(this.attrs.path,i).end;}var d=J(this.attrs.path,e,1);return i?J(d,i).end:d;};an.easing_formulas={linear:function(d){return d;},"<":function(d){return aM(d,3);},">":function(d){return aM(d-1,3)+1;},"<>":function(d){d=d*2;if(d<1){return aM(d,3)/2;}d-=2;return(aM(d,3)+2)/2;},backIn:function(e){var d=1.70158;return e*e*((d+1)*e-d);},backOut:function(e){e=e-1;var d=1.70158;return e*e*((d+1)*e+d)+1;},elastic:function(i){if(i==0||i==1){return i;}var e=0.3,d=e/4;return aM(2,-10*i)*ab.sin((i-d)*(2*ab.PI)/e)+1;},bounce:function(E){var e=7.5625,i=2.75,d;if(E<(1/i)){d=e*E*E;}else{if(E<(2/i)){E-=(1.5/i);d=e*E*E+0.75;}else{if(E<(2.5/i)){E-=(2.25/i);d=e*E*E+0.9375;}else{E-=(2.625/i);d=e*E*E+0.984375;}}}return d;}};var I={length:0},aR=function(){var a2=+new Date;for(var be in I){if(be!="length"&&I[Q](be)){var bj=I[be];if(bj.stop){delete I[be];I[m]--;continue;}var a0=a2-bj.start,bb=bj.ms,ba=bj.easing,bf=bj.from,a7=bj.diff,E=bj.to,a6=bj.t,a9=bj.prev||0,a1=bj.el,R=bj.callback,a8={},d;if(a0255?255:(d<0?0:d);},t=function(d,i){if(d==null){return{x:this._.tx,y:this._.ty,toString:u};}this._.tx+=+d;this._.ty+=+i;switch(this.type){case"circle":case"ellipse":this.attr({cx:+d+this.attrs.cx,cy:+i+this.attrs.cy});break;case"rect":case"image":case"text":this.attr({x:+d+this.attrs.x,y:+i+this.attrs.y});break;case"path":var e=ad(this.attrs.path);e[0][1]+=+d;e[0][2]+=+i;this.attr({path:e});break;}return this;};ax[aY].animateWith=function(e,i,d,R,E){I[e.id]&&(i.start=I[e.id].start);return this.animate(i,d,R,E);};ax[aY].animateAlong=ay();ax[aY].animateAlongBack=ay(1);function ay(d){return function(E,i,e,S){var R={back:d};an.is(e,"function")?(S=e):(R.rot=e);E&&E.constructor==ax&&(E=E.attrs.path);E&&(R.along=E);return this.animate(R,i,S);};}ax[aY].onAnimation=function(d){this._run=d||0;return this;};ax[aY].animate=function(be,a5,a4,E){if(an.is(a4,"function")||!a4){E=a4||null;}var a9={},e={},a2={};for(var a6 in be){if(be[Q](a6)){if(Z[Q](a6)){a9[a6]=this.attr(a6);(a9[a6]==null)&&(a9[a6]=j[a6]);e[a6]=be[a6];switch(Z[a6]){case"along":var bc=ap(be[a6]),a7=C(be[a6],bc*!!be.back),R=this.getBBox();a2[a6]=bc/a5;a2.tx=R.x;a2.ty=R.y;a2.sx=a7.x;a2.sy=a7.y;e.rot=be.rot;e.back=be.back;e.len=bc;be.rot&&(a2.r=W(this.rotate())||0);break;case"number":a2[a6]=(e[a6]-a9[a6])/a5;break;case"colour":a9[a6]=an.getRGB(a9[a6]);var a8=an.getRGB(e[a6]);a2[a6]={r:(a8.r-a9[a6].r)/a5,g:(a8.g-a9[a6].g)/a5,b:(a8.b-a9[a6].b)/a5};break;case"path":var S=H(a9[a6],e[a6]);a9[a6]=S[0];var a3=S[1];a2[a6]=[];for(var bb=0,a1=a9[a6][m];bb +// +// Math.seedrandom('yipee'); Sets Math.random to a function that is +// initialized using the given explicit seed. +// +// Math.seedrandom(); Sets Math.random to a function that is +// seeded using the current time, dom state, +// and other accumulated local entropy. +// The generated seed string is returned. +// +// Math.seedrandom('yowza', true); +// Seeds using the given explicit seed mixed +// together with accumulated entropy. +// +// +// Seeds using physical random bits downloaded +// from random.org. +// +// Examples: +// +// Math.seedrandom("hello"); // Use "hello" as the seed. +// document.write(Math.random()); // Always 0.5463663768140734 +// document.write(Math.random()); // Always 0.43973793770592234 +// var rng1 = Math.random; // Remember the current prng. +// +// var autoseed = Math.seedrandom(); // New prng with an automatic seed. +// document.write(Math.random()); // Pretty much unpredictable. +// +// Math.random = rng1; // Continue "hello" prng sequence. +// document.write(Math.random()); // Always 0.554769432473455 +// +// Math.seedrandom(autoseed); // Restart at the previous seed. +// document.write(Math.random()); // Repeat the 'unpredictable' value. +// +// Notes: +// +// Each time seedrandom('arg') is called, entropy from the passed seed +// is accumulated in a pool to help generate future seeds for the +// zero-argument form of Math.seedrandom, so entropy can be injected over +// time by calling seedrandom with explicit data repeatedly. +// +// On speed - This javascript implementation of Math.random() is about +// 3-10x slower than the built-in Math.random() because it is not native +// code, but this is typically fast enough anyway. Seeding is more expensive, +// especially if you use auto-seeding. Some details (timings on Chrome 4): +// +// Our Math.random() - avg less than 0.002 milliseconds per call +// seedrandom('explicit') - avg less than 0.5 milliseconds per call +// seedrandom('explicit', true) - avg less than 2 milliseconds per call +// seedrandom() - avg about 38 milliseconds per call +// +// LICENSE (BSD): +// +// Copyright 2010 David Bau, all rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of this module nor the names of its contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/** + * All code is in an anonymous closure to keep the global namespace clean. + * + * @param {number=} overflow + * @param {number=} startdenom + */ +(function (pool, math, width, chunks, significance, overflow, startdenom) { + + +// +// seedrandom() +// This is the seedrandom function described above. +// +math['seedrandom'] = function seedrandom(seed, use_entropy) { + var key = []; + var arc4; + + // Flatten the seed string or build one from local entropy if needed. + seed = mixkey(flatten( + use_entropy ? [seed, pool] : + arguments.length ? seed : + [new Date().getTime(), pool, window], 3), key); + + // Use the seed to initialize an ARC4 generator. + arc4 = new ARC4(key); + + // Mix the randomness into accumulated entropy. + mixkey(arc4.S, pool); + + // Override Math.random + + // This function returns a random double in [0, 1) that contains + // randomness in every bit of the mantissa of the IEEE 754 value. + + math['random'] = function random() { // Closure to return a random double: + var n = arc4.g(chunks); // Start with a numerator n < 2 ^ 48 + var d = startdenom; // and denominator d = 2 ^ 48. + var x = 0; // and no 'extra last byte'. + while (n < significance) { // Fill up all significant digits by + n = (n + x) * width; // shifting numerator and + d *= width; // denominator and generating a + x = arc4.g(1); // new least-significant-byte. + } + while (n >= overflow) { // To avoid rounding up, before adding + n /= 2; // last byte, shift everything + d /= 2; // right using integer math until + x >>>= 1; // we have exactly the desired bits. + } + return (n + x) / d; // Form the number within [0, 1). + }; + + // Return the seed that was used + return seed; +}; + +// +// ARC4 +// +// An ARC4 implementation. The constructor takes a key in the form of +// an array of at most (width) integers that should be 0 <= x < (width). +// +// The g(count) method returns a pseudorandom integer that concatenates +// the next (count) outputs from ARC4. Its return value is a number x +// that is in the range 0 <= x < (width ^ count). +// +/** @constructor */ +function ARC4(key) { + var t, u, me = this, keylen = key.length; + var i = 0, j = me.i = me.j = me.m = 0; + me.S = []; + me.c = []; + + // The empty key [] is treated as [0]. + if (!keylen) { key = [keylen++]; } + + // Set up S using the standard key scheduling algorithm. + while (i < width) { me.S[i] = i++; } + for (i = 0; i < width; i++) { + t = me.S[i]; + j = lowbits(j + t + key[i % keylen]); + u = me.S[j]; + me.S[i] = u; + me.S[j] = t; + } + + // The "g" method returns the next (count) outputs as one number. + me.g = function getnext(count) { + var s = me.S; + var i = lowbits(me.i + 1); var t = s[i]; + var j = lowbits(me.j + t); var u = s[j]; + s[i] = u; + s[j] = t; + var r = s[lowbits(t + u)]; + while (--count) { + i = lowbits(i + 1); t = s[i]; + j = lowbits(j + t); u = s[j]; + s[i] = u; + s[j] = t; + r = r * width + s[lowbits(t + u)]; + } + me.i = i; + me.j = j; + return r; + }; + // For robust unpredictability discard an initial batch of values. + // See http://www.rsa.com/rsalabs/node.asp?id=2009 + me.g(width); +} + +// +// flatten() +// Converts an object tree to nested arrays of strings. +// +/** @param {Object=} result + * @param {string=} prop */ +function flatten(obj, depth, result, prop) { + result = []; + if (depth && typeof(obj) == 'object') { + for (prop in obj) { + if (prop.indexOf('S') < 5) { // Avoid FF3 bug (local/sessionStorage) + try { result.push(flatten(obj[prop], depth - 1)); } catch (e) {} + } + } + } + return result.length ? result : '' + obj; +} + +// +// mixkey() +// Mixes a string seed into a key that is an array of integers, and +// returns a shortened string seed that is equivalent to the result key. +// +/** @param {number=} smear + * @param {number=} j */ +function mixkey(seed, key, smear, j) { + seed += ''; // Ensure the seed is a string + smear = 0; + for (j = 0; j < seed.length; j++) { + key[lowbits(j)] = + lowbits((smear ^= key[lowbits(j)] * 19) + seed.charCodeAt(j)); + } + seed = ''; + for (j in key) { seed += String.fromCharCode(key[j]); } + return seed; +} + +// +// lowbits() +// A quick "n mod width" for width a power of 2. +// +function lowbits(n) { return n & (width - 1); } + +// +// The following constants are related to IEEE 754 limits. +// +startdenom = math.pow(width, chunks); +significance = math.pow(2, significance); +overflow = significance * 2; + +// +// When seedrandom.js is loaded, we immediately mix a few bits +// from the built-in RNG into the entropy pool. Because we do +// not want to intefere with determinstic PRNG state later, +// seedrandom will not call math.random on its own again after +// initialization. +// +mixkey(math.random(), pool); + +// End anonymous scope, and pass initial values. +})( + [], // pool: entropy pool starts empty + Math, // math: package containing random, pow, and seedrandom + 256, // width: each RC4 output is 0 <= x < 256 + 6, // chunks: at least six RC4 outputs for each double + 52 // significance: there are 52 significant digits in a double +); diff --git a/addons/base_diagram/static/src/js/diagram.js b/addons/base_diagram/static/src/js/diagram.js new file mode 100644 index 00000000000..af56c256ee7 --- /dev/null +++ b/addons/base_diagram/static/src/js/diagram.js @@ -0,0 +1,183 @@ +/*--------------------------------------------------------- + * OpenERP base library + *---------------------------------------------------------*/ + +openerp.base.diagram = function (openerp) { + +openerp.base.views.add('diagram', 'openerp.base.DiagramView'); +openerp.base.DiagramView = openerp.base.Controller.extend({ + init: function(view_manager, session, element_id, dataset, view_id){ + this._super(session, element_id); + this.view_manager = view_manager; + this.dataset = dataset; + this.model = dataset.model; + this.view_id = view_id; + this.name = ""; + this.domain = this.dataset._domain ? this.dataset._domain: []; + this.context = {}; + this.ids = this.dataset.ids; + + console.log('data set>>',this.dataset) + }, + start: function() { + this.rpc("/base_diagram/diagram/load", {"model": this.model, "view_id": this.view_id}, this.on_loaded); + }, + + toTitleCase: function(str) { + return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}); + }, + + on_loaded: function(result) { + + var self = this; + if(this.ids && this.ids.length) { + this.id = this.ids[0]; + } + + this.fields_view = result.fields_view; + this.view_id = this.fields_view.view_id; + this.name = this.fields_view.name; + + this.fields = this.fields_view.fields; + + var children = this.fields_view.arch.children; + /* + * For Nodes (Fields) + */ + this.node = ''; + this.bgcolor = ''; + this.shape = ''; + this.visible_fields_nodes = []; + this.invisible_fields_nodes = []; + this.fields_nodes_string = []; + + /* + * For Arraows(Connector) + */ + this.connector = ''; + this.src_node = ''; + this.des_node = ''; + this.connector_fields = []; + this.fields_connector_string = []; + + for(ch in children) { + if(children[ch]['tag'] == 'node') { + this.node = children[ch]['attrs']['object']; + this.bgcolor = children[ch]['attrs']['bgcolor'] || ''; + this.shape = children[ch]['attrs']['shape'] || ''; + for(node_chld in children[ch]['children']) { + if (children[ch]['children'][node_chld]['tag'] = 'field') { + var ch_name = children[ch]['children'][node_chld]['attrs']['name']; + + if (children[ch]['children'][node_chld]['attrs']['invisible']) { + if (children[ch]['children'][node_chld]['attrs']['invisible'] == 1 && children[ch]['children'][node_chld]['attrs']['invisible'] == '1') { + this.invisible_fields_nodes.push(ch_name) + } + } + else { + this.visible_fields_nodes.push(ch_name); + var ch_node_string = this.fields[ch_name]['string'] || this.toTitleCase(ch_name); + this.fields_nodes_string.push(ch_node_string) + } + } + } + } else if(children[ch]['tag'] == 'arrow') { + this.connector = children[ch]['attrs']['object']; + this.src_node = children[ch]['attrs']['source']; + this.des_node = children[ch]['attrs']['destination']; + for (arrow_chld in children[ch]['children']) { + if (children[ch]['children'][arrow_chld]['tag'] = 'field') { + var arr_ch_name = children[ch]['children'][arrow_chld]['attrs']['name']; + var ch_node_string = this.fields[arr_ch_name]['string'] || this.toTitleCase(arr_ch_name); + this.fields_connector_string.push(ch_node_string); + this.connector_fields.push(arr_ch_name); + } + } + } + } + this.$element.html(QWeb.render("DiagramView", {"fields_view": this.fields_view})); + + if(this.id) { + this.rpc( + '/base_diagram/diagram/get_diagram_info', + { + 'id': this.id, + 'model': this.model, + 'bgcolor': this.bgcolor, + 'shape': this.shape, + 'node': this.node, + 'connector': this.connector, + 'src_node': this.src_node, + 'des_node': this.des_node, + 'visible_node_fields': this.visible_fields_nodes, + 'invisible_node_fields': this.invisible_fields_nodes, + 'node_fields_string': this.fields_nodes_string, + 'connector_fields': this.connector_fields, + 'connector_fields_string': this.fields_connector_string + }, + function(result) { + self.draw_diagram(result); + } + ) + } + }, + + draw_diagram: function(result) { + console.log('this>>>',this) + var g = new Graph(); +// var raphel = new + this.in_transition_field = result['in_transition_field']; + this.out_transition_field = result['out_transition_field']; + var res_nodes = result['nodes']; + var res_connectors = result['conn']; + + var render = function(r, n) { + var set; + if (n.node.shape == 'ellipse') { + set = r.set().push( + r.ellipse(n.node.x - 30, n.node.y - 13, 40, 40).attr({ + "fill": n.node.color, + r: "12px", + "stroke-width": n.distance == 0 ? "3px" : "1px" + })).push(r.text(n.node.x - 30, n.node.y - 10, (n.label || n.id))); + } else { + set = r.set().push( + r.rect(n.node.x-30, n.node.y-13, 60, 44).attr({"fill": n.node.color, r : "12px", "stroke-width" : n.distance == 0 ? "3px" : "1px" })).push( + r.text(n.point[0], n.point[1] + 10, (n.label || n.id) + "\n(" + (n.distance == undefined ? "Infinity" : n.distance) + ")")); + + } + return set; + }; + + for(nd in res_nodes) { + var res_node = res_nodes[nd]; + g.addNode(res_node['name'], + { + node: res_node, + render: render + }); + } + + for(cr in res_connectors) { + var res_connector = res_connectors[cr]; + g.addEdge(res_connector['source'], res_connector['destination']); + } + + var layouter = new Graph.Layout.Spring(g); + layouter.layout(); + + var renderer = new Graph.Renderer.Raphael('dia-canvas', g, 800, 800); + renderer.draw(); + }, + + do_show: function () { + this.$element.show(); + }, + + do_hide: function () { + this.$element.hide(); + } +}); +}; + +// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/base_diagram/static/src/js/views.js b/addons/base_diagram/static/src/js/views.js deleted file mode 100644 index 606e1e5c78c..00000000000 --- a/addons/base_diagram/static/src/js/views.js +++ /dev/null @@ -1,12 +0,0 @@ -/*--------------------------------------------------------- - * OpenERP base library - *---------------------------------------------------------*/ - -openerp.base_diagram = function(openerp) { - -openerp.base_diagram.DiagramView = openerp.base.Controller.extend({ -}); - -}; - -// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax: diff --git a/addons/base_gantt/__openerp__.py b/addons/base_gantt/__openerp__.py index d3b4dbd3885..55cec2c0863 100644 --- a/addons/base_gantt/__openerp__.py +++ b/addons/base_gantt/__openerp__.py @@ -1,7 +1,12 @@ { "name": "Base Gantt", "version": "2.0", - "depends": [], - "js": ["static/*/js/*.js"], - "css": [], + "depends": ['base'], + "js": [ + 'static/lib/dhtmlxGantt/codebase/dhtmlxcommon.js', + 'static/lib/dhtmlxGantt/codebase/dhtmlxgantt.js', + 'static/src/js/gantt.js' + ], + "css": ['static/lib/dhtmlxGantt/codebase/dhtmlxgantt.css'], + 'active': True } diff --git a/addons/base_gantt/static/src/gantt.js b/addons/base_gantt/static/src/js/gantt.js similarity index 97% rename from addons/base_gantt/static/src/gantt.js rename to addons/base_gantt/static/src/js/gantt.js index 0e65fb48b5b..f8391f2744b 100644 --- a/addons/base_gantt/static/src/gantt.js +++ b/addons/base_gantt/static/src/js/gantt.js @@ -2,9 +2,10 @@ * OpenERP base_gantt *---------------------------------------------------------*/ -openerp.base.gantt = function (openerp) { -openerp.base.views.add('gantt', 'openerp.base.GanttView'); -openerp.base.GanttView = openerp.base.Controller.extend({ +openerp.base_gantt = function (openerp) { +QWeb.add_template('/base_gantt/static/src/xml/base_gantt.xml'); +openerp.base.views.add('gantt', 'openerp.base_gantt.GanttView'); +openerp.base_gantt.GanttView = openerp.base.Controller.extend({ init: function(view_manager, session, element_id, dataset, view_id) { this._super(session, element_id); @@ -216,7 +217,7 @@ openerp.base.GanttView = openerp.base.Controller.extend({ }, function(result) { }) - }, + } }); diff --git a/addons/base_gantt/static/src/xml/base_gantt.xml b/addons/base_gantt/static/src/xml/base_gantt.xml new file mode 100644 index 00000000000..72c14ceb16c --- /dev/null +++ b/addons/base_gantt/static/src/xml/base_gantt.xml @@ -0,0 +1,15 @@ + diff --git a/addons/web_chat/__openerp__.py b/addons/web_chat/__openerp__.py index 132986ff90d..3d5358702c2 100644 --- a/addons/web_chat/__openerp__.py +++ b/addons/web_chat/__openerp__.py @@ -1,8 +1,14 @@ { "name": "Web Chat", "version": "2.0", - "depends": [], - "js": ["static/src/web_chat.js"], + "depends": ['base'], + "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': True, + 'active': False, } diff --git a/addons/web_chat/controllers/main.py b/addons/web_chat/controllers/main.py index d8d33bac445..5e8d48344f8 100644 --- a/addons/web_chat/controllers/main.py +++ b/addons/web_chat/controllers/main.py @@ -1,8 +1,9 @@ # -*- coding: utf-8 -*- import sys, time +import cherrypy import simplejson - +import random import openerpweb #---------------------------------------------------------- @@ -11,23 +12,32 @@ import openerpweb class PollServerMessageQueue(object): def __init__(self): # message queue - self.l = [] + self.messages = [] # online users self.users = {} # should contains: { # 'user1234' : { s:1, m:"status message", timestamp: last_contact_timestamp } # } - def userlist(): - # return user list - pass + 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"}, +# ] - def write(self, m_type, m_sender, m_recipent, m_message, m_group): - # appends messages to l - # when status message uupdate users - pass - def read(self, recpient, timestamp): - # return matching message + 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(): # remove message older than 300s from self.l # remove dead users from self.users @@ -38,6 +48,7 @@ class PollServer(openerpweb.Controller): @openerpweb.httprequest def login(self, req, **kw): + """ --> POST http://ajaxim.com/wp-content/plugins/im/ajaxim.php/login Form Data @@ -56,23 +67,32 @@ class PollServer(openerpweb.Controller): ] } """ - mq = req.applicationsession.setdefault("web_chat",PollServerMessageQueue()) - print "chat login",kw - # r = 'loggued in' + mq = req.applicationsession.setdefault("web_chat", PollServerMessageQueue()) + mq.messages = [] + + #r = 'logged in' #u = generate random.randint(0,2**32) #s = cherrypy cookie id #f = mq.userlist() - return """ - { - "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"}, - ] - } - """ + +# 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): @@ -98,29 +118,34 @@ class PollServer(openerpweb.Controller): jsonp1302140441577([{"t":"s","s":"Guest130214038974.31","r":"","m":"0:"}]); receive message: - jsonp1302140191599([{"t":"m","s":"Guest130214008855.5","r":"Guest130214013134.26","m":"fuck"}]); + 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 '' - """ - # for i in range(60): - #r = mq.read(username,timestamp) - # if messages - # return r - # if no message sleep 2s and retry - # sleep 2 - # else - # return emptylist - print "chat poll",kw - time.sleep(2) - # it's http://localhost:8002/web_chat/pollserver/poll?method=long?callback=jsonp1302147330483&_1302147330483= - return '%s([{"t":"m","s":"Guest130214008855.5","r":"Guest130214013134.26","m":"fuck"}]);'%kw.get('callback','') - return None + mq = req.applicationsession.setdefault("web_chat", PollServerMessageQueue()) + + # Method: Long Poll - @openerpweb.jsonrequest + + msg = '[]' + + cherrypy.response.headers['content-type'] = 'application/javascript'; + + 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= @@ -138,11 +163,26 @@ class PollServer(openerpweb.Controller): return array('r' => 'error', 'e' => 'send error'); """ - print "chat send",kw - # mq.write() - return {"action": actions} + + to = kw.get('to') + message = kw.get('message') + + mq = req.applicationsession.setdefault("web_chat", PollServerMessageQueue()) - @openerpweb.jsonrequest + + 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 @@ -158,8 +198,20 @@ class PollServer(openerpweb.Controller): return array('r' => 'error', 'e' => 'no session found'); return array('r' => 'error', 'e' => 'status error'); """ - print "chat status",kw + mq = req.applicationsession.setdefault("web_chat", PollServerMessageQueue()) + + print "======== chat status ========",kw # mq.write() - return {"action": actions} + 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('>', '>').replace('<', '<').replace('&', '&'); diff --git a/addons/web_chat/controllers/noz_ajaxim.py b/addons/web_chat/controllers/noz_ajaxim.py deleted file mode 100644 index abcaded7d0d..00000000000 --- a/addons/web_chat/controllers/noz_ajaxim.py +++ /dev/null @@ -1,21 +0,0 @@ - -import im -from server import main # import the server library - -im = Webchat_IM() -action = preg_replace('/^' . preg_quote($_SERVER['SCRIPT_NAME'], '/') . '\/(.+?)(\?.+)?$/', '\1', $_SERVER['REQUEST_URI']); - -if(substr(action, 0, 1) != '_' && method_exists(im, action)) - if(action == 'poll') { - if($_GET['method'] == 'comet') { - im->poll('comet'); - } else { - print $_GET['callback'] . '(' . json_encode(im->poll($_GET['method'])) . ')'; - } - } else { - execute = call_user_func_array(array(im, action), $_POST); - if(execute) - print json_encode(execute !== false ? execute : array('e'=>'wrong args')); - } -else - print json_encode(array('e'=>'no method')); \ No newline at end of file diff --git a/addons/web_chat/controllers/noz_im.py b/addons/web_chat/controllers/noz_im.py deleted file mode 100644 index 392a56645fa..00000000000 --- a/addons/web_chat/controllers/noz_im.py +++ /dev/null @@ -1,22 +0,0 @@ - -import openerpweb - -class IM(openerpweb.Controller): - def __init__(self): - super(IM, self).__init__() - return; - - def chat_login(self, username, password): - return dict() - - def chat_logout(self): - return dict() - - def send(self): - return dict() - - def status(self, status, message): - return dict() - - def poll(self, method): - return dict() diff --git a/addons/web_chat/controllers/noz_main.py b/addons/web_chat/controllers/noz_main.py deleted file mode 100644 index b48513eaf0c..00000000000 --- a/addons/web_chat/controllers/noz_main.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- - -import simplejson -import openerpweb - -from web_chat.controllers import im - -__all__ = ['Webchat_IM'] - -chat_config_options = {'IM_LIBRARY': 'main', # The IM server library. - 'COOKIE_NAME': 'ajaxim_session', # Session cookie used by Ajax IM - 'COOKIE_PERIOD': 365 # Cookie period, in days - } - -nodejs_memcache_server = ['localhost:11211'] - -class Webchat_IM(im.IM): - - _cp_path = "/webchat/webchatim" - - def __init__(self): - super(Webchat_IM, self).__init__() - - return; - - @openerpweb.jsonrequest - def index(self, req, username="admin", password="admin"): - - if req._login: - self.username = req._login - self.uid = req._uid - self.db = req._db - - return; - - @openerpweb.jsonrequest - def chat_login(self, req, username="admin", password="admin"): - # TODO: use db and uid for unique identification. - - self.auth = [['admin', 'a'], ['demo', 'demo']] - - self.user_pass = [] - self.user_session = None - - if username and password: - self.user_pass = [username, password] - - if self.user_pass in self.auth: - self.user_session = username + '_' + str(req.session_id) - - data = {'username': username, 'user_id': username, 'user_session': self.user_session, - 'friends': {'u': 'demo', 'g': 'Friends', 's': '1'} # {'u': 'username', 'g': 'group', 's': 'status'} - } - - # Get the list of friends from memcache. - - return dict(r='logged in', s=self.user_session, f=data['friends']) - - @openerpweb.jsonrequest - def chat_logout(self): - return dict(r='Logged out') \ No newline at end of file diff --git a/addons/web_chat/static/lib/AjaxIM/js/im.js b/addons/web_chat/static/lib/AjaxIM/js/im.js index fbf6a1552f3..9ab195fd6b6 100644 --- a/addons/web_chat/static/lib/AjaxIM/js/im.js +++ b/addons/web_chat/static/lib/AjaxIM/js/im.js @@ -1 +1,2101 @@ -// = im.js = // // **Copyright © 2005 – 2010 Joshua Gross**\\ // //MIT Licensed// // // 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. // // This is the main library for Ajax IM. It encompasses the UI controls, // and connecting with the server. It does //not// handle registration or // account management. (function($, _instance) { AjaxIM = function(options, actions) { if(this instanceof AjaxIM) { var self = this; // === {{{ defaults }}} === // // These are the available settings for Ajax IM, and the associated // defaults: // // * {{{pollType}}} determines the way in which the client will talk to // the server. // ** {{{comet}}} will use http streaming, wherein a connection to the server will be held open indefinitely, and the server will push down new events (messages, status updates) as they occur. // ** {{{long}}} will hold open a connection with the server for as long as possible, or until a new event is received. Upon the server sending an event or closing the connection, the client will automatically—and immediately—reconnect. // ** {{{short}}} will open a connection, and the server (if this method is supported) will //immediately// provide a response as to whether or not there are any new events. Once a response is received, the client will wait 5 seconds, and then reconnect. // * {{{pollServer}}} is the default URL to which all actions refer. It is // possible to specify certain action URLs separately (as is used with the // NodeJS server). // * {{{cookieName}}} is the name of the session cookie used by the server. // If this is not set properly, the IM engine will not be able to automatically // reinitialize sessions. // * {{{theme}}} is the name of the theme folder that defines the HTML and // CSS of the IM bar and chat boxes. Usually, themes are deposited in the // provided "themes" folder and specified by that path, e.g. {{{themes/default}}}. // Theme files within the theme folder must be named {{{theme.html}}} and // {{{theme.css}}}. // * {{{storageMethod}}} defines the way in which data (chat sessions) are // temporarily stored client-side. By default, {{{"flash"}}} is used because // it is the most widely supported method. However, // [[http://eric.garside.name/docs.html?p=jstore#js-engines|other storage engines]] // are available, with their respective up- and down-sides // outlined, on the jStore website. // * {{{storeSession}}} (**not implemented**) sets the number of days to // retain stored chat session data before it should be deleted. // * {{{checkResume}}} is a flag that sets whether or not the client should // make a call to the server before resuming the session (such as on a page // reload). This will ensure that the session has not expired. If set to {{{false}}}, // a call to the server will not be made, and the session will be assumed to // be active. var defaults = { pollType: 'long', pollServer: './ajaxim.php', cookieName: 'ajaxim_session', theme: 'themes/default', storageMethod: 'auto', flashStorage: 'js/jStore.Flash.html', storeSession: 5, // number of days to store chat data (0 for current session only) checkResume: true }; // === {{{AjaxIM.}}}**{{{settings}}}** === // // These are the settings for the IM. If particular options are not specified, // the defaults (see above) will be used. //These options will be defined // upon calling the initialization function, and not set directly.// this.settings = $.extend(defaults, options); // === {{{AjaxIM.}}}**{{{actions}}}** === // // Each individual action that the IM engine can execute is predefined here. // By default, it merely appends the action onto the end of the {{{pollServer}}} url, // however, it is possible to define actions individually. //The alternative actions // will be defined upon calling the initialization function, and not set directly.// // // Should you define an action at a different URL, Ajax IM will determine whether // or not this URL is within the current domain. If it is within a subdomain of // the current domain, it will set the document.domain variable for you, // to match a broader hostname scope; the action will continue to use {{{$.post}}} // (the default AJAX method for Ajax IM). // // On the other hand, should you choose a URL outside the current domain // Ajax IM will switch to {{{$.getJSON}}} (a get request) to avoid // cross-domain scripting issues. This means that a server on a different // port or at a different address will need to be able to handle GET // requests rather than POST requests (such as how the Node.JS Ajax IM // server works). this.actions = $.extend({ login: this.settings.pollServer + '/login', logout: this.settings.pollServer + '/logout', register: this.settings.pollServer + '/register', poll: this.settings.pollServer + '/poll?method=' + this.settings.pollType, send: this.settings.pollServer + '/send', status: this.settings.pollServer + '/status', resume: this.settings.pollServer + '/resume' }, actions); var httpRx = new RegExp('^http://', 'i'), slashslashRx = new RegExp('^//', 'i'), queryStrRx = new RegExp('[?](.+)$'), subdomainRx = new RegExp('((http[s]?:)?//)?(.+?)[.]' + window.location.host, 'i'); $.each(this.actions, function(name, action) { if(name == 'poll') { if(self.settings.pollType != 'comet') action += (queryStrRx.test(action[1]) ? '&' : '?') + 'callback=?'; action = ['jsonp', action]; } else { action = ['ajax', action]; if(subdomainRx.test(action[1])) { document.domain = '.' + window.location.host; } else if((http = httpRx.test(action[1])) || slashslashRx.test(action[1])) { if(!(new RegExp('//' + window.location.host + '/', 'i')).test(action[1])) { action[1] += (queryStrRx.test(action[1]) ? '&' : '?') + 'callback=?'; action = ['jsonp', action[1]]; } } } self.actions[name] = action; }); // We load the theme dynamically based on the passed // settings. If the theme is set to false, we assume // that the user is going to load it himself. this.themeLoaded = false; if(this.settings.theme) { $('
').appendTo('body').load(this.settings.theme + '/theme.html #imjs-bar, .imjs-tooltip', function() { self.themeLoaded = true; setup.apply(self); } ); if(typeof document.createStyleSheet == 'function') document.createStyleSheet(this.settings.theme + '/theme.css'); else $('body').append(''); } else { this.themeLoaded = true; setup.apply(this); } // Client-side storage for keeping track of // conversation states, active tabs, etc. // The default is flash storage, however, other // options are available via the jStore library. if(this.settings.storageMethod) { this.storageBrowserKey = 'unknown'; this.storeKey = ''; $.each($.browser, function(k, v) { if(k == 'version') return true; else if(v == true) { self.storageBrowserKey = k; return false; } }); if(this.settings.storageMethod == 'auto') { $.each(['ie', 'html5', 'local', 'flash'], function() { if($.jStore.Availability[this]()) { self.settings.storageMethod = this; return false; } }); } $.extend($.jStore.defaults, { project: 'im.js', engine: this.settings.storageMethod, flash: this.settings.flashStorage }); this.storageReady = false; if(this.settings.storageMethod == 'flash') { $.jStore.ready(function(engine) { $.jStore.flashReady(function() { self.storageReady = true; setup.apply(self); }); }) } else { $.jStore.ready(function(engine) { self.storageReady = true; setup.apply(self); }); } $.jStore.load(); } else { this.storageReady = true; setup.apply(this); } // Allow a chatbox to me minimized $('.imjs-chatbox').live('click', function(e) { e.preventDefault(); return false; }); $('.imjs-chatbox .imjs-minimize').live('click', function() { $(this).parents('.imjs-chatbox').data('tab').click(); }); // Allow a chatbox to be closed $('.imjs-chatbox .imjs-close').live('click', function() { var chatbox = $(this).parents('.imjs-chatbox'); chatbox.data('tab') .data('state', 'closed').css('display', 'none'); if(self.settings.storageMethod && self.storageReady) { delete self.chatstore[chatbox.data('username')]; if(self.storageReady) { $.jStore.store( self.storageBrowserKey + '-' + self.username + '-chats', self.chatstore); } } }); // Setup message sending for all chatboxes $('.imjs-chatbox .imjs-input').live('keydown', function(event) { var obj = $(this); if(event.keyCode == 13 && !($.browser.msie && $.browser.version < 8)) { self.send(obj.parents('.imjs-chatbox').data('username'), obj.val()); } }).live('keyup', function(event) { if(event.keyCode == 13) { if($.browser.msie && $.browser.version < 8) { var obj = $(this); self.send(obj.parents('.imjs-chatbox').data('username'), obj.val()); } var obj = $(this); obj.val(''); obj.height(obj.data('height')); } }).live('keypress', function(e) { var obj = $(this); if(!($.browser.msie && $.browser.opera)) obj.height(0); if(this.scrollHeight > obj.height() || this.scrollHeight < obj.height()) { obj.height(this.scrollHeight); } }); $('.imjs-msglog').live('click', function() { var chatbox = $(this).parents('.imjs-chatbox'); chatbox.find('.imjs-input').focus(); }); // Create a chatbox when a buddylist item is clicked $('.imjs-friend').live('click', function() { var chatbox = self._createChatbox($(this).data('friend')); if(chatbox.data('tab').data('state') != 'active') chatbox.data('tab').click(); chatbox.find('.imjs-input').focus(); }); // Setup and hide the scrollers $('.imjs-scroll').css('display', 'none'); $('#imjs-scroll-left').live('click', function() { var hiddenTab = $('#imjs-bar li.imjs-tab:visible').slice(-1) .next('#imjs-bar li.imjs-tab:hidden') .filter(function() { return $(this).data('state') != 'closed' }) .not('.imjs-default').slice(-1).css('display', ''); if(hiddenTab.length) { $('#imjs-bar li.imjs-tab:visible').eq(0).css('display', 'none'); $(this).html(parseInt($(this).html()) - 1); $('#imjs-scroll-right').html(parseInt($('#imjs-scroll-right').html()) + 1); } return false; }); $('#imjs-scroll-right').live('click', function() { var hiddenTab = $('#imjs-bar li.imjs-tab:visible').eq(0) .prev('#imjs-bar li.imjs-tab:hidden') .filter(function() { return $(this).data('state') != 'closed' }) .not('.imjs-default').slice(-1).css('display', ''); if(hiddenTab.length) { $('#imjs-bar li.imjs-tab:visible').slice(-1).css('display', 'none'); $(this).html(parseInt($(this).html()) - 1); $('#imjs-scroll-left').html(parseInt($('#imjs-scroll-left').html()) + 1); } return false; }); // Initialize the chatbox hash this.chats = {}; // Try to resume any existing session this.resume(); $(window).resize(function() { self.bar._scrollers(); }); } else return AjaxIM.init(options); }; // We predefine all public functions here... // If they are called before everything (theme, storage engine) has loaded, // then they get put into a "prequeue" and run when everything *does* // finally load. // // This ensures that nothing loads without all of the principal components // being pre-loaded. If that were to occur (without this prequeue), things // would surely break. var prequeue = []; var empty = function() { var func = this; return function() { prequeue.push([func, arguments]) }; }; $.extend(AjaxIM.prototype, { settings: {}, friends: {}, chats: {}, storage: empty.apply('storage'), login: empty.apply('login'), logout: empty.apply('logout'), resume: empty.apply('resume'), form: empty.apply('form'), poll: empty.apply('poll'), incoming: empty.apply('incoming'), send: empty.apply('send'), status: empty.apply('status'), statuses: {}, bar: { initialize: empty.apply('bar.initialize'), activateTab: empty.apply('bar.activateTab'), closeTab: empty.apply('bar.closeTab'), addTab: empty.apply('bar.addTab'), notification: empty.apply('bar.notification'), _scrollers: empty.apply('bar._scrollers') } }); setup = (function() { var self = this; if(!this.storageReady || !this.themeLoaded) return; $(self).trigger('loadComplete'); $(window).resize(); $.extend(AjaxIM.prototype, { // == Cookies == // // The "cookies" functions can be used to set, get, and erase JSON-based cookies. // These functions are primarily used to manage and read the server-set cookie // that handles the user's chat session ID. cookies: { // === {{{AjaxIM.}}}**{{{cookies.set(name, value, days)}}}** === // // Sets a cookie, stringifying the JSON value upon storing it. // // ==== Parameters ==== // * {{{name}}} is the cookie name.\\ // * {{{value}}} is the cookie data that you would like to store.\\ // * {{{days}}} is the number of days that the cookie will be stored for. set: function(name, value, days) { if (days) { var date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); var expires = "; expires=" + date.toGMTString(); } else var expires = ""; document.cookie = name + "=" + $.compactJSON(value) + expires + "; path=/"; }, // === {{{AjaxIM.}}}**{{{cookies.get(name)}}}** === // // Gets a cookie, decoding the JSON value before returning the data. // // ==== Parameters ==== // * {{{name}}} is the cookie name that you would like to retrieve. get: function(name) { var nameEQ = name + "="; var ca = document.cookie.split(';'); for(var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') c = c.substring(1, c.length); if (c.indexOf(nameEQ) == 0) { var cval = decodeURIComponent(c.substring(nameEQ.length, c.length)); return $.secureEvalJSON(cval); } } return null; }, // === {{{AjaxIM.}}}**{{{cookies.erase(name)}}}** === // // Deletes a cookie. // // {{{name}}} is the existing cookie that you would like to delete. erase: function(name) { self.cookies.set(name, '', -1); } }, // == Main == // === {{{AjaxIM.}}}**{{{storage()}}}** === // // Retrieves chat session data from whatever storage engine is enabled // (provided that one is enabled at all). If a page reloads, this function // is called to restore the user's chat state (existing conversations, active tab). // This function is called //automatically//, upon initialization of the IM engine. storage: function() { if(!self.storeKey.length) return; try { var chatstore = $.jStore.store(self.storeKey + 'chats') || {}; } catch(e) { $.jStore.remove(self.storeKey + 'chats'); var chatstore = {}; } if(this.chatstore) { $.each(this.chatstore, function(username, convo) { if(username in chatstore) chatstore[username] = $.merge(chatstore[username], self.chatstore[username]); else chatstore[username] = self.chatstore[username]; }); this.chatstore = chatstore; $.jStore.store(self.storeKey + 'chats', chatstore); } else { this.chatstore = chatstore; } $.each(this.chatstore, function(username, convo) { if(!convo.length) return; var chatbox = self._createChatbox(username, true); chatbox.data('lastDateStamp', null).css('display', 'none'); // Remove the automatic date stamp chatbox.find('.imjs-msglog').empty(); // Restore all messages, date stamps, and errors $.each(convo, function() { switch(this[0]) { case 'error': self._addError(chatbox, decodeURIComponent(this[2]), this[3]); break; case 'datestamp': self._addDateStamp(chatbox, this[3]); break; case 'a': case 'b': self._addMessage(this[0], chatbox, this[1], decodeURIComponent(this[2]), this[3]); break; } }); $(self).trigger('chatRestored', [username, chatbox]); }); var activeTab = $.jStore.store(self.storeKey + 'activeTab') || []; if(activeTab.length && (activeTab = activeTab[0]) && activeTab in this.chats) { this.chats[activeTab].data('tab').click(); var msglog = this.chats[activeTab].find('.imjs-msglog'); msglog[0].scrollTop = msglog[0].scrollHeight; } }, // === {{{AjaxIM.}}}**{{{login(username, password)}}}** === // // Authenticates a user and initializes the IM engine. If the user is // already logged in, [s]he is logged out, the session is cleared, and // the new user is logged in. // // Returns the user's properly formatted username, session ID, and online // friends in JSON, if successful; e.g.:\\ // {{{ {u: 'username', s: 'longsessionid', f: [{u: 'friend', s: 1, g: 'group'}]} }}} // // If unsuccessful, {{{false}}} is returned. // // ==== Parameters ==== // * {{{username}}} is the user's username.\\ // * {{{password}}} is the user's password. This password will be MD5 hashed // before it is sent to the server. login: function(username, password) { if(!username) username = ''; if(!password) password = ''; if(this.username) return true; // Already logged in! // hash password before sending it to the server password = $.md5(password); // authenticate AjaxIM.request( this.actions.login, {'username': username, 'password': password}, function(auth) { if(auth.r == 'logged in') { self.username = ('u' in auth ? auth.u : username); if(self.settings.storageMethod) self.storeKey = [self.storageBrowserKey, self.username, ''].join('-'); var existing = self.cookies.get(self.settings.cookieName); self.storage(); // Begin the session $.each(auth.f, function() { self.friends[this.u] = {status: [this.s, ''], group: this.g}; }); self._session(self.friends); self._storeFriends(); $(self).trigger('loginSuccessful', [auth]); return auth; } else { $(self).trigger('loginError', [auth]); } return false; } ); }, // === {{{AjaxIM.}}}**{{{logout()}}}** === // // Logs the user out and removes his/her session cookie. As well, it // will close all existing chat windows, clear the storage engine, and // remove the IM bar. logout: function() { AjaxIM.request( this.actions.logout, {}, function(done) { if(done) { self.cookies.erase(self.settings.cookieName); self._clearSession(); $(self).trigger('logoutSuccessful'); return true; } else { $(self).trigger('logoutError'); return false; } } ); }, // === {{{AjaxIM.}}}**{{{resume()}}}** === // // Resumes an existing session based on a session ID stored in the // server-set cookie. This function is called //automatically// upon IM // engine (re-)initialization, so the user does not need to re-login // should a session already exist. resume: function() { var session = this.cookies.get(this.settings.cookieName); if(session && session.sid) { this.username = session.user; this.storeKey = [this.storageBrowserKey, this.username, ''].join('-'); var friends = $.jStore.store(this.storeKey + 'friends') || []; if(self.settings.checkResume) { AjaxIM.request( this.actions.resume, {}, function(response) { if(response.r == 'connected') { self._session(friends); self.storage(); } else { var username = this.username; self._clearSession(); $(self).trigger('sessionNotResumed', [username]); } } ); } else { self._session(friends); self.storage(); } } else { $(self).trigger('noSession'); } }, // === //private// {{{AjaxIM.}}}**{{{_session(friends)}}}** === // // Restores session data (username, friends) and begins polling the server. // Called only by {{{AjaxIM.resume()}}}. // // ==== Parameters ==== // * {{{friends}}} is a list of "friend" objects, e.g.:\\ // {{{[{u: 'friend', s: 1, g: 'group'}, ...]}}} // ** {{{u}}} being the friend's username. // ** {{{s}}} being one of the available status codes (see {{{AjaxIM.statuses}}}), depending on the friend's current status. // ** {{{g}}} being the group that the friend is in. _session: function(friends) { $('#imjs-friends-panel .imjs-header span').html(this.username); $('#imjs-friends').removeClass('imjs-not-connected'); $.each(friends, function(friend, info) { self.addFriend.apply(self, [friend, info.status, info.group]); }); self._storeFriends(); $(self).trigger('sessionResumed', [this.username]); setTimeout(function() { self.poll(); }, 0); }, // === //private// {{{AjaxIM.}}}**{{{_clearSession()}}}** === // // Clears all session data from the last known user. _clearSession: function() { if(self.settings.storageMethod && self.storageReady) { $.jStore.remove(self.storeKey + 'chats'); $.jStore.remove(self.storeKey + 'friends'); $.jStore.remove(self.storeKey + 'activeTab'); } self.chats = {}; $('.imjs-tab').not('.imjs-tab.imjs-default').remove(); self.cookies.erase('ajaxim_session'); delete self.username; }, // === {{{AjaxIM.}}}**{{{form(element)}}}** === // // Loads a login and registration form into the specified element // or, if no element is supplied, to the location on the page from // which this function was called. form: function(element) { $(element).load(this.settings.theme + '/theme.html #imjs-lr', function() { $('#imjs-lr .error').hide(); if(self.username) { $('#imjs-register, #imjs-login fieldset').hide(); $('#imjs-logged-in') .show() .html($('#imjs-logged-in').html().replace('{username}', self.username)); } else { $('#imjs-logged-in').hide(); } // Handle logout success $(self).bind('logoutSuccessful', function() { $('#imjs-login fieldset').slideDown(); $('#imjs-register').slideDown(); $('#imjs-logged-in') .html($('#imjs-logged-in strong').html('{username}')) .slideUp(); }); $('#imjs-logged-in a').click(function() { self.logout(); return false; }); // Handle login error or success $(self).bind('loginError', function() { $('#imjs-login .error').html(AjaxIM.i18n.authInvalid).slideDown('fast'); $('#imjs-login input') .addClass('imjs-lr-error') .blur(function() { $(this).removeClass('imjs-lr-error'); }); }).bind('loginSuccessful', function() { $('#imjs-login fieldset').slideUp(); $('#imjs-register').slideUp(); $('#imjs-logged-in') .html($('#imjs-logged-in').html().replace('{username}', self.username)) .slideDown(); }); var login = function() { self.login($('#imjs-login-username').val(), $('#imjs-login-password').val()); return false; }; $('#imjs-login').submit(login); $('#imjs-login-submit').click(login); var regIssues = false; var regError = function(error, fields) { $('#imjs-register .error') .append(AjaxIM.i18n['register' + error] + ' ') .slideDown(); $(fields) .addClass('imjs-lr-error') .blur(function() { $(this).removeClass('imjs-lr-error'); }); regIssues = true; }; var register = function() { $('#imjs-register .error').empty(); regIssues = false; var username = $('#imjs-register-username').val(); var password = $('#imjs-register-password').val(); if(password.length < 4) regError('PasswordLength', '#imjs-register-password'); if(password != $('#imjs-register-cpassword').val()) regError('PasswordMatch', '#imjs-register-password, #imjs-register-cpassword'); if(username.length <= 2 || !$('#imjs-register-username').val().match(/^[A-Za-z0-9_.]+$/)) regError('UsernameLength', '#imjs-register-username'); if(!regIssues) { AjaxIM.request( self.actions.register, {username: username, password: password}, function(response) { if(response.r == 'registered') { self.login(username, password); } else if(response.r == 'error') { switch(response.e) { case 'unknown': regError('Unknown', ''); break; case 'invalid password': regError('PasswordLength', '#imjs-register-password'); break; case 'invalid username': regError('UsernameLength', '#imjs-register-username'); break; case 'username taken': regError('UsernameTaken', '#imjs-register-username'); break; } } }, function(error) { regError('Unknown', ''); } ); } return false; }; $('#imjs-register').submit(register); $('#imjs-register-submit').click(register); }); }, // === {{{AjaxIM.}}}**{{{poll()}}}** === // // Queries the server for new messages. If a 'long' or 'short' poll // type is used, jQuery's {{{$.post}}} or {{{$.getJSON}}} will be // used. If 'comet' is used, the server connection will be deferred // to the comet set of functions. poll: function() { if(/^(short|long)$/.test(this.settings.pollType)) { AjaxIM.request( this.actions.poll, {}, function(response) { if(!response['e']) { if(response.length) self._parseMessages(response); setTimeout(function() { self.poll(); }, 0); } else { switch(response.e) { case 'no session found': self._notConnected(); break; } $(self).trigger('pollFailed', [response.e]); } }, function(error) { self._notConnected(); $(self).trigger('pollFailed', ['not connected']); // try reconnecting? } ); } else if(this.settings.pollType == 'comet') { this.comet.connect(); } }, // === //private// {{{AjaxIM.}}}**{{{_parseMessages(messages)}}}** === // // Handles an incoming message array:\\ // {{{[{t: 'type', s: 'sender', r: 'recipient', m: 'message'}, ...]}}} // // * {{{t}}} (message type) is one of: // ** {{{m}}} — a standard message // ** {{{s}}} — a user's status update // ** {{{b}}} — a broadcasted message (sent to many users simultaneously) // * {{{s}}} is the sender of the message. // * {{{r}}} is the intended recipient of the message. Most of the time, this will // simply be the logged in user, however, a broadcasted message may not specify // a recipient or may specify a different recipient. Also provides future // compatability for chatrooms. // * {{{m}}} is the actual message. For something such as a status update, this can // be a JSON object or parsable string; e.g. {{{"2:I'm away."}}} // // ==== Parameters ==== // * {{{messages}}} is the message array _parseMessages: function(messages) { if($.isArray(messages)) { $.each(messages, function() { $(self).trigger('parseMessage', [this]); switch(this.t) { case 'm': self.incoming(this.s, this.m); break; case 's': var status = this.m.split(':'); if(this['g']) self.addFriend(this.s, status, this.g); self._friendUpdate(this.s, status[0], status.slice(1).join(':')); self._storeFriends(); break; case 'b': break; default: break; } }); } }, // === {{{AjaxIM.}}}**{{{incoming(from, message)}}}** === // // Handles a new message from another user. If a chatbox for that // user does not yet exist, one is created. If it does exist, but // is minimized, the user is notified but the chatbox is not brought // to the front. This function also stores the message, if a storage // method is set. // // ==== Parameters ==== // * {{{from}}} is the username of the sender. // * {{{message}}} is the body. incoming: function(from, message) { // check if IM exists, otherwise create new window // TODO: If friend is not on the buddylist, // should add them to a temp list? var chatbox = this._createChatbox(from); if(!$('#imjs-bar .imjs-selected').length) { chatbox.data('tab').click(); } else if(chatbox.data('tab').data('state') != 'active') { this.bar.notification(chatbox.data('tab')); } var time = this._addMessage('b', chatbox, from, message); this._storeMessage('b', chatbox, from, message, time); }, // === {{{AjaxIM.}}}**{{{addFriend(username, group)}}}** === // // Inserts a new friend into the friends list. If the group specified // doesn't exist, it is created. If the friend is already in this group, // they aren't added again, however, the friend item is returned. // // ==== Parameters ==== // * {{{username}}} is the username of the new friend. // * {{{status}}} is the current status of the friend. // * {{{group}}} is the user group to which the friend should be added. addFriend: function(username, status, group) { var status_name = 'available'; $.each(this.statuses, function(key, val) { if(status[0] == val) { status_name = key; return false; } }); var group_id = 'imjs-group-' + $.md5(group); if(!(group_item = $('#' + group_id)).length) { var group_item = $('.imjs-friend-group.imjs-default').clone() .removeClass('imjs-default') .attr('id', group_id) .data('group', group) .appendTo('#imjs-friends-list'); var group_header = group_item.find('.imjs-friend-group-header'); group_header.html(group_header.html().replace('{group}', group)); } var user_id = 'imjs-friend-' + $.md5(username + group); if(!$('#' + user_id).length) { var user_item = group_item.find('ul li.imjs-default').clone() .removeClass('imjs-default') .addClass('imjs-' + status_name) .attr('id', user_id) .data('friend', username) .appendTo(group_item.find('ul')); if(status[0] == 0) user_item.hide(); user_item.html(user_item.html().replace('{username}', username)); } this.friends[username] = {'status': status, group: group}; this._updateFriendCount(); return this.friends[username]; }, // === //private// {{{AjaxIM.}}}**{{{_updateFriendCount()}}}** === // // Counts the number of online friends and updates the friends count // in the friend tab. _updateFriendCount: function() { var friendsLength = 0; for(var f in this.friends) { if(this.friends[f].status[0] != 0) friendsLength++; } $('#imjs-friends .imjs-tab-text span span').html(friendsLength); }, // === //private// {{{AjaxIM.}}}**{{{_storeFriends()}}}** === // // If a storage method is enabled, the current state of the // user's friends list is stored. _storeFriends: function() { if(this.settings.storageMethod && this.storageReady) $.jStore.store(this.storeKey + 'friends', this.friends); }, // === //private// {{{AjaxIM.}}}**{{{_createChatbox(username)}}}** === // // Builds a chatbox based on the default chatbox HTML and CSS defined // in the current theme. Should a chatbox for this user already exist, // a new one is not created. Instead, it is either given focus (should // no other windows already have focus), or a notification is issued. // // As well, if the chatbox does not exist, an associated tab will be // created. // // ==== Parameters ==== // * {{{username}}} is the name of the user for whom the chatbox is intended // for. // * {{{no_stamp}}} sets whther or not to add a date stamp to the chatbox // upon creation. // // //Note:// New chatboxes are given an automatically generated ID in the // format of {{{#imjs-[md5 of username]}}}. _createChatbox: function(username, no_stamp) { var chatbox_id = 'imjs-' + $.md5(username); if(!(chatbox = $('#' + chatbox_id)).size()) { // add a tab var tab = this.bar.addTab(username, '#' + chatbox_id); var chatbox = tab.find('.imjs-chatbox'); chatbox.attr('id', chatbox_id); chatbox.data('tab', tab); // remove default items from the message log var message_log = chatbox.find('.imjs-msglog').empty(); // setup the chatbox header var cb_header = chatbox.find('.imjs-header'); cb_header.html(cb_header.html().replace('{username}', username)); if(!no_stamp) { // add a date stamp var time = this._addDateStamp(chatbox); this._storeNonMessage('datestamp', username, null, time); } // associate the username with the object and vice-versa this.chats[username] = chatbox; chatbox.data('username', username); // did this chatbox fall down? this.bar._scrollers(); if(username in this.friends) { status = this.friends[username].status; var status_name = 'available'; $.each(this.statuses, function(key, val) { if(status[0] == val) { status_name = key; return false; } }); tab.addClass('imjs-' + status_name); } // store inputbox height //var input = chatbox.find('.imjs-input'); //input.data('height', input.height()); } else if(chatbox.data('tab').data('state') == 'closed') { chatbox.find('.imjs-msglog > *').addClass('imjs-msg-old'); var tab = chatbox.data('tab'); if(tab.css('display') == 'none') tab.css('display', '').removeClass('imjs-selected') .appendTo('#imjs-bar'); if(!no_stamp) { // possibly add a date stamp var time = this._addDateStamp(chatbox); this._storeNonMessage('datestamp', username, null, time); } if(!$('#imjs-bar .imjs-selected').length) { tab.click(); } else { this.bar.notification(tab); } } return chatbox; }, // === //private// {{{AjaxIM.}}}**{{{_addDateStamp(chatbox)}}}** // // // Adds a date/time notifier to a chatbox. These are generally // inserted upon creation of a chatbox, or upon the date changing // since the last time a date stamp was added. If a date stamp for // the current date already exists, a new one will not be added. // // ==== Parameters ==== // * {{{chatbox}}} refers to the jQuery-selected chatbox DOM element. // * {{{time}}} is the date/time the date stamp will show. It is specified // in milliseconds since the Unix Epoch. This is //only// defined when // date stamps are being restored from storage; if not specified, the // current computer time will be used. _addDateStamp: function(chatbox, time) { var message_log = $(chatbox).find('.imjs-msglog'); if(!time) time = (new Date()).getTime(); var date_stamp = $('.imjs-tab.imjs-default .imjs-chatbox .imjs-msglog .imjs-date').clone(); var date_stamp_time = date_stamp.find('.imjs-msg-time'); if(date_stamp_time.length) date_stamp_time.html(AjaxIM.dateFormat(time, date_stamp_time.html())); var date_stamp_date = date_stamp.find('.imjs-date-date'); var formatted_date = AjaxIM.dateFormat(time, date_stamp_date.html()); if(chatbox.data('lastDateStamp') != formatted_date) { if(date_stamp_date.length) date_stamp_date.html(AjaxIM.dateFormat(time, date_stamp_date.html())); chatbox.data('lastDateStamp', formatted_date); date_stamp.appendTo(message_log); } else { //$('
').appendTo(message_log); } return time; }, // === //private// {{{AjaxIM.}}}**{{{_addError(chatbox, error)}}}** // // // Adds an error to a chatbox. These are generally inserted after // a user sends a message unsuccessfully. If an error message // was already added, another one will be added anyway. // // ==== Parameters ==== // * {{{chatbox}}} refers to the jQuery-selected chatbox DOM element. // * {{{error}}} is the error message string. // * {{{time}}} is the date/time the error occurred. It is specified in // milliseconds since the Unix Epoch. This is //only// defined when // errors are being restored from storage; if not specified, the current // computer time will be used. _addError: function(chatbox, error, time) { var message_log = $(chatbox).find('.imjs-msglog'); var error_item = $('.imjs-tab.imjs-default .imjs-chatbox .imjs-msglog .imjs-error').clone(); var error_item_time = error_item.find('.imjs-msg-time'); if(error_item_time.length) { if(!time) time = (new Date()).getTime(); error_item_time.html(AjaxIM.dateFormat(time, error_item_time.html())); } error_item.find('.imjs-error-error').html(error); error_item.appendTo(message_log); message_log[0].scrollTop = message_log[0].scrollHeight; }, // === //private// {{{AjaxIM.}}}**{{{_addMessage(ab, chatbox, username, message, time)}}}** // // // Adds a message to a chatbox. Depending on the {{{ab}}} value, // the color of the username may change as a way of visually // identifying users (however, this depends on the theme's CSS). // A timestamp is added to the message, and the chatbox is scrolled // to the bottom, such that the new message is visible. // // Messages will be automatically tag-escaped, so as to prevent // any potential cross-site scripting problems. Additionally, // URLs will be automatically linked. // // ==== Parameters ==== // * {{{ab}}} refers to whether the user is "a" or "b" in a conversation. // For the general case, "you" are "a" and "they" are "b". // * {{{chatbox}}} refers to the jQuery-selected chatbox DOM element. // * {{{username}}} is the username of the user who sent the message. // * {{{time}}} is the time the message was sent in milliseconds since // the Unix Epoch. This is //only// defined when messages are being // restored from storage. For new messages, the current computer // time is automatically used. _addMessage: function(ab, chatbox, username, message, time) { var last_message = chatbox.find('.imjs-msglog > *:last-child'); if(last_message.hasClass('imjs-msg-' + ab)) { // Last message was from the same person, so let's just add another imjs-msg-*-msg var message_container = (last_message.hasClass('imjs-msg-' + ab + '-container') ? last_message : last_message.find('.imjs-msg-' + ab + '-container')); var single_message = $('.imjs-tab.imjs-default .imjs-chatbox .imjs-msglog .imjs-msg-' + ab + '-msg') .clone().appendTo(message_container); single_message.html(single_message.html().replace('{username}', username)); } else if(!last_message.length || !last_message.hasClass('imjs-msg-' + ab)) { var message_group = $('.imjs-tab.imjs-default .imjs-chatbox .imjs-msg-' + ab) .clone().appendTo(chatbox.find('.imjs-msglog')); message_group.html(message_group.html().replace('{username}', username)); var single_message = message_group.find('.imjs-msg-' + ab + '-msg'); } // clean up the message message = message.replace(//g, '>') .replace(/(^|.*)\*([^*]+)\*(.*|$)/, '$1$2$3'); // autolink URLs message = message.replace( new RegExp('([A-Za-z][A-Za-z0-9+.-]{1,120}:[A-Za-z0-9/]' + '(([A-Za-z0-9$_.+!*,;/?:@&~=-])|%[A-Fa-f0-9]{2}){1,333}' + '(#([a-zA-Z0-9][a-zA-Z0-9$_.+!*,;/?:@&~=%-]{0,1000}))?)', 'g'), '$1'); // insert the message single_message.html(single_message.html().replace('{message}', message)); // set the message time var msgtime = single_message.find('.imjs-msg-time'); if(!time) time = new Date(); if(typeof time != 'string') time = AjaxIM.dateFormat(time, msgtime.html()); msgtime.html(time); var msglog = chatbox.find('.imjs-msglog'); msglog[0].scrollTop = msglog[0].scrollHeight; return time; }, // === //private// {{{AjaxIM.}}}**{{{_storeNonMessage(type, username, data, time)}}}** === // // **Redundant?**\\ // Similar to {{{AjaxIM._storeMessage}}}, but stores items that aren't messages, // such as datestamps and errors. // // ==== Parameters ==== // * {{{type}}} is the type of non-message (error, datestamp). // * {{{username}}} is the username of the user being chatted with. // * {{{data}}} is the (optional) data of the non-message to be stored. // * {{{time}}} is the time of the message. _storeNonMessage: function(type, username, data, time) { // If storage is on & ready, store the non-message if(this.settings.storageMethod) { if(!this.chatstore) this.chatstore = {}; if(!(username in this.chatstore)) this.chatstore[username] = []; // If the chat store gets too long, it becomes slow to load. if(this.chatstore[username].length > 300) this.chatstore[username].shift(); // For some reason, if we don't encode and decode the message, it *will* break // (at least) the Flash storage engine's retrieval. Gah! this.chatstore[username].push( [type, username, encodeURIComponent(data), time]); if(this.storageReady) $.jStore.store(self.storeKey + 'chats', this.chatstore); } }, // === //private// {{{AjaxIM.}}}**{{{_storeMessage(ab, chatbox, username, message, time)}}}** === // // Taking the same arguments as {{{AjaxIM._addMessage}}}, {{{_storeMessage}}} pushes a message // into the storage hash, if storage is enabled. // // Messages are added to a message array, by username. The entire chat hash is stored as // a {{{'chats'}}} object in whatever storage engine is enabled. _storeMessage: function(ab, chatbox, username, message, time) { // If storage is on & ready, store the message if(this.settings.storageMethod) { if(!this.chatstore) this.chatstore = {}; message = message.replace(//g, '>'); if(!(username in this.chatstore)) { this.chatstore[username] = []; } else if(this.chatstore[username].length > 300) { // If the chat store gets too long, it becomes slow to load. this.chatstore[username].shift(); } // For some reason, if we don't encode and decode the message, it *will* break // (at least) the Flash storage engine's retrieval. Gah! this.chatstore[chatbox.data('username')].push( [ab, username, encodeURIComponent(message), time]); if(this.storageReady) $.jStore.store(this.storeKey + 'chats', this.chatstore); } }, // === //private// {{{AjaxIM.}}}**{{{_friendUpdate(friend, status, statusMessage)}}}** === // // Called when a friend's status is updated. This function will update all locations // where a status icon is displayed (chat tab, friends list), as well as insert // a notification, should a chatbox be open. // // ==== Parameters ==== // * {{{friend}}} is the username of the friend. // * {{{status}}} is the new status code. See {{{AjaxIM.statuses}}} for a list of available // codes. //Note: If an invalid status is specified, no action will be taken.// // * {{{statusMessage}}} is a message that was, optionally, specified by the user. It will be // used should "you" send the user an IM while they are away, or if their status is viewed // in another way (such as via the friends list [**not yet implemented**]). _friendUpdate: function(friend, status, statusMessage) { // add friend to buddylist, update their status, etc. var status_name = 'available'; $.each(this.statuses, function(key, val) { if(status == val) { status_name = key; return false; } }); if(this.chats[friend]) { var tab = this.chats[friend].data('tab'); var tab_class = 'imjs-tab'; if(tab.data('state') == 'active') tab_class += ' imjs-selected'; tab_class += ' imjs-' + status_name; tab.attr('class', tab_class); // display the status in the chatbox var date_stamp = $('.imjs-tab.imjs-default .imjs-chatbox .imjs-msglog .imjs-date').clone(); var date_stamp_time = date_stamp.find('.imjs-msg-time'); if(date_stamp_time.length) date_stamp_time.html(AjaxIM.dateFormat(date_stamp_time.html())); var date_stamp_date = date_stamp.find('.imjs-date-date').html( AjaxIM.i18n[ 'chat' + status_name[0].toUpperCase() + status_name.slice(1) ].replace(/%s/g, friend)); var msglog = this.chats[friend].find('.imjs-msglog'); date_stamp.appendTo(msglog); msglog[0].scrollTop = msglog[0].scrollHeight; } if(this.friends[friend]) { var friend_id = 'imjs-friend-' + $.md5(friend + this.friends[friend].group); $('#' + friend_id).attr('class', 'imjs-friend imjs-' + status_name); if(status == 0) { $('#' + friend_id + ':visible').slideUp(); $('#' + friend_id + ':hidden').hide(); } else if(!$('#' + friend_id + ':visible').length) { $('#' + friend_id).slideDown(); } this.friends[friend].status = [status, statusMessage]; this._updateFriendCount(); } }, // === //private// {{{AjaxIM.}}}**{{{_notConnected()}}}** === // // Puts the user into a visible state of disconnection. Sets the // friends list to "not connected" and empties it; disallows new messages // to be sent. _notConnected: function() { $('#imjs-friends').addClass('imjs-not-connected').unbind('click', this.activateTab); }, // === {{{AjaxIM.}}}**{{{send(to, message)}}}** === // // Sends a message to another user. The message will be added // to the chatbox before it is actually sent, however, if an // error occurs during sending, that will be indicated immediately // afterward. // // After sending the message, one of three status codes should be // returned as a JSON object, e.g. {{{{r: 'code'}}}}: // * {{{ok}}} — Message was sent successfully. // * {{{offline}}} — The user is offline or unavailable to // receive messages. // * {{{error}}} — a problem occurred, unrelated to the user // being unavailable. // // ==== Parameters ==== // * {{{to}}} is the username of the recipient. // * {{{message}}} is the content to be sent. send: function(to, message) { if(!message) return; if(this.chats[to]) { // REMOVE ME? // possibly add a datestamp var time = self._addDateStamp(this.chats[to]); this._storeNonMessage('datestamp', to, null, time); time = this._addMessage('a', this.chats[to], this.username, message); this._storeMessage('a', this.chats[to], this.username, message, time); } $(self).trigger('sendingMessage', [to, message]); AjaxIM.request( this.actions.send, {'to': to, 'message': message}, function(result) { switch(result.r) { case 'ok': $(self).trigger('sendMessageSuccessful', [to, message]); break; case 'offline': $(self).trigger('sendMessageFailed', ['offline', to, message]); break; case 'error': default: if(result.e == 'no session found') { self._notConnected(); self._addError(self.chats[to], AjaxIM.i18n.notConnected); self._storeNonMessage('error', to, AjaxIM.i18n.notConnected, (new Date()).getTime()); } $(self).trigger('sendMessageFailed', [result.e, to, message]); break; } }, function(error) { self._notConnected(); self._addError(self.chats[to], AjaxIM.i18n.notConnected); self._storeNonMessage('error', to, AjaxIM.i18n.notConnected, (new Date()).getTime()); $(self).trigger('sendMessageFailed', ['not connected', to, message]); } ); }, // === {{{AjaxIM.}}}**{{{status(s, message)}}}** === // // Sets the user's status and status message. It is possible to not // set a status message by setting it to an empty string. The status // will be sent to the server, where upon the server will broadcast // the update to all individuals with "you" on their friends list. // // ==== Parameters ==== // * {{{s}}} is the status code, as defined by {{{AjaxIM.statuses}}}. // * {{{message}}} is the custom status message. status: function(s, message) { // update status icon(s) if(!this.statuses[s]) return; $('#imjs-friends').attr('class', 'imjs-' + s); $(self).trigger('changingStatus', [s, message]); AjaxIM.request( this.actions.status, {'status': this.statuses[s], 'message': message}, function(result) { switch(result.r) { case 'ok': $(self).trigger('changeStatusSuccessful', [s, message]); break; case 'error': default: $(self).trigger('changeStatusFailed', [result.e, s, message]); break; } }, function(error) { $(self).trigger('changeStatusFailed', ['not connected', s, message]); } ); }, // === {{{AjaxIM.}}}**{{{statuses}}}** === // // These are the available status codes and their associated identities: // * {{{offline}}} (0) — Only used when signing out/when another // user has signed out, as once this status is set, the user is removed // from the server and friends will be unable to contact the user. // * {{{available}}} (1) — The user is online and ready to be messaged. // * {{{away}}} (2) — The user is online but is not available. Others // may still contact this user, however, the user may not respond. Anyone // contacting an away user will receive a notice stating that the user is away, // and (if one is set) their custom status message. // * {{{invisible}}} (3; **not yet implemented**) — The user is online, // but other users are made unaware, and the user will be represented // as being offline. It is still possible to contact this user, and for this // user to contact others; no status message or notice will be sent to others // messaging this user. statuses: {offline: 0, available: 1, away: 2, invisible: 3}, // == Footer bar == // // The footer bar is the bar that sits at the bottom of the page, in a fixed // position. It contains a tab for the friends list, and tabs for any open // chat boxes. It is also possible to add custom tabs for other functionality. bar: { // === {{{AjaxIM.}}}**{{{bar.initialize()}}}** === // // Setup the footer bar and enable tab actions. This function // uses {{{jQuery.live}}} to set hooks on any bar tabs created // in the future. initialize: function() { // Set up your standard tab actions $('.imjs-tab') .live('click', this.activateTab); $('.imjs-tab .imjs-close') .live('click', this.closeTab); // Set up the friends list actions var self = this; $(document).click(function(e) { if(e.target.id == 'imjs-friends' || $(e.target).parents('#imjs-friends').length) { return; } if($('#imjs-friends').data('state') == 'active') self.activateTab.call($('#imjs-friends')); }); $('#imjs-friends') .data('state', 'minimized') .click(function(e) { if(!$(this).hasClass('imjs-not-connected') && e.target.id != 'imjs-friends-panel' && !$(e.target).parents('#imjs-friends-panel').length) self.activateTab.call(this); }) .mouseenter(function() { if($(this).hasClass('imjs-not-connected')) { $('.imjs-tooltip').css('display', 'block'); $('.imjs-tooltip p').html(AjaxIM.i18n.notConnectedTip); var tip_left = $(this).offset().left - $('.imjs-tooltip').outerWidth() + ($(this).outerWidth() / 2); var tip_top = $(this).offset().top - $('.imjs-tooltip').outerHeight(true); $('.imjs-tooltip').css({ left: tip_left, top: tip_top }); } }) .mouseleave(function() { if($(this).hasClass('imjs-not-connected')) { $('.imjs-tooltip').css('display', ''); } }); $('#imjs-friends-panel') .data('tab', $('#imjs-friends')) .css('display', 'none'); }, // === {{{AjaxIM.}}}**{{{bar.activateTab()}}}** === // // Activate a tab by setting it to the 'active' state and // showing any related chatbox. If a chatbox is available // for this tab, also focus the input box. // // //Note:// {{{this}}}, here, refers to the tab DOM element. activateTab: function() { var chatbox = $(this).find('.imjs-chatbox') || false; if($(this).data('state') != 'active') { if($(this).attr('id') != 'imjs-friends') { $('#imjs-bar > li') .not($(this)) .not('#imjs-friends') .removeClass('imjs-selected') .each(function() { if($(this).data('state') != 'closed') { $(this).data('state', 'minimized'); var chatbox = $(this).find('.imjs-chatbox'); if(chatbox.length) chatbox.css('display', 'none'); } }); } if(chatbox && chatbox.css('display') == 'none') chatbox.css('display', ''); // set the tab to active... var tab = $(this).addClass('imjs-selected').data('state', 'active'); // ...and hide and reset the notification icon tab.find('.imjs-notification').css('display', 'none') .data('count', 0); if(self.settings.storageMethod && self.storageReady && chatbox && (username = chatbox.data('username'))) { $.jStore.store(self.storeKey + 'activeTab', [username]); } $(self).trigger('tabToggled', ['activated', tab]); } else { var tab = $(this).removeClass('imjs-selected').data('state', 'minimized'); if(chatbox && chatbox.css('display') != 'none') chatbox.css('display', 'none'); if(self.settings.storageMethod && self.storageReady) { $.jStore.store(self.storeKey + 'activeTab', ['*']); } $(self).trigger('tabToggled', ['minimized', tab]); } if(chatbox) { if(!(input = chatbox.find('.imjs-input')).data('height')) { // store the height for resizing later input.data('height', input.height()); } try { var msglog = chatbox.find('.imjs-msglog'); msglog[0].scrollTop = msglog[0].scrollHeight; } catch(e) {} try { chatbox.find('.imjs-input').focus(); } catch(e) {} } }, // === {{{AjaxIM.}}}**{{{bar.closeTab()}}}** === // // Close a tab and hide any related chatbox, such that // the chatbox can not be reopened without reinitializing // the tab. // // //Note:// {{{this}}}, here, refers to the tab DOM element. closeTab: function() { var tab = $(this).parents('.imjs-tab'); tab.css('display', 'none').data('state', 'closed'); if(self.settings.storageMethod && self.storageReady) { delete self.chatstore[tab.find('.imjs-chatbox').data('username')]; if(self.storageReady) $.jStore.store(self.storeKey + 'chats', self.chatstore); } $(self).trigger('tabToggled', ['closed', tab]); self.bar._scrollers(); return false; }, // === {{{AjaxIM.}}}**{{{bar.addTab(label, action, closable)}}}** === // // Adds a tab to the tab bar, with the label {{{label}}}. When // clicked, it will call a callback function, {{{action}}}. If // {{{action}}} is a string, it is assumed that the string is // referring to a chatbox ID. // // ==== Parameters ==== // * {{{label}}} is the text that will be displayed on the tab.\\ // * {{{action}}} is the callback function, if it is a non-chatbox // tab, or a string if it //is// a chatbox tab.\\ // * {{{closable}}} is a boolean value that determines whether or not // it is possible for a user to close this tab. // // //Note:// New tabs are given an automatically generated ID // in the format of {{{#imjs-tab-[md5 of label]}}}. addTab: function(label, action, closable) { var tab = $('.imjs-tab.imjs-default').clone().insertAfter('#imjs-scroll-right'); tab.removeClass('imjs-default') .attr('id', 'imjs-tab-' + $.md5(label)) .html(tab.html().replace('{label}', label)) .data('state', 'minimized'); var notification = tab.find('.imjs-notification'); notification.css('display', 'none') .data('count', 0) .data('default-text', notification.html()) .html(notification.html().replace('{count}', '0')); if(closable === false) tab.find('.imjs-close').eq(0).remove(); if(typeof action == 'string') { //tab.data('chatbox', action); } else { tab.find('.imjs-chatbox').remove(); tab.click(action); } return tab; }, // === {{{AjaxIM.}}}**{{{bar.notification(tab)}}}** === // // Displays a notification on a tab. Generally, this is called when // a tab is minimized to let the user know that there is an update // for them. The way the notification is displayed depends on the // theme CSS. // // ==== Parameters ==== // * {{{tab}}} is the jQuery-selected tab DOM element. notification: function(tab) { var notify = tab.find('.imjs-notification'); var notify_count = notify.data('count') + 1; notify.data('count', notify_count) .html(notify.data('default-text').replace('{count}', notify_count)) .css('display', ''); }, // === //private// {{{AjaxIM.}}}**{{{bar._scrollers()}}}** === // // Document me! _scrollers: function() { var needScrollers = false; $('.imjs-tab').filter(function() { return $(this).data('state') != 'closed' }).css('display', ''); $.each(self.chats, function(username, chatbox) { var tab = chatbox.data('tab'); if(tab.data('state') == 'closed') return true; if(tab.position().top > $('#imjs-bar').height()) { $('.imjs-scroll').css('display', ''); tab.css('display', 'none'); needScrollers = true; } else { tab.css('display', ''); } }); if(!needScrollers) { $('.imjs-scroll').css('display', 'none'); } if($('#imjs-scroll-left').css('display') != 'none' && $('#imjs-scroll-left').position().top > $('#imjs-bar').height()) { $('#imjs-bar li.imjs-tab:visible').slice(-1).css('display', 'none'); } var hiddenLeft = $('#imjs-bar li.imjs-tab:visible').slice(-1) .nextAll('#imjs-bar li.imjs-tab:hidden') .not('.imjs-default') .filter(function() { return $(this).data('state') != 'closed' }).length; var hiddenRight = $('#imjs-bar li.imjs-tab:visible').eq(0) .prevAll('#imjs-bar li.imjs-tab:hidden') .not('.imjs-default') .filter(function() { return $(this).data('state') != 'closed' }).length; $('#imjs-scroll-left').html(hiddenLeft); $('#imjs-scroll-right').html(hiddenRight); } }, // == Comet == // // Comet, or HTTP streaming, holds open a connection between the client and // the server indefinitely. As the server receives new messages or events, // they are passed down to the client in a {{{<script>}}} // tag which calls the {{{AjaxIM.incoming()}}} function. The connection is // opened using either an {{{iframe}}} (in Opera or Internet Explorer) or // an {{{XMLHTTPRequest}}} object. Due to the extra flexibility necessary // with the {{{XMLHTTPRequest}}} object, jQuery's {{{$.ajax}}} is not used. comet: { type: '', obj: null, onbeforeunload: null, onreadystatechange: null, iframe: function() { if(/loaded|complete/i.test(this.obj.readyState)) throw new Error("IM server not available!"); }, // === {{{AjaxIM.}}}**{{{comet.connect()}}}** === // // Creates and initializes the object and connection between the server // and the client. For Internet Explorer and Opera, we use an // {{{<iframe>}}} element; for all other browsers, we create an // {{{XMLHTTPRequest}}} object. The server connects to the URI defined // as the "poll" action. This function is called automatically, when // the IM engine is initialized and the {{{AjaxIM.poll()}}} function // is called. connect: function() { var self = _instance; if($.browser.opera || $.browser.msie) { var iframe = $(''); with(iframe) { css({ position: 'absolute', visibility: 'visible', display: 'block', left: '-10000px', top: '-10000px', width: '1px', height: '1px' }); attr('src', self.actions.poll[1]); appendTo('body'); bind('readystatechange', self.comet.onreadystatechange = function() { self.comet.iframe() }); bind('beforeunload', self.comet.onbeforeunload = function() { self.comet.disconnect() }); } self.comet.type = 'iframe'; self.comet.obj = iframe; } else { var xhr = new XMLHttpRequest; var length = 1029; var code = /^\s*]*>parent\.(.+);<\/script>$/; xhr.open('get', self.actions.poll[1], true); xhr.onreadystatechange = function(){ if(xhr.readyState > 2) { if(xhr.status == 200) { responseText = xhr.responseText.substring(length); length = xhr.responseText.length; if(responseText != ' ') eval(responseText.replace(code, "$1")); } // We need an "else" here. If the state changes to // "loaded", the user needs to know they're // disconnected. } }; self.comet.type = 'xhr'; self.comet.obj = xhr; addEventListener('beforeunload', self.comet.beforeunload = function() { self.comet.disconnect(); }, false); setTimeout(function() { xhr.send(null) }, 10); } }, // === {{{AjaxIM.}}}**{{{comet.disconnect()}}}** === // // Disconnect from the server and destroy the connection object. This // function is called before the page unloads, so that we plug up and // potential leaks and free memory. disconnect: function() { var self = _instance.comet; if(!this.type || !this.obj) return; if(this.type == 'iframe') { detachEvent('onreadystatechange', this.onreadystatechange); detachEvent('onbeforeunload', this.onbeforeunload); this.obj.src = '.'; $(this.obj).remove(); } else { removeEventListener('beforeunload', this.onbeforeunload, false); this.obj.onreadystatechange = function(){}; this.obj.abort(); } delete this.obj; } } }) self.bar.initialize(); if(prequeue.length) { $.each(prequeue, function() { var func = this[0].split('.'); if(func.length > 1) self[func[0]][func[1]].apply(self, this[1]); else self[func[0]].apply(self, this[1]); }); } }); // == Static functions and variables == // // The following functions and variables are available outside of an initialized // {{{AjaxIM}}} object. // === {{{AjaxIM.}}}**{{{client}}}** === // // Once {{{AjaxIM.init()}}} is called, this will be set to the active AjaxIM // object. Only one AjaxIM object instance can exist at a time. This variable // can and should be accessed directly. AjaxIM.client = null; // === {{{AjaxIM.}}}**{{{init(options, actions)}}}** === // // Initialize the AjaxIM client object and engine. Here, you can define your // options and actions as outlined at the top of this documentation. // // ==== Parameters ==== // * {{{options}}} is the hash of custom settings to initialize Ajax IM with. // * {{{actions}}} is the hash of any custom action URLs. AjaxIM.init = function(options, actions) { if(!_instance) { _instance = new AjaxIM(options, actions); AjaxIM.client = _instance; } return _instance; } // === {{{AjaxIM.}}}**{{{request(url, data, successFunc, failureFunc)}}}** === // // Wrapper around {{{$.jsonp}}}, the JSON-P library for jQuery, and {{{$.ajax}}}, // jQuery's ajax library. Allows either function to be called, automatically, // depending on the request's URL array (see {{{AjaxIM.actions}}}). // // ==== Parameters ==== // {{{url}}} is the URL of the request. // {{{data}}} are any arguments that go along with the request. // {{{success}}} is a callback function called when a request has completed // without issue. // {{{_ignore_}}} is simply to provide compatability with {{{$.post}}}. // {{{failure}}} is a callback function called when a request hasn't not // completed successfully. AjaxIM.request = function(url, data, successFunc, failureFunc) { if(typeof failureFunc != 'function'); failureFunc = function(){}; $[url[0]]({ 'url': url[1], 'data': data, dataType: (url[0] == 'ajax' ? 'json' : 'jsonp'), type: 'POST', cache: false, timeout: 60000, callback: 'jsonp' + (new Date()).getTime(), success: function(json, textStatus) { successFunc(json); }, error: function(xOptions, error) { failureFunc(error); } }); // This prevents Firefox from spinning indefinitely // while it waits for a response. Why? Fuck if I know. if(url[0] == 'jsonp' && $.browser.mozilla) { $.jsonp({ 'url': 'about:', timeout: 0 }); } }; // === {{{AjaxIM.}}}**{{{incoming(data)}}}** === // // Never call this directly. It is used as a connecting function between // client and server for Comet. // // //Note:// There are two {{{AjaxIM.incoming()}}} functions. This one is a // static function called outside of the initialized AjaxIM object; the other // is only called within the initalized AjaxIM object. AjaxIM.incoming = function(data) { if(!_instance) return false; if(data.length) _instance._parseMessages(data); } // === {{{AjaxIM.}}}**{{{loaded}}}** === // // If Ajax IM has been loaded with the im.load.js file, this function will be // called when the library is finally loaded and ready for use. Similar to // jQuery's $(document).ready(), but for Ajax IM. AjaxIM.loaded = function() { if(typeof AjaxIMLoadedFunction == 'function') { AjaxIMLoadedFunction(); delete AjaxIMLoadedFunction; // clean up the global namespace } }; // === {{{AjaxIM.}}}**{{{dateFormat([date,] [mask,] utc)}}}** === // // Date Format 1.2.3\\ // © 2007-2009 Steven Levithan ([[http://blog.stevenlevithan.com/archives/date-time-format|stevenlevithan.com]])\\ // MIT license // // Includes enhancements by Scott Trenda // and Kris Kowal ([[http://cixar.com/~kris.kowal/|cixar.com/~kris.kowal/]]) // // Accepts a date, a mask, or a date and a mask and returns a formatted version // of the given date. // // ==== Parameters ==== // * {{{date}}} is a {{{Date()}}} object. If not specified, the date defaults to the // current date/time. // * {{{mask}}} is a string that defines the formatting of the date. Formatting // options can be found in the // [[http://blog.stevenlevithan.com/archives/date-time-format|Date Format]] // documentation. If not specified, the mask defaults to {{{dateFormat.masks.default}}}. AjaxIM.dateFormat = function () { var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, timezone = new RegExp('\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) ' + '(?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b', 'g'), timezoneClip = /[^-+\dA-Z]/g, pad = function (val, len) { val = String(val); len = len || 2; while (val.length < len) val = "0" + val; return val; }; // Regexes and supporting functions are cached through closure return function (date, mask, utc) { var dF = AjaxIM.dateFormat; // You can't provide utc if you skip other args (use the "UTC:" mask prefix) if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) { mask = date; date = undefined; } // Passing date through Date applies Date.parse, if necessary date = date ? new Date(date) : new Date; if (isNaN(date)) throw SyntaxError("invalid date"); mask = String(dF.masks[mask] || mask || dF.masks["default"]); // Allow setting the utc argument via the mask if (mask.slice(0, 4) == "UTC:") { mask = mask.slice(4); utc = true; } var _ = utc ? "getUTC" : "get", d = date[_ + "Date"](), D = date[_ + "Day"](), m = date[_ + "Month"](), y = date[_ + "FullYear"](), H = date[_ + "Hours"](), M = date[_ + "Minutes"](), s = date[_ + "Seconds"](), L = date[_ + "Milliseconds"](), o = utc ? 0 : date.getTimezoneOffset(), flags = { d: d, dd: pad(d), ddd: AjaxIM.i18n.dayNames[D], dddd: AjaxIM.i18n.dayNames[D + 7], m: m + 1, mm: pad(m + 1), mmm: AjaxIM.i18n.monthNames[m], mmmm: AjaxIM.i18n.monthNames[m + 12], yy: String(y).slice(2), yyyy: y, h: H % 12 || 12, hh: pad(H % 12 || 12), H: H, HH: pad(H), M: M, MM: pad(M), s: s, ss: pad(s), l: pad(L, 3), L: pad(L > 99 ? Math.round(L / 10) : L), t: H < 12 ? "a" : "p", tt: H < 12 ? "am" : "pm", T: H < 12 ? "A" : "P", TT: H < 12 ? "AM" : "PM", Z: utc ? "UTC" : (String(date).match(timezone) || [""]) .pop().replace(timezoneClip, ""), o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10] }; return mask.replace(token, function ($0) { return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); }); }; }(); // Some common format strings AjaxIM.dateFormat.masks = { "default": "ddd mmm dd yyyy HH:MM:ss", shortDate: "m/d/yy", mediumDate: "mmm d, yyyy", longDate: "mmmm d, yyyy", fullDate: "dddd, mmmm d, yyyy", shortTime: "h:MM TT", mediumTime: "h:MM:ss TT", longTime: "h:MM:ss TT Z", isoDate: "yyyy-mm-dd", isoTime: "HH:MM:ss", isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" }; // === {{{AjaxIM.}}}**{{{i18n}}}** === // // Text strings used by Ajax IM. Should you want to translate Ajax IM into // another language, merely change these strings. // // {{{%s}}} denotes text that will be automatically replaced when the string is // used. AjaxIM.i18n = { dayNames: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], monthNames: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], chatOffline: '%s signed off.', chatAvailable: '%s became available.', chatAway: '%s went away.', notConnected: 'You are currently not connected or the server is not available. ' + 'Please ensure that you are signed in and try again.', notConnectedTip: 'You are currently not connected.', authInvalid: 'Invalid username or password.', registerPasswordLength: 'Passwords must be more than 4 characters in length.', registerUsernameLength: 'Usernames must be more than 2 characters in length and ' + ' contain only A-Z, a-z, 0-9, underscores (_) and periods (.).', registerPasswordMatch: 'Entered passwords do not match.', registerUsernameTaken: 'The chosen username is already in use; please choose another.', registerUnknown: 'An unknown error occurred. Please try again.' } })(jQuery, false); \ No newline at end of file +// = im.js = +// +// **Copyright © 2005 – 2010 Joshua Gross**\\ +// //MIT Licensed// +// +// 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. +// +// This is the main library for Ajax IM. It encompasses the UI controls, +// and connecting with the server. It does //not// handle registration or +// account management. + +(function($, _instance) { + AjaxIM = function(options, actions) { + if(this instanceof AjaxIM) { + var self = this; + + // === {{{ defaults }}} === + // + // These are the available settings for Ajax IM, and the associated + // defaults: + // + // * {{{pollType}}} determines the way in which the client will talk to + // the server. + // ** {{{comet}}} will use http streaming, wherein a connection to the server will be held open indefinitely, and the server will push down new events (messages, status updates) as they occur. + // ** {{{long}}} will hold open a connection with the server for as long as possible, or until a new event is received. Upon the server sending an event or closing the connection, the client will automatically—and immediately—reconnect. + // ** {{{short}}} will open a connection, and the server (if this method is supported) will //immediately// provide a response as to whether or not there are any new events. Once a response is received, the client will wait 5 seconds, and then reconnect. + // * {{{pollServer}}} is the default URL to which all actions refer. It is + // possible to specify certain action URLs separately (as is used with the + // NodeJS server). + // * {{{cookieName}}} is the name of the session cookie used by the server. + // If this is not set properly, the IM engine will not be able to automatically + // reinitialize sessions. + // * {{{theme}}} is the name of the theme folder that defines the HTML and + // CSS of the IM bar and chat boxes. Usually, themes are deposited in the + // provided "themes" folder and specified by that path, e.g. {{{themes/default}}}. + // Theme files within the theme folder must be named {{{theme.html}}} and + // {{{theme.css}}}. + // * {{{storageMethod}}} defines the way in which data (chat sessions) are + // temporarily stored client-side. By default, {{{"flash"}}} is used because + // it is the most widely supported method. However, + // [[http://eric.garside.name/docs.html?p=jstore#js-engines|other storage engines]] + // are available, with their respective up- and down-sides + // outlined, on the jStore website. + // * {{{storeSession}}} (**not implemented**) sets the number of days to + // retain stored chat session data before it should be deleted. + // * {{{checkResume}}} is a flag that sets whether or not the client should + // make a call to the server before resuming the session (such as on a page + // reload). This will ensure that the session has not expired. If set to {{{false}}}, + // a call to the server will not be made, and the session will be assumed to + // be active. + var defaults = { + pollType: 'long', + pollServer: './ajaxim.php', + cookieName: 'ajaxim_session', + theme: 'themes/default', + storageMethod: 'auto', + flashStorage: 'js/jStore.Flash.html', + storeSession: 5, // number of days to store chat data (0 for current session only) + checkResume: true + }; + + // === {{{AjaxIM.}}}**{{{settings}}}** === + // + // These are the settings for the IM. If particular options are not specified, + // the defaults (see above) will be used. //These options will be defined + // upon calling the initialization function, and not set directly.// + this.settings = $.extend(defaults, options); + + // === {{{AjaxIM.}}}**{{{actions}}}** === + // + // Each individual action that the IM engine can execute is predefined here. + // By default, it merely appends the action onto the end of the {{{pollServer}}} url, + // however, it is possible to define actions individually. //The alternative actions + // will be defined upon calling the initialization function, and not set directly.// + // + // Should you define an action at a different URL, Ajax IM will determine whether + // or not this URL is within the current domain. If it is within a subdomain of + // the current domain, it will set the document.domain variable for you, + // to match a broader hostname scope; the action will continue to use {{{$.post}}} + // (the default AJAX method for Ajax IM). + // + // On the other hand, should you choose a URL outside the current domain + // Ajax IM will switch to {{{$.getJSON}}} (a get request) to avoid + // cross-domain scripting issues. This means that a server on a different + // port or at a different address will need to be able to handle GET + // requests rather than POST requests (such as how the Node.JS Ajax IM + // server works). + this.actions = $.extend({ + login: this.settings.pollServer + '/login', + logout: this.settings.pollServer + '/logout', + register: this.settings.pollServer + '/register', + poll: this.settings.pollServer + '/poll', + send: this.settings.pollServer + '/send', + status: this.settings.pollServer + '/status', + resume: this.settings.pollServer + '/resume' + }, actions); + + var httpRx = new RegExp('^http://', 'i'), + slashslashRx = new RegExp('^//', 'i'), + queryStrRx = new RegExp('[?](.+)$'), + subdomainRx = new RegExp('((http[s]?:)?//)?(.+?)[.]' + window.location.host, 'i'); + $.each(this.actions, function(name, action) { + if(name == 'poll' || name == 'send') { + if(self.settings.pollType != 'comet') + action += (queryStrRx.test(action[1]) ? '&' : '?') + 'callback=?'; + + action = ['jsonp', action]; + } else { + action = ['ajax', action]; + if(subdomainRx.test(action[1])) { + document.domain = '.' + window.location.host; + } else if((http = httpRx.test(action[1])) || slashslashRx.test(action[1])) { + if(!(new RegExp('//' + window.location.host + '/', 'i')).test(action[1])) { + action[1] += (queryStrRx.test(action[1]) ? '&' : '?') + 'callback=?'; + action = ['jsonp', action[1]]; + } + } + } + + self.actions[name] = action; + }); + + // We load the theme dynamically based on the passed + // settings. If the theme is set to false, we assume + // that the user is going to load it himself. + this.themeLoaded = false; + if(this.settings.theme) { + $('
').appendTo('body').load(this.settings.theme + '/theme.html #imjs-bar, .imjs-tooltip', + function() { + self.themeLoaded = true; + setup.apply(self); + } + ); + if(typeof document.createStyleSheet == 'function') + document.createStyleSheet(this.settings.theme + '/theme.css'); + else + $('body').append(''); + } else { + this.themeLoaded = true; + setup.apply(this); + } + + // Client-side storage for keeping track of + // conversation states, active tabs, etc. + // The default is flash storage, however, other + // options are available via the jStore library. + if(this.settings.storageMethod) { + this.storageBrowserKey = 'unknown'; + this.storeKey = ''; + + $.each($.browser, function(k, v) { + if(k == 'version') return true; + else if(v == true) { + self.storageBrowserKey = k; + return false; + } + }); + + if(this.settings.storageMethod == 'auto') { + $.each(['ie', 'html5', 'local', 'flash'], function() { + if($.jStore.Availability[this]()) { + self.settings.storageMethod = this; + return false; + } + }); + } + + $.extend($.jStore.defaults, { + project: 'im.js', + engine: this.settings.storageMethod, + flash: this.settings.flashStorage + }); + + this.storageReady = false; + + if(this.settings.storageMethod == 'flash') { + $.jStore.ready(function(engine) { + $.jStore.flashReady(function() { + self.storageReady = true; + setup.apply(self); + }); + }) + } else { + $.jStore.ready(function(engine) { + self.storageReady = true; + setup.apply(self); + }); + } + + $.jStore.load(); + } else { + this.storageReady = true; + setup.apply(this); + } + + // Allow a chatbox to me minimized + $('.imjs-chatbox').live('click', function(e) { + e.preventDefault(); + return false; + }); + + $('.imjs-chatbox .imjs-minimize').live('click', function() { + $(this).parents('.imjs-chatbox').data('tab').click(); + }); + + // Allow a chatbox to be closed + $('.imjs-chatbox .imjs-close').live('click', function() { + var chatbox = $(this).parents('.imjs-chatbox'); + chatbox.data('tab') + .data('state', 'closed').css('display', 'none'); + + if(self.settings.storageMethod && self.storageReady) { + delete self.chatstore[chatbox.data('username')]; + if(self.storageReady) { + $.jStore.store( + self.storageBrowserKey + '-' + + self.username + '-chats', + self.chatstore); + } + } + }); + + // Setup message sending for all chatboxes + $('.imjs-chatbox .imjs-input').live('keydown', function(event) { + var obj = $(this); + if(event.keyCode == 13 && !($.browser.msie && $.browser.version < 8)) { + self.send(obj.parents('.imjs-chatbox').data('username'), obj.val()); + } + }).live('keyup', function(event) { + if(event.keyCode == 13) { + if($.browser.msie && $.browser.version < 8) { + var obj = $(this); + self.send(obj.parents('.imjs-chatbox').data('username'), obj.val()); + } + + var obj = $(this); + obj.val(''); + obj.height(obj.data('height')); + } + }).live('keypress', function(e) { + var obj = $(this); + if(!($.browser.msie && $.browser.opera)) obj.height(0); + if(this.scrollHeight > obj.height() || this.scrollHeight < obj.height()) { + obj.height(this.scrollHeight); + } + }); + + $('.imjs-msglog').live('click', function() { + var chatbox = $(this).parents('.imjs-chatbox'); + chatbox.find('.imjs-input').focus(); + }); + + // Create a chatbox when a buddylist item is clicked + $('.imjs-friend').live('click', function() { + var chatbox = self._createChatbox($(this).data('friend')); + + if(chatbox.data('tab').data('state') != 'active') + chatbox.data('tab').click(); + + chatbox.find('.imjs-input').focus(); + }); + + // Setup and hide the scrollers + $('.imjs-scroll').css('display', 'none'); + $('#imjs-scroll-left').live('click', function() { + var hiddenTab = $('#imjs-bar li.imjs-tab:visible').slice(-1) + .next('#imjs-bar li.imjs-tab:hidden') + .filter(function() { + return $(this).data('state') != 'closed' + }) + .not('.imjs-default').slice(-1).css('display', ''); + + if(hiddenTab.length) { + $('#imjs-bar li.imjs-tab:visible').eq(0).css('display', 'none'); + $(this).html(parseInt($(this).html()) - 1); + $('#imjs-scroll-right').html(parseInt($('#imjs-scroll-right').html()) + 1); + } + + return false; + }); + $('#imjs-scroll-right').live('click', function() { + var hiddenTab = $('#imjs-bar li.imjs-tab:visible').eq(0) + .prev('#imjs-bar li.imjs-tab:hidden') + .filter(function() { + return $(this).data('state') != 'closed' + }) + .not('.imjs-default').slice(-1).css('display', ''); + + if(hiddenTab.length) { + $('#imjs-bar li.imjs-tab:visible').slice(-1).css('display', 'none'); + $(this).html(parseInt($(this).html()) - 1); + $('#imjs-scroll-left').html(parseInt($('#imjs-scroll-left').html()) + 1); + } + + return false; + }); + + // Initialize the chatbox hash + this.chats = {}; + + // Try to resume any existing session + this.resume(); + + $(window).resize(function() { + self.bar._scrollers(); + }); + } else + return AjaxIM.init(options); + }; + + // We predefine all public functions here... + // If they are called before everything (theme, storage engine) has loaded, + // then they get put into a "prequeue" and run when everything *does* + // finally load. + // + // This ensures that nothing loads without all of the principal components + // being pre-loaded. If that were to occur (without this prequeue), things + // would surely break. + var prequeue = []; + var empty = function() { + var func = this; + return function() { prequeue.push([func, arguments]) }; + }; + $.extend(AjaxIM.prototype, { + settings: {}, + friends: {}, + chats: {}, + + storage: empty.apply('storage'), + login: empty.apply('login'), + logout: empty.apply('logout'), + resume: empty.apply('resume'), + form: empty.apply('form'), + poll: empty.apply('poll'), + incoming: empty.apply('incoming'), + send: empty.apply('send'), + status: empty.apply('status'), + statuses: {}, + bar: { + initialize: empty.apply('bar.initialize'), + activateTab: empty.apply('bar.activateTab'), + closeTab: empty.apply('bar.closeTab'), + addTab: empty.apply('bar.addTab'), + notification: empty.apply('bar.notification'), + _scrollers: empty.apply('bar._scrollers') + } + }); + + setup = (function() { + var self = this; + if(!this.storageReady || !this.themeLoaded) return; + + $(self).trigger('loadComplete'); + $(window).resize(); + + $.extend(AjaxIM.prototype, { + // == Cookies == + // + // The "cookies" functions can be used to set, get, and erase JSON-based cookies. + // These functions are primarily used to manage and read the server-set cookie + // that handles the user's chat session ID. + cookies: { + // === {{{AjaxIM.}}}**{{{cookies.set(name, value, days)}}}** === + // + // Sets a cookie, stringifying the JSON value upon storing it. + // + // ==== Parameters ==== + // * {{{name}}} is the cookie name.\\ + // * {{{value}}} is the cookie data that you would like to store.\\ + // * {{{days}}} is the number of days that the cookie will be stored for. + set: function(name, value, days) { + if (days) { + var date = new Date(); + date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); + var expires = "; expires=" + date.toGMTString(); + } else var expires = ""; + document.cookie = name + "=" + $.compactJSON(value) + expires + "; path=/"; + }, + + // === {{{AjaxIM.}}}**{{{cookies.get(name)}}}** === + // + // Gets a cookie, decoding the JSON value before returning the data. + // + // ==== Parameters ==== + // * {{{name}}} is the cookie name that you would like to retrieve. + get: function(name) { + var nameEQ = name + "="; + var ca = document.cookie.split(';'); + for(var i = 0; i < ca.length; i++) { + var c = ca[i]; + while (c.charAt(0) == ' ') c = c.substring(1, c.length); + if (c.indexOf(nameEQ) == 0) { + var cval = decodeURIComponent(c.substring(nameEQ.length, c.length)); + return $.secureEvalJSON(cval); + } + } + return null; + }, + + // === {{{AjaxIM.}}}**{{{cookies.erase(name)}}}** === + // + // Deletes a cookie. + // + // {{{name}}} is the existing cookie that you would like to delete. + erase: function(name) { + self.cookies.set(name, '', -1); + } + }, + + // == Main == + + // === {{{AjaxIM.}}}**{{{storage()}}}** === + // + // Retrieves chat session data from whatever storage engine is enabled + // (provided that one is enabled at all). If a page reloads, this function + // is called to restore the user's chat state (existing conversations, active tab). + // This function is called //automatically//, upon initialization of the IM engine. + storage: function() { + if(!self.storeKey.length) return; + + try { + var chatstore = $.jStore.store(self.storeKey + 'chats') || {}; + } catch(e) { + $.jStore.remove(self.storeKey + 'chats'); + var chatstore = {}; + } + + if(this.chatstore) { + $.each(this.chatstore, function(username, convo) { + if(username in chatstore) + chatstore[username] = $.merge(chatstore[username], self.chatstore[username]); + else + chatstore[username] = self.chatstore[username]; + }); + + this.chatstore = chatstore; + $.jStore.store(self.storeKey + 'chats', chatstore); + } else { + this.chatstore = chatstore; + } + + $.each(this.chatstore, function(username, convo) { + if(!convo.length) return; + + var chatbox = self._createChatbox(username, true); + chatbox.data('lastDateStamp', null).css('display', 'none'); + + // Remove the automatic date stamp + chatbox.find('.imjs-msglog').empty(); + + // Restore all messages, date stamps, and errors + $.each(convo, function() { + switch(this[0]) { + case 'error': + self._addError(chatbox, decodeURIComponent(this[2]), this[3]); + break; + + case 'datestamp': + self._addDateStamp(chatbox, this[3]); + break; + + case 'a': + case 'b': + self._addMessage(this[0], chatbox, this[1], + decodeURIComponent(this[2]), this[3]); + break; + } + }); + + $(self).trigger('chatRestored', [username, chatbox]); + }); + + var activeTab = $.jStore.store(self.storeKey + 'activeTab') || []; + if(activeTab.length && (activeTab = activeTab[0]) && activeTab in this.chats) { + this.chats[activeTab].data('tab').click(); + var msglog = this.chats[activeTab].find('.imjs-msglog'); + msglog[0].scrollTop = msglog[0].scrollHeight; + } + }, + + // === {{{AjaxIM.}}}**{{{login(username, password)}}}** === + // + // Authenticates a user and initializes the IM engine. If the user is + // already logged in, [s]he is logged out, the session is cleared, and + // the new user is logged in. + // + // Returns the user's properly formatted username, session ID, and online + // friends in JSON, if successful; e.g.:\\ + // {{{ {u: 'username', s: 'longsessionid', f: [{u: 'friend', s: 1, g: 'group'}]} }}} + // + // If unsuccessful, {{{false}}} is returned. + // + // ==== Parameters ==== + // * {{{username}}} is the user's username.\\ + // * {{{password}}} is the user's password. This password will be MD5 hashed + // before it is sent to the server. + login: function(username, password) { + if(!username) username = ''; + if(!password) password = ''; + + if(this.username) + return true; // Already logged in! + + // hash password before sending it to the server + password = $.md5(password); + + // authenticate + AjaxIM.request( + this.actions.login, + {'username': username, 'password': password}, + function(auth) { + if(auth.r == 'logged in') { + self.username = ('u' in auth ? auth.u : username); + + if(self.settings.storageMethod) + self.storeKey = [self.storageBrowserKey, self.username, ''].join('-'); + + var existing = self.cookies.get(self.settings.cookieName); + self.storage(); + + // Begin the session + $.each(auth.f, function() { + self.friends[this.u] = {status: [this.s, ''], group: this.g}; + }); + self._session(self.friends); + self._storeFriends(); + + $(self).trigger('loginSuccessful', [auth]); + + return auth; + } else { + $(self).trigger('loginError', [auth]); + } + + return false; + } + ); + }, + + // === {{{AjaxIM.}}}**{{{logout()}}}** === + // + // Logs the user out and removes his/her session cookie. As well, it + // will close all existing chat windows, clear the storage engine, and + // remove the IM bar. + logout: function() { + AjaxIM.request( + this.actions.logout, + {}, + function(done) { + if(done) { + self.cookies.erase(self.settings.cookieName); + self._clearSession(); + $(self).trigger('logoutSuccessful'); + return true; + } else { + $(self).trigger('logoutError'); + return false; + } + } + ); + }, + + // === {{{AjaxIM.}}}**{{{resume()}}}** === + // + // Resumes an existing session based on a session ID stored in the + // server-set cookie. This function is called //automatically// upon IM + // engine (re-)initialization, so the user does not need to re-login + // should a session already exist. + resume: function() { + var session = this.cookies.get(this.settings.cookieName); + + if(session && session.sid) { + this.username = session.user; + + this.storeKey = [this.storageBrowserKey, this.username, ''].join('-'); + + var friends = $.jStore.store(this.storeKey + 'friends') || []; + if(self.settings.checkResume) { + AjaxIM.request( + this.actions.resume, + {}, + function(response) { + if(response.r == 'connected') { + self._session(friends); + self.storage(); + } else { + var username = this.username; + self._clearSession(); + $(self).trigger('sessionNotResumed', [username]); + } + } + ); + } else { + self._session(friends); + self.storage(); + } + } else { + $(self).trigger('noSession'); + } + }, + + // === //private// {{{AjaxIM.}}}**{{{_session(friends)}}}** === + // + // Restores session data (username, friends) and begins polling the server. + // Called only by {{{AjaxIM.resume()}}}. + // + // ==== Parameters ==== + // * {{{friends}}} is a list of "friend" objects, e.g.:\\ + // {{{[{u: 'friend', s: 1, g: 'group'}, ...]}}} + // ** {{{u}}} being the friend's username. + // ** {{{s}}} being one of the available status codes (see {{{AjaxIM.statuses}}}), depending on the friend's current status. + // ** {{{g}}} being the group that the friend is in. + _session: function(friends) { + $('#imjs-friends-panel .imjs-header span').html(this.username); + $('#imjs-friends').removeClass('imjs-not-connected'); + + $.each(friends, function(friend, info) { + self.addFriend.apply(self, [friend, info.status, info.group]); + }); + self._storeFriends(); + + $(self).trigger('sessionResumed', [this.username]); + + setTimeout(function() { self.poll(); }, 0); + }, + + // === //private// {{{AjaxIM.}}}**{{{_clearSession()}}}** === + // + // Clears all session data from the last known user. + _clearSession: function() { + if(self.settings.storageMethod && self.storageReady) { + $.jStore.remove(self.storeKey + 'chats'); + $.jStore.remove(self.storeKey + 'friends'); + $.jStore.remove(self.storeKey + 'activeTab'); + } + + self.chats = {}; + $('.imjs-tab').not('.imjs-tab.imjs-default').remove(); + + self.cookies.erase('ajaxim_session'); + delete self.username; + }, + + // === {{{AjaxIM.}}}**{{{form(element)}}}** === + // + // Loads a login and registration form into the specified element + // or, if no element is supplied, to the location on the page from + // which this function was called. + form: function(element) { + $(element).load(this.settings.theme + '/theme.html #imjs-lr', function() { + $('#imjs-lr .error').hide(); + + if(self.username) { + $('#imjs-register, #imjs-login fieldset').hide(); + $('#imjs-logged-in') + .show() + .html($('#imjs-logged-in').html().replace('{username}', self.username)); + } else { + $('#imjs-logged-in').hide(); + } + + // Handle logout success + $(self).bind('logoutSuccessful', function() { + $('#imjs-login fieldset').slideDown(); + $('#imjs-register').slideDown(); + + $('#imjs-logged-in') + .html($('#imjs-logged-in strong').html('{username}')) + .slideUp(); + }); + $('#imjs-logged-in a').click(function() { + self.logout(); + return false; + }); + + // Handle login error or success + $(self).bind('loginError', function() { + $('#imjs-login .error').html(AjaxIM.i18n.authInvalid).slideDown('fast'); + $('#imjs-login input') + .addClass('imjs-lr-error') + .blur(function() { $(this).removeClass('imjs-lr-error'); }); + }).bind('loginSuccessful', function() { + $('#imjs-login fieldset').slideUp(); + $('#imjs-register').slideUp(); + + $('#imjs-logged-in') + .html($('#imjs-logged-in').html().replace('{username}', self.username)) + .slideDown(); + }); + var login = function() { + self.login($('#imjs-login-username').val(), $('#imjs-login-password').val()); + return false; + }; + $('#imjs-login').submit(login); + $('#imjs-login-submit').click(login); + + var regIssues = false; + var regError = function(error, fields) { + $('#imjs-register .error') + .append(AjaxIM.i18n['register' + error] + ' ') + .slideDown(); + $(fields) + .addClass('imjs-lr-error') + .blur(function() { $(this).removeClass('imjs-lr-error'); }); + regIssues = true; + }; + + var register = function() { + $('#imjs-register .error').empty(); + + regIssues = false; + + var username = $('#imjs-register-username').val(); + var password = $('#imjs-register-password').val(); + + if(password.length < 4) + regError('PasswordLength', '#imjs-register-password'); + + if(password != $('#imjs-register-cpassword').val()) + regError('PasswordMatch', '#imjs-register-password, #imjs-register-cpassword'); + + if(username.length <= 2 || + !$('#imjs-register-username').val().match(/^[A-Za-z0-9_.]+$/)) + regError('UsernameLength', '#imjs-register-username'); + + if(!regIssues) { + AjaxIM.request( + self.actions.register, + {username: username, password: password}, + function(response) { + if(response.r == 'registered') { + self.login(username, password); + } else if(response.r == 'error') { + switch(response.e) { + case 'unknown': + regError('Unknown', ''); + break; + + case 'invalid password': + regError('PasswordLength', '#imjs-register-password'); + break; + + case 'invalid username': + regError('UsernameLength', '#imjs-register-username'); + break; + + case 'username taken': + regError('UsernameTaken', '#imjs-register-username'); + break; + } + } + }, + function(error) { + regError('Unknown', ''); + } + ); + } + + return false; + }; + $('#imjs-register').submit(register); + $('#imjs-register-submit').click(register); + }); + }, + + // === {{{AjaxIM.}}}**{{{poll()}}}** === + // + // Queries the server for new messages. If a 'long' or 'short' poll + // type is used, jQuery's {{{$.post}}} or {{{$.getJSON}}} will be + // used. If 'comet' is used, the server connection will be deferred + // to the comet set of functions. + poll: function() { + if(/^(short|long)$/.test(this.settings.pollType)) { + AjaxIM.request( + this.actions.poll, + {}, + function(response) { + if(!response['e']) { + if(response.length) + self._parseMessages(response); + + setTimeout(function() { self.poll(); }, 0); + } else { + switch(response.e) { + case 'no session found': + self._notConnected(); + break; + } + + $(self).trigger('pollFailed', [response.e]); + } + }, + function(error) { + self._notConnected(); + $(self).trigger('pollFailed', ['not connected']); + // try reconnecting? + } + ); + } else if(this.settings.pollType == 'comet') { + this.comet.connect(); + } + }, + + // === //private// {{{AjaxIM.}}}**{{{_parseMessages(messages)}}}** === + // + // Handles an incoming message array:\\ + // {{{[{t: 'type', s: 'sender', r: 'recipient', m: 'message'}, ...]}}} + // + // * {{{t}}} (message type) is one of: + // ** {{{m}}} — a standard message + // ** {{{s}}} — a user's status update + // ** {{{b}}} — a broadcasted message (sent to many users simultaneously) + // * {{{s}}} is the sender of the message. + // * {{{r}}} is the intended recipient of the message. Most of the time, this will + // simply be the logged in user, however, a broadcasted message may not specify + // a recipient or may specify a different recipient. Also provides future + // compatability for chatrooms. + // * {{{m}}} is the actual message. For something such as a status update, this can + // be a JSON object or parsable string; e.g. {{{"2:I'm away."}}} + // + // ==== Parameters ==== + // * {{{messages}}} is the message array + _parseMessages: function(messages) { + if($.isArray(messages)) { + $.each(messages, function() { + $(self).trigger('parseMessage', [this]); + + switch(this.t) { + case 'm': + self.incoming(this.s, this.m); + break; + + case 's': + var status = this.m.split(':'); + if(this['g']) + self.addFriend(this.s, status, this.g); + self._friendUpdate(this.s, status[0], status.slice(1).join(':')); + self._storeFriends(); + break; + + case 'b': + break; + + default: + break; + } + }); + } + }, + + // === {{{AjaxIM.}}}**{{{incoming(from, message)}}}** === + // + // Handles a new message from another user. If a chatbox for that + // user does not yet exist, one is created. If it does exist, but + // is minimized, the user is notified but the chatbox is not brought + // to the front. This function also stores the message, if a storage + // method is set. + // + // ==== Parameters ==== + // * {{{from}}} is the username of the sender. + // * {{{message}}} is the body. + incoming: function(from, message) { + // check if IM exists, otherwise create new window + // TODO: If friend is not on the buddylist, + // should add them to a temp list? + var chatbox = this._createChatbox(from); + + if(!$('#imjs-bar .imjs-selected').length) { + chatbox.data('tab').click(); + } else if(chatbox.data('tab').data('state') != 'active') { + this.bar.notification(chatbox.data('tab')); + } + + var time = this._addMessage('b', chatbox, from, message); + this._storeMessage('b', chatbox, from, message, time); + }, + + // === {{{AjaxIM.}}}**{{{addFriend(username, group)}}}** === + // + // Inserts a new friend into the friends list. If the group specified + // doesn't exist, it is created. If the friend is already in this group, + // they aren't added again, however, the friend item is returned. + // + // ==== Parameters ==== + // * {{{username}}} is the username of the new friend. + // * {{{status}}} is the current status of the friend. + // * {{{group}}} is the user group to which the friend should be added. + addFriend: function(username, status, group) { + var status_name = 'available'; + $.each(this.statuses, + function(key, val) { if(status[0] == val) { status_name = key; return false; } }); + + var group_id = 'imjs-group-' + $.md5(group); + + if(!(group_item = $('#' + group_id)).length) { + var group_item = $('.imjs-friend-group.imjs-default').clone() + .removeClass('imjs-default') + .attr('id', group_id) + .data('group', group) + .appendTo('#imjs-friends-list'); + + var group_header = group_item.find('.imjs-friend-group-header'); + group_header.html(group_header.html().replace('{group}', group)); + } + + var user_id = 'imjs-friend-' + $.md5(username + group); + + if(!$('#' + user_id).length) { + var user_item = group_item.find('ul li.imjs-default').clone() + .removeClass('imjs-default') + .addClass('imjs-' + status_name) + .attr('id', user_id) + .data('friend', username) + .appendTo(group_item.find('ul')); + if(status[0] == 0) user_item.hide(); + user_item.html(user_item.html().replace('{username}', username)); + } + + this.friends[username] = {'status': status, group: group}; + + this._updateFriendCount(); + + return this.friends[username]; + }, + + // === //private// {{{AjaxIM.}}}**{{{_updateFriendCount()}}}** === + // + // Counts the number of online friends and updates the friends count + // in the friend tab. + _updateFriendCount: function() { + var friendsLength = 0; + for(var f in this.friends) { + if(this.friends[f].status[0] != 0) + friendsLength++; + } + $('#imjs-friends .imjs-tab-text span span').html(friendsLength); + }, + + // === //private// {{{AjaxIM.}}}**{{{_storeFriends()}}}** === + // + // If a storage method is enabled, the current state of the + // user's friends list is stored. + _storeFriends: function() { + if(this.settings.storageMethod && this.storageReady) + $.jStore.store(this.storeKey + 'friends', this.friends); + }, + + // === //private// {{{AjaxIM.}}}**{{{_createChatbox(username)}}}** === + // + // Builds a chatbox based on the default chatbox HTML and CSS defined + // in the current theme. Should a chatbox for this user already exist, + // a new one is not created. Instead, it is either given focus (should + // no other windows already have focus), or a notification is issued. + // + // As well, if the chatbox does not exist, an associated tab will be + // created. + // + // ==== Parameters ==== + // * {{{username}}} is the name of the user for whom the chatbox is intended + // for. + // * {{{no_stamp}}} sets whther or not to add a date stamp to the chatbox + // upon creation. + // + // //Note:// New chatboxes are given an automatically generated ID in the + // format of {{{#imjs-[md5 of username]}}}. + _createChatbox: function(username, no_stamp) { + var chatbox_id = 'imjs-' + $.md5(username); + if(!(chatbox = $('#' + chatbox_id)).size()) { + // add a tab + var tab = this.bar.addTab(username, '#' + chatbox_id); + var chatbox = tab.find('.imjs-chatbox'); + chatbox.attr('id', chatbox_id); + + chatbox.data('tab', tab); + + // remove default items from the message log + var message_log = chatbox.find('.imjs-msglog').empty(); + + // setup the chatbox header + var cb_header = chatbox.find('.imjs-header'); + cb_header.html(cb_header.html().replace('{username}', username)); + + if(!no_stamp) { + // add a date stamp + var time = this._addDateStamp(chatbox); + this._storeNonMessage('datestamp', username, null, time); + } + + // associate the username with the object and vice-versa + this.chats[username] = chatbox; + chatbox.data('username', username); + + // did this chatbox fall down? + this.bar._scrollers(); + + if(username in this.friends) { + status = this.friends[username].status; + var status_name = 'available'; + $.each(this.statuses, + function(key, val) { if(status[0] == val) { status_name = key; return false; } }); + tab.addClass('imjs-' + status_name); + } + + // store inputbox height + //var input = chatbox.find('.imjs-input'); + //input.data('height', input.height()); + } else if(chatbox.data('tab').data('state') == 'closed') { + chatbox.find('.imjs-msglog > *').addClass('imjs-msg-old'); + + var tab = chatbox.data('tab'); + if(tab.css('display') == 'none') + tab.css('display', '').removeClass('imjs-selected') + .appendTo('#imjs-bar'); + + if(!no_stamp) { + // possibly add a date stamp + var time = this._addDateStamp(chatbox); + this._storeNonMessage('datestamp', username, null, time); + } + + if(!$('#imjs-bar .imjs-selected').length) { + tab.click(); + } else { + this.bar.notification(tab); + } + } + + return chatbox; + }, + + // === //private// {{{AjaxIM.}}}**{{{_addDateStamp(chatbox)}}}** // + // + // Adds a date/time notifier to a chatbox. These are generally + // inserted upon creation of a chatbox, or upon the date changing + // since the last time a date stamp was added. If a date stamp for + // the current date already exists, a new one will not be added. + // + // ==== Parameters ==== + // * {{{chatbox}}} refers to the jQuery-selected chatbox DOM element. + // * {{{time}}} is the date/time the date stamp will show. It is specified + // in milliseconds since the Unix Epoch. This is //only// defined when + // date stamps are being restored from storage; if not specified, the + // current computer time will be used. + _addDateStamp: function(chatbox, time) { + var message_log = $(chatbox).find('.imjs-msglog'); + if(!time) + time = (new Date()).getTime(); + + var date_stamp = $('.imjs-tab.imjs-default .imjs-chatbox .imjs-msglog .imjs-date').clone(); + var date_stamp_time = date_stamp.find('.imjs-msg-time'); + if(date_stamp_time.length) + date_stamp_time.html(AjaxIM.dateFormat(time, date_stamp_time.html())); + + var date_stamp_date = date_stamp.find('.imjs-date-date'); + var formatted_date = AjaxIM.dateFormat(time, date_stamp_date.html()); + if(chatbox.data('lastDateStamp') != formatted_date) { + if(date_stamp_date.length) + date_stamp_date.html(AjaxIM.dateFormat(time, date_stamp_date.html())); + + chatbox.data('lastDateStamp', formatted_date); + date_stamp.appendTo(message_log); + } else { + //$('
').appendTo(message_log); + } + + return time; + }, + + // === //private// {{{AjaxIM.}}}**{{{_addError(chatbox, error)}}}** // + // + // Adds an error to a chatbox. These are generally inserted after + // a user sends a message unsuccessfully. If an error message + // was already added, another one will be added anyway. + // + // ==== Parameters ==== + // * {{{chatbox}}} refers to the jQuery-selected chatbox DOM element. + // * {{{error}}} is the error message string. + // * {{{time}}} is the date/time the error occurred. It is specified in + // milliseconds since the Unix Epoch. This is //only// defined when + // errors are being restored from storage; if not specified, the current + // computer time will be used. + _addError: function(chatbox, error, time) { + var message_log = $(chatbox).find('.imjs-msglog'); + + var error_item = + $('.imjs-tab.imjs-default .imjs-chatbox .imjs-msglog .imjs-error').clone(); + + var error_item_time = error_item.find('.imjs-msg-time'); + if(error_item_time.length) { + if(!time) + time = (new Date()).getTime(); + error_item_time.html(AjaxIM.dateFormat(time, error_item_time.html())); + } + + error_item.find('.imjs-error-error').html(error); + error_item.appendTo(message_log); + + message_log[0].scrollTop = message_log[0].scrollHeight; + }, + + // === //private// {{{AjaxIM.}}}**{{{_addMessage(ab, chatbox, username, message, time)}}}** // + // + // Adds a message to a chatbox. Depending on the {{{ab}}} value, + // the color of the username may change as a way of visually + // identifying users (however, this depends on the theme's CSS). + // A timestamp is added to the message, and the chatbox is scrolled + // to the bottom, such that the new message is visible. + // + // Messages will be automatically tag-escaped, so as to prevent + // any potential cross-site scripting problems. Additionally, + // URLs will be automatically linked. + // + // ==== Parameters ==== + // * {{{ab}}} refers to whether the user is "a" or "b" in a conversation. + // For the general case, "you" are "a" and "they" are "b". + // * {{{chatbox}}} refers to the jQuery-selected chatbox DOM element. + // * {{{username}}} is the username of the user who sent the message. + // * {{{time}}} is the time the message was sent in milliseconds since + // the Unix Epoch. This is //only// defined when messages are being + // restored from storage. For new messages, the current computer + // time is automatically used. + _addMessage: function(ab, chatbox, username, message, time) { + var last_message = chatbox.find('.imjs-msglog > *:last-child'); + if(last_message.hasClass('imjs-msg-' + ab)) { + // Last message was from the same person, so let's just add another imjs-msg-*-msg + var message_container = (last_message.hasClass('imjs-msg-' + ab + '-container') ? + last_message : + last_message.find('.imjs-msg-' + ab + '-container')); + + var single_message = + $('.imjs-tab.imjs-default .imjs-chatbox .imjs-msglog .imjs-msg-' + ab + '-msg') + .clone().appendTo(message_container); + + single_message.html(single_message.html().replace('{username}', username)); + } else if(!last_message.length || !last_message.hasClass('imjs-msg-' + ab)) { + var message_group = $('.imjs-tab.imjs-default .imjs-chatbox .imjs-msg-' + ab) + .clone().appendTo(chatbox.find('.imjs-msglog')); + message_group.html(message_group.html().replace('{username}', username)); + + var single_message = message_group.find('.imjs-msg-' + ab + '-msg'); + } + + // clean up the message + message = message.replace(//g, '>') + .replace(/(^|.*)\*([^*]+)\*(.*|$)/, '$1$2$3'); + + // autolink URLs + message = message.replace( + new RegExp('([A-Za-z][A-Za-z0-9+.-]{1,120}:[A-Za-z0-9/]' + + '(([A-Za-z0-9$_.+!*,;/?:@&~=-])|%[A-Fa-f0-9]{2}){1,333}' + + '(#([a-zA-Z0-9][a-zA-Z0-9$_.+!*,;/?:@&~=%-]{0,1000}))?)', 'g'), + '$1'); + + // insert the message + single_message.html(single_message.html().replace('{message}', message)); + + // set the message time + var msgtime = single_message.find('.imjs-msg-time'); + if(!time) + time = new Date(); + + if(typeof time != 'string') + time = AjaxIM.dateFormat(time, msgtime.html()); + + msgtime.html(time); + + var msglog = chatbox.find('.imjs-msglog'); + msglog[0].scrollTop = msglog[0].scrollHeight; + + return time; + }, + + // === //private// {{{AjaxIM.}}}**{{{_storeNonMessage(type, username, data, time)}}}** === + // + // **Redundant?**\\ + // Similar to {{{AjaxIM._storeMessage}}}, but stores items that aren't messages, + // such as datestamps and errors. + // + // ==== Parameters ==== + // * {{{type}}} is the type of non-message (error, datestamp). + // * {{{username}}} is the username of the user being chatted with. + // * {{{data}}} is the (optional) data of the non-message to be stored. + // * {{{time}}} is the time of the message. + _storeNonMessage: function(type, username, data, time) { + // If storage is on & ready, store the non-message + if(this.settings.storageMethod) { + if(!this.chatstore) this.chatstore = {}; + if(!(username in this.chatstore)) this.chatstore[username] = []; + + // If the chat store gets too long, it becomes slow to load. + if(this.chatstore[username].length > 300) + this.chatstore[username].shift(); + + // For some reason, if we don't encode and decode the message, it *will* break + // (at least) the Flash storage engine's retrieval. Gah! + this.chatstore[username].push( + [type, username, encodeURIComponent(data), time]); + + if(this.storageReady) $.jStore.store(self.storeKey + 'chats', this.chatstore); + } + }, + + // === //private// {{{AjaxIM.}}}**{{{_storeMessage(ab, chatbox, username, message, time)}}}** === + // + // Taking the same arguments as {{{AjaxIM._addMessage}}}, {{{_storeMessage}}} pushes a message + // into the storage hash, if storage is enabled. + // + // Messages are added to a message array, by username. The entire chat hash is stored as + // a {{{'chats'}}} object in whatever storage engine is enabled. + _storeMessage: function(ab, chatbox, username, message, time) { + // If storage is on & ready, store the message + if(this.settings.storageMethod) { + if(!this.chatstore) this.chatstore = {}; + + message = message.replace(//g, '>'); + + if(!(username in this.chatstore)) { + this.chatstore[username] = []; + } else if(this.chatstore[username].length > 300) { + // If the chat store gets too long, it becomes slow to load. + this.chatstore[username].shift(); + } + + // For some reason, if we don't encode and decode the message, it *will* break + // (at least) the Flash storage engine's retrieval. Gah! + this.chatstore[chatbox.data('username')].push( + [ab, username, encodeURIComponent(message), time]); + + if(this.storageReady) $.jStore.store(this.storeKey + 'chats', this.chatstore); + } + }, + + // === //private// {{{AjaxIM.}}}**{{{_friendUpdate(friend, status, statusMessage)}}}** === + // + // Called when a friend's status is updated. This function will update all locations + // where a status icon is displayed (chat tab, friends list), as well as insert + // a notification, should a chatbox be open. + // + // ==== Parameters ==== + // * {{{friend}}} is the username of the friend. + // * {{{status}}} is the new status code. See {{{AjaxIM.statuses}}} for a list of available + // codes. //Note: If an invalid status is specified, no action will be taken.// + // * {{{statusMessage}}} is a message that was, optionally, specified by the user. It will be + // used should "you" send the user an IM while they are away, or if their status is viewed + // in another way (such as via the friends list [**not yet implemented**]). + _friendUpdate: function(friend, status, statusMessage) { + // add friend to buddylist, update their status, etc. + var status_name = 'available'; + $.each(this.statuses, + function(key, val) { if(status == val) { status_name = key; return false; } }); + + if(this.chats[friend]) { + var tab = this.chats[friend].data('tab'); + var tab_class = 'imjs-tab'; + if(tab.data('state') == 'active') tab_class += ' imjs-selected'; + tab_class += ' imjs-' + status_name; + + tab.attr('class', tab_class); + + // display the status in the chatbox + var date_stamp = + $('.imjs-tab.imjs-default .imjs-chatbox .imjs-msglog .imjs-date').clone(); + + var date_stamp_time = date_stamp.find('.imjs-msg-time'); + if(date_stamp_time.length) + date_stamp_time.html(AjaxIM.dateFormat(date_stamp_time.html())); + + var date_stamp_date = date_stamp.find('.imjs-date-date').html( + AjaxIM.i18n[ + 'chat' + status_name[0].toUpperCase() + status_name.slice(1) + ].replace(/%s/g, friend)); + + var msglog = this.chats[friend].find('.imjs-msglog'); + date_stamp.appendTo(msglog); + msglog[0].scrollTop = msglog[0].scrollHeight; + } + + if(this.friends[friend]) { + var friend_id = 'imjs-friend-' + $.md5(friend + this.friends[friend].group); + $('#' + friend_id).attr('class', 'imjs-friend imjs-' + status_name); + + if(status == 0) { + $('#' + friend_id + ':visible').slideUp(); + $('#' + friend_id + ':hidden').hide(); + } else if(!$('#' + friend_id + ':visible').length) { + $('#' + friend_id).slideDown(); + } + + this.friends[friend].status = [status, statusMessage]; + this._updateFriendCount(); + } + }, + + // === //private// {{{AjaxIM.}}}**{{{_notConnected()}}}** === + // + // Puts the user into a visible state of disconnection. Sets the + // friends list to "not connected" and empties it; disallows new messages + // to be sent. + _notConnected: function() { + $('#imjs-friends').addClass('imjs-not-connected').unbind('click', this.activateTab); + }, + + // === {{{AjaxIM.}}}**{{{send(to, message)}}}** === + // + // Sends a message to another user. The message will be added + // to the chatbox before it is actually sent, however, if an + // error occurs during sending, that will be indicated immediately + // afterward. + // + // After sending the message, one of three status codes should be + // returned as a JSON object, e.g. {{{{r: 'code'}}}}: + // * {{{ok}}} — Message was sent successfully. + // * {{{offline}}} — The user is offline or unavailable to + // receive messages. + // * {{{error}}} — a problem occurred, unrelated to the user + // being unavailable. + // + // ==== Parameters ==== + // * {{{to}}} is the username of the recipient. + // * {{{message}}} is the content to be sent. + send: function(to, message) { + if(!message) return; + + if(this.chats[to]) { // REMOVE ME? + // possibly add a datestamp + var time = self._addDateStamp(this.chats[to]); + this._storeNonMessage('datestamp', to, null, time); + + time = this._addMessage('a', this.chats[to], this.username, message); + this._storeMessage('a', this.chats[to], this.username, message, time); + } + + $(self).trigger('sendingMessage', [to, message]); + + AjaxIM.request( + this.actions.send, + {'to': to, 'message': message}, + function(result) { + switch(result.r) { + case 'ok': + $(self).trigger('sendMessageSuccessful', [to, message]); + break; + + case 'offline': + $(self).trigger('sendMessageFailed', ['offline', to, message]); + break; + + case 'error': + default: + if(result.e == 'no session found') { + self._notConnected(); + self._addError(self.chats[to], AjaxIM.i18n.notConnected); + self._storeNonMessage('error', to, + AjaxIM.i18n.notConnected, (new Date()).getTime()); + } + + $(self).trigger('sendMessageFailed', [result.e, to, message]); + break; + } + }, + function(error) { + self._notConnected(); + self._addError(self.chats[to], AjaxIM.i18n.notConnected); + self._storeNonMessage('error', to, + AjaxIM.i18n.notConnected, (new Date()).getTime()); + + $(self).trigger('sendMessageFailed', ['not connected', to, message]); + } + ); + }, + + // === {{{AjaxIM.}}}**{{{status(s, message)}}}** === + // + // Sets the user's status and status message. It is possible to not + // set a status message by setting it to an empty string. The status + // will be sent to the server, where upon the server will broadcast + // the update to all individuals with "you" on their friends list. + // + // ==== Parameters ==== + // * {{{s}}} is the status code, as defined by {{{AjaxIM.statuses}}}. + // * {{{message}}} is the custom status message. + status: function(s, message) { + // update status icon(s) + if(!this.statuses[s]) + return; + + $('#imjs-friends').attr('class', 'imjs-' + s); + + $(self).trigger('changingStatus', [s, message]); + + AjaxIM.request( + this.actions.status, + {'status': this.statuses[s], 'message': message}, + function(result) { + switch(result.r) { + case 'ok': + $(self).trigger('changeStatusSuccessful', [s, message]); + break; + + case 'error': + default: + $(self).trigger('changeStatusFailed', [result.e, s, message]); + break; + } + }, + function(error) { + $(self).trigger('changeStatusFailed', ['not connected', s, message]); + } + ); + }, + + // === {{{AjaxIM.}}}**{{{statuses}}}** === + // + // These are the available status codes and their associated identities: + // * {{{offline}}} (0) — Only used when signing out/when another + // user has signed out, as once this status is set, the user is removed + // from the server and friends will be unable to contact the user. + // * {{{available}}} (1) — The user is online and ready to be messaged. + // * {{{away}}} (2) — The user is online but is not available. Others + // may still contact this user, however, the user may not respond. Anyone + // contacting an away user will receive a notice stating that the user is away, + // and (if one is set) their custom status message. + // * {{{invisible}}} (3; **not yet implemented**) — The user is online, + // but other users are made unaware, and the user will be represented + // as being offline. It is still possible to contact this user, and for this + // user to contact others; no status message or notice will be sent to others + // messaging this user. + statuses: {offline: 0, available: 1, away: 2, invisible: 3}, + + // == Footer bar == + // + // The footer bar is the bar that sits at the bottom of the page, in a fixed + // position. It contains a tab for the friends list, and tabs for any open + // chat boxes. It is also possible to add custom tabs for other functionality. + bar: { + // === {{{AjaxIM.}}}**{{{bar.initialize()}}}** === + // + // Setup the footer bar and enable tab actions. This function + // uses {{{jQuery.live}}} to set hooks on any bar tabs created + // in the future. + initialize: function() { + // Set up your standard tab actions + $('.imjs-tab') + .live('click', this.activateTab); + + $('.imjs-tab .imjs-close') + .live('click', this.closeTab); + + // Set up the friends list actions + var self = this; + $(document).click(function(e) { + if(e.target.id == 'imjs-friends' || + $(e.target).parents('#imjs-friends').length) { + return; + } + + if($('#imjs-friends').data('state') == 'active') + self.activateTab.call($('#imjs-friends')); + }); + $('#imjs-friends') + .data('state', 'minimized') + .click(function(e) { + if(!$(this).hasClass('imjs-not-connected') && + e.target.id != 'imjs-friends-panel' && + !$(e.target).parents('#imjs-friends-panel').length) + self.activateTab.call(this); + }) + .mouseenter(function() { + if($(this).hasClass('imjs-not-connected')) { + $('.imjs-tooltip').css('display', 'block'); + $('.imjs-tooltip p').html(AjaxIM.i18n.notConnectedTip); + + var tip_left = $(this).offset().left - + $('.imjs-tooltip').outerWidth() + + ($(this).outerWidth() / 2); + var tip_top = $(this).offset().top - + $('.imjs-tooltip').outerHeight(true); + + $('.imjs-tooltip').css({ + left: tip_left, + top: tip_top + }); + } + }) + .mouseleave(function() { + if($(this).hasClass('imjs-not-connected')) { + $('.imjs-tooltip').css('display', ''); + } + }); + $('#imjs-friends-panel') + .data('tab', $('#imjs-friends')) + .css('display', 'none'); + }, + + // === {{{AjaxIM.}}}**{{{bar.activateTab()}}}** === + // + // Activate a tab by setting it to the 'active' state and + // showing any related chatbox. If a chatbox is available + // for this tab, also focus the input box. + // + // //Note:// {{{this}}}, here, refers to the tab DOM element. + activateTab: function() { + var chatbox = $(this).find('.imjs-chatbox') || false; + + if($(this).data('state') != 'active') { + if($(this).attr('id') != 'imjs-friends') { + $('#imjs-bar > li') + .not($(this)) + .not('#imjs-friends') + .removeClass('imjs-selected') + .each(function() { + if($(this).data('state') != 'closed') { + $(this).data('state', 'minimized'); + var chatbox = $(this).find('.imjs-chatbox'); + if(chatbox.length) + chatbox.css('display', 'none'); + } + }); + } + + if(chatbox && chatbox.css('display') == 'none') + chatbox.css('display', ''); + + // set the tab to active... + var tab = $(this).addClass('imjs-selected').data('state', 'active'); + + // ...and hide and reset the notification icon + tab.find('.imjs-notification').css('display', 'none') + .data('count', 0); + + if(self.settings.storageMethod && self.storageReady && + chatbox && (username = chatbox.data('username'))) { + $.jStore.store(self.storeKey + 'activeTab', [username]); + } + + $(self).trigger('tabToggled', ['activated', tab]); + } else { + var tab = $(this).removeClass('imjs-selected').data('state', 'minimized'); + + if(chatbox && chatbox.css('display') != 'none') + chatbox.css('display', 'none'); + + if(self.settings.storageMethod && self.storageReady) { + $.jStore.store(self.storeKey + 'activeTab', ['*']); + } + + $(self).trigger('tabToggled', ['minimized', tab]); + } + + if(chatbox) { + if(!(input = chatbox.find('.imjs-input')).data('height')) { + // store the height for resizing later + input.data('height', input.height()); + } + + try { + var msglog = chatbox.find('.imjs-msglog'); + msglog[0].scrollTop = msglog[0].scrollHeight; + } catch(e) {} + + try { chatbox.find('.imjs-input').focus(); } catch(e) {} + } + }, + + // === {{{AjaxIM.}}}**{{{bar.closeTab()}}}** === + // + // Close a tab and hide any related chatbox, such that + // the chatbox can not be reopened without reinitializing + // the tab. + // + // //Note:// {{{this}}}, here, refers to the tab DOM element. + closeTab: function() { + var tab = $(this).parents('.imjs-tab'); + tab.css('display', 'none').data('state', 'closed'); + + if(self.settings.storageMethod && self.storageReady) { + delete self.chatstore[tab.find('.imjs-chatbox').data('username')]; + if(self.storageReady) $.jStore.store(self.storeKey + 'chats', self.chatstore); + } + + $(self).trigger('tabToggled', ['closed', tab]); + + self.bar._scrollers(); + + return false; + }, + + // === {{{AjaxIM.}}}**{{{bar.addTab(label, action, closable)}}}** === + // + // Adds a tab to the tab bar, with the label {{{label}}}. When + // clicked, it will call a callback function, {{{action}}}. If + // {{{action}}} is a string, it is assumed that the string is + // referring to a chatbox ID. + // + // ==== Parameters ==== + // * {{{label}}} is the text that will be displayed on the tab.\\ + // * {{{action}}} is the callback function, if it is a non-chatbox + // tab, or a string if it //is// a chatbox tab.\\ + // * {{{closable}}} is a boolean value that determines whether or not + // it is possible for a user to close this tab. + // + // //Note:// New tabs are given an automatically generated ID + // in the format of {{{#imjs-tab-[md5 of label]}}}. + addTab: function(label, action, closable) { + var tab = $('.imjs-tab.imjs-default').clone().insertAfter('#imjs-scroll-right'); + tab.removeClass('imjs-default') + .attr('id', 'imjs-tab-' + $.md5(label)) + .html(tab.html().replace('{label}', label)) + .data('state', 'minimized'); + + var notification = tab.find('.imjs-notification'); + notification.css('display', 'none') + .data('count', 0) + .data('default-text', notification.html()) + .html(notification.html().replace('{count}', '0')); + + if(closable === false) + tab.find('.imjs-close').eq(0).remove(); + + if(typeof action == 'string') { + //tab.data('chatbox', action); + } else { + tab.find('.imjs-chatbox').remove(); + tab.click(action); + } + + return tab; + }, + + // === {{{AjaxIM.}}}**{{{bar.notification(tab)}}}** === + // + // Displays a notification on a tab. Generally, this is called when + // a tab is minimized to let the user know that there is an update + // for them. The way the notification is displayed depends on the + // theme CSS. + // + // ==== Parameters ==== + // * {{{tab}}} is the jQuery-selected tab DOM element. + notification: function(tab) { + var notify = tab.find('.imjs-notification'); + var notify_count = notify.data('count') + 1; + + notify.data('count', notify_count) + .html(notify.data('default-text').replace('{count}', notify_count)) + .css('display', ''); + }, + + // === //private// {{{AjaxIM.}}}**{{{bar._scrollers()}}}** === + // + // Document me! + _scrollers: function() { + var needScrollers = false; + $('.imjs-tab').filter(function() { + return $(this).data('state') != 'closed' + }).css('display', ''); + + $.each(self.chats, function(username, chatbox) { + var tab = chatbox.data('tab'); + if(tab.data('state') == 'closed') return true; + + if(tab.position().top > $('#imjs-bar').height()) { + $('.imjs-scroll').css('display', ''); + tab.css('display', 'none'); + needScrollers = true; + } else { + tab.css('display', ''); + } + }); + + if(!needScrollers) { + $('.imjs-scroll').css('display', 'none'); + } + + if($('#imjs-scroll-left').css('display') != 'none' && + $('#imjs-scroll-left').position().top > $('#imjs-bar').height()) { + $('#imjs-bar li.imjs-tab:visible').slice(-1).css('display', 'none'); + } + + var hiddenLeft = $('#imjs-bar li.imjs-tab:visible').slice(-1) + .nextAll('#imjs-bar li.imjs-tab:hidden') + .not('.imjs-default') + .filter(function() { + return $(this).data('state') != 'closed' + }).length; + + var hiddenRight = $('#imjs-bar li.imjs-tab:visible').eq(0) + .prevAll('#imjs-bar li.imjs-tab:hidden') + .not('.imjs-default') + .filter(function() { + return $(this).data('state') != 'closed' + }).length; + + $('#imjs-scroll-left').html(hiddenLeft); + $('#imjs-scroll-right').html(hiddenRight); + } + }, + + // == Comet == + // + // Comet, or HTTP streaming, holds open a connection between the client and + // the server indefinitely. As the server receives new messages or events, + // they are passed down to the client in a {{{<script>}}} + // tag which calls the {{{AjaxIM.incoming()}}} function. The connection is + // opened using either an {{{iframe}}} (in Opera or Internet Explorer) or + // an {{{XMLHTTPRequest}}} object. Due to the extra flexibility necessary + // with the {{{XMLHTTPRequest}}} object, jQuery's {{{$.ajax}}} is not used. + comet: { + type: '', + obj: null, + + onbeforeunload: null, + onreadystatechange: null, + + iframe: function() { + if(/loaded|complete/i.test(this.obj.readyState)) + throw new Error("IM server not available!"); + }, + + // === {{{AjaxIM.}}}**{{{comet.connect()}}}** === + // + // Creates and initializes the object and connection between the server + // and the client. For Internet Explorer and Opera, we use an + // {{{<iframe>}}} element; for all other browsers, we create an + // {{{XMLHTTPRequest}}} object. The server connects to the URI defined + // as the "poll" action. This function is called automatically, when + // the IM engine is initialized and the {{{AjaxIM.poll()}}} function + // is called. + connect: function() { + var self = _instance; + + if($.browser.opera || $.browser.msie) { + var iframe = $(''); + with(iframe) { + css({ + position: 'absolute', + visibility: 'visible', + display: 'block', + left: '-10000px', + top: '-10000px', + width: '1px', + height: '1px' + }); + + attr('src', self.actions.poll[1]); + appendTo('body'); + + bind('readystatechange', + self.comet.onreadystatechange = function() { self.comet.iframe() }); + bind('beforeunload', + self.comet.onbeforeunload = function() { self.comet.disconnect() }); + } + + self.comet.type = 'iframe'; + self.comet.obj = iframe; + } else { + var xhr = new XMLHttpRequest; + var length = 1029; + var code = /^\s*]*>parent\.(.+);<\/script>$/; + + xhr.open('get', self.actions.poll[1], true); + xhr.onreadystatechange = function(){ + if(xhr.readyState > 2) { + if(xhr.status == 200) { + responseText = xhr.responseText.substring(length); + length = xhr.responseText.length; + if(responseText != ' ') + eval(responseText.replace(code, "$1")); + } + // We need an "else" here. If the state changes to + // "loaded", the user needs to know they're + // disconnected. + } + }; + + self.comet.type = 'xhr'; + self.comet.obj = xhr; + + addEventListener('beforeunload', + self.comet.beforeunload = function() { self.comet.disconnect(); }, false); + setTimeout(function() { xhr.send(null) }, 10); + } + }, + + // === {{{AjaxIM.}}}**{{{comet.disconnect()}}}** === + // + // Disconnect from the server and destroy the connection object. This + // function is called before the page unloads, so that we plug up and + // potential leaks and free memory. + disconnect: function() { + var self = _instance.comet; + + if(!this.type || !this.obj) + return; + + if(this.type == 'iframe') { + detachEvent('onreadystatechange', this.onreadystatechange); + detachEvent('onbeforeunload', this.onbeforeunload); + this.obj.src = '.'; + $(this.obj).remove(); + } else { + removeEventListener('beforeunload', this.onbeforeunload, false); + this.obj.onreadystatechange = function(){}; + this.obj.abort(); + } + + delete this.obj; + } + } + }) + + self.bar.initialize(); + + if(prequeue.length) { + $.each(prequeue, function() { + var func = this[0].split('.'); + if(func.length > 1) + self[func[0]][func[1]].apply(self, this[1]); + else + self[func[0]].apply(self, this[1]); + }); + } + }); + + // == Static functions and variables == + // + // The following functions and variables are available outside of an initialized + // {{{AjaxIM}}} object. + + // === {{{AjaxIM.}}}**{{{client}}}** === + // + // Once {{{AjaxIM.init()}}} is called, this will be set to the active AjaxIM + // object. Only one AjaxIM object instance can exist at a time. This variable + // can and should be accessed directly. + AjaxIM.client = null; + + // === {{{AjaxIM.}}}**{{{init(options, actions)}}}** === + // + // Initialize the AjaxIM client object and engine. Here, you can define your + // options and actions as outlined at the top of this documentation. + // + // ==== Parameters ==== + // * {{{options}}} is the hash of custom settings to initialize Ajax IM with. + // * {{{actions}}} is the hash of any custom action URLs. + AjaxIM.init = function(options, actions) { + if(!_instance) { + _instance = new AjaxIM(options, actions); + AjaxIM.client = _instance; + } + + return _instance; + } + + + // === {{{AjaxIM.}}}**{{{request(url, data, successFunc, failureFunc)}}}** === + // + // Wrapper around {{{$.jsonp}}}, the JSON-P library for jQuery, and {{{$.ajax}}}, + // jQuery's ajax library. Allows either function to be called, automatically, + // depending on the request's URL array (see {{{AjaxIM.actions}}}). + // + // ==== Parameters ==== + // {{{url}}} is the URL of the request. + // {{{data}}} are any arguments that go along with the request. + // {{{success}}} is a callback function called when a request has completed + // without issue. + // {{{_ignore_}}} is simply to provide compatability with {{{$.post}}}. + // {{{failure}}} is a callback function called when a request hasn't not + // completed successfully. + AjaxIM.request = function(url, data, successFunc, failureFunc) { + if(typeof failureFunc != 'function'); + failureFunc = function(){}; + + $[url[0]]({ + 'url': url[1], + 'data': data, + dataType: (url[0] == 'ajax' ? 'json' : 'jsonp'), + type: 'POST', + cache: false, + timeout: 60000, + callback: 'jsonp' + (new Date()).getTime(), + success: function(json, textStatus) { + successFunc(json); + }, + error: function(xOptions, error) { + failureFunc(error); + } + }); + + // This prevents Firefox from spinning indefinitely + // while it waits for a response. Why? Fuck if I know. + if(url[0] == 'jsonp' && $.browser.mozilla) { + $.jsonp({ + 'url': 'about:', + timeout: 0 + }); + } + }; + + // === {{{AjaxIM.}}}**{{{incoming(data)}}}** === + // + // Never call this directly. It is used as a connecting function between + // client and server for Comet. + // + // //Note:// There are two {{{AjaxIM.incoming()}}} functions. This one is a + // static function called outside of the initialized AjaxIM object; the other + // is only called within the initalized AjaxIM object. + AjaxIM.incoming = function(data) { + if(!_instance) + return false; + + if(data.length) + _instance._parseMessages(data); + } + + // === {{{AjaxIM.}}}**{{{loaded}}}** === + // + // If Ajax IM has been loaded with the im.load.js file, this function will be + // called when the library is finally loaded and ready for use. Similar to + // jQuery's $(document).ready(), but for Ajax IM. + AjaxIM.loaded = function() { + if(typeof AjaxIMLoadedFunction == 'function') { + AjaxIMLoadedFunction(); + delete AjaxIMLoadedFunction; // clean up the global namespace + } + }; + + // === {{{AjaxIM.}}}**{{{dateFormat([date,] [mask,] utc)}}}** === + // + // Date Format 1.2.3\\ + // © 2007-2009 Steven Levithan ([[http://blog.stevenlevithan.com/archives/date-time-format|stevenlevithan.com]])\\ + // MIT license + // + // Includes enhancements by Scott Trenda + // and Kris Kowal ([[http://cixar.com/~kris.kowal/|cixar.com/~kris.kowal/]]) + // + // Accepts a date, a mask, or a date and a mask and returns a formatted version + // of the given date. + // + // ==== Parameters ==== + // * {{{date}}} is a {{{Date()}}} object. If not specified, the date defaults to the + // current date/time. + // * {{{mask}}} is a string that defines the formatting of the date. Formatting + // options can be found in the + // [[http://blog.stevenlevithan.com/archives/date-time-format|Date Format]] + // documentation. If not specified, the mask defaults to {{{dateFormat.masks.default}}}. + + AjaxIM.dateFormat = function () { + var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, + timezone = new RegExp('\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) ' + + '(?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b', + 'g'), + timezoneClip = /[^-+\dA-Z]/g, + pad = function (val, len) { + val = String(val); + len = len || 2; + while (val.length < len) val = "0" + val; + return val; + }; + + // Regexes and supporting functions are cached through closure + return function (date, mask, utc) { + var dF = AjaxIM.dateFormat; + + // You can't provide utc if you skip other args (use the "UTC:" mask prefix) + if (arguments.length == 1 && Object.prototype.toString.call(date) == + "[object String]" && !/\d/.test(date)) { + mask = date; + date = undefined; + } + + // Passing date through Date applies Date.parse, if necessary + date = date ? new Date(date) : new Date; + if (isNaN(date)) throw SyntaxError("invalid date"); + + mask = String(dF.masks[mask] || mask || dF.masks["default"]); + + // Allow setting the utc argument via the mask + if (mask.slice(0, 4) == "UTC:") { + mask = mask.slice(4); + utc = true; + } + + var _ = utc ? "getUTC" : "get", + d = date[_ + "Date"](), + D = date[_ + "Day"](), + m = date[_ + "Month"](), + y = date[_ + "FullYear"](), + H = date[_ + "Hours"](), + M = date[_ + "Minutes"](), + s = date[_ + "Seconds"](), + L = date[_ + "Milliseconds"](), + o = utc ? 0 : date.getTimezoneOffset(), + flags = { + d: d, + dd: pad(d), + ddd: AjaxIM.i18n.dayNames[D], + dddd: AjaxIM.i18n.dayNames[D + 7], + m: m + 1, + mm: pad(m + 1), + mmm: AjaxIM.i18n.monthNames[m], + mmmm: AjaxIM.i18n.monthNames[m + 12], + yy: String(y).slice(2), + yyyy: y, + h: H % 12 || 12, + hh: pad(H % 12 || 12), + H: H, + HH: pad(H), + M: M, + MM: pad(M), + s: s, + ss: pad(s), + l: pad(L, 3), + L: pad(L > 99 ? Math.round(L / 10) : L), + t: H < 12 ? "a" : "p", + tt: H < 12 ? "am" : "pm", + T: H < 12 ? "A" : "P", + TT: H < 12 ? "AM" : "PM", + Z: utc ? "UTC" : + (String(date).match(timezone) || [""]) + .pop().replace(timezoneClip, ""), + o: (o > 0 ? "-" : "+") + + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), + S: ["th", "st", "nd", "rd"][d % 10 > 3 ? + 0 : + (d % 100 - d % 10 != 10) * d % 10] + }; + + return mask.replace(token, function ($0) { + return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); + }); + }; + }(); + + // Some common format strings + AjaxIM.dateFormat.masks = { + "default": "ddd mmm dd yyyy HH:MM:ss", + shortDate: "m/d/yy", + mediumDate: "mmm d, yyyy", + longDate: "mmmm d, yyyy", + fullDate: "dddd, mmmm d, yyyy", + shortTime: "h:MM TT", + mediumTime: "h:MM:ss TT", + longTime: "h:MM:ss TT Z", + isoDate: "yyyy-mm-dd", + isoTime: "HH:MM:ss", + isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", + isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" + }; + + // === {{{AjaxIM.}}}**{{{i18n}}}** === + // + // Text strings used by Ajax IM. Should you want to translate Ajax IM into + // another language, merely change these strings. + // + // {{{%s}}} denotes text that will be automatically replaced when the string is + // used. + AjaxIM.i18n = { + dayNames: [ + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + ], + monthNames: [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + "January", "February", "March", "April", "May", "June", "July", "August", "September", + "October", "November", "December" + ], + + chatOffline: '%s signed off.', + chatAvailable: '%s became available.', + chatAway: '%s went away.', + + notConnected: 'You are currently not connected or the server is not available. ' + + 'Please ensure that you are signed in and try again.', + notConnectedTip: 'You are currently not connected.', + + authInvalid: 'Invalid username or password.', + + registerPasswordLength: 'Passwords must be more than 4 characters in length.', + registerUsernameLength: 'Usernames must be more than 2 characters in length and ' + + ' contain only A-Z, a-z, 0-9, underscores (_) and periods (.).', + registerPasswordMatch: 'Entered passwords do not match.', + registerUsernameTaken: 'The chosen username is already in use; please choose another.', + registerUnknown: 'An unknown error occurred. Please try again.' + } +})(jQuery, false); diff --git a/addons/web_chat/static/src/js/web_chat.js b/addons/web_chat/static/src/js/web_chat.js new file mode 100644 index 00000000000..fce64ee6f78 --- /dev/null +++ b/addons/web_chat/static/src/js/web_chat.js @@ -0,0 +1,10 @@ +openerp.web_chat = function (openerp) { + openerp.web_chat = {}; + openerp.web_chat.im = new AjaxIM({ + storageMethod: 'local', + pollServer: '/web_chat/pollserver', + theme: '/web_chat/static/lib/AjaxIM/themes/default', + flashStorage: '/web_chat/static/lib/AjaxIM/js/jStore.Flash.html' + }); + openerp.web_chat.im.login(); +}; diff --git a/addons/web_chat/static/src/web_chat.html b/addons/web_chat/static/src/web_chat.html deleted file mode 100644 index 5f11f01ee7b..00000000000 --- a/addons/web_chat/static/src/web_chat.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - diff --git a/addons/web_chat/static/src/web_chat.js b/addons/web_chat/static/src/web_chat.js deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/doc/source/addons.rst b/doc/source/addons.rst index 548e8ad461d..bca568f58df 100644 --- a/doc/source/addons.rst +++ b/doc/source/addons.rst @@ -1,6 +1,10 @@ Developing OpenERP Web Addons ============================= +An OpenERP Web addon is simply a Python package with an openerp +descriptor (a ``__openerp__.py`` file) which follows a few structural +and namespacing rules. + Structure --------- @@ -50,6 +54,79 @@ Structure ``test/`` The directories in which all tests for the addon are located. +Some of these are guidelines (and not enforced by code), but it's +suggested that these be followed. Code which does not fit into these +categories can go wherever deemed suitable. + +Namespacing +----------- + +Python +++++++ + +Because addons are also Python packages, they're inherently namespaced +and nothing special needs to be done on that front. + +JavaScript +++++++++++ + +The JavaScript side of an addon has to live in the namespace +``openerp.$addon_name``. For instance, everything created by the addon +``base`` lives in ``openerp.base``. + +The root namespace of the addon is a function which takes a single +parameter ``openerp``, which is an OpenERP client instance. Objects +(as well as functions, registry instances, etc...) should be added on +the correct namespace on that object. + +The root function will be called by the OpenERP Web client when +initializing the addon. + +.. code-block:: javascript + + // root namespace of the openerp.example addon + /** @namespace */ + openerp.example = function (openerp) { + // basic initialization code (e.g. templates loading) + openerp.example.SomeClass = Class.extend( + /** @lends openerp.example.SomeClass# */{ + /** + * Description for SomeClass's constructor here + * + * @constructs + */ + init: function () { + // SomeClass initialization code + } + // rest of SomeClass + }); + + // access an object in an other addon namespace to replace it + openerp.base.SearchView = openerp.base.SearchView.extend({ + init: function () { + this._super.apply(this, arguments); + console.log('Search view initialized'); + } + }); + } + +Utility behaviors +----------------- + +JavaScript +++++++++++ + +* All javascript objects inheriting from + :js:class:`openerp.base.BasicConroller` will have all methods + starting with ``on_`` or ``do_`` bound to their ``this``. This means + they don't have to be manually bound (via ``_.bind`` or ``$.proxy``) + in order to be useable as bound event handlers (event handlers + keeping their object as ``this`` rather than taking whatever + ``this`` object they were called with). + + Beware that this is only valid for methods starting with ``do_`` and + ``on_``, any other method will have to be bound manually. + .. _addons-testing: Testing diff --git a/doc/source/getting-started.rst b/doc/source/getting-started.rst index 49398a725b6..cd7f7ee8926 100644 --- a/doc/source/getting-started.rst +++ b/doc/source/getting-started.rst @@ -4,5 +4,7 @@ Getting Started with OpenERP Web Installing ---------- +.. per-distro packaging + Launching --------- diff --git a/doc/source/project.rst b/doc/source/project.rst index c9cef20af6f..6f9a06b2f0d 100644 --- a/doc/source/project.rst +++ b/doc/source/project.rst @@ -212,6 +212,8 @@ OpenERP Web over time Release process +++++++++++++++ +OpenSUSE packaging: http://blog.lowkster.com/2011/04/packaging-python-packages-in-opensuse.html + Roadmap +++++++ diff --git a/openerpweb/openerpweb.py b/openerpweb/openerpweb.py index 30c0f03f4ba..8423dc878ab 100644 --- a/openerpweb/openerpweb.py +++ b/openerpweb/openerpweb.py @@ -10,6 +10,7 @@ import time import traceback import uuid import xmlrpclib +import pytz import cherrypy import cherrypy.lib.static @@ -17,6 +18,7 @@ import simplejson import nonliterals import xmlrpctimeout +import logging #----------------------------------------------------------- # Globals @@ -83,10 +85,13 @@ class OpenERPSession(object): self._login = False self._password = False self.model_factory = model_factory - + self._locale = 'en_US' self.context = {} self.contexts_store = {} self.domains_store = {} + self._lang = {} + self.remote_timezone = 'utc' + self.client_timezone = False def proxy(self, service): s = xmlrpctimeout.TimeoutServerProxy('http://%s:%s/xmlrpc/%s' % (self._server, self._port, service), timeout=5) @@ -101,9 +106,8 @@ class OpenERPSession(object): uid = self.proxy('common').login(db, login, password) self.bind(db, uid, password) self._login = login - + if uid: self.get_context() - return uid def execute(self, model, func, *l, **d): @@ -130,6 +134,15 @@ class OpenERPSession(object): """ assert self._uid, "The user needs to be logged-in to initialize his context" self.context = self.model('res.users').context_get(self.context) + + self.client_timezone = self.context.get("tz", False) + if self.client_timezone: + self.remote_timezone = self.execute('common', 'timezone_get') + + self._locale = self.context.get('lang','en_US') + lang_ids = self.execute('res.lang','search', [('code', '=', self._locale)]) + if lang_ids: + self._lang = self.execute('res.lang', 'read',lang_ids[0], []) return self.context @property @@ -183,7 +196,7 @@ class OpenERPSession(object): if isinstance(context_to_eval, dict): return context_to_eval - ctx = context or {} + ctx = dict(context or {}) ctx['context'] = ctx # if the domain was unpacked from JSON, it needs the current @@ -239,7 +252,7 @@ class OpenERPSession(object): if isinstance(domain, list): return domain - ctx = context or {} + ctx = dict(context or {}) ctx['context'] = ctx # if the domain was unpacked from JSON, it needs the current @@ -343,6 +356,8 @@ class JsonRequest(object): } } except Exception: + cherrypy.log("An error occured while handling a json request", + severity=logging.ERROR, traceback=True) error = { 'code': 300, 'message': "OpenERP WebClient Error", @@ -483,3 +498,4 @@ def main(argv): cherrypy.server.subscribe() cherrypy.engine.start() cherrypy.engine.block() +