﻿

;jQuery.ui.ju || (function ($) {
    $.widget("ui.ju", {
        options: {
            sp: '/scripts/mgrqispi.dll?appname=tin&prgname=',
            dn: '',                 // domain name - http://beta.tin.info
            k: 'janooo_ui',         //do not change, this is not what it seems it is (eto kluc)
            root: '/css/nd/jscript/',
            activeCookie: false
        },
        el: { s: '<span />', d: '<div />', li: '<li />', i: '<img />', u: '<ul />', p: '<input />', o: '<option />' },
        u: {
            sp: '/scripts/mgrqispi.dll?appname=tin&prgname=',
            s: '', login_name: '', display_name: '', pwd: '', lang: '', user_isn: 0, login_email: '', tag_id: '',
            sidO: { logged_in: '', badPwdCount: 0, lastLogon: '', lastLogoff: '' },
            roles: {},
            show_eo: { user_isn: 0, name: '' },
            req: { target: '' },                    // target: 'NONE' - stay on the same page
            pages: [{ name: '', link: ''}]
        },
        _init: function () {
            var t = this;
            //alert($(t.element[0]).html());
            //alert($(t.element).attr('id'));
            //alert($(t.element).attr('textContent'));
            //alert('_init');


            $.ajax({ url: this.options.sp + 'user_api&ARGUMENTS=-A<a iaAction="user.init" aSID="' + this.options.s + '" />',
                dataType: 'script',         // add rel.get_partners
                cache: false,               // HAS TO BE FALSE!
                success: function () {
                    if ($('#aShowEOname').length) {
                        $('#aShowEOname').html(t.u.show_eo.name);
                    }
                }
            });



        },

        u_alert: function (p) {         // calling the method: $('#ju').ju( 'u_alert', ['p1'] );
            alert('from user ' + p);
        },

        get_u: function () {
            return this.u;
        },
        set_u: function (o) {
            $.extend(true, this.u, o);
        },
        set_u_page: function (i, p) {
            if (this.u.pages[i] == undefined) this.u.pages[i] = {};
            $.extend(true, this.u.pages[i], p);
        },
        open_profile: function () {
            var t = this;
            if ($.ui.ju.prototype.profile === undefined)
                $.ajax({ url: this.options.root + 'ju/ju.ui.profile.js', dataType: 'script', cache: false, async: false,
                    success: function (o) { t.profile(); }
                });
            else
                t.profile();
        },
        open_login_popup: function () {
            var t = this;
            if ($.ui.ju.prototype.login_popup === undefined)
                $.ajax({ url: this.options.root + 'ju/ju.ui.login_popup.js', dataType: 'script', cache: false, async: false,
                    success: function (o) {
                        var u = t.u;
                        if (u.sidO.logged_in == 'Y') {
                            $.ajax({ url: u.sp + 'user_api&ARGUMENTS=-A<a iaAction="rel.member_partner.create" aSID="' + u.s + '" eo1_isn="' + u.show_eo.user_isn + '" eo2_isn="' + u.user_isn + '" />',
                                dataType: 'script', // rel.get_partners
                                success: function () {
                                }
                            });
                            alert('Thank you for registration.');
                        }
                        else { t.login_popup(); }
                    }
                });
            else if (this.u.sidO.logged_in == 'Y') {
                $.ajax({ url: t.options.sp + 'user_api&ARGUMENTS=-A<a iaAction="rel.member_partner.create" aSID="' + t.options.s + '" eo1_isn="' + t.u.show_eo.user_isn + '" eo2_isn="' + t.u.user_isn + '" />',
                    dataType: 'script', // rel.get_partners
                    success: function () {
                    }
                });
                alert('Thank you for registration!');
            }
            else
                t.login_popup();
        },
        load_login_popup: function () {
            if ($.ui.ju.prototype.login_popup === undefined)
                $.ajax({ url: this.options.root + 'ju/ju.ui.login_popup.js', dataType: 'script', cache: false, async: false,
                    success: function (o) { }
                });
        },
        home_page_popup: function () {
            var r = '<ul>';
            $.each(this.u.pages, function (i, v) {
                r = r + '<li><a href="/member' + v.link + '">' + v.name + '</a></li>';
            });
            r = r + '</ul>';
            r = r + '<a href="#" onclick="_hidepagetopDiv(this);" title="Close" class="pagetopClose"></a>';
            return r;
        },
        checkCookie: function (f) {
            //if($("#linkLogin").is(':visible')){
            var ju_nps = $.cookie("ju_nps");
            var n = $.rc4DecryptStr(this.strToken(ju_nps, 1, ','), this.options.k);
            var p = $.rc4DecryptStr(this.strToken(ju_nps, 2, ','), this.options.k);
            var s = ($.rc4DecryptStr(this.strToken(ju_nps, 3, ','), this.options.k) == 'Y');
            this.u.login_name = n; this.u.pwd = p;

            this.options.activeCookie = n == null || n == "" || n == "undefined" ? false : true;
            f[0].pwd.value = '';
            if (this.options.activeCookie) {
                f[0].usr.value = (s ? n : "");
                f[0].pwd.value = (s ? p : "");
                f[0].rememberme.checked = s;
            }
            //}
        },

        saveCookie: function (f) {
            var isSave = f[0].rememberme.checked; 	// Update???
            if (!window.navigator.cookieEnabled) { alert(msgs['WARNING~DISABLED_COOKIE']); return; }
            //---		fields		---
            var name = f[0].usr.value;
            var psw = f[0].pwd.value;
            //-----------------------

            var itemsChanged = (name != this.u.login_name) || (psw != this.u.pwd); // has been changed!
            var proceedCookie = (isSave && !this.options.activeCookie) || (!isSave && this.options.activeCookie) || (isSave && itemsChanged);
            if (proceedCookie) {
                var aName = $.rc4EncryptStr((isSave ? name : ''), this.options.k);
                var aPsw = $.rc4EncryptStr((isSave ? psw : ''), this.options.k);
                var bStatus = $.rc4EncryptStr((isSave ? 'Y' : 'N'), this.options.k);
                $.cookie('ju_nps', aName + ',' + aPsw + ',' + bStatus, { expires: getExpireDate(365), path: '/' });
            }
        },

        strToken: function (source, index, delimiter) {
            if (source == null) return '';
            var tokens = new Array();
            if (!delimiter) delimiter = '~';
            tokens[0] = source.length;
            if (source.indexOf(delimiter) == -1 && index == 1) return source;
            else if (source.indexOf(delimiter) == -1 && index > 1) return '';
            else for (var i = 1; source.lastIndexOf(delimiter, tokens[i - 1]) > 0; i++) {
                tokens[i] = source.lastIndexOf(delimiter, tokens[i - 1] - delimiter.length);
            }
            if (index < tokens.length)
                return source.substring(index <= 1 ? 0 : tokens[tokens.length - index] + delimiter.length, tokens[tokens.length - index - 1]);
            else return '';
        }
    });
})(jQuery);




