4 * {@link http://ajatus.info Ajatus - Distributed CRM}
5 * @requires jQuery v1.2.1
7 * Copyright (c) 2007 Jerry Jalava <jerry.jalava@gmail.com>
8 * Copyright (c) 2007 Nemein Oy <http://nemein.com>
9 * Website: http://ajatus.info
10 * Licensed under the GPL license
11 * http://www.gnu.org/licenses/gpl.html
17 TODO Additional fields [widget]
18 TODO Skype widget -bergie
19 TODO Formatter service
20 TODO XMMP & Email formatter
22 TODO Implement arhive view
23 TODO Implement file attachments
24 TODO Documentation (API)
27 if (typeof console == 'undefined') {
29 console.log = function() {
36 $.ajatus.application_content_area = null;
38 $.ajatus.version = [0, 6, 'x'];
40 $.ajatus.active_type = null;
43 * Holds all converters available in Ajatus.
45 $.ajatus.converter = {};
48 * Parses and evaluates JSON string to Javascript
49 * @param {String} json_str JSON String
50 * @returns Parsed JSON string or false on failure
52 $.ajatus.converter.parseJSON = function (json_str) {
54 var re = new RegExp('[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]');
55 return !(re.test(json_str.replace(/"(\\.|[^"\\])*"/g, ''))) && eval('(' + json_str + ')');
62 * Parses Javascript to JSON
63 * @param {Mixed} item Javascript to be parsed
64 * @param {String} type of the Javascript item to be parsed (Optional)
65 * @returns JSON string
68 $.ajatus.converter.toJSON = function (item,item_type) {
80 var a = ['['], b, f, i, l = x.length, v;
81 for (i = 0; i < l; i += 1) {
84 if (typeof v == 'string') {
102 return isFinite(x) ? String(x) : 'null';
106 if (x instanceof Array) {
109 var a = ['{'], b, f, i, v;
113 if (typeof v == 'string') {
117 a.push(s.str(i), ':', v);
127 if (/["\\\x00-\x1f]/.test(x)) {
128 x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
135 Math.floor(c / 16).toString(16) +
136 (c % 16).toString(16);
139 return '"' + x + '"';
142 conv = function (x) {
143 var itemtype = typeof x;
166 var itemtype = item_type || typeof item;
187 throw("Unknown type for $.ajatus.converter.toJSON");
192 * Holds all formatters available in Ajatus.
195 $.ajatus.formatter = {};
198 * Holds all date formatters available in Ajatus.
201 $.ajatus.formatter.date = {};
204 * Formats numbers < 10 to two digit numbers
205 * @param {Number} number Number to format
206 * @returns Formatted number
209 $.ajatus.formatter.date.fix_length = function(number){
210 return ((number < 10) ? '0' : '') + number;
214 * Checks if given value is ISO8601 Formatted Date
215 * @param {String} value Value to check
216 * @returns True, False if value not string or ISO8601 formatted
219 $.ajatus.formatter.date.is_iso8601 = function(value) {
220 if ( typeof value != 'string'
226 var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
227 var isod = value.match(new RegExp(regexp));
229 if ( typeof isod == 'object'
230 && typeof isod[10] != 'undefined')
239 * Converts JS Date to ISO8601 Formatted JS Date
240 * @param {Date} date Javascript date to convert
241 * @returns ISO8601 formatted Date
244 $.ajatus.formatter.date.js_to_iso8601 = function(date) {
246 str += date.getFullYear();
247 str += "-" + $.ajatus.formatter.date.fix_length(date.getMonth() + 1);
248 str += "-" + $.ajatus.formatter.date.fix_length(date.getDate());
249 str += "T" + $.ajatus.formatter.date.fix_length(date.getHours());
250 str += ":" + $.ajatus.formatter.date.fix_length(date.getMinutes());
251 str += ":" + $.ajatus.formatter.date.fix_length(date.getSeconds());
258 * Converts ISO8601 Formatted JS Date to JS Date
259 * @param {Date} iso_date ISO8601 formatted date to convert
260 * @returns Javascript Date
263 $.ajatus.formatter.date.iso8601_to_js = function(iso_date) {
264 var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
265 var isod = iso_date.match(new RegExp(regexp));
273 var date = new Date(isod[1], 0, 1);
274 date.setMonth(isod[3] - 1);
275 date.setDate(isod[5]);
276 date.setHours(isod[7]);
277 date.setMinutes(isod[8]);
278 date.setSeconds(isod[10]);
284 * Converts Date string from calendar widget to ISO8601 Formatted JS Date
285 * @param {String} caldate Date value from calendar widget
286 * @param {String} format Format used in conversion (Default: "MDY/")
287 * @param {String} caltime Time value from calendar widget
288 * @param {String} time_format Format used in conversion (Default: "HMS:")
289 * @returns ISO8601 formatted Javascript Date
292 $.ajatus.formatter.date.caldate_to_iso8601 = function(caldate, format, caltime, time_format) {
294 var format = format || ($.ajatus.i10n.datetime.date || "MDY/");
295 var time_format = time_format || ($.ajatus.i10n.datetime.time || "HMS:");
297 var cdparts = caldate.split(format.charAt(3));
298 var fparts = format.split("");
299 var date = new Date();
301 $.each(cdparts, function(i,v){
303 if (fparts[i] == 'M') {
306 if (fparts[i] == 'D') {
309 if (fparts[i] == 'Y') {
315 var time_separator = time_format.charAt(time_format.length - 1);
316 var tfparts = time_format.split("");
317 var ctparts = caltime.split(time_separator);
319 $.each(ctparts, function(i,v){
321 if (tfparts[i] == 'H') {
324 if (tfparts[i] == 'M') {
327 if (tfparts[i] == 'S') {
337 return $.ajatus.formatter.date.js_to_iso8601(date);
341 * Converts ISO8601 Formatted JS Date to calendar widget date string
342 * @param {Date} iso_date ISO8601 Formatted Date
343 * @param {String} format Format used in conversion (Default: "MDY/")
344 * @returns Calendar widget supported value
347 $.ajatus.formatter.date.iso8601_to_caldate = function(iso_date, format) {
348 var format = format || ($.ajatus.i10n.datetime.date || "MDY/");
350 var date = $.ajatus.formatter.date.iso8601_to_js(iso_date);
353 var day = date.getDate();
354 var month = date.getMonth();
355 var year = date.getFullYear();
358 for (var i = 0; i < 3; i++) {
359 date_str += format.charAt(3) +
360 (format.charAt(i) == 'D' ? $.ajatus.formatter.date.fix_length(day) :
361 (format.charAt(i) == 'M' ? $.ajatus.formatter.date.fix_length(month) :
362 (format.charAt(i) == 'Y' ? year : '?')));
364 date_str = date_str.substring(format.charAt(3) ? 1 : 0);
370 * Converts ISO8601 Formatted JS Date to calendar widget time string
371 * @param {Date} iso_date ISO8601 Formatted Date
372 * @param {String} format Format used in conversion (Default: "HMS:")
373 * @returns Calendar widget supported value
376 $.ajatus.formatter.date.iso8601_to_caltime = function(iso_date, format) {
377 var format = format || ($.ajatus.i10n.datetime.time || "HMS:");
379 var date = $.ajatus.formatter.date.iso8601_to_js(iso_date);
383 H: $.ajatus.formatter.date.fix_length(date.getHours()),
384 M: $.ajatus.formatter.date.fix_length(date.getMinutes()),
385 S: $.ajatus.formatter.date.fix_length(date.getSeconds())
388 var separator = format.charAt(format.length - 1);
389 var fparts = format.split("");
391 $.each(fparts, function(i,k){
392 if (typeof idparts[k] != 'undefined') {
393 time_str += idparts[k] + separator;
396 time_str = time_str.substring((time_str.length-1), -1);
402 $.ajatus.tabs.prepare = function(tab) {
403 tab.bind('mouseover', function(e){
404 tab.addClass('tabs-hover');
406 tab.bind('mouseout', function(e){
407 tab.removeClass('tabs-hover');
410 $.ajatus.tabs.set_active_by_hash = function(hash) {
411 // $.ajatus.debug('$.ajatus.tabs.set_active_by_hash('+hash+')');
413 var views_tab_holder = $('#tabs-views ul');
414 var app_tab_holder = $('#tabs-application ul');
416 var selected_tab = $('li a[@href$="' + hash + '"]', views_tab_holder).parent();
417 if (typeof selected_tab[0] != 'undefined') {
418 // $.ajatus.debug('views selected_tab:');
419 // $.ajatus.debug(selected_tab);
420 $('li', views_tab_holder).removeClass('tabs-selected').blur();
421 $('li', app_tab_holder).removeClass('tabs-selected').blur();
422 selected_tab.addClass('tabs-selected').focus();
424 selected_tab = $('li a[@href$="' + hash + '"]', app_tab_holder).parent();
425 // $.ajatus.debug('app selected_tab:');
426 // $.ajatus.debug(selected_tab);
427 if (typeof selected_tab[0] != 'undefined') {
428 $('li', views_tab_holder).removeClass('tabs-selected').blur();
429 $('li', app_tab_holder).removeClass('tabs-selected').blur();
430 selected_tab.addClass('tabs-selected').focus();
432 $('li', views_tab_holder).removeClass('tabs-selected').blur();
433 $('li', app_tab_holder).removeClass('tabs-selected').blur();
437 $.ajatus.tabs.on_click = function(e) {
438 var trgt = target(e);
439 $("li", parent(e)).removeClass("tabs-selected").index(trgt);
440 $(trgt).addClass("tabs-selected");
442 var new_hash = $('a', trgt)[0].hash;
443 location.hash = new_hash;
445 $.ajatus.history.update(new_hash);
447 $.ajatus.views.on_change(new_hash);
449 function parent(event) {
450 var element = event.target;
453 if (element.tagName == "UL")
458 while(element.tagName != "UL")
460 element = element.parentNode;
466 function target(event) {
467 var element = event.target;
470 if (element.tagName == "UL")
472 element = $(element).find('li').eq(0);
476 while(element.tagName != "LI")
478 element = element.parentNode;
485 $.ajatus.security_pass = function() {
487 netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead UniversalBrowserWrite UniversalFileRead");
489 alert("Permission UniversalBrowserRead denied. with error "+e);
493 $.ajatus.init = function(element, options) {
494 //$.ajatus.security_pass();
496 var application_element = $(element);
497 $.ajatus.application_element = application_element;
498 $.ajatus.application_content_area = $('#middle #content', $.ajatus.application_element);
499 $.ajatus.application_dynamic_elements = $('#dynamic-elements', $.ajatus.application_element);
501 $.ajatus.preferences.client.server_url = window.location.protocol + '//' + document.hostname + (window.location.port != '' ? ':'+window.location.port : '') + '/';
503 $.ajatus.preferences.client = $.extend({}, $.ajatus.preferences.client_defaults, options);
504 //Force the system types to load:
505 $.ajatus.preferences.client.types.system = $.ajatus.preferences.client_defaults.types.system;
507 $.jqCouch.set_defaults({
508 server_url: $.ajatus.preferences.client.server_url
511 var a_db_suffix = $.ajatus.preferences.client.application_database_identifier != '' ? '_db' : 'db';
512 $.ajatus.preferences.client.application_database = 'ajatus_' + $.ajatus.preferences.client.application_database_identifier + a_db_suffix;
513 $.ajatus.preferences.client.content_database = $.ajatus.preferences.client.application_database + '_content';
517 url: $.ajatus.preferences.client.server_url,
523 if ($.ajatus.preferences.client.developer_tools) {
524 $.ajatus.utils.load_script($.ajatus.preferences.client.application_url + 'js/ajatus.development.js');
527 $.ajatus.installer.is_installed();
528 if ($.ajatus.installer.installed == false) {
530 if ($.ajatus.preferences.client.language == null) {
532 $.ajatus.preferences.client.language = 'en_GB';
534 $.ajatus.i10n.init($.ajatus.preferences.client.language, function(){
535 var status = $.ajatus.installer.install();
536 $.ajatus.debug("Installer finished with status: "+status);
538 window.location = window.location + "#view.preferences";
546 // $.ajatus.installer.uninstall();
550 $.ajatus.preload = function() {
551 var preference_loader = new $.ajatus.preferences.loader;
552 preference_loader.load();
554 if ($.ajatus.preferences.client.language == null) {
556 if (typeof($.ajatus.preferences.local.localization) != 'undefined') {
557 lang = $.ajatus.preferences.local.localization.language;
559 $.ajatus.preferences.client.language = lang;
562 if ($.ajatus.utils.version.differs($.ajatus.installer.installed_version, $.ajatus.version)) {
563 $.ajatus.maintenance.version_upgrade();
566 $.ajatus.i10n.init($.ajatus.preferences.client.language, function(){
567 $.ajatus.types.init(function(){
573 $.ajatus.start = function() {
574 $.ajatus.debug('started', 'Ajatus start');
576 $.ajatus.events.lock_pool.increase();
578 // $.ajatus.cookies.init();
580 if ($.ajatus.preferences.local.layout.theme_name != 'default') {
581 $.ajatus.preferences.client.theme_url = 'themes/' + $.ajatus.preferences.local.layout.theme_name + '/';
582 $.ajatus.preferences.client.theme_icons_url = 'themes/' + $.ajatus.preferences.local.layout.icon_set + '/images/icons/';
584 $.ajatus.layout.styles.load($.ajatus.preferences.client.theme_url + 'css/structure.css');
585 $.ajatus.layout.styles.load($.ajatus.preferences.client.theme_url + 'css/common.css');
586 $.ajatus.layout.styles.load($.ajatus.preferences.client.theme_url + 'css/elements.css');
589 $.ajatus.locker = new $.ajatus.events.lock({
591 validate: function(){return $.ajatus.events.lock_pool.count == 0;},
595 on_release: function(){
596 $.ajatus.application_element.addClass('ajatus_initialized');
598 var show_frontpage = !$.ajatus.history.check();
600 if (show_frontpage) {
601 $.ajatus.views.system.frontpage.render();
604 // var gen_docs = $.ajatus.utils.doc_generator('contacts', 200, 'contact', {
605 // firstname: 'Firstname',
606 // lastname: 'Lastname',
607 // email: 'firstname.lastname@email.com'
609 // $.jqCouch.connection('doc').bulk_save($.ajatus.preferences.client.content_database, gen_docs);
613 if (! $.jqCouch.connection('doc').get($.ajatus.preferences.client.application_database + '/version')._id) {
614 $.jqCouch.connection('doc').put($.ajatus.preferences.client.application_database + '/version', {value: $.ajatus.version});
617 $('#header .app_version', $.ajatus.application_element).html($.ajatus.version.join('.'));
618 $('#header .tagline', $.ajatus.application_element).html($.ajatus.i10n.get('Distributed CRM'));
619 $('#new-item-button').text($.ajatus.i10n.get('new'));
621 $.ajatus.toolbar.init();
622 $.ajatus.history.init();
623 $.ajatus.tags.init();
624 $.ajatus.widgets.init();
625 $.ajatus.views.init();
627 $.ajatus.extensions.init({
628 on_ready: function(){
629 $.ajatus.active_type = $.ajatus.preferences.client.content_types['note'];
631 if ($.ajatus.preferences.modified) {
632 $.ajatus.views.on_change_actions.add('$.ajatus.preferences.view.save($.ajatus.preferences.local)');
635 // var gen_docs = $.ajatus.utils.doc_generator('notes', 200);
636 // $.jqCouch.connection('doc').bulk_save($.ajatus.preferences.client.content_database, gen_docs);
637 // var gen_docs = $.ajatus.utils.doc_generator('events', 200, 'event');
638 // $.jqCouch.connection('doc').bulk_save($.ajatus.preferences.client.content_database, gen_docs);
640 // Release the first lock
641 $.ajatus.events.lock_pool.decrease();
645 $.ajatus.elements.messages.set_holder();
647 window.onbeforeunload = function() {
648 if ($.ajatus.events.named_lock_pool.count('unsaved') > 0) {
649 return $.ajatus.i10n.get('You have unsaved changes.');
653 $.ajatus.debug('ended', 'Ajatus start');
656 $.ajatus.ajax_error = function(request, caller) {
657 $.ajatus.debug("Ajax error request.status: "+request.status);
659 if (typeof caller != 'undefined') {
660 $.ajatus.debug("Caller method: "+caller.method);
661 $.ajatus.debug("Caller action:");
662 $.ajatus.debug(caller.action);
664 if (caller.args != undefined) {
665 $.ajatus.debug("Caller args:");
666 $.ajatus.debug(caller.args);
670 if (request.responseText != '') {
671 var response = eval("(" + request.responseText + ")");
672 $.ajatus.debug('response.error.reason: '+response.error.reason);
675 $.ajatus.ajax_success = function(data, caller) {
676 $.ajatus.debug("Ajax success");
678 if (typeof caller != 'undefined') {
679 $.ajatus.debug("Caller method: "+caller.method);
680 $.ajatus.debug("Caller action: "+caller.action);
682 if (typeof caller.args != 'undefined') {
683 $.ajatus.debug("Caller args: "+caller.args);
686 $.ajatus.debug("data: "+data);
691 $.ajatus.debug = function(msg, title, type) {
692 if ($.ajatus.preferences.client.debug == true) {
693 if (typeof(console.log) != 'undefined') {
694 debug_console(msg, title, type);
696 debug_static(msg, title, type);
700 function debug_console(msg, title, type) {
701 if (typeof type == 'undefined') {
705 if (typeof(console[type]) != 'undefined') {
706 console.log(format(msg, title));
708 console.log(format(msg, title));
712 function debug_static(msg, title, type) {
713 // TODO: Implement Static debug handler
716 function format(msg, title) {
719 if (typeof title != 'undefined') {
720 string += title += ': ';
723 if (typeof msg != 'string') {
724 string += $.ajatus.utils.pretty_print(msg);
733 $.fn.initialize_ajatus = function(options) {
734 if (! $(this).is('.ajatus_initialized')) {
735 return new $.ajatus.init(this, options);
741 function initialize_ajatus() {
742 if (typeof ajatus_client_config == 'undefined') {
743 var ajatus_client_config = {};
746 jQuery('#application').initialize_ajatus($.extend({
751 application_url: '/_utils/ajatus_dev/', // '/_utils/ajatus/'
752 application_database_identifier: 'dev', // ''
753 developer_tools: true
754 }, ajatus_client_config));
757 $(document).ready(function() {
761 alert("could not initialize ajatus! Reason: "+e);