cubicweb/web/data/cubicweb.js
changeset 11057 0b59724cb3f2
parent 10433 523a7f098066
child 12503 b01dd0ef43aa
equal deleted inserted replaced
11052:058bb3dc685f 11057:0b59724cb3f2
       
     1 
       
     2 function Namespace(name) {
       
     3    this.__name__ = name;
       
     4 }
       
     5 
       
     6 cw = new Namespace('cw');
       
     7 
       
     8 jQuery.extend(cw, {
       
     9     cubes: new Namespace('cubes'),
       
    10     /* provide a removeEventListener / detachEvent definition to
       
    11      * to bypass a jQuery 1.4.2 bug when unbind() is called on a
       
    12      * plain JS object and not a DOM node.
       
    13      * see http://dev.jquery.com/ticket/6184 for more details
       
    14      */
       
    15     removeEventListener: function() {},
       
    16     detachEvent: function() {},
       
    17 
       
    18     log: function log() {
       
    19         if (typeof window !== "undefined" && window.console && window.console.log) {
       
    20             // NOTE console.log requires "console" to be the console to be "this"
       
    21             window.console.log.apply(console, arguments);
       
    22         }
       
    23     },
       
    24 
       
    25     //removed: getElementsByTagAndClassName, replaceChildNodes, toggleElementClass
       
    26     //         partial, merge, isNotEmpty, update,
       
    27     //         String.in_, String.join, list, getattr, attrgetter, methodcaller,
       
    28     //         min, max, dict, concat
       
    29     jqNode: function (node) {
       
    30     /**
       
    31      * .. function:: jqNode(node)
       
    32      *
       
    33      * safe version of jQuery('#nodeid') because we use ':' in nodeids
       
    34      * which messes with jQuery selection mechanism
       
    35      */
       
    36         if (typeof node === 'string') {
       
    37             node = document.getElementById(node);
       
    38         }
       
    39         if (node) {
       
    40             return $(node);
       
    41         }
       
    42         return null;
       
    43     },
       
    44 
       
    45     // escapes string selectors (e.g. "foo.[subject]:42" -> "foo\.\[subject\]\:42"
       
    46     escape: function(selector) {
       
    47         if (typeof selector === 'string') {
       
    48             return  selector.replace( /(:|\.|\[|\])/g, "\\$1" );
       
    49         }
       
    50         // cw.log('non string selector', selector);
       
    51         return '';
       
    52     },
       
    53 
       
    54     getNode: function (node) {
       
    55         if (typeof node === 'string') {
       
    56             return document.getElementById(node);
       
    57         }
       
    58         return node;
       
    59     },
       
    60 
       
    61     evalJSON: function (json) { // trust source
       
    62         try {
       
    63             return eval("(" + json + ")");
       
    64         } catch(e) {
       
    65           cw.log(e);
       
    66           cw.log('The faulty json source was', json);
       
    67           throw (e);
       
    68        }
       
    69     },
       
    70 
       
    71     urlEncode: function (str) {
       
    72         if (typeof encodeURIComponent !== "undefined") {
       
    73             return encodeURIComponent(str).replace(/\'/g, '%27');
       
    74         } else {
       
    75             return escape(str).replace(/\+/g, '%2B').replace(/\"/g, '%22').
       
    76                     rval.replace(/\'/g, '%27');
       
    77         }
       
    78     },
       
    79 
       
    80     swapDOM: function (dest, src) {
       
    81         dest = cw.getNode(dest);
       
    82         var parent = dest.parentNode;
       
    83         if (src) {
       
    84             src = cw.getNode(src);
       
    85             parent.replaceChild(src, dest);
       
    86         } else {
       
    87             parent.removeChild(dest);
       
    88         }
       
    89         return src;
       
    90     },
       
    91 
       
    92     sortValueExtraction: function (node) {
       
    93         var $node = $(node);
       
    94         var sortvalue = $node.attr('cubicweb:sortvalue');
       
    95         // No metadata found, use cell content as sort key
       
    96         if (typeof sortvalue === 'undefined') {
       
    97             return $node.text();
       
    98         }
       
    99         return cw.evalJSON(sortvalue);
       
   100     },
       
   101 
       
   102 });
       
   103 
       
   104 
       
   105 cw.utils = new Namespace('cw.utils');
       
   106 jQuery.extend(cw.utils, {
       
   107 
       
   108     deprecatedFunction: function (msg, newfunc) {
       
   109         return function () {
       
   110             cw.log(msg);
       
   111             return newfunc.apply(this, arguments);
       
   112         };
       
   113     },
       
   114 
       
   115     createDomFunction: function (tag) {
       
   116         function builddom(params, children) {
       
   117             var node = document.createElement(tag);
       
   118             for (key in params) {
       
   119                 var value = params[key];
       
   120                 if (key.substring(0, 2) === 'on') {
       
   121                     // this is an event handler definition
       
   122                     if (typeof value === 'string') {
       
   123                         // litteral definition
       
   124                         value = new Function(value);
       
   125                     }
       
   126                     node[key] = value;
       
   127                 } else { // normal node attribute
       
   128                     jQuery(node).attr(key, params[key]);
       
   129                 }
       
   130             }
       
   131             if (children) {
       
   132                 if (!cw.utils.isArrayLike(children)) {
       
   133                     children = [children];
       
   134                     for (var i = 2; i < arguments.length; i++) {
       
   135                         var arg = arguments[i];
       
   136                         if (cw.utils.isArray(arg)) {
       
   137                             jQuery.merge(children, arg);
       
   138                         } else {
       
   139                             children.push(arg);
       
   140                         }
       
   141                     }
       
   142                 }
       
   143                 for (var i = 0; i < children.length; i++) {
       
   144                     var child = children[i];
       
   145                     if (typeof child === "string" || typeof child === "number") {
       
   146                         child = document.createTextNode(child);
       
   147                     }
       
   148                     node.appendChild(child);
       
   149                 }
       
   150             }
       
   151             return node;
       
   152         }
       
   153         return builddom;
       
   154     },
       
   155 
       
   156     /**
       
   157      * .. function:: toISOTimestamp(date)
       
   158      *
       
   159      */
       
   160     toISOTimestamp: function (date) {
       
   161         if (date == null) {
       
   162             return null;
       
   163         }
       
   164 
       
   165         function _padTwo(n) {
       
   166             return (n > 9) ? n : "0" + n;
       
   167         }
       
   168         var isoTime = [_padTwo(date.getHours()), _padTwo(date.getMinutes()),
       
   169                        _padTwo(date.getSeconds())].join(':');
       
   170         var isoDate = [date.getFullYear(), _padTwo(date.getMonth() + 1),
       
   171                        _padTwo(date.getDate())].join("-");
       
   172         return isoDate + " " + isoTime;
       
   173     },
       
   174 
       
   175     /**
       
   176      * .. function:: nodeWalkDepthFirst(node, visitor)
       
   177      *
       
   178      * depth-first implementation of the nodeWalk function found
       
   179      * in `MochiKit.Base <http://mochikit.com/doc/html/MochiKit/Base.html#fn-nodewalk>`_
       
   180      */
       
   181     nodeWalkDepthFirst: function (node, visitor) {
       
   182         var children = visitor(node);
       
   183         if (children) {
       
   184             for (var i = 0; i < children.length; i++) {
       
   185                 cw.utils.nodeWalkDepthFirst(children[i], visitor);
       
   186             }
       
   187         }
       
   188     },
       
   189 
       
   190     isArray: function (it) { // taken from dojo
       
   191         return it && (it instanceof Array || typeof it === "array");
       
   192     },
       
   193 
       
   194     isString: function (it) { // taken from dojo
       
   195         return !!arguments.length && it != null && (typeof it === "string" || it instanceof String);
       
   196     },
       
   197 
       
   198     isArrayLike: function (it) { // taken from dojo
       
   199         return (it && it !== undefined &&
       
   200                 // keep out built-in constructors (Number, String, ...)
       
   201                 // which have length properties
       
   202                 !cw.utils.isString(it) && !jQuery.isFunction(it) &&
       
   203                 !(it.tagName && it.tagName.toLowerCase() == 'form') &&
       
   204                 (cw.utils.isArray(it) || isFinite(it.length)));
       
   205     },
       
   206 
       
   207     /**
       
   208      * .. function:: formContents(elem)
       
   209      *
       
   210      * cannot use jQuery.serializeArray() directly because of FCKeditor
       
   211      */
       
   212     formContents: function (elem) {
       
   213         var $elem, array, names, values;
       
   214         $elem = cw.jqNode(elem);
       
   215         array = $elem.serializeArray();
       
   216 
       
   217         if (typeof FCKeditor !== 'undefined') {
       
   218             $elem.find('textarea').each(function (idx, textarea) {
       
   219                 var fck = FCKeditorAPI.GetInstance(textarea.id);
       
   220                 if (fck) {
       
   221                     array = jQuery.map(array, function (dict) {
       
   222                         if (dict.name === textarea.name) {
       
   223                             // filter out the textarea's - likely empty - value ...
       
   224                             return null;
       
   225                         }
       
   226                         return dict;
       
   227                     });
       
   228                     // ... so we can put the HTML coming from FCKeditor instead.
       
   229                     array.push({
       
   230                         name: textarea.name,
       
   231                         value: fck.GetHTML()
       
   232                     });
       
   233                 }
       
   234             });
       
   235         }
       
   236 
       
   237         names = [];
       
   238         values = [];
       
   239         jQuery.each(array, function (idx, dict) {
       
   240             names.push(dict.name);
       
   241             values.push(dict.value);
       
   242         });
       
   243         return [names, values];
       
   244     },
       
   245 
       
   246     /**
       
   247      * .. function:: sliceList(lst, start, stop, step)
       
   248      *
       
   249      * returns a subslice of `lst` using `start`/`stop`/`step`
       
   250      * start, stop might be negative
       
   251      *
       
   252      * >>> sliceList(['a', 'b', 'c', 'd', 'e', 'f'], 2)
       
   253      * ['c', 'd', 'e', 'f']
       
   254      * >>> sliceList(['a', 'b', 'c', 'd', 'e', 'f'], 2, -2)
       
   255      * ['c', 'd']
       
   256      * >>> sliceList(['a', 'b', 'c', 'd', 'e', 'f'], -3)
       
   257      * ['d', 'e', 'f']
       
   258      */
       
   259     sliceList: function (lst, start, stop, step) {
       
   260         start = start || 0;
       
   261         stop = stop || lst.length;
       
   262         step = step || 1;
       
   263         if (stop < 0) {
       
   264             stop = Math.max(lst.length + stop, 0);
       
   265         }
       
   266         if (start < 0) {
       
   267             start = Math.min(lst.length + start, lst.length);
       
   268         }
       
   269         var result = [];
       
   270         for (var i = start; i < stop; i += step) {
       
   271             result.push(lst[i]);
       
   272         }
       
   273         return result;
       
   274     },
       
   275 
       
   276     /**
       
   277      * returns the last element of an array-like object or undefined if empty
       
   278      */
       
   279     lastOf: function(array) {
       
   280         if (array.length) {
       
   281             return array[array.length-1];
       
   282         } else {
       
   283             return undefined;
       
   284         }
       
   285     },
       
   286 
       
   287 
       
   288     /**
       
   289      * .. function:: extend(array1, array2)
       
   290      *
       
   291      * equivalent of python ``+=`` statement on lists (array1 += array2)
       
   292      */
       
   293     extend: function(array1, array2) {
       
   294         array1.push.apply(array1, array2);
       
   295         return array1; // return array1 for convenience
       
   296     },
       
   297 
       
   298     /**
       
   299      * .. function:: difference(lst1, lst2)
       
   300      *
       
   301      * returns a list containing all elements in `lst1` that are not
       
   302      * in `lst2`.
       
   303      */
       
   304     difference: function(lst1, lst2) {
       
   305         return jQuery.grep(lst1, function(elt, i) {
       
   306             return jQuery.inArray(elt, lst2) == -1;
       
   307         });
       
   308     },
       
   309     /**
       
   310      * .. function:: domid(string)
       
   311      *
       
   312      * return a valid DOM id from a string (should also be usable in jQuery
       
   313      * search expression...). This is the javascript implementation of
       
   314      * :func:`cubicweb.uilib.domid`.
       
   315      */
       
   316     domid: function (string) {
       
   317 	var newstring = string.replace(".", "_").replace("-", "_");
       
   318 	while (newstring != string) {
       
   319 	    string = newstring;
       
   320 	    newstring = newstring.replace(".", "_").replace("-", "_");
       
   321 	}
       
   322 	return newstring; // XXX
       
   323     },
       
   324 
       
   325     /**
       
   326      * .. function:: strFuncCall(fname, *args)
       
   327      *
       
   328      * return a string suitable to call the `fname` javascript function with the
       
   329      * given arguments (which should be correctly typed).. This is providing
       
   330      * javascript implementation equivalent to :func:`cubicweb.uilib.js`.
       
   331      */
       
   332     strFuncCall: function(fname /* ...*/) {
       
   333 	    return (fname + '(' +
       
   334 		    $.map(cw.utils.sliceList(arguments, 1), JSON.stringify).join(',')
       
   335 		    + ')'
       
   336 		    );
       
   337     },
       
   338 
       
   339     callAjaxFuncThenReload: function callAjaxFuncThenReload (/*...*/) {
       
   340         var d = asyncRemoteExec.apply(null, arguments);
       
   341         d.addCallback(function(msg) {
       
   342             window.location.reload();
       
   343             if (msg)
       
   344                 updateMessage(msg);
       
   345         });
       
   346     }
       
   347 });
       
   348 
       
   349 /** DOM factories ************************************************************/
       
   350 A = cw.utils.createDomFunction('a');
       
   351 BUTTON = cw.utils.createDomFunction('button');
       
   352 BR = cw.utils.createDomFunction('br');
       
   353 CANVAS = cw.utils.createDomFunction('canvas');
       
   354 DD = cw.utils.createDomFunction('dd');
       
   355 DIV = cw.utils.createDomFunction('div');
       
   356 DL = cw.utils.createDomFunction('dl');
       
   357 DT = cw.utils.createDomFunction('dt');
       
   358 FIELDSET = cw.utils.createDomFunction('fieldset');
       
   359 FORM = cw.utils.createDomFunction('form');
       
   360 H1 = cw.utils.createDomFunction('H1');
       
   361 H2 = cw.utils.createDomFunction('H2');
       
   362 H3 = cw.utils.createDomFunction('H3');
       
   363 H4 = cw.utils.createDomFunction('H4');
       
   364 H5 = cw.utils.createDomFunction('H5');
       
   365 H6 = cw.utils.createDomFunction('H6');
       
   366 HR = cw.utils.createDomFunction('hr');
       
   367 IMG = cw.utils.createDomFunction('img');
       
   368 INPUT = cw.utils.createDomFunction('input');
       
   369 LABEL = cw.utils.createDomFunction('label');
       
   370 LEGEND = cw.utils.createDomFunction('legend');
       
   371 LI = cw.utils.createDomFunction('li');
       
   372 OL = cw.utils.createDomFunction('ol');
       
   373 OPTGROUP = cw.utils.createDomFunction('optgroup');
       
   374 OPTION = cw.utils.createDomFunction('option');
       
   375 P = cw.utils.createDomFunction('p');
       
   376 PRE = cw.utils.createDomFunction('pre');
       
   377 SELECT = cw.utils.createDomFunction('select');
       
   378 SPAN = cw.utils.createDomFunction('span');
       
   379 STRONG = cw.utils.createDomFunction('strong');
       
   380 TABLE = cw.utils.createDomFunction('table');
       
   381 TBODY = cw.utils.createDomFunction('tbody');
       
   382 TD = cw.utils.createDomFunction('td');
       
   383 TEXTAREA = cw.utils.createDomFunction('textarea');
       
   384 TFOOT = cw.utils.createDomFunction('tfoot');
       
   385 TH = cw.utils.createDomFunction('th');
       
   386 THEAD = cw.utils.createDomFunction('thead');
       
   387 TR = cw.utils.createDomFunction('tr');
       
   388 TT = cw.utils.createDomFunction('tt');
       
   389 UL = cw.utils.createDomFunction('ul');
       
   390 
       
   391 // cubicweb specific
       
   392 //IFRAME = cw.utils.createDomFunction('iframe');
       
   393 
       
   394 
       
   395 function IFRAME(params) {
       
   396     if ('name' in params) {
       
   397         try {
       
   398             var node = document.createElement('<iframe name="' + params['name'] + '">');
       
   399         } catch (ex) {
       
   400             var node = document.createElement('iframe');
       
   401             node.id = node.name = params.name;
       
   402         }
       
   403     }
       
   404     else {
       
   405         var node = document.createElement('iframe');
       
   406     }
       
   407     for (key in params) {
       
   408         if (key !== 'name') {
       
   409             var value = params[key];
       
   410             if (key.substring(0, 2) === 'on') {
       
   411                 // this is an event handler definition
       
   412                 if (typeof value === 'string') {
       
   413                     // litteral definition
       
   414                     value = new Function(value);
       
   415                 }
       
   416                 node[key] = value;
       
   417             } else { // normal node attribute
       
   418                 node.setAttribute(key, params[key]);
       
   419             }
       
   420         }
       
   421     }
       
   422     return node;
       
   423 }
       
   424 
       
   425 // cubes: tag, keyword and apycot seem to use this, including require/provide
       
   426 // backward compat
       
   427 CubicWeb = cw;
       
   428 
       
   429 jQuery.extend(cw, {
       
   430     require: cw.utils.deprecatedFunction(
       
   431         '[3.9] CubicWeb.require() is not used anymore',
       
   432         function(module) {}),
       
   433     provide: cw.utils.deprecatedFunction(
       
   434         '[3.9] CubicWeb.provide() is not used anymore',
       
   435         function(module) {})
       
   436 });
       
   437 
       
   438 jQuery(document).ready(function() {
       
   439     $(cw).trigger('server-response', [false, document]);
       
   440 });