;jQuery.ui.janooo_div || (function ($) {
    $.widget("ui.janooo_div", {
        options: {
            leftTabPadding: '10px',
            numberOfDivs: 5
        },
        el: { s: '<span />', d: '<div />', li: '<li />', i: '<img />', u: '<ul />', p: '<input />', o: '<option />' }, //element definitions. do not change
        tab_list: { "tab": [{}] },
        width: 200, //width of the outside container
        height: 200, //total height of the container

        background: 'transparent', //background of the container default: transparent
        text: {
            allowWrapAround: false,
            checkBoxPosition: 'left', //allow for check box on left & right
            textSize: null,
            textAlign: null
        },
        input_options: {},
        _init: function () {

            var t = this,
                elm = this.element,
                options = this.options, itms = '';

            $(t).data("iopts", options); // save this instance init options (how it was created)

            if (options.height < 200)
                options.height = 200;
            if (options.width < 200)
                options.width = 200;

            this.jt = $(t.el.d)
                           .css({ 'height': ((!options.expanded && options.allowCollapse) ? 28 : (!options.allowInput ? 28 - options.height : options.height)) + 'px', 'width': options.width + 'px', 'background': options.background, 'padding': '0', 'margin': '0', 'overflow': 'hidden', 'position': 'relative' })
                           .attr('id', elm.attr('id') + '_jtWrapper')
                           .addClass('ui-tabs')
                           .addClass('ui-widget')
                           .click(function () {
                               alert('Handler for .click() called.');
                               t._handleClick(this);
                           })
                           .html('Hello, this is janooo tabs object: ');
            elm.addClass('ui-tabs ui-widget ui-helper-reset ui-helper-clearfix');
            elm.children().each(function (index, value) {
                //alert($('<div>').append($(value).clone()).remove().html());
                //alert($(value).html());
                //alert($(value).children('a').html());
                $(value).click(function () {
                    alert('Handler for .click() called. ' + $(value).html()); // does not work
                });
                t.tab_list.tab[index] = { "text": $(value).html() };

                if (index < options) {
                    itms += '<li class="ui-jt-tab-li ui-corner-top">' + $(value).html() + '</li>';
                    $(value).addClass('ui-jt-tab-li ui-corner-top');
                }
            });

            //elm.addClass('ui-helper-reset ui-helper-clearfix');
            //$(elm).html('<ul class="ui-helper-reset ui-helper-clearfix">' + itms + '</ul>');
            $(elm).html(itms);
            $(elm).show();
            //$(('<ul class="ui-helper-reset ui-helper-clearfix">' + itms + '</ul>')).appendTo(this.jt);
            //$(this.jt).html(elm.clone()); //pm-ui-tabs pm-ui-widget pm-ui-widget-content ui-corner-all
            elm.after(this.jt);




            if (options.showTitle) {
                this.header = $(t.el.d)
                            .css({ 'height': '22px', 'line-height': '22px', 'padding': '0 0 0 4px', 'margin': '2px' })
                            .addClass('ui-widget-header')
                            .addClass('ui-corner-all')
                            .attr('id', elm.attr('id') + '_header');
                if (options.allowCollapse) {
                    this.header.click(function () {
                        t._expand();
                    });
                    this.header.append($(t.el.s)
                                       .css({ 'width': options.width - 40 + 'px', 'display': 'inline-block', 'overflow': 'hidden' })
                                       .html(options.title)
                                       .addClass('ui-sexyselect-header-text')
                                       );
                }
                else
                    this.header.html(options.title);
                this.jt.append(this.header);
            }
            //elm.after(this.jt);
            //this._syncItems();
        },
        _handleClick: function (elem) {
            var t = this;
            alert('inside the _handleClick() ' + $(elem).html());
            t._createDivs();
        },
        _createDivs: function () {
            var t = this, opts = $(t).data("iopts"), tab_list = $(t).data("tab_list");
            for (var i = 0; i < opts.numberOfDivs; i++) {

            }

        },
        _resetCreateEventArgs: function () {
            var t = this;
            t.createEventArgs.create = true;
            t.createEventArgs.errorText = '';
        },
        addItem: function (inputText, index) {
            var t = this,
                newOption = $('<option />')
                                    .val(inputText)
                                    .text(inputText);
            if (index !== undefined && index < t.element.children('option').size() - 1)
                newOption.insertBefore(t.element.children('option:eq(' + index + ')'));
            else
                t.element.append(newOption);
            t._syncItems();
        },
        _syncItems: function () {
        },
        destroy: function () {
            var t = this, elm = this.element;
            //$('#' +elm.attr('id') + '_ssWrapper').remove();
            //elm.show();
        },
        totalItems: function () {
            return this.element.children().size();
        },
        totalVisibleItems: function () {
            return $('#' + this.element.attr('id') + '_items ul').children('li:visible').size();
        },
        _expand: function () {
            var t = this, elm = this.element, dir = (t.options.expanded = (!t.options.expanded)),
                ico = $('#' + elm.attr('id') + '_icon');
            ico.removeClass('ui-icon-circle-triangle-n')
               .removeClass('ui-icon-circle-triangle-s')
               .addClass((dir ? 'ui-icon-circle-triangle-s' : 'ui-icon-circle-triangle-n'));
            $('#' + elm.attr('id') + '_ssWrapper').animate({
                height: (!dir ? 28 : t.options.height) + 'px'
            }, 500, function () { });
        },

        getOption: function (optionName) {
            if (optionName == 'autoSort') return this.options.autoSort;
        }

    });
})(jQuery);







/**
* Cookie plugin
*
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/

jQuery.cookie = function (name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
        options = options || {};
        if (value === null) {
            value = '';
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        }
        var path = options.path ? '; path=' + options.path : '';
        var domain = options.domain ? '; domain=' + options.domain : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};




/*
Usage 1: define the default prefix by using an object with the property prefix as a parameter which contains a string value; {prefix: 'id'}
Usage 2: call the function jQuery.uuid() with a string parameter p to be used as a prefix to generate a random uuid;
Usage 3: call the function jQuery.uuid() with no parameters to generate a uuid with the default prefix; defaul prefix: '' (empty string)
*/

/*
Generate fragment of random numbers
*/
jQuery._uuid_default_prefix = '';
jQuery._uuidlet = function () {
    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
};
/*
Generates random uuid
*/
jQuery.uuid = function (p) {
    if (typeof (p) == 'object' && typeof (p.prefix) == 'string') {
        jQuery._uuid_default_prefix = p.prefix;
    } else {
        p = p || jQuery._uuid_default_prefix || '';
        return (p + jQuery._uuidlet() + jQuery._uuidlet() + "-" + jQuery._uuidlet() + "-" + jQuery._uuidlet() + "-" + jQuery._uuidlet() + "-" + jQuery._uuidlet() + jQuery._uuidlet() + jQuery._uuidlet());
    };
};



/* JQuery RC4 encryption/decryption
* Copyright (c) 2009 by Tony Simek.
* released under the terms of the Gnu Public License.
* Email: tony.simek@gmail.com
*/
(function ($) {
    $.fn.rc4 = function (settings) {
        var defaults = { key: null, method: "encrypt", callback: null };
        var options = $.extend(defaults, settings);
        if ($.fn.rc4.ctrlrInst == null) { $.fn.rc4.ctrlrInst = new $.fn.rc4.ctrlr(options); }
        return this.each(function () {
            $.fn.rc4.ctrlrInst.settings = options;
            $.fn.rc4.ctrlrInst.container = this; $.fn.rc4.ctrlrInst.initialise(this);
        });
    }
    $.extend({ hexEncode: function (data) {
        var b16D = '0123456789abcdef'; var b16M = new Array();
        for (var i = 0; i < 256; i++) { b16M[i] = b16D.charAt(i >> 4) + b16D.charAt(i & 15); }
        var result = new Array(); for (var i = 0; i < data.length; i++) { result[i] = b16M[data.charCodeAt(i)]; }
        return result.join('');
    }, hexDecode: function (data) {
        var b16D = '0123456789abcdef'; var b16M = new Array();
        for (var i = 0; i < 256; i++) { b16M[b16D.charAt(i >> 4) + b16D.charAt(i & 15)] = String.fromCharCode(i); }
        if (!data.match(/^[a-f0-9]*$/i)) return false; if (data.length % 2) data = '0' + data;
        var result = new Array(); var j = 0; for (var i = 0; i < data.length; i += 2) { result[j++] = b16M[data.substr(i, 2)]; }
        return result.join('');
    }, rc4Encrypt: function (key, pt) {
        var s = new Array(); for (var i = 0; i < 256; i++) { s[i] = i; }; var j = 0; var x;
        for (i = 0; i < 256; i++) { j = (j + s[i] + key.charCodeAt(i % key.length)) % 256; x = s[i]; s[i] = s[j]; s[j] = x; }
        i = 0; j = 0; var ct = ''; for (var y = 0; y < pt.length; y++) {
            i = (i + 1) % 256; j = (j + s[i]) % 256; x = s[i]; s[i] = s[j]; s[j] = x;
            ct += String.fromCharCode(pt.charCodeAt(y) ^ s[(s[i] + s[j]) % 256]);
        } return ct;
    }, rc4Decrypt: function (key, ct) {
        return $.rc4Encrypt(key, ct);
    }, rc4EncryptStr: function (str, key) {
        return $.hexEncode($.rc4Encrypt(key, unescape(encodeURIComponent(str))));
    }, rc4DecryptStr: function (hexStr, key) { return decodeURIComponent(escape($.rc4Decrypt(key, $.hexDecode(hexStr)))); }
    });
    $.rc4 = {}; $.fn.rc4.ctrlrInst = null; $.fn.rc4.ctrlr = function (settings) { this.settings = settings; }; var ctrlr = $.fn.rc4.ctrlr;
    ctrlr.prototype.initialise = function () {
        if (this.settings.key) {
            if (this.settings.method) {
                if ($.trim(this.settings.method.toUpperCase()) == "ENCRYPT") {
                    this.setObjectValue($.hexEncode($.rc4Encrypt(this.settings.key, this.getObjectValue())))
                }
                if ($.trim(this.settings.method.toUpperCase()) == "DECRYPT") {
                    this.setObjectValue($.rc4Decrypt(this.settings.key, $.hexDecode(this.getObjectValue())));
                }
            }
        };
    }
    ctrlr.prototype.getObjectValue = function () {
        if ($.fn.rc4.ctrlrInst.container.innerHTML) { return $.fn.rc4.ctrlrInst.container.innerHTML; }
        if ($.fn.rc4.ctrlrInst.container.value) { return $.fn.rc4.ctrlrInst.container.value; }
    }
    ctrlr.prototype.setObjectValue = function (data) {
        if ($.fn.rc4.ctrlrInst.container.innerHTML) { $.fn.rc4.ctrlrInst.container.innerHTML = data; }
        if ($.fn.rc4.ctrlrInst.container.value) { $.fn.rc4.ctrlrInst.container.value = data; }
    }
})(jQuery);


/**
* jQuery.timers - Timer abstractions for jQuery
* Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
* Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
* Date: 2009/10/16
*
* @author Blair Mitchelmore
* @version 1.2
*
**/

jQuery.fn.extend({
    everyTime: function (interval, label, fn, times) {
        return this.each(function () {
            jQuery.timer.add(this, interval, label, fn, times);
        });
    },
    oneTime: function (interval, label, fn) {
        return this.each(function () {
            jQuery.timer.add(this, interval, label, fn, 1);
        });
    },
    stopTime: function (label, fn) {
        return this.each(function () {
            jQuery.timer.remove(this, label, fn);
        });
    }
});

jQuery.extend({
    timer: {
        global: [],
        guid: 1,
        dataKey: "jQuery.timer",
        regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
        powers: {
            // Yeah this is major overkill...
            'ms': 1,
            'cs': 10,
            'ds': 100,
            's': 1000,
            'das': 10000,
            'hs': 100000,
            'ks': 1000000
        },
        timeParse: function (value) {
            if (value == undefined || value == null)
                return null;
            var result = this.regex.exec(jQuery.trim(value.toString()));
            if (result[2]) {
                var num = parseFloat(result[1]);
                var mult = this.powers[result[2]] || 1;
                return num * mult;
            } else {
                return value;
            }
        },
        add: function (element, interval, label, fn, times) {
            var counter = 0;

            if (jQuery.isFunction(label)) {
                if (!times)
                    times = fn;
                fn = label;
                label = interval;
            }

            interval = jQuery.timer.timeParse(interval);

            if (typeof interval != 'number' || isNaN(interval) || interval < 0)
                return;

            if (typeof times != 'number' || isNaN(times) || times < 0)
                times = 0;

            times = times || 0;

            var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});

            if (!timers[label])
                timers[label] = {};

            fn.timerID = fn.timerID || this.guid++;

            var handler = function () {
                if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
                    jQuery.timer.remove(element, label, fn);
            };

            handler.timerID = fn.timerID;

            if (!timers[label][fn.timerID])
                timers[label][fn.timerID] = window.setInterval(handler, interval);

            this.global.push(element);

        },
        remove: function (element, label, fn) {
            var timers = jQuery.data(element, this.dataKey), ret;

            if (timers) {

                if (!label) {
                    for (label in timers)
                        this.remove(element, label, fn);
                } else if (timers[label]) {
                    if (fn) {
                        if (fn.timerID) {
                            window.clearInterval(timers[label][fn.timerID]);
                            delete timers[label][fn.timerID];
                        }
                    } else {
                        for (var fn in timers[label]) {
                            window.clearInterval(timers[label][fn]);
                            delete timers[label][fn];
                        }
                    }

                    for (ret in timers[label]) break;
                    if (!ret) {
                        ret = null;
                        delete timers[label];
                    }
                }

                for (ret in timers) break;
                if (!ret)
                    jQuery.removeData(element, this.dataKey);
            }
        }
    }
});

jQuery(window).bind("unload", function () {
    jQuery.each(jQuery.timer.global, function (index, item) {
        jQuery.timer.remove(item);
    });
});

// end jQuery.timers



/**
* JSON to XML jQuery plugin. Provides quick way to convert JSON object to XML 
* string. To some extent, allows control over XML output.
* Just as jQuery itself, this plugin is released under both MIT & GPL licences.
* 
* @version 1.02
* @author Micha³ Korecki, www.michalkorecki.com
*/
(function ($) {
    /**
    * Converts JSON object to XML string.
    * 
    * @param json object to convert
    * @param options additional parameters 
    * @return XML string 
    */
    $.json2xml = function (json, options) {
        settings = {};
        settings = $.extend(true, settings, defaultSettings, options || {});
        return convertToXml(json, settings.rootTagName, '', 0);
    };

    var defaultSettings = {
        formatOutput: false,
        formatTextNodes: false,
        indentString: '',
        rootTagName: 'root',
        ignore: [],
        replace: [],
        nodes: [],
        ///TODO: exceptions system
        exceptions: []
    };

    /**
    * This is actual settings object used throught plugin, default settings
    * are stored separately to prevent overriding when using multiple times.
    */
    var settings = {};

    /**
    * Core function parsing JSON to XML. It iterates over object properties and
    * creates XML attributes appended to main tag, if property is primitive 
    * value (eg. string, number).
    * Otherwise, if it's array or object, new node is created and appened to
    * parent tag. 
    * You can alter this behaviour by providing values in settings.ignore, 
    * settings.replace and settings.nodes arrays. 
    * 
    * @param json object to parse
    * @param tagName name of tag created for parsed object
    * @param parentPath path to properly identify elements in ignore, replace 
    * 	      and nodes arrays
    * @param depth current element's depth 
    * @return XML string
    */
    var convertToXml = function (json, tagName, parentPath, depth) {
        var suffix = (settings.formatOutput) ? '\r\n' : '';
        var indent = (settings.formatOutput) ? getIndent(depth) : '';
        var xmlTag = indent + '<' + tagName;
        var children = '';

        for (var key in json) {
            if (json.hasOwnProperty(key)) {
                var propertyPath = parentPath + key;
                var propertyName = getPropertyName(parentPath, key);
                // element not in ignore array, process
                if ($.inArray(propertyPath, settings.ignore) == -1) {
                    // array, create new child element
                    if ($.isArray(json[key])) {
                        children += createNodeFromArray(json[key], propertyName,
								propertyPath + '.', depth + 1, suffix);
                    }
                    // object, new child element aswell
                    else if (typeof (json[key]) === 'object') {
                        children += convertToXml(json[key], propertyName,
								propertyPath + '.', depth + 1);
                    }
                    // primitive value property as attribute
                    else {
                        // unless it's explicitly defined it should be node
                        if ($.inArray(propertyPath, settings.nodes) != -1) {
                            children += createTextNode(propertyName, json[key],
									depth, suffix);
                        }
                        else {
                            xmlTag += ' ' + propertyName + '="' + json[key].replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') + '"';
                        }
                    }
                }
            }
        }
        // close tag properly
        if (children !== '') {
            xmlTag += '>' + suffix + children + indent + '</' + tagName + '>' + suffix;
        }
        else {
            xmlTag += '/>' + suffix;
        }
        return xmlTag;
    };


    /**
    * Creates indent string for provided depth value. See settings for details.
    * 
    * @param depth
    * @return indent string 
    */
    var getIndent = function (depth) {
        var output = '';
        for (var i = 0; i < depth; i++) {
            output += settings.indentString;
        }
        return output;
    };


    /**
    * Checks settings.replace array for provided name, if it exists returns
    * replacement name. Else, original name is returned.
    * 
    * @param parentPath path to this element's parent
    * @param name name of element to look up
    * @return element's final name
    */
    var getPropertyName = function (parentPath, name) {
        var index = settings.replace.length;
        var searchName = parentPath + name;
        while (index--) {
            // settings.replace array consists of {original : replacement} 
            // objects 
            if (settings.replace[index].hasOwnProperty(searchName)) {
                return settings.replace[index][searchName];
            }
        }
        return name;
    };

    /**
    * Creates XML node from javascript array object.
    * 
    * @param source 
    * @param name XML element name
    * @param path parent element path string
    * @param depth
    * @param suffix node suffix (whether to format output or not)
    * @return XML tag string for provided array
    */
    var createNodeFromArray = function (source, name, path, depth, suffix) {
        var xmlNode = '';
        if (source.length > 0) {
            for (var index in source) {
                // array's element isn't object - it's primitive value, which
                // means array might need to be converted to text nodes
                if (typeof (source[index]) !== 'object') {
                    // empty strings will be converted to empty nodes
                    if (source[index] === "") {
                        xmlNode += getIndent(depth) + '<' + name + '/>' + suffix;
                    }
                    else {
                        var textPrefix = (settings.formatTextNodes)
                    ? suffix + getIndent(depth + 1) : '';
                        var textSuffix = (settings.formatTextNodes)
        					? suffix + getIndent(depth) : '';
                        xmlNode += getIndent(depth) + '<' + name + '>'
	                			+ textPrefix + source[index] + textSuffix
	                			+ '</' + name + '>' + suffix;
                    }
                }
                // else regular conversion applies
                else {
                    xmlNode += convertToXml(source[index], name, path, depth);
                }
            }
        }
        // array is empty, also creating empty XML node		
        else {
            xmlNode += getIndent(depth) + '<' + name + '/>' + suffix;
        }
        return xmlNode;
    };

    /**
    * Creates node containing text only.
    * 
    * @param name node's name
    * @param text node text string
    * @param parentDepth this node's parent element depth
    * @param suffix node suffix (whether to format output or not)
    * @return XML tag string
    */
    var createTextNode = function (name, text, parentDepth, suffix) {
        // unformatted text node: <node>value</node>
        // formatting includes value indentation and new lines
        var textPrefix = (settings.formatTextNodes)
			? suffix + getIndent(parentDepth + 2) : '';
        var textSuffix = (settings.formatTextNodes)
			? suffix + getIndent(parentDepth + 1) : '';
        var xmlNode = getIndent(parentDepth + 1) + '<' + name + '>'
					+ textPrefix + text + textSuffix
					+ '</' + name + '>' + suffix;
        return xmlNode;
    };
})(jQuery);

// JSON to XML jQuery plugin ends.

