/*!
 * AskiaVista AJAX
 *
 * Copyright (c) Askia 2017
 * Under the AskiaVistaSDK license
 *
 * Author: Mamadou Sy
 *
 * Version 2.2.6 (09-NAR-2017)
 *      + Issue #7624: `Total response` options (in surveySettings and in xTab question)
 *                     Add `groupAll` option in xTab response to automatically group all responses
 *      + Issue #7480: Add error messages for the password quality.
 *      + Issue #7513: Add calculation option to run totals in sub level
 *
 * Version 2.2.5 (15-SEP-2016)
 *      + Feature #7218: Add getActivityStats() method to obtain statistics on the activity
 *                       Add the getActivityFilters() method to obtain the possible list of filters for the activity
 *                       Implements the filtering on the getActivity()
 *                       Add the 'activityStats' in the exportTo method
 *      + Issue #6880: Add nested in xTab.settings.edges
 *      + Don't send null or undefined query parameters (this is a tip to remove key using the replay plugin)
 *      + Start using an internal utilities instead of jQuery
 *      + The cookie management is now builtin, we no longer deals with the jQuery.cookie plugin
 *      + [DEPRECATED] jQuery.cookie plugin is no longer used
 *
 * Version 2.2.4 (18-NOV-2015)
 *      + Issue #6933: Add the new method `validateCleanupScript` to validate the cleanup script
 *      + Issue #6933: Take in accounts the `cleanupScript` key to clean-up a table
 *      + Issue #6934: New authorizations for the `general` section (title, topLeftCell, footnote, transposeTable, transposeChart, singlePage, superpose, cleanupScript)
 *      + Fix #6525: Bad escaping/encoding (" is transform to ") while submitting the query using a form
 *                   Use a plain DHTML fashion to have the benefits of the native escaping/encoding
 *
 * Version 2.2.3 (16-JUN-2015)
 *      + Add appName, appVersion in the config
 *      + Send the current ajaxApiVersion and the client timeOffset to the server-side
 *      + Add methods getActivity
 *      + Add new entity 'activity' for export to Excel
 *      + Take in account the sub-population while exporting portfolio / portfolio items to Excel
 *
 * Version 2.2.2 (14-APR-2015)
 *      + Update of pagination / highcharts plugins
 *
 * Version 2.2.1 (08-MAR-2015)
 *      + SSO management working with AskiaVistaSSO Web Service
 *      + Add verbosity on getQuestions from profile
 *
 *
 * Version 2.2.0 (27-NOV-2014)
 *      + Allows the usage of object for the survey parameter (fix the bug when the name of the survey is a number)
 *      + Add 'footnote' parameter in cross-tab query (settings.results.footnote)
 *      + Add 'language' parameter in queries to specify the survey language.
 *          It could also be add on the config, or specify via url
 *      + Add a new 'languageUrlParam' in the configuration to read the survey language via the URL
 *      + Add a dedicated exception severity flag when the authenticity token in cookie is bad or obsolete,
 *          it then ask again the login form
 *      + Add methods getPortfolioLinks, getPortfolioLink, savePortfolioLink, deletePortfolioLink,
 *          getPortfolioLinkLayouts,
 *          getPortfolioLinkThemes, savePortfolioLinkTheme, deletePortfolioLinkTheme
 *           getResources, saveResource, deleteResource,
 *           htmlEncode
 *      + Add the 'baseUrl' key in the config
 *      + Manage the new 'rawdata' and 'sectionpage' portfolio item type
 *      + Manage severity on server-side error to throw the securityError when it's needed
 *      + Error messages are now htmlEncoded in the client side.
 *      + Security error don't block the query stack, it now fire the security error and the regular error event
 *
 * Version 2.1.0 (15-JAN-2014)
 *      + Add methods getSubPopulation, saveTabStyle, deleteTabStyle, saveChartTemplate, deleteChartTemplate
 *      + Add parameter `fileNameFromTitle` for the export
 *      + Add management of the tab-style export
 *      + Add management of the chart template export
 *      + Add management of queries through iFrame
 *      + Add timer management: timer object in queries and methods startTimers, stopTimers, clearTimers
 * Version 2.1.0.beta (09-APR-2013)
 *      + Add method getLanguages
 *      + Add method getSharings, saveSharing, deleteSharing, getContacts, getSurveySettings, saveSurveySettings
 *      + Add method getPortfolioToken
 *      + Add the flag 'temporary' to save a temporary sub-population
 *		+ Allow to create sub-population for each responses in the specified question
 *      + Add the method validateCalculatedQuestion
 *		+ Add the method exportTo to export 'crosstab', 'portfolio' to Excel document
 *		+ Add the method download to download a file through a fake of AJAX request (using form)
 *		+ Make the method sanitizeQuery public
 *		+ Add the method getPortfolio to obtain information of a single portfolio
 *		+ Add the method 'logout'
 *		+ Deals with the new options 'singlePage' and do the merge all pages in the client-side
 *		+ Add options.chart in getPages() and display() with the definition of the chart when using javascript chart
 *		+ Add the method getPlugin(name) (Public now)
 *		+ Use the config of the require to load the right config in AMD
 *		+ Add a new dataType in AJAX to loadLocale and execute it
 *		+ Implements the ranking options for the calculation in the server-side
 *		+ Add methods: getUserInfo(), saveUserInfo()
 *		+ Use define() of CommonJS when it exist
 *		+ Add an xhr object in the query to allow developer to abort the query
 *		+ Load the tabstyle automatically (in server-side the tabstyle is now a .less file)
 *		+ Works with the new HTML table strucutre (implements colgroup, col, caption, thead, th, tbody, tfoot)
 *		+ Implements the tabStyle parameter
 *		+ Allow to add more global parameters in config: settings, calculations, chart, tabStyle, subPopulation, waves, universe,
 *      weighting, level, title, width, height
 *		+ Add methods : loadStylesheet()
 *		+ Add the verbose options on getSubPopulations to obtain the definition
 *		+ Add the verbose options on getCalulatedQuestions to obtain the definition
 *		+ Add the verbose options on getProfiles to obtain the definition
 *		+ Add the verbose options on getXTabSettings to obtain the definition
 *		+ Add ability to make the script asynchronous with the async : false parameter
 *		+ Add the methods: saveSubPopulation, deleteSubPopulation, validateScript, saveCalculatedQuestion, deleteCalculatedQuestion
 *			saveProfile, deleteProfile, saveXTabSettings, deleteXTabSettings, getPortfolioItem, savePortfolioItem, deletePortfolioItem,
 *			savePortfolio, deletePortfolio
 *		+ Add the options parameters on the callback success
 *		+ Remove the key '__create_json_chart__' in favor of the chart definition stringify and encapsulate into string
 *		+ Expose the methods executeSuccess, executeError in order to execute the action with all associated plugins
 *		+ Add the methods doTransaction to execute multiple query in a single query transaction
 *
 * Version 2.0.2 (12-OCT-2011)
 *		+ Add the 'recursive' parameter in getQuestions() to obtain the entire survey structure
 *		+ New JSON format of responses and waves
 *		+ Management of the calculations
 *			> New JSON format of the getCalculations response
 *			> The key calculations could be an array with the properties for the calculations
 *		+ Improve getPages
 *			> Manage the keys containerId and loadingMessage like the display method
 *			> The key format could a regular string or a has object with { table : "html", chart : "json" }
 *		+ Add a new public method displayResult(data, query, [index]) used to display the result of the display() method and the getPages() method
 *		+ Use jQuery version 1.6.4
 *		+ Add methods: getInterviews()
 *		+ Add the 'verbose' attribute in getResponses() to obtain the list of response with the count
 *			(run a flat count in background to obtain the list according to the settings of the users)
 *		+ Add the 'parentNode' attribute in getQuestions() to obtain the questions in the treeview node
 *		+ Creates temporary sub-population
 *		+ The keys rows, columns, edges, settings could be send in JSON format. That allow us to send properties and responses of the questions
 *		+ Read the 'locale' url parameter to load locale (add more keys in the config)
 *		+ Fix an issue with loadLocale, all locale files are now be load before the first action
 *		+ Includes the json2.js of Douglas Crockford (http://www.JSON.org/json2.js)
 *		+ Code validates by jsHint with the strict mode *use strict"
 *
 * Version 2.0.1 (25-NOV-2010)
 *		+ Big improvement of the structure and the syntax of the code (refactoring to use the javascript best practice)
 *			> No longer eval, no private variable with the dangling '_', usage of === and !=== instead of == and !=, make all statements in a {}, usage of a single var per scope...
 *			> Only expose public methods and members
 *		+ Code validates by jsLint
 *		+ Improve the plugins registration and management
 *		+ Improve the queries stack management
 *		+ Improve the management of plugins: before > base action > after (for Success, Error, Abort, securityError)
 *		+ Improve the method about() to manage the global about or per plugin
 *		+ Add the format parameter to obtain the cross-tab in JSON
 *		+ Management of chart plugins using the draw() method
 *		+ Add methods: getPages()(with is verbose option), help(), addPlugin(),extend(), loadLocale(), translate()
 *		+ Add methods in plugin: translate() => To translate the locale of plugin, about() => specific to the plugin
 *		+ Add the 'locale' in the config to manage the translation
 *		+ Add the 'survey' in the config to use as default survey (preserve the DRY principle)
 *		+ Add properties: action, parameter
 *		+ Rename 'params' to 'query' to be more understandable
 *		+ Add the loadingMessage options in the display() method.
 *		- [DEPRECATED] declarePlugin()
 *
 * Version 2.00 (22-SEP-2010)
 *		+ Improve the management of query stack
 *		+ Dynamic creation of methods in askiaVista
 *		+ Add a security frame using the authenticity token, allowed domains and the login form
 *		+ Implement the MoonWalk(c)Askia encryption algorithm for the login
 *		+ Manage the authenticity token accross pages using a cookie (require the cookie plugin)
 *		+ extend jQuery with getUrlParameter() method
 *		+ Implement the callbacks methods for success and error as a method parameter
 *		+ Add methods: login(), getSurveys(), getProfiles(), getQuestions(), getResponses(), getSubPopulations(), getUniverses(),
 *				getLevels(), getWeightings(), getWaves(), getCalculatedQuestions(), getXTabSettings(), getPortfolios(), getChartTemplates(), getTabStyles(),
 *				getPortfolioItems(), getCalculations(), search(), config(), version(), about(), declarePlugin(),encrypt()
 *		- [DEPRECATED] getProfile(), getProfileCallBack(), askiaSettings
 *
 * Version 1.00 (16-APR-2010)
 *		+ Implements object askiaSettings, askiaVista and the query stack management
 *		+ Display a cross-tab in HTML format
 *		+ Get the list of questions in a given profile
 *
 * #requires jQuery v1.4.1 or later
 * #requires jquery.blockUI.js for the default Login form
 * #requires jquery.cookie.js to store the cookie authentication token
 *
 */

(function (window, $) {
    "use strict";

    // PRIVATES
    var document = window.document,
        infos,
        action,
        parameters,
        entities,
        configuration,
        timers,
        plugins,
        queries,
        XHR,
        IFrame,
        core,
        htmlEncoder,
        util,
        dom,
        initializing = true;

    // Constants to manage the exception severity
    var INVALID_AUTHENTICITY_TOKEN_EXCEPTION = 1,
        SECURITY_EXCEPTION = 10;


    // Meta information
    infos = {
        // Current plugin version
        version: '2.2.6',
        // Help url
        helpUrl: "http://www.askia.com/Downloads/dev/docs/AskiaVistaAJAX/index.html",
        // Help url of jQuery
        jqueryHelpUrl: "http://docs.jquery.com",
        // Dependencies
        dependencies: [{ name: 'jquery', version: '>=1.5.2'}],
        // Time offset
        timeOffset : ((new Date().getTimezoneOffset() / 60) * -1)
    };


    /**
     * Enumerates all available action available through askiaVista.
     *
     * @member askiaVista
     * @property {askiaVista.enumerators.action} action
     * @static
     * @readonly
     */
    /**
     * # Enumeration of actions
     *
     * Enumerates all available action available through askiaVista.
     *
     * Accessible via
     *    
     *      askiaVista.action
     *
     * While a query is done by askiaVista, it add an extra `action` key in the query itself
     * to make the context in the callback more clear.
     *
     *      askiaVista.display({
     *           success : function (data, query) {
     *              console.log(query.action);
     *              // => 'display'
     *           }
     *      });
     *
     *      askiaVista.getSubPopulations({
     *           success : function (data, query) {
     *              console.log(query.action);
     *              // => 'getSubPopulations'
     *           }
     *      });
     *
     * @enum askiaVista.enumerators.action
     * @protected
     */
    action = {
        /**
         * Action to log-in the user
         *
         * Also see: askiaVista#login
         */
         login: "login",

        /**
         * Action to log-out the user
         *
         * Also see: askiaVista#logout
         * @since 2.1.0
         */
         logout: "logout",

        /**
         * Execute the query to obtain the information of the current authenticated user.
         *
         * This method is only available when the user is explicitly authenticated, otherwise it raise an error.
         * This method as all others could fire the `config.showLoginForm` if the user is not authenticated.
         *
         * If you want to ensure that a user is explicitly authenticated, you can first call this method and use is success
         * to load the rest of your page.
         *
         *
         *       // Get the information of the current authenticated user
         *       askiaVista.getUserInfo({
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method getUserInfo
         * @static
         * @since 2.1.0
         * @param {askiaVista.queries.get.userInfo} query Query to obtain the user information
         */
        /**
         * Action to obtain the information of the current authenticated user.
         *
         * Also see: askiaVista#getUserInfo
         */
        getUserInfo: "getUserInfo",

        // TODO::Document
        // Save the information of the current user
        saveUserInfo : "saveUserInfo",

        /**
         * Execute a cross-tab and display the result
         *
         * @member askiaVista
         * @method display
         * @static
         * @param {askiaVista.queries.xTab} query Cross-tab query
         */
        /**
         * Action to execute a cross-tab and display the result
         *
         * Also see: askiaVista#display
         */
         display: "display",

        /**
         * Execute the query to obtain the list of the entire list of questions or the list of questions within the specified profile.
         *
         *       // Get the entire list of questions
         *       askiaVista.getQuestions({
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the list of questions from the specified profile
         *       askiaVista.getQuestions({
         *            profile : "CSP",
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method getQuestions
         * @static
         * @param {askiaVista.queries.get.questions} query Query to obtain the list of questions.
         */
        /**
         * Action to obtain the entire list of questions or the questions from given profile
         *
         * Also see: askiaVista#getQuestions
         */
         getQuestions: "getQuestions",

        /**
         * Execute the query to obtain the responses of the specified question.
         *
         * This method can returns the responses of the specified question in the specified profile.<br />
         * If the question is specified several times in the profile, it will returns the responses of the first found question.
         *
         *       // Get the list of responses
         *       askiaVista.getResponses({
         *            survey  : "EX",
         *            question : "gender",
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the responses of the specified question in the profile
         *       askiaVista.getResponses({
         *            survey  : "EX",
         *            profile : "CSP",
         *            question : "gender",
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the responses with the count
         *       askiaVista.getResponses({
         *           question : "gender",
         *           verbose : true,
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method getResponses
         * @static
         * @param {askiaVista.queries.get.responses} query Query to obtain the list of responses.
         */
        /**
         * Action to obtain the responses of a given question
         *
         * Also see: askiaVista#getResponses
         */
         getResponses: "getResponses",

        /**
         * Execute the query to obtain the languages of the survey
         *
         *       // Get the languages of the survey
         *       askiaVista.getLanguages({
         *            survey  : "EX",
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method getLanguages
         * @static
         * @since 2.1.0
         * @param {askiaVista.queries.get.languages} query Query to obtain the langauges of the survey
         */
        /**
         * Action to obtain the languages of the survey
         *
         * Also see: askiaVista#getLanguages
         * @since 2.1.0
         */
         getLanguages : "getLanguages",

        /**
         * Execute the query to obtain the list of the surveys available for the current user.
         *
         *       // Get the list of the surveys
         *       askiaVista.getSurveys({
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method getSurveys
         * @static
         * @param {askiaVista.queries.get.surveys} query Query to obtain the list of surveys.
         */
        /**
         * Action to obtain the list of surveys
         *
         * Also see: askiaVista#getSurveys
         */
         getSurveys: "getSurveys",


        /**
         * Execute the query to obtain the status of the survey
         *
         *       // Get the status of the survey
         *       askiaVista.getSurveyStatus({
         *            survey  : "EX",
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method getSurveyStatus
         * @static
         * @since 2.1.0
         * @param {askiaVista.queries.get.surveyStatus} query Query to obtain the status of the survey
         */
        /**
         * Action to obtain the status of the survey
         *
         * Also see: askiaVista#getSurveyStatus
         * @since 2.1.0
         */
         getSurveyStatus : "getSurveyStatus",

        /**
         * Execute the query to obtain the settings of the survey
         *
         *       // Get the settings of the survey
         *       askiaVista.getSurveySettings({
         *            survey  : "EX",
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method getSurveySettings
         * @static
         * @since 2.1.0
         * @param {askiaVista.queries.get.surveySettings} query Query to obtain the settings of the survey
         */
        /**
         * Action to obtain the settings of the survey
         *
         * Also see: askiaVista#getSurveySettings
         * @since 2.1.0
         */
         getSurveySettings : "getSurveySettings",

        // TODO::Document
        // Save the settings of the survey
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method saveSurveySettings
         * @static
         * @since 2.1.0
         * @param query
         */
         saveSurveySettings : "saveSurveySettings",

        /**
         * Execute the query to obtain the list of profiles of questions
         *
         *       // Get the profiles of questions
         *       askiaVista.getProfiles({
         *            survey : "EX",
		 *            verbose : true,
		 *            success : function (data, query) {
		 *               console.log(JSON.parse(data));
		 *            },
		 *            error : function (message, query) {
		 *                alert(message);
		 *            }
		 *       });
         *
         * @member askiaVista
         * @method getProfiles
         * @static
         * @param {askiaVista.queries.get.profiles} query Query to obtain the list of profiles of questions
         */
        /**
         * Action to obtain the list of profiles of questions
         *
         * Also see: askiaVista#getProfiles
         */
         getProfiles: "getProfiles",

        // TODO::Document
        // Save a profile
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method saveProfile
         * @static
         * @since 2.1.0
         * @param query
         */
         saveProfile: "saveProfile",

        // TODO::Document
        // Delete a profile
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method deleteProfile
         * @static
         * @since 2.1.0
         * @param query
         */
         deleteProfile: "deleteProfile",

		/**
		 * Execute the query to obtain the specified sub-population
		 *
		 *       // Get the definition of the sub-population
		 *       askiaVista.getSubPopulation({
		 *            id      : 1, 
		 *            verbose : true,
		 *            success : function (data, query) {
		 *               console.log(JSON.parse(data));
		 *            },
		 *            error : function (message, query) {
		 *                alert(message);
		 *            }
		 *       });
		 *
		 * @member askiaVista
		 * @method getSubPopulation
		 * @static
		 * @param {askiaVista.queries.get.subPopulation} query Query to obtain the specified of sub-population.
		 */
		/**
		 * Action to obtain the specified sub-population (filter).
		 *
		 * Also see: askiaVista#getSubPopulation
		 */
         getSubPopulation : "getSubPopulation",

		/**
		 * Execute the query to obtain the list of the sub-populations (filters) created in AskiaVista and available for the current user.
		 *
		 *       // Get the list of the sub-populations
		 *       askiaVista.getSubPopulations({
		 *            success : function (data, query) {
		 *               console.log(JSON.parse(data));
		 *            },
		 *            error : function (message, query) {
		 *                alert(message);
		 *            }
		 *       });
		 *
		 * @member askiaVista
		 * @method getSubPopulations
		 * @static
		 * @param {askiaVista.queries.get.subPopulations} query Query to obtain the list of sub-populations.
		 */
		/**
		 * Action to obtain the list of sub-populations (filters) created in AskiaVista
		 *
		 * Also see: askiaVista#getSubPopulations
		 */
         getSubPopulations: "getSubPopulations",

        // TODO::Document
        // Save a sub-population
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method saveSubPopulation
         * @static
         * @since 2.1.0
         * @param query
         */
         saveSubPopulation: "saveSubPopulation",

        // TODO::Document
        // Delete a sub-population
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method deleteSubPopulation
         * @static
         * @since 2.1.0
         * @param query
         */
         deleteSubPopulation: "deleteSubPopulation",

        /**
         * Execute the query to obtain the list of the waves.
         * Only available for Surf file (*.qew)
         *
         *       // Get the list of waves
         *       askiaVista.getWaves({
		 *            success : function (data, query) {
		 *               console.log(JSON.parse(data));
		 *            },
		 *            error : function (message, query) {
		 *                alert(message);
		 *            }
		 *       });
         *
         * @member askiaVista
         * @method getWaves
         * @static
         * @param {askiaVista.queries.get.waves} query Query to obtain the list of waves.
         */
        /**
         * Action to obtain the list of waves
         *
         * Also see: askiaVista#getWaves
         */
         getWaves: "getWaves",

        /**
         * Execute the query to obtain the list of the universes.
         *
         *       // Get the list of universes
         *       askiaVista.getUniverses({
		 *            success : function (data, query) {
		 *               console.log(JSON.parse(data));
		 *            },
		 *            error : function (message, query) {
		 *                alert(message);
		 *            }
		 *       });
         *
         * @member askiaVista
         * @method getUniverses
         * @static
         * @param {askiaVista.queries.get.universes} query Query to obtain the list of universes.
         */
        /**
         * Action to obtain the list of universes
         *
         * Also see: askiaVista#getUniverses
         */
         getUniverses: "getUniverses",

        /**
         * Execute the query to obtain the list of the weightings.
         *
         *       // Get the list of weightings
         *       askiaVista.getWeightings({
		 *            success : function (data, query) {
		 *               console.log(JSON.parse(data));
		 *            },
		 *            error : function (message, query) {
		 *                alert(message);
		 *            }
		 *       });
         *
         * @member askiaVista
         * @method getWeightings
         * @static
         * @param {askiaVista.queries.get.weightings} query Query to obtain the list of weightings.
         */
        /**
         * Action to obtain the list of weightings
         *
         * Also see: askiaVista#getWeightings
         */
         getWeightings: "getWeightings",

		/**
		 * Execute the query to obtain the list of the survey loop levels.
		 *
		 *       // Get the list of the levels
		 *       askiaVista.getLevels({
		 *            success : function (data, query) {
		 *               console.log(JSON.parse(data));
		 *            },
		 *            error : function (message, query) {
		 *                alert(message);
		 *            }
		 *       });
		 *
		 * @member askiaVista
		 * @method getLevels
		 * @static
		 * @param {askiaVista.queries.get.levels} query Query to obtain the list of survey loop levels.
		 */
		/**
		 * Action to obtain the list of survey loop levels
		 *
		 * Also see: askiaVista#getLevels
		 */
         getLevels: "getLevels",

        /**
         * Execute the query to obtain the list of the chart templates available for the current user.
         *
         *       // Get the list of the chart templates
         *       askiaVista.getChartTemplates({
         *            verbose : true,
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method getChartTemplates
         * @static
         * @param {askiaVista.queries.get.chartTemplates} query Query to obtain the list of chart templates.
         */
        /**
         * Action to obtain the list of chart templates available for the current user
         *
         * Also see: askiaVista#getChartTemplates
         */
         getChartTemplates: "getChartTemplates",

        // TODO::Document
        // Save a chart template
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method saveChartTemplate
         * @static
         * @since 2.1.0
         * @param query
         */
         saveChartTemplate : "saveChartTemplate",

        // TODO::Document
        // Delete a chart template
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method deleteChartTemplate
         * @static
         * @since 2.1.0
         * @param query
         */
         deleteChartTemplate : "deleteChartTemplate",

        /**
         * Execute the query to obtain the list of the table styles available for the current user.
         *
         *       // Get the list of the table styles
         *       askiaVista.getTabStyles({
         *            verbose : true,
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method getTabStyles
         * @static
         * @param {askiaVista.queries.get.tabStyles} query Query to obtain the list of table styles.
         */
        /**
         * Action to obtain the list of table styles available for the current user
         *
         * Also see: askiaVista#getTabStyles
         */
         getTabStyles: "getTabStyles",

        // TODO::Document
        // Save a tab-style
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method saveTabStyle
         * @static
         * @since 2.1.0
         * @param query
         */
         saveTabStyle : "saveTabStyle",

        // TODO::Document
        // Delete a tab-style
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method deleteTabStyle
         * @static
         * @since 2.1.0
         * @param query
         */
         deleteTabStyle : "deleteTabStyle",

        /**
         * Execute the query to obtain the list of the cross-tab settings created in AskiaVista and available for the current user.
         *
         *       // Get the list of the cross-tab settings
         *       askiaVista.getXTabSettings({
         *            survey : "EX",
         *            verbose : true,
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method getXTabSettings
         * @static
         * @param {askiaVista.queries.get.xTabSettings} query Query to obtain the list of cross-tab settings.
         */
        /**
         * Action to obtain the list of cross-tab settings created in AskiaVista and available for the current user
         *
         * Also see: askiaVista#getXTabSettings
         */
         getXTabSettings: "getXTabSettings",

        // Save a XTab settings
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method saveXTabSettings
         * @static
         * @since 2.1.0
         * @param query
         */
         saveXTabSettings: "saveXTabSettings",

        // Delete a XTab settings
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method deleteXTabSettings
         * @static
         * @since 2.1.0
         * @param query
         */
         deleteXTabSettings: "deleteXTabSettings",

        /**
         * Execute the query to obtain the specified portfolio
         *
         *       // Get the portfolio using his id
         *       askiaVista.getPortfolio({
         *            id      : 1,
         *            verbose : true,
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the portfolio by his name
         *       askiaVista.getPortfolio({
         *            name    : "CSP",
         *            verbose : true,
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the portfolio using the portfolioToken
         *       askiaVista.getPortfolio({
         *            portfolioToken   : "M8bpZj%2b%2fYMJLlj0KTkIbiktbcu4fBToYQVhDfa4p7k8%3d",
         *            verbose : true,
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the portfolio using the portfolioItemToken
         *       askiaVista.getPortfolio({
         *            portfolioItemToken   : "M8bpZj%2b%2fYMJLlj0KTkIbitd3ID7q2Kmg%2bXbWUd%2bsixHzfqBfpcoXY%2bQdBtHFRE8N",
         *            verbose : true,
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @since 2.1.0
         * @member askiaVista
         * @method getPortfolio
         * @static
         * @param {askiaVista.queries.get.portfolio} query Query to obtain the specified of portfolio
         */
        /**
         * Action to obtain the specified portfolio.
         *
         * Also see: askiaVista#getPortfolio
         * @since 2.1.0
         */
         getPortfolio: "getPortfolio",


        /**
         * Execute the query to obtain a token to access a portfolio or a portfolio token
         *
         * It is mostly use to build a restrictive page, which only
         * have an access to the portfolio/portfolio item optionally with a specific context
         *
         *       // Get the token of the portfolio by his id
         *       askiaVista.getPortfolioToken({
         *            id      : 1,
         *            success : function (data, query) {
         *               console.log('The token is:' + data);
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the token of the portfolio by his name
         *       askiaVista.getPortfolioToken({
         *            name    : "CSP",
         *            success : function (data, query) {
         *               console.log('The token is:' + data);
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the token of the portfolio item by his id
         *       askiaVista.getPortfolioToken({
         *            portfolioItem : 1,
         *            success : function (data, query) {
         *               console.log('The token is:' + data);
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the token of the portfolio item by his name
         *       askiaVista.getPortfolioToken({
         *            portfolioItem : "Gender by Age",
         *            portfolio : "CSP",
         *            success : function (data, query) {
         *               console.log('The token is:' + data);
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the token of the portfolio where all items will be filtered by a given sub-population
         *       askiaVista.getPortfolioToken({
         *            portfolio : 1,
         *            subPopulation : 'Man',
         *            success : function (data, query) {
         *               console.log('The token is:' + data);
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the token of the portfolio item filtered by a given sub-population
         *       askiaVista.getPortfolioToken({
         *            portfolioItem : 1,
         *            subPopulation : 'Man',
         *            success : function (data, query) {
         *               console.log('The token is:' + data);
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @since 2.1.0
         * @member askiaVista
         * @method getPortfolioToken
         * @static
         * @param {askiaVista.queries.get.portfolioToken} query Query to obtain the token of a portfolio or a portfolio item
         */
        /**
         * Action to obtain the token of a portfolio or a portfolio item.
         *
         * Also see: askiaVista#getPortfolioToken
         * @since 2.1.0
         */
         getPortfolioToken : "getPortfolioToken",

        /**
         * Execute the query to obtain the list of portfolios
         *
         *       // Get the portfolios
         *       askiaVista.getPortfolios({
         *            survey : "EX",
		 *            verbose : true,
		 *            success : function (data, query) {
		 *               console.log(JSON.parse(data));
		 *            },
		 *            error : function (message, query) {
		 *                alert(message);
		 *            }
		 *       });
         *
         * @member askiaVista
         * @method getPortfolios
         * @static
         * @param {askiaVista.queries.get.portfolios} query Query to obtain the list of portfolios
         */
        /**
         * Action to obtain the list of portfolios
         *
         * Also see: askiaVista#getPortfolios
         */
         getPortfolios: "getPortfolios",

        // TODO::Document
        // Save a portfolio
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method savePortfolio
         * @static
         * @since 2.1.0
         * @param query
         */
         savePortfolio: "savePortfolio",

        // TODO::Document
        // Delete a portfolio
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method deletePortfolio
         * @static
         * @since 2.1.0
         * @param query
         */
         deletePortfolio: "deletePortfolio",


        /**
         * Execute the query to obtain the list one portfolio link
         *
         *       // Get the portfolio link
         *       askiaVista.getPortfolioLink({
         *            linkId  : "AAA-BBB-CCC",
		 *            success : function (data, query) {
		 *               console.log(JSON.parse(data));
		 *            },
		 *            error : function (message, query) {
		 *                alert(message);
		 *            }
		 *       });
         *
         * @since 2.2.0
         * @member askiaVista
         * @method getPortfolioLink
         * @static
         * @param {askiaVista.queries.get.portfolioLink} query Query to obtain a list of portfolio link
         */
        /**
         * Action to obtain the a  portfolio link
         *
         * Also see: askiaVista#getPortfolioLink
         *
         * @since 2.2.0
         */
         getPortfolioLink : "getPortfolioLink",

        /**
         * Execute the query to obtain the list of portfolio links
         *
         *       // Get the portfolio links
         *       askiaVista.getPortfolioLinks({
         *            survey : "EX",
		 *            success : function (data, query) {
		 *               console.log(JSON.parse(data));
		 *            },
		 *            error : function (message, query) {
		 *                alert(message);
		 *            }
		 *       });
         *
         * @since 2.2.0
         * @member askiaVista
         * @method getPortfolioLinks
         * @static
         * @param {askiaVista.queries.get.portfolioLinks} query Query to obtain the list of portfolio links
         */
        /**
         * Action to obtain the list of portfolio links
         *
         * Also see: askiaVista#getPortfolioLinks
         *
         * @since 2.2.0
         */
        getPortfolioLinks : "getPortfolioLinks",

        // TODO::Document
        // Save a portfolio link
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method savePortfolioLink
         * @static
         * @since 2.2.0
         * @param query
         */
        savePortfolioLink: "savePortfolioLink",

        // TODO::Document
        // Delete a portfolio link
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method deletePortfolioLink
         * @static
         * @since 2.2.0
         * @param query
         */
        deletePortfolioLink: "deletePortfolioLink",

        // TODO::Document
        // Get the list of portfolio link layouts
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method getPortfolioLinkLayouts
         * @static
         * @since 2.2.0
         * @param query
         */
        getPortfolioLinkLayouts : "getPortfolioLinkLayouts",

        // TODO::Document
        // Get the list of portfolio link themes
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method getPortfolioLinkThemes
         * @static
         * @since 2.2.0
         * @param query
         */
        getPortfolioLinkThemes : "getPortfolioLinkThemes",

        // TODO::Document
        // Save a theme of portfolio link
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method savePortfolioLinkTheme
         * @static
         * @since 2.2.0
         * @param query
         */
        savePortfolioLinkTheme : "savePortfolioLinkTheme",

        // TODO::Document
        // Delete a theme of portfolio link
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method deletePortfolioLinkTheme
         * @static
         * @since 2.2.0
         * @param query
         */
        deletePortfolioLinkTheme : "deletePortfolioLinkTheme",


        /**
         * Execute the query to obtain the list of portfolio items
         *
         *       // Get the portfolio items
         *       askiaVista.getPortfolioItems({
         *            survey : "EX",
         *            portfolio : "CSP",
		 *            success : function (data, query) {
		 *               console.log(JSON.parse(data));
		 *            },
		 *            error : function (message, query) {
		 *                alert(message);
		 *            }
		 *       });
         *
         * @member askiaVista
         * @method getPortfolioItems
         * @static
         * @param {askiaVista.queries.get.portfolioItems} query Query to obtain the list of portfolio items
         */
        /**
         * Action to obtain the list of portfolio items
         *
         * Also see: askiaVista#getPortfolioItems
         */
         getPortfolioItems: "getPortfolioItems",

        /**
         * Execute the query to obtain the specified portfolio item
         *
         * Using the verbose option, you can also get the results of the portfolio as if you are calling askiaVista#getPages
         *
         *       // Get the portfolio item using his id
         *       askiaVista.getPortfolioItem({
         *            id      : 1,
         *            verbose : true,
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the portfolio item by his name in that case also specified the portfolio
         *       askiaVista.getPortfolioItem({
         *            name    : "Gender by Age",
         *            portfolio : "CSP",
         *            verbose : true,
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @since 2.1.0
         * @member askiaVista
         * @method getPortfolioItem
         * @static
         * @param {askiaVista.queries.get.portfolioItem} query Query to obtain the specified of portfolio item
         */
        /**
         * Action to obtain the specified portfolio item.
         *
         * Also see: askiaVista#getPortfolioItem
         * @since 2.1.0
         */
         getPortfolioItem: "getPortfolioItem",

        /**
         * Execute the query to create or update a portfolio item
         *
         *       // Create a portfolio item with cross-tab
         *       // Save into an existing portfolio
         *       askiaVista.savePortfolioItem({
         *            survey  : 'EX',
         *            id      : 0,
         *            portfolio : 'My existing portfolio',
         *            type    : 'xTab',
         *            name : "Cross-tab 1",
         *            definition : {
         *               rows : 'age',
         *               columns : 'gender'
         *            },
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Create a portfolio item with cross-tab
         *       // Also create new portfolio to save the item on it
         *       askiaVista.savePortfolioItem({
         *            survey  : 'EX',
         *            id      : 0,
         *            portfolio : {
         *                id   : 0,
         *                name : 'A new portfolio'
         *            },
         *            type    : 'xTab',
         *            name : "Cross-tab 1",
         *            definition : {
         *               rows : 'age',
         *               columns : 'gender'
         *            },
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Create a portfolio item with raw-data
         *       // Since 2.2.0
         *       askiaVista.savePortfolioItem({
         *            survey  : 'EX',
         *            id      : 0,
         *            portfolio : 'My existing portfolio'
         *            type    : 'rawData',
         *            name : "Raw-data 1",
         *            definition : {
         *               questions  : ['gender', 'age', 'appreciation', 'comment']
         *            },
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Create a portfolio item with section page
         *       // Since 2.2.0
         *       askiaVista.savePortfolioItem({
         *            survey  : 'EX',
         *            id      : 0,
         *            portfolio : 'My existing portfolio'
         *            type    : 'sectionPage',
         *            caption : "Section page",
         *            definition : '<h1>Welcome to the portfolio</h1>...',
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method savePortfolioItem
         * @static
         * @since 2.1.0
         * @param {askiaVista.queries.save.portfolioItem} query
         */
        /**
         * Action to create or update a portfolio item
         *
         * Also see: askiaVista#savePortfolioItem
         * @since 2.1.0
         */
         savePortfolioItem: "savePortfolioItem",


        /**
         * Execute the query to re-order portfolio items
         *
         *       // Move portfolio items at the first position
         *       askiaVista.movePortfolioItems({
         *            survey  : 'EX',
         *            portfolio : 'My portfolio',
         *            items   : ['item 4', 'item 5', 'item 6'],
         *            before  : 'firstItem',
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Move portfolio items at the latest position
         *       askiaVista.movePortfolioItems({
         *            survey  : 'EX',
         *            portfolio : 'My portfolio',
         *            items     : ['item 1', 'item 2'],
         *            after   : 'lastItem',
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Move portfolio items after a given item
         *       askiaVista.movePortfolioItems({
         *            survey  : 'EX',
         *            portfolio : 'My portfolio'
         *            items   : ['item 3', 'item 7']
         *            after   : 'item 9',
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Move portfolio items before a given item
         *       askiaVista.movePortfolioItems({
         *            survey  : 'EX',
         *            portfolio : 'My portfolio'
         *            items   : ['item 12', 'item 15']
         *            before  : 'item 9',
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method movePortfolioItems
         * @static
         * @since 2.2.0
         * @param {askiaVista.queries.move.portfolioItems} query
         */
        /**
         * Action to re-order the portfolio items
         *
         * Also see: askiaVista#movePortfolioItems
         * @since 2.2.0
         */
         movePortfolioItems : "movePortfolioItems",

        // TODO::Document
        // Delete a portfolio item
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method deletePortfolioItem
         * @static
         * @since 2.1.0
         * @param query
         */
         deletePortfolioItem: "deletePortfolioItem",

        /**
         * Execute the query to obtain the list of the calculated questions created in AskiaVista and available for the current user.
         *
         *       // Get the list of the calculated questions
         *       askiaVista.getCalculatedQuestions({
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method getCalculatedQuestions
         * @static
         * @param {askiaVista.queries.get.calculatedQuestions} query Query to obtain the list of calculated questions.
         */
        /**
         * Action to obtain the list of calculated questions created in AskiaVista
         *
         * Also see: askiaVista#getCalculatedQuestions
         */
         getCalculatedQuestions: "getCalculatedQuestions",

        /**
         * Execute the query to create or update a calculated question
         *
         *       // Create a numeric calculated question
         *       askiaVista.saveCalculatedQuestion({
         *            id      : 0,
         *            caption : "Man less than 25",
         *            script : "??gender?? has {1} and ??age?? has {1}",
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Create a closed calculated question
         *       askiaVista.saveCalculatedQuestion({
         *            id      : 0,
         *            caption : "Gender by age",
         *            responses : [
         *               {
         *                  name : "Man less than 25",
         *                  definition : "??gender?? has {1} and ??age?? has {1}"
         *               },
         *               {
         *                  name : "Man 25-34",
         *                  definition : "??gender?? has {1} and ??age?? has {2}"
         *               },
         *               {
         *                  name : "Woman less than 25",
         *                  definition : "??gender?? has {2} and ??age?? has {1}"
         *               },
         *               {
         *                  name : "Woman 25-34",
         *                  definition : "??gender?? has {2} and ??age?? has {2}"
         *               }
         *            ],
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method saveCalculatedQuestion
         * @static
         * @since 2.1.0
         * @param {askiaVista.queries.save.calculatedQuestion} query
         */
        /**
         * Action to create or update a calculated question
         *
         * Also see: askiaVista#saveCalculatedQuestion
         * @since 2.1.0
         */
         saveCalculatedQuestion: "saveCalculatedQuestion",

        /**
         * Execute a query to validate the definition of a calculated question.
         *
         *       // Validate a closed calculated question
         *       askiaVista.validateCalculatedQuestion({
         *            responses : [
         *               {
         *                  name : "Man less than 25",
         *                  definition : "??gender?? has {1} and ??age?? has {1}"
         *               },
         *               {
         *                  name : "Man 25-34",
         *                  definition : "??gender?? has {1} and ??age?? has {2}"
         *               },
         *               {
         *                  name : "Woman less than 25",
         *                  definition : "??gender?? has {2} and ??age?? has {1}"
         *               },
         *               {
         *                  name : "Woman 25-34",
         *                  definition : "??gender?? has {2} and ??age?? has {2}"
         *               }
         *            ],
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Validate a numeric calculated question
         *       askiaVista.validateCalculatedQuestion({
         *            definition : "??gender has {1} and ??age?? has {1;2;3}",
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method validateCalculatedQuestion
         * @static
         * @since 2.1.0
         *
         * @param {askiaVista.queries.validate.calculatedQuestion} query
         */
        /**
         * Action to validate a calculated question
         *
         * Also see: askiaVista#validateCalculatedQuestion
         */
         validateCalculatedQuestion: "validateCalculatedQuestion",

        // TODO::Document
        // Delete a calculated question
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method deleteCalculatedQuestion
         * @static
         * @since 2.1.0
         * @param query
         */
         deleteCalculatedQuestion: "deleteCalculatedQuestion",

        /**
         * Execute a query to validate the script or the base script of a calculation.
         *
         *       // Validate a calculation
         *       askiaVista.validateCalculation({
         *            index  : 2,
         *            type   : 'script',
         *            calculations    : [
         *              0, 1, {
         *                  code : 711,
         *                  name : "Arithmetic Script (Number)",
         *                  script : "({1} + {2}) / 2"
         *              }
         *            ],
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method validateCalculation
         * @static
         * @since 2.2.0
         *
         * @param {askiaVista.queries.validate.calculation} query
         */
        /**
         * Action to validate the script or the base script of a calculation
         *
         * Also see: askiaVista#validateCalculation
         */
        validateCalculation : "validateCalculation",

        /**
         * Execute the query to obtain the list of the calculations
         *
         * There is several list of calculations:
         *
         * * Default list of calculations
         * * List of calculations from a cross-tab settings
         * * List of all available calculations in the system
         * * List of calculations for total in rows/columns of a cross-calculation
         * * List of calculations for the advanced sort on dimension
         *
         *       // Get the default list of calculations
         *       askiaVista.getCalculations({
         *            verbose : true,
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the list of flat-calculations
         *       // For flat table: questions only in one dimension (rows)
         *       askiaVista.getCalculations({
         *            verbose : true,
         *            dimension : "flat",
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the list of cross-calculations
         *       // For cross-tab: questions in several dimensions (rows/columns/edges)
         *       askiaVista.getCalculations({
         *            verbose : true,
         *            dimension : "cross",
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the list of calculations from a cross-tab settings
         *       askiaVista.getCalculations({
         *            survey : "EX",
         *            verbose : true,
         *            settings : "Custom settings",
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       //  List of available all calculations in the system
         *       askiaVista.getCalculations({
         *            toBuild : "main",
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       //  List of calculations for total in rows/columns of a cross-calculation
         *       askiaVista.getCalculations({
         *            toBuild : "total",
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the list of calculations for the advanced sort on dimension (rows/columns/edges)
         *       askiaVista.getCalculations({
         *            toBuild : "sort",
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *
         * @member askiaVista
         * @method getCalculations
         * @static
         * @param {askiaVista.queries.get.calculations} query Query to obtain the list of calculations
         */
        /**
         * Action to obtain the list of calculations
         *
         * Also see: askiaVista#getCalculations
         */
        getCalculations: "getCalculations",

        /**
         * Execute a query to validate the definition of a calculated response.
         *
         *       // Validate a calculated response
         *       askiaVista.validateCalculatedResponse({
         *            question  : "gender",
         *            script    : "{1} + {2}"
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method validateCalculatedResponse
         * @static
         * @since 2.1.0
         *
         * @param {askiaVista.queries.validate.calculatedResponse} query
         */
        /**
         * Action to validate a calculated response
         *
         * Also see: askiaVista#validateCalculatedResponse
         */
        validateCalculatedResponse : "validateCalculatedResponse",


        /**
         * Execute a cross-tab and return the entire list of pages generated in the callback.
         * It display the first page when the containerId key is define.
         *
         * @member askiaVista
         * @method getPages
         * @static
         *
         * @param {askiaVista.queries.xTab} query Cross-tab query
         */
        /**
         * Action to obtain the list of pages generated by a cross-tab
         *
         * Also see: askiaVista#getPages
         */
        getPages: "getPages",

        /**
         * Action to load the localization files for translations
         *
         * Also see: askiaVista#loadLocale
         * @since 2.1.0
         */
        loadLocale: "loadLocale",

        /**
         * Execute the query to search questions which match the pattern.
         *
         * The search is done against all type of questions and all question captions (shortcut, analysis caption, long caption)
         *
         *       // Search the question which contains the word "appreciation"
         *       askiaVista.search({
         *            pattern : "appreciation",
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @member askiaVista
         * @method search
         * @static
         * @param {askiaVista.queries.get.search} query Query to search questions.
         */
        /**
         * Action to search questions
         *
         * Also see: askiaVista#search
         */
        search: "search",

        /**
         * Returns the raw data (non-aggregate) of the specified questions.
         *
         * This method allow the usage of all type of questions (closed, numeric, open-ended, date-time)
         *
         * For performance reason, the data returned are paginate.
         *
         *
         *       // Get the answers of the specified profile of questions
         *       // from the interviews within the specified sub-population
         *       askiaVista.getInterviews({
         *            survey        : 'EX',
         *            profile       : 'CSP'
         *            maxPerPage    : 250,
         *            page          : 3,
         *            subPopulation : 'UK'
         *       });
         *
         *       // Get the answers of the specified questions
         *       // in HTML format
         *       askiaVista.getInterviews({
         *          survey : "EX",
         *          containerId : "results",
         *          questions : ['date_of_interviews', 'gender', 'age', 'appreciation', 'comments'],
         *          maxPerPage : 250,
         *          subPopulation : 'UK',
         *          format : 'html',
         *          tabStyle : 'Default'
         *       });
         *
         *       // Get the answers of the specified questions
         *       // in HTML format, with the lazy-loading options
         *       //
         *       // The first page will returns table header, table body ...
         *       // All sub-sequent pages will only return the table rows (TR) to append in the existing table body (TBody)
         *       askiaVista.getInterviews({
         *          survey : "EX",
         *          containerId : "results",
         *          questions : ['date_of_interviews', 'gender', 'age', 'appreciation', 'comments'],
         *          maxPerPage : 250,
         *          subPopulation : 'UK',
         *          format : 'html',
         *          tabStyle : 'Default',
         *          lazyLoading : true
         *       });
         *
         * @member askiaVista
         * @method getInterviews
         * @static
         *
         * @param {askiaVista.queries.get.interviews} query
         */
        /**
         * Action to obtain the raw data interviews
         *
         * Also see: askiaVista#getInterviews
         */
        getInterviews: "getInterviews",

        /**
         * Execute the query to obtain the share options for a given item
         *
         *       // Get the share options for a sub-population
         *       askiaVista.getSharings({
         *            survey  : "EX",
         *            subPopulation : "Man",
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *       // Get the share options for a profile
         *       askiaVista.getSharings({
         *           survey : "EX",
         *           profile : 12,
         *           success : function (data, query) {
         *               console.log(JSON.parse(data));
         *           },
         *           error : function (message, query) {
         *               alert(message);
         *           }
         *       });
         *
         * @member askiaVista
         * @method getSharings
         * @static
         * @since 2.1.0
         * @param {askiaVista.queries.get.sharings} query Query to obtain the share options for a given item
         */
        /**
         * Action to obtain the share options for a given item
         *
         * Also see: askiaVista#getSharings
         * @since 2.1.0
         */
        getSharings : "getSharings",

        // TODO::Document
        // Share the specify item with the specified contacts
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method saveSharing
         * @static
         * @since 2.1.0
         * @param query
         */
        saveSharing : "saveSharing",

        // TODO::Document
        // Remove the sharing for the specify item and contacts
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method deleteSharing
         * @static
         * @since 2.1.0
         * @param query
         */
        deleteSharing : "deleteSharing",

        // TODO::Document
        // Get the list of contacts
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method getContacts
         * @static
         * @since 2.1.0
         * @param query
         */
        getContacts   : "getContacts",

        /**
         * Execute a query to validate an AskiaScript.
         *
         * Validate an AskiaScript for the sub-population (filter) or a calculated-question.
         *
         * This method returned (in the callback) the number of interviews associated with the script of the validation succeed
         *
         *       // Validate the AskiaScript
         *       askiaVista.validateScript({
         *            script : "??gender?? has {1}",
         *            success : function (data, query) {
         *               console.log(data + ' interviews');
         *            },
         *            error : function (error, query) {
         *                var obj;
         *                try {
         *                    obj = JSON.parse(error);
         *                } catch {
         *                  // Do nothing
         *                }
         *
         *                if (obj) {
         *                   alert(obj.message + ", start: " + obj.start + ", length: " + obj.length);
         *                } else {
         *                   alert(error);
         *                }
         *            }
         *       });
         *
         * @member askiaVista
         * @method validateScript
         * @static
         * @since 2.1.0
         *
         * @param {askiaVista.queries.validate.script} query
         */
        /**
         * Action to validate an AskiaScript
         *
         * Also see: askiaVista#validateScript
         * @since 2.1.0
         */
        validateScript: "validateScript",

        /**
         * Execute a query to validate the cleanup script.
         *
         * Validate the cleanup script.
         *
         *       // Validate the cleanup script
         *       askiaVista.validateCleanupScript({
         *            script : "Dim i\nFor i = CurrentTable.StartX To CurrentTable.MaxX\n  CurrentTable.GetCell(i, 2).SetText(\"Cell\" + i)\nNext",
         *            success : function (data, query) {
         *               console.log('Valid script');
         *            },
         *            error : function (error, query) {
         *                var obj;
         *                try {
         *                    obj = JSON.parse(error);
         *                } catch {
         *                  // Do nothing
         *                }
         *
         *                if (obj) {
         *                   alert(obj.message + ", start: " + obj.start + ", length: " + obj.length);
         *                } else {
         *                   alert(error);
         *                }
         *            }
         *       });
         *
         * @member askiaVista
         * @method validateCleanupScript
         * @static
         * @since 2.2.4
         *
         * @param {askiaVista.queries.validate.cleanupScript} query
         */
        /**
         * Action to validate the cleanup script
         *
         * Also see: askiaVista#validateCleanupScript
         * @since 2.2.4
         */
        validateCleanupScript : "validateCleanupScript",

        /**
         * Action to export an entity to a file to download
         *
         * Also see: askiaVista#exportTo
         * @since 2.1.0
         */
        exportTo: "exportTo",

        /**
         * Action to download a file
         *
         * Also see: askiaVista#download
         * @since 2.1.0
         */
        download: "download",

        // TODO::Document
        // Create iFrame to execute query through
        createIFrame : 'createIFrame',

        /**
         * Execute the query to obtain the list of the resources available for the current user.
         *
         *       // Get the list of the resouces
         *       askiaVista.getResources({
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @since 2.2.0
         * @member askiaVista
         * @method getResources
         * @static
         * @param {askiaVista.queries.get.resources} query Query to obtain the list of resources.
         */
        /**
         * Action to obtain the list of resources available for the current user
         *
         * Also see: askiaVista#getResources
         */
        getResources : "getResources",

        // TODO::Document
        // Save a resource
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method saveResource
         * @static
         * @since 2.2.0
         * @param query
         */
        saveResource : "saveResource",

        // TODO::Document
        // Delete a resource
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method deleteResource
         * @static
         * @since 2.2.0
         * @param query
         */
        deleteResource : "deleteResource",

        /**
         * Execute the query to obtain the raw activity records.
         *
         *       // Get the raw activity records
         *       askiaVista.getActivity({
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @since 2.2.3
         * @member askiaVista
         * @method getActivity
         * @static
         * @param {askiaVista.queries.get.activity} query Query to obtain the raw activity records.
         */
        /**
         * Action to obtain the raw activity records
         *
         * Also see: askiaVista#getActivity
         */
        getActivity    : "getActivity",

        /**
         * Execute the query to obtain statistical result on activity.
         *
         *       // Get the statistical result on activity.
         *       askiaVista.getActivityStats({
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *
         *       // Get the statistical result on activity,
         *       // for specific metrics
         *       askiaVista.getActivityStats({
         *            metrics : [
         *              "queries",                  // Counts of queries
         *              "success",                  // Counts of success
         *              "errors",                   // Counts of errors
         *              "users",                    // Counts of users
         *              "surveys",                  // Counts of surveys
         *              "avsServers",               // Counts of AVS Servers
         *              "webServers",               // Counts of Web Servers
         *              "applications",             // Counts of applications
         *              "sessions",                 // Counts of sessions
         *              "sessions.queries.min",     // Minimum queries per session
         *              "sessions.queries.max",     // Maximum queries per session
         *              "sessions.queries.avg",     // Average queries per session
         *              "elapsedTime.min",          // Minimum elapsed time (in milliseconds)
         *              "elapsedTime.max",          // Maximum elasped time (in milliseconds)
         *              "elapsedTime.avg"           // Average elapsed time (in milliseconds)
         *            ],
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @since 2.2.5
         * @member askiaVista
         * @method getActivityStats
         * @static
         * @param {askiaVista.queries.get.activityStats} query Query to obtain the statisticals result on activity.
         */
        /**
         * Action to obtain the statisticals result on activity
         *
         * Also see: askiaVista#getActivityStats
         * @since 2.2.5
         */
        getActivityStats : "getActivityStats",

        /**
         * Execute the query to obtain the list of possible filters to apply on activity.
         *
         *       // Get the list of possible filters
         *       askiaVista.getActivityilters({
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         *
         *       // Get the possible list of the specified filters.
         *       askiaVista.getActivityFilters({
         *            filters : [
         *              "users",
         *              "userGroups",
         *              "companies",
         *              "surveys",
         *              "avsServers",
         *              "webServers",
         *              "applications",
         *              "errorCodes"
         *            ],
         *            success : function (data, query) {
         *               console.log(JSON.parse(data));
         *            },
         *            error : function (message, query) {
         *                alert(message);
         *            }
         *       });
         *
         * @since 2.2.5
         * @member askiaVista
         * @method getActivityFilters
         * @static
         * @param {askiaVista.queries.get.activityFilters} query Query to obtain the list of possible filters to apply on activity.
         */
        /**
         * Action to obtain the list of possible filters to apply on activity
         *
         * Also see: askiaVista#getActivityFilters
         * @since 2.2.5
         */
        getActivityFilters : "getActivityFilters"

    };


    /**
     * White list of parameters that will be sent to the server-side.
     *
     * @member askiaVista
     * @property {askiaVista.enumerators.parameter} parameter
     * @static
     * @readonly
     */
    /**
     * # Enumeration of parameters
     *
     * White list of parameters that will be sent to the server-side.
     * 
	 * Accessible via 
	 *      
	 *      askiaVista.parameter
     * 
     * @enum askiaVista.enumerators.parameter
     * @protected
     */
    parameters = {
        /* Indicates the type of query if not defined the XTab is used */
        action: "action",

        /* Current application name */
        appName : "appName",

        /* Current application version */
        appVersion : "appVersion",

        /* Version of the current framework */
        ajaxApiVersion : "ajaxApiVersion",

        /* Offset time of the current client browser */
        timeOffset  : "timeOffset",

        /* Id of object */
        id: 'id',

        /* List of fields */
        fields : 'fields',

        /* Name of object */
        name: 'name',
        /* Type of object */
        type : 'type',
        /* Index of object */
        index : 'index',
        /* Shortcut of question */
        shortcut: 'shortcut',
        /**
         * Key of item
         */
        key     : 'key',
        /* Caption of question */
        caption: 'caption',
        /* Description of object */
        description: 'description',
        /* Definition of object */
        definition: 'definition',
        /* Responses for the calculated questions */
        responses: 'responses',
        /* Script */
        script: 'script',
        /* Id or name of survey (mandatory) */
        survey: "survey",
        /* Id or name of profile (used by the action =action.getQuestions and action =action.getInterviews ) */
        profile: "profile",
        /* Id of name of portfolio (used by the action =action.getPortfolioItems) */
        portfolio: "portfolio",
        /* Shortcut of question (used by the action==action.getResponses) */
        question: "question",
        /* Shortcut of questions (used by the action==action.getInterviews) */
        questions: "questions",
        /* Id or name of portfolio item (the name of portfolio item must be formatted like that: "name_of_portfolio|name_of_portfolio_item" */
        portfolioItem: "portfolioItem",
        /* Id or name of profile questions to apply in rows */
        profileRows: "profileRows",
        /* Shortcut of questions in rows (separate multiple with the pipe character '|') */
        rows: "rows",
        /* Id or name of profile questions to apply in columns */
        profileColumns: "profileColumns",
        /* Shortcut of questions in columns (separate multiple with the pipe character '|') */
        columns: "columns",
        /* Id or name of profile questions to apply in edges */
        profileEdges: "profileEdges",
        /* Shortcut of questions in edges (separate multiple with the pipe character '|') */
        edges: "edges",
        /* Id or name of settings */
        settings: "settings",
        /* Id of calculations (separate by the '|' character) */
        calculations: "calculations",
        /* Change the script of calculation using this format: "name_of_calculation§script_to_apply" */
        changeScriptOfCalculation: "changeScriptOfCalculation",
        /* Id or name of chart template to apply (if empty render a table) */
        chart: "chart",
        /* Id or name of chart template */
        chartTemplate : "chartTemplate",
        /* Id or name of table-style to apply  */
        tabStyle: "tabStyle",
        /* Id or name of sub-population */
        subPopulation: "subPopulation",
        /* Id or name of the calculated question */
        calculatedQuestion : "calculatedQuestion",
        /* Id or name of wave (separate multiple with the character '|') */
        waves: "waves",
        /* Id or name of weighting */
        weighting: "weighting",
        /* Id or name of universe */
        universe: "universe",
        /* Id or name of level */
        level: "level",
        /* Overwrite the title of cross-tab */
        title: "title",
        /* Indicates the maximum number of interviews per page (action === getInterviews*/
        maxPerPage: "maxPerPage",
        /* Index of page to display */
        page: "page",
        /* Dimension of the calculations */
        dimension: "dimension",
        /* Indicates the which kind of calculations to obtain ('main'/'total') */
        toBuild: "toBuild",
        /* Width of chart */
        width: "width",
        /* Height of chart */
        height: "height",
        /* Pattern for the searching */
        pattern: "pattern",
        /* HTML Id of the container */
        containerId: "containerId",
        /* Login of user */
        login: "login",
        /* Password of user */
        password: "password",
        /* Confirm the session disconnection */
        confirmSessionDisconnection : 'confirmSessionDisconnection',
        /* Password confirmation */
        passwordConfirm : "passwordConfirm",
        /* Actual password */
        passwordActual  : "passwordActual",
        /**
         * Explicit authenticity token.
         *
         * Only for internal usage, it indicates at which security level to apply
         * @private
         */
        explicitAuthenticityToken : 'explicitAuthenticityToken',
        /* Authenticity token */
        authenticityToken: "authenticityToken",
        /* Portfolio token */
        portfolioToken: "portfolioToken",
        /* Portfolio item token */
        portfolioItemToken: "portfolioItemToken",
        /* Link id for the portfolio link*/
        linkId : "linkId",
        /* Expiration date for the portfolio link*/
        expireAt : "expireAt",
        /**
         * Layout for the portfolio links
         */
        layout   : "layout",
        /**
         * Theme for the portfolio link
         */
        theme    : "theme",
        /**
         * Theme for the portfolio link
         */
        portfolioLinkTheme : 'portfolioLinkTheme',
        /**
         * Default portfolio item
         */
        defaultPortfolioItem : "defaultPortfolioItem",
        /* Format  */
        format: "format",
        /* Lazy loading */
        lazyLoading : "lazyLoading",
        /* Verbose */
        verbose: "verbose",
        /* Locale */
        locale: "locale",
        /* Id of the parent question for the getQuestions method */
        parentNode: "parentNode",
        /* Indicates the recursivity for getQuestions method */
        recursive: "recursive",
        /* Indicates a transaction */
        transactions: "transactions",
        /* Entity to export */
        entity: 'entity',
        /* Format of the file to export */
        fileFormat: 'fileFormat',
        /* Name of the file to export */
        fileName: 'fileName',
        /* Name of the file coming from cross-tab title */
        fileNameFromTitle : 'fileNameFromTitle',
        /* Overwrite */
        overwrite: 'overwrite',
        /* Use the definition of the calculated question when creating a sub-population with responses of question */
        useDefinition  : 'useDefinition',
        /* Save a temporay object */
        temporary      : 'temporary',
        /* List of sharing */
        sharings       : 'sharings',
        /* XTabSettings for the current survey only */
        currentSurveyOnly : 'currentSurveyOnly',
        /* Language */
        language          : 'language',
        /* Default survey */
        defaultSurvey     : 'defaultSurvey',
        /* Email */
        email             : 'email',
        /* UI Preferences */
        uiPreferences     : 'uiPreferences',
        /**
         * Caption in tree-view
         */
        captionInTree     : 'captionInTree',
        /**
         * Caption in dimension
         */
        captionInDimension : 'captionInDimension',
        /* Request are done from iFrame */
        fromIFrame        : 'fromIFrame',
        /* Specify the name of the input file created in the iFrame  */
        fileUploadName    : 'fileUploadName',
        /**
         *  Indicates that the query has a timer on it
         *  The server will not change the expiration date of the session
         */
        timer             : 'timer',
        /**
         * Resources parameter
         */
        resources         : 'resources',
        /**
         * Resource parameter
         */
        resource          : 'resource',
        /**
         * Content parameter
         */
        content           : 'content',
        /**
         * Url parameter
         */
        url               : 'url',
        /**
         * Items parameter
         */
        items             : 'items',
        /**
         * Before parameter
         */
        before            : 'before',
        /**
         * After parameter
         */
        after              : 'after',
        /**
         * SSO Key
         */
        ssoKey             : 'ssoKey',
        /**
         * Metrics
         */
        metrics            : 'metrics',
        /**
         * Group By criteria
         */
        groupBy            : 'groupBy',
        /**
         * Filters
         */
        filters            : 'filters',
        /**
         * Total responses
         */
        totalResponses     : 'totalResponses',
        /* Dummy parameter */
        dmy: "dmy"
    };

    // Enumerates available entities for export
    entities = [
        'crosstab',
        'interviews',
        'portfolio',
        'portfolioItem',
        'subPopulations',
        'calculatedQuestions',
        'weightings',
        'universes',
        'levels',
        'waves',
        'profiles',
        'portfolios',
        'portfolioItems',
        'surveys',
        'xTabSettings',
        'tabStyle',
        'chartTemplate',
        'portfolioLinkTheme',
        'activity',
        'activityStats'
    ];

    /**
     * # AskiaVista AJAX configuration.
     *
     * This configuration could be accessible by calling the askiaVista#config method.
     *
     * Get or sets the configuration of the askiaVista
     *
     * Be careful, the configuration have to be specified before the execution of queries
     *
     *     // Set a configuration
     *     askiaVista.config({
     *        url : 'http://my.server.com/AskiaVistaReader/AjaxEmbedHandler.aspx',
     *        loadingMessage :'<img src="http://my.server.com/ajax-loader.gif" alt="Loading..." />',
     *        authenticityToken : '35f0461d-a1a2-4477-9c22-a008ae8839f3',
     *        cookie : {enable : false},
     *        survey : 'EX',
     *        locale : 'fr'
     *     });
     *
     *     // Get the entire configuration
     *     var config = askiaVista.config();
     *
     *     // Get the value of a given configuration key
     *     var locale = askiaVista.config('locale');
     *
     * A change of the `locale` key in the configuration will load all localization files
     * (askiaVista.loadLocale() will be called internally)
     *
     * All keys available for queries like (language, settings, calculations, chart, tabStyle, subPopulation ...) could also be specified
     * and will be used as the default value of queries.
     *
     * Also see:
     *
     * - askiaVista#config
     * - askiaVista#loadLocale
     *
     * @class askiaVista.queries.config
     * @protected
     */
    configuration = {
        /**
         * Name of the web application that currently used the API
         *
         * It's mostly used for the server-side logs and specific settings/behaviour
         * Please try to avoid usage of "AskiaVista" as application name
         *
         * We recommend short-name (< 20 characters) with only ANSI characters
         *
         *
         *     askiaVista.config({
         *         appName : 'Awesome-Dashboard'
         *     });
         *
         * @since 2.2.3
         */
        appName : "",
        /**
         * Version of the web application that currently used the API
         *
         * It's mostly used for the server-side logs
         *
         * We recommend three digits version MAJOR.MINOR.REVISION
         *
         *
         *     askiaVista.config({
         *         appVersion : '1.0.0'
         *     });
         *
         * @since 2.2.3
         */
        appVersion : "",
        /**
         * Base Url of server side web site which handle the AJAX requests
         * The base url only specify the root path of web site without the page name
         *
         * Changing the baseUrl will also change the url if not specified or already override in the config
         *
         *     askiaVista.config({
         *         baseUrl : 'http://my.server.con/AskiaVistaReader/'
         *     });
         *
         * @since 2.2.0
         */
        baseUrl : 'http://localhost/AskiaVistaReader.Net4/',
        /**
         * Url of server side page to handle the AJAX requests
         *
         *     askiaVista.config({
         *         url : 'http://my.server.con/AskiaVistaReader/AjaxEmbedHandler.aspx'
         *     });
         */
        url: 'http://localhost/AskiaVistaReader.Net4/AjaxEmbedHandler.aspx',
        /**
         * Indicates the shorthand name of the localization (`en` for English, `fr` for French ...)
         *
         * If the value of this change askiaVista will automatically load the localization files storing in the server at:
         * http://.../AskiaVistaReader/Scripts/locale/
         *
         *      askiaVista.config({
         *           locale : 'fr'
         *      });
         *
         *      // Equivalent to
         *      askiaVista.loadLocale('fr');
         *
         * Also see:
         *
         * - askiaVista.queries.config.localeUrlParam
         * - askiaVista#loadLocale
         */
        locale: 'en',
        /**
         * Name of parameter in the URL to retrieve the localization.
         *
         * Specify a blank value to disable the auto-detection of the localization via URL
         *
         *      // Search the parameter `lang` in the url to automatically load the right localization
         *      // If the page is called with:
         *      // index.html?lang=fr
         *      // That will automatically called:
         *      // askiaVista.loadLocale('fr');
         *      //
         *      askiaVista.config({
         *           localeUrlParam : 'lang'
         *      });
         *
         * Also see:
         *
         * - askiaVista.queries.config.locale
         */
        localeUrlParam: 'locale',
        /**
         * Name of parameter in the URL to set the language of the survey.
         *
         * Specify a blank value to disable the auto-detection of the survey language via URL
         *
         *      // Search the parameter `surveyLang` in the url to automatically load the right survey language
         *      // If the page is called with:
         *      // index.html?surveyLang=fra
         *      //
         *      askiaVista.config({
         *           surveyLanguageUrlParam : 'surveyLang'
         *      });
         */
        languageUrlParam : 'language',
        /**
         * Id or name of the default survey to use for all queries (except that one where the `survey` key is specified)
         *
         *     // Specify the default survey 'EX'
         *     askiaVista.config({
         *         survey : 'EX'
         *     });
         *
         *     // Query that uses the default 'EX' survey
         *     askiaVista.display({
         *         containerId : 'result1',
         *         rows : 'i1. Gender'
         *     });
         *
         *     // Query that uses the specified 'Demo' survey
         *     askiaVista.display({
         *        survey : 'Demo',
         *        containerId : 'result2',
         *        rows : 'CSP'
         *     });
         *
         * @type {String|Number}
         */
        survey: '',
        /**
         * i18n stand for internationalization.
         *
         * This object is use to store the default translation use the askiaVista AJAX.
         *
         * This object is override by the askiaVista#loadLocale method
         *
         * Also see:
         *
         * - askiaVista#loadLocale
         * - askiaVista#translate
         *
         */
        i18n: {
            aborted: "Aborted.",
            error: {
                undefinedDrawMethod: "The draw method of the chart plugin '{0}' is not defined or is not a function",
                undefinedPluginName: "Please indicates the name of the plugin.",
                undefinedTypeOfQuery: "The type of query was undefined",
                unknownErrorDuringEncryption: "Unknown error during the encryption",
                unknownErrorDuringSearch: "Error while searching.",
                missingDependency: "     - Missing dependency '{0}' for the plugin '{1}'",
                incorrectVersionOfPlugin: "     - The version {0} of '{1}' is require for the plugin '{2}'",
                pluginsExceptions: "Plugins exceptions:\r\n",
                unhandleError: "Oops an unhandled error was occured.",
                authenticationRequire: "Authentication required!",
                deprecatedMethod: "Sorry but the method '{0}' was deprecated.",
                invalidAuthenticityToken: "Invalid authenticity token",
                allowedDomainsUndefined: "The allowed domains are undefined",
                pageNotAllowedToQuery: "Sorry this page is not allowed to execute the query",
                surveyDeleted: "This survey was deleted",
                surveyAccessDenied: "Survey access denied",
                incorrectLoginOrPwd: "Incorrect login or password",
                incorrectPassword: "Incorrect password",
                userAccountDisabled: "You're account was disabled",
                userAccountDeleted: "Your account was deleted",
                portfolioDeleted: "The portfolio was deleted",
                licenseExpired: "Your licence was expired",
                passwordExpired: "Your password was expired",
                noResult: "No results.",
                noQuestionsDefined: "No questions defined",
                cannotFoundListOfSurveys: "Cannot find the list of surveys",
                cannotFoundListOfProfiles: "Cannot find the list of Profiles",
                cannotFoundListOfSubPops: "Cannot find the list of Filters",
                cannotFoundListOfWaves: "Cannot find the list of waves",
                cannotFoundListOfUniverses: "Cannot find the list of universes",
                cannotFoundListOfWeightings: "Cannot find the list of weightings",
                cannotFoundListOfLevels: "Cannot find the list of levels",
                cannotFoundListOfChartTemplates: "Cannot find the list of chart templates",
                cannotFoundListOfTabStyles: "Cannot find the list of table styles",
                cannotFoundListOfXTabSettings: "Cannot find the list of settings",
                cannotFoundListOfPortfolios: "Cannot find the list of portfolios",
                cannotFoundListOfCalculatedQuestions: "Cannot find the list of Variables",
                cannotFoundListOfCalculations: "Cannot find the list of calculations",
                cannotFoundListOfPortfolioLinks : 'Cannot find the list of portfolio links',
                cannotFoundProfile: "Cannot find the Profile",
                cannotFoundQuestion: "Cannot find the question",
                cannotFoundPortfolio: "Cannot find the Portfolio",
                cannotFoundPortfolioItem: "Cannot find the Portfolio item",
                cannotFoundSettingsForUserAndSurvey: "Cannot find user settings for the current survey",
                cannotFoundHelpFor: "Cannot find help for '{0}'",
                cannotFoundPlugin: "Cannot find the plugin {0}.",
                cannotFoundSurvey: "Cannot find the survey",
                cannotReadUsersTable: "Cannot obtain the DataReader to the users table",
                cannotFoundUser: "Cannot find the user",
                cannotShowLoginForm: "Cannot display the login form.\r\n In order to solve the problem, you can apply one of this following fix: \r\n- Include the jquery.blockUI.js\r\n- Authenticate the user explicitly \r\n- Implement your own showLoginForm() function through the askiaVista.config method",
                cannotExecuteCrossTab: "Cannot execute the cross-tab. Unknown exception",
                cannotCreateCrossTabDef: "Cannot create the cross-tab definition",
                cannotCreateRawDataDef : "Cannot create the raw-data definition",
                expectedSurveyParam: "The survey parameter is expected",
                expectedQuestionParam: "The question parameter is expected",
                expectedClosedQuestion: "This method must be invoked on closed question",
                expectedSurfFile: "The survey is not a surf file (.qew), you cannot obtain the list of waves",
                expectedPortfolioParam: "The portfolio parameter is expected",
                expectedPatternParam: "The pattern parameter is expected",
                expectedIdOrName: "The id or name parameter is expected",
                expectedEntityParameter: "The entity parameter is expected",
                invalidEntityParameter: "Invalid entity parameter.\r\n Available entities are:\r\n'crosstab', 'interviews', 'portfolio', 'portfolioItem', 'portfolioLinkTheme'\r\n'subPopulations', 'calculatedQuestions', 'weightings', 'universes', 'levels', 'waves',\r\n 'profiles', 'portfolios', 'portfolioItems',\r\n 'surveys', 'xTabSettings',\r\n'tabStyle', 'chartTemplate'",
                expectedFileFormatParameter: "The fileFormat parameter is expected",
                invalidFileFormat: "The export doesn't support the specified file format",
                invalidFileExtension: "Invalid file extension",
                unknowErrorDuringExport: "An unknown error occurred during the export",
                incorrectExportDownloadDataArg: "The 'data' argument of the method askiaVista.download must be a string or a flat hash object",
                invalidSubPopulationId: "Invalid Filter id",
                cannotFoundSpecifySubPopulation: "Cannot find the specified Filter",
                invalidCalculatedQuestionId: "Invalid Variable id",
                cannotFoundSpecifyCalculatedQuestion: "Cannot find the specified Variable",
                expectedDefinitionOrResponses: "One of the parameter 'definition' or 'responses' is expected",
                expectedDefinitionOrScript : "One of the parameter 'definition' or 'script' is expected",
                invalidResponseObject: "Invalid response object",
                invalidProfileId: "Invalid Profile id",
                cannotFoundSpecifyProfile: "Cannot find the specify profile",
                invalidProfileDefinition: "Invalid Profile definition",
                invalidXTabSettingsId: "Invalid settings id",
                cannotFoundSpecifyXTabSettings: "Cannot find the specify settings",
                invalidXTabSettingsDefinition: "Invalid settings definition",
                invalidPortfolioItemId: "Invalid portfolio item id",
                invalidPortfolioId: "Invalid portfolio id",
                expectedTransactionsParameter: "The transactions parameter is expected",
                invalidTransactionParameter: "Invalid transactions parameter",
                invalidTransactionItem: "Invalid transaction item",
                cannotExecuteTransaction: "Cannot execute the transaction",
                unauthorizedQuery: "Unauthorized query",
                noSubPopulationsCreated : "No sub-population created",
                incompleteQuery : "Incomplete query",
                invalidPermissionParameter : "Invalid permission parameter",
                invalidResharingParameter : "Invalid resharing parameter",
                expectedSharingsParameter : "Expected 'sharings' parameter",
                invalidSharingsParameter  : "The 'sharings' parameter is invalid, expect an array of sharing",
                notAllowedToShareThisItem : "You're not allowed to share this item",
                notAllowedToShareWithEveryBody : "You're not allowed to share with every body.",
                cannotFoundTheSpecifyContact : "Cannot found the specify contact",
                cannotFoundSurveyLanguage    : "Cannot found the specify language",
                cannotFoundSpecifyWeighting  : "Cannot found the specify weighting",
                cannotFoundSpecifyLevel      : "Cannot found the specify level",
                cannotFoundSpecifyUniverse   : "Cannot found the specify universe",
                cannotFoundSpecifyTabStyle   : "Cannot found the specify table style",
                expectedActualAndConfirmPassword : "Expected the password confirmation and the actual password",
                passwordDoesntMatchConfirm   : "The password and the confirmation doesn't match",
                unexpectedCharacters         : "Unexpected characters",
                cannotFoundTheSpecifyLanguage   : "Cannot found the specify language",
                invalidEmailAddress          : "Invalid email address",
                invalidTabStyleId: "Invalid Table style id",
                couldNotFindTheIFrame : "Could not find the specified iFrame",
                incorrectIFrameArg : "Incorrect iframe arguments",
                noFileUploadNameSpecified : "Input file name was not specified use the parameter `fileUploadName`",
                couldNotFindInputFile : "Could not find or create the input file",
                invalidChartTemplateId: "Invalid Chart template id",
                cannotFoundSpecifyChartTemplate   : "Cannot found the specify Chart template",
                invalidPortfolioLinkId : "Invalid portfolio link id",
                cannotFoundSpecifyPortfolioLink : "Cannot found the specify portfolio link",
                invalidPortfolioLinkIdFormat : "Invalid portfolio link format, min chars: 3, max chars: 25, only alpha-numeric characters without spaces",
                invalidDateFormat : "Invalid date format, expected ISO date",
                invalidSubPopulationObject : "Invalid sub-population object",
                invalidLevelObject : "Invalid level object",
                invalidWavesObject   : "Invalid waves object",
                invalidProfileObject : "Invalid profile object",
                invalidPortfolioResourceFormat : "Invalid format of the resource",
                expectedResourceParam : "`resource` parameter is expected",
                invalidResourceParam : "Invalid `resource` parameter",
                cannotFoundResource  : "Cannot found the resource",
                invalidResourceId    : "Invalid resource id",
                resourceSizeTooLarge  : "The file size is too large (max: 2 MB)",
                expectedItemsParam     : "Expected `items` parameter",
                invalidItemsParam      : "Invalid `items` parameter",
                expectedBeforeOrAfterParam : "Expected `before` OR `after` parameter",
                couldNotContainsBeforeAndAfter : "`before` AND `after` parameters could not be use at the same time",
                cannotFoundTheme        : "Could not find the theme",
                cannotFoundLayout       : "Could not find the layout",
                invalidThemeId          : "Invalid theme id",
                expectedCalculationsParam : "Expected `calculations` parameter",
                invalidCalculationsParam : "Invalid `calculations` parameter",
                expectedIndexParam      : "Expected `index` parameter",
                invalidIndexParam       : "Invalid `index` parameter",
                scriptEmpty             : "Expected a non-empty script",
                invalidSSOKey           : "Invalid SSO key",
                sessionDisconnected     : "Your session has been disconnected.",
                expectedMediocrePasswordQuality : "The quality of the password is too low, please mix at least 2 criteria between lower/upper case, punctuations and numbers.",
                expectedGoodPasswordQuality : "The quality of the password is too low, please mix at least 3 criteria between lower/upper case, punctuations and numbers.",
                expectedGreatPasswordQuality : "The quality of the password is too low, please mix all of these criteria lower/upper case, punctuations and numbers."
            },
            showLoginForm: {
                message: "This page requires an authentication.",
                sessionTimeoutMessage : "Your session has timed out.<br />Please re-enter your password:",
                login: "Login",
                password: "Password",
                submit: "Ok",
                cancel: "Cancel",
                changeUserAccount : "Switch user account",
                reconnect : "Reconnect",
                unsupportedType : "Unsupported type"
            },
            confirmSessionDisconnection : {
                message : "Your account seems already in use elsewhere.<br /> Do you want to enforce the connection?",
                yes     : "Yes",
                no      : "No"
            },
            about: {
                message: "You are using the AskiaVista AJAX jQuery plugin version {0}",
                enablePlugins: "\r\n\r\nEnable plugins:\r\n",
                category: "      - Category: {0}\r\n",
                version: "      - Version: {0}\r\n",
                date: "      - Date: {0}\r\n",
                author: "      - Author: {0}\r\n",
                site: "      - Site: {0}\r\n",
                help: "      - Help: {0}\r\n",
                description: "      - Description: {0}\r\n",
                dependencies: "\r\n      DEPENDENCIES:\r\n",
                optional: " [Optional]"
            },
            humanActionSingular: {
                getQuestions: "a question",
                getResponses: "a response",
                getSurveys: "a survey",
                getProfiles: "a profile",
                getSubPopulations: "a sub-population",
                getWaves: "a wave",
                getUniverses: "a universe",
                getWeightings: "a weighting",
                getLevels: "a level",
                getChartTemplates: "a chart template",
                getTabStyles: "a table style",
                getXTabSettings: "a cross-tab settings",
                getPortfolios: "a portfolio",
                getPortfolioItems: "a portfolio item",
                getCalculatedQuestions: "a calculated question",
                getCalculations: "a calculation",
                getPages: "a page",
                search: "a question"
            }
        },
        /**
         * The AskiaVista AJAX is a JavaScript file executed on the client-side. That means that the authentication is available for the currently displayed page.<br />
         * If you go to another page of your dashboard or refresh the current page, the authentication process will be re-executed.<br />
         * So, if you use the explicit authentication, the AskiaVista AJAX will ask again the credential of user.
         *
         * To avoid this behaviour and maintain the session across pages, the AskiaVista AJAX saves the encrypted data in a cookie.<br />
         * This cookie is not permanent and will be removed when the user closes his browser.
         *
         * By default, if the jquery.cookie.js plugin is declared in your page, the AskiaVista AJAX plugin automatically saves information in the cookie to maintain the session.<br />
         * However, the cookie is the last place to search the information, so if you specify an authenticityToken using the url parameter or the config(), this authenticityToken will be used in priority.
         *
         * The askiaVista#config method allows you to interact with the settings of the cookie.<br />
         * You can for example disable it, change the name of the cookie key (we advise you do so) or use a secure cookie (only sent to the server-side through the https protocol)
         *
         *      // Disable the cookie
         *      askiaVista.config({
         *          cookie : {
         *              enable : false
         *          }
         *      });
         *
         *
         *      // Change the name of the cookie and set it as secure
         *      askiaVista.config({
         *          cookie : {
         *              name : 'myCompany',
         *              secure : true
         *          }
         *      });
         *
         * @type askiaVista.queries.config.cookie
         * @protected
         */
        cookie: {
            /**
             * Enable or disable the cookie even if the jquery.cookie is available
             * @member askiaVista.queries.config.cookie
             */
            enable: true,
            /**
             * Name of the cookie use to maintain the session
             * @member askiaVista.queries.config.cookie
             */
            name: 'askiavistaAuth',
            /**
             * Over HTTPS protocol it's strongly recommended to flag the cookie as secure
             * @member askiaVista.queries.config.cookie
             */
            secure: false
        },
        /**
         * Default message to display while a query is loading
         *
         * * It could be a string which represent the HTML code to use
         * * It could be a function that will be called when the load is require, in this case the `query` will be passed in parameter of this function
         * * `false` value will disable the message
         *
         *
         *     // Change the loading message with `Loading ....`
         *     askiaVista.config({
         *         loadingMessage : 'Loading ....'
         *     });
         *
         *     // Change the loading message with custom loading management
         *     askiaVista.config({
         *         loadingMessage : function (query) {
         *             if (query.bigTable) {
         *                document.getElementById(query.containerId).innerHTML = 'Please wait during the loading.<br />This could a while because the request table is too big';
         *             } else {
         *                document.getElementById(query.containerId).innerHTML = Loading the result ...';
         *             }
         *         }
         *     });
         *
         *     // Disable the loading message by default
         *     askiaVista.config({
         *         loadingMessage : false
         *     });
         *
         * @type {String|Function|Boolean}
         */
        loadingMessage: '<img src="http://localhost/AskiaVistaReader.Net4/ajax-loader.gif" alt="Loading..." />',
        /**
         * Authenticity token of user.
         *
         * Indicates which AskiaVista user account will be use to execute queries.
         *
         * This token can be found in AskiaVista / Administration
         *
         * When blank an explicit login/password is required
         *
         *      // Automatically load the user with the specified authenticity token
         *      askiaVista.config({
         *          authenticityToken : '35f0461d-a1a2-4477-9c22-a008ae8839f3'
         *      });
         *
         *
         * Also see:
         *
         * - askiaVista.queries.config.authenticityTokenUrlParam
         * - askiaVista.queries.config.showLoginForm
         * - [Authentication in AskiaVista AJAX Framework](#!/guide/authentication)
         */
        authenticityToken: '',
        /**
         * Name of parameter in the URL to retrieve the authenticity token.
         *
         * Specify a blank value to disable the auto-detection of the authenticity via URL
         *
         *      // Search the parameter `sso` in the url to automatically authenticate the user
         *      // If the page is called with:
         *      // index.html?sso=35f0461d-a1a2-4477-9c22-a008ae8839f3
         *      // That will automatically called:
         *      // askiaVista.config({
         *      //     authenticityToken : '35f0461d-a1a2-4477-9c22-a008ae8839f3'
         *      // });
         *      //
         *      askiaVista.config({
         *          authenticityTokenUrlParam : 'sso'
         *      });
         *
         * Also see:
         *
         * - askiaVista.queries.config.authenticityToken
         * - [Authentication in AskiaVista AJAX Framework](#!/guide/authentication)
         */
        authenticityTokenUrlParam: 'askiaAuth',
        /**
         * Management of important error
         *
         *     // Redirect the error in the console instead of alert
         *     askiaVista.config({
         *         error : function (message) {
         *             console.warn(message);
         *         }
         *     });
         *
         * @param {String} message Error message to display
         */
        error: function (message) {
            alert(message);
        },
        /**
         * Method to execute when the login is require.
         * By default it display the login form when the jquery.blockUI from {#link http://malsup.com/jquery/block/ M Alsup.} is available.
         * Otherwise it raises an error if not implemented
         *
         *      // When the authentication is require, redirect to the login.html page
         *      askiaVista.config({
         *          showLoginForm : function () {
         *             location.href = "login.html";
         *          }
         *      });
         *
         *      // When the session has timed out
         *      askiaVista.config({
         *          showLoginForm : function (cause) {
         *              if (cause === 'sessionTimeout') {
         *                  showLoginLightBox();
         *              } else {
         *                  location.href = 'login.html';
         *              }
         *          }
         *      });
         *
         * Also see:
         *
         * - askiaVista#login
         * - [Authentication in AskiaVista AJAX Framework](#!/guide/authentication)
         *
         * @returns {boolean}
         * @param {'requireLogin'|'sessionTimeout'} cause Cause for login request
         */
        showLoginForm: function (cause) {
            // Require the jquery.blockUI.js
            if (!$.blockUI) {
                error(translate("error.cannotShowLoginForm"));
                core.abort();
                return false;
            }
            var text = (cause === 'sessionTimeout') ? 'showLoginForm.sessionTimeoutMessage' : 'showLoginForm.message',
                submitText = (cause === 'sessionTimeout') ? 'showLoginForm.reconnect' : 'showLoginForm.submit',
                cancelText = (cause === 'sessionTimeout') ? 'showLoginForm.changeUserAccount' : 'showLoginForm.cancel',
                message =  [];

            message.push('<h3>' + translate(text) + '</h3>');
            message.push('<div>');
            message.push('<p id="askiavista_error_message"></p>');
            message.push('<table align="center">');
            // Don't ask the login for reconnection
            if (cause !== 'sessionTimeout') {
                message.push('<tr>');
                message.push('<td align="right"><label for="askiavista_login">' + translate("showLoginForm.login") + '</label></td>');
                message.push('<td><input type="text" id="askiavista_login" size="20" /></td>');
                message.push('</tr>');
            }
            message.push('<tr>');
            message.push('<td align="right"><label for="askiavista_password">' + translate("showLoginForm.password") + '</label></td>');
            message.push('<td align="left"><input type="password" id="askiavista_password" size="20" /></td>');
            message.push('</tr>');
            message.push('<tr>');
            message.push('<td><a href="#" id="askiavista_cancel">' + translate(cancelText) + '</a></td>');
            message.push('<td align="right"><input type="button" id="askiavista_submit" value="' + translate(submitText) + '" /></td>');
            message.push('</tr>');
            message.push('</table>');
            message.push('<br/></div>');

            $.blockUI({
                css: {
                    cursor: ''
                },
                message: message.join('')
            });
            document.getElementById("askiavista_cancel").addEventListener("click", function () {
                if (cause !== 'sessionTimeout') {
                    $.unblockUI();
                    core.abort();
                } else {
                    core.logout();
                    location.reload(); // Reload the page
                }
                return false;
            });
            document.getElementById("askiavista_password").addEventListener("keyup", function (e) {
                if (e.keyCode === 13) {
                    document.getElementById("askiavista_submit").click();
                }
            });
            document.getElementById("askiavista_submit").addEventListener("click", function () {
                document.getElementById("askiavista_error_message").innerHTML = config('loadingMessage');
                var loginQuery = {
                    password: document.getElementById('askiavista_password').value,
                    success: function () {
                        $.unblockUI();
                    },
                    error: function (message) {
                        document.getElementById('askiavista_error_message').innerHTML = message;
                    }
                };
                if (cause !== 'sessionTimeout') {
                    loginQuery.login = document.getElementById('askiavista_login').value;
                }
                core.login(loginQuery);
            });
            return true;
        },
        /**
         * When the concurrent user is disable, this method is executed to let the user to confirm the disconnection of
         * other sessions
         *
         * By default it display the confirmation message using jquery.blockUI when it's available
         * {#link http://malsup.com/jquery/block/ M Alsup.}
         * If it's not available it uses the native window.confirm method
         *
         * Otherwise it raises an error if not implemented
         *
         *      // With manual callback to login() method
         *      askiaVista.config({
         *          confirmSessionDisconnection : function (query) {
         *             var confirmSessionDisconnection = window.confirm("You seems already connected elsewhere, clicking Ok will disconnect other sessions?");
         *             askiaVista.login({
         *                 confirmSessionDisconnection : confirmSessionDisconnection,
         *                 success : query.success,
         *                 error : query.error
         *             });
         *          }
         *      });
         *
         *      // With automatic callback
         *      askiaVista.config({
         *          confirmSessionDisconnection : function () {
         *             return window.confirm("You seems already connected elsewhere, clicking Ok will disconnect other sessions?");
         *          }
         *      });
         *
         * Also see:
         *
         * - askiaVista#login
         * - [Authentication in AskiaVista AJAX Framework](#!/guide/authentication)
         *
         * @returns {boolean|undefined}
         * @param {Object} query Query context, use it to rebind the callback
         * @since 2.2.3
         */
        confirmSessionDisconnection : function (query) {
            query = query || {};

            // Require the jquery.blockUI.js
            if (!$.blockUI) {
                return confirm(translate('confirmSessionDisconnection.message').replace(/<br\s*\/?>/gi, '\r\n'));
            }
            var message =  [];

            message.push('<h3>' + translate('confirmSessionDisconnection.message') + '</h3>');
            message.push('<div>');
            message.push('<table align="center">');
            message.push('<tr><td align="right"><input type="button" id="askiavista_dont_confirm" value="' + translate('confirmSessionDisconnection.no') + '" /></td>');
            message.push('<td align="right"><input type="button" id="askiavista_confirm" value="' + translate(confirmSessionDisconnection.yes) + '" /></td>');
            message.push('</tr>');
            message.push('</table>');
            message.push('<br/></div>');

            $.blockUI({
                css: {
                    cursor: ''
                },
                message: message.join('')
            });
            document.getElementById("askiavista_dont_confirm").addEventListener("click", function () {
                core.login({
                    confirmSessionDisconnection : false,
                    success : query.success,
                    error : query.error
                });
                $.unblockUI();
                core.abort();
                return false;
            });
            document.getElementById("askiavista_confirm").addEventListener("click", function () {
                core.login({
                    confirmSessionDisconnection : true,
                    success : query.success,
                    error : query.error
                });
            });
        },
        /**
         * Method to execute when the session has been disconnected.
         *
         * BE CAREFUL: Once this method is called the stack of queries is dropped.
         * You may redirect the user, reload the page or recreate the queries stack from scracth.
         *
         *      // When the authentication is require, redirect to the login.html page
         *      askiaVista.config({
         *          disconnect : function () {
         *             location.href = "login.html";
         *          }
         *      });
         *
         * @since 2.2.3
         */
        disconnect  : function () {
            alert(translate('error.sessionDisconnected'));
            var ssoKey = getUrlParameter('sso');
            if (ssoKey) {
                window.location = window.location.toString().replace('sso=' + ssoKey, '');
            }  else {
                window.location.reload();
            }
        }
    };

    /*
     * Utilities
     */
    util = {
        /*
         * Test if the value is an plain object object
         *
         * @param value Value to test
         * @returns {boolean} True if the value is a plain object
         */
        isObject : function isObject(value) {
            return value != null && Object.prototype.toString.call(value) === "[object Object]";
        },
        /*
         * Test if the value is an array
         *
         * @param value Value to test
         * @returns {boolean} True if the value is an array
         */
        isArray : function isArray(value) {
            return typeof Array.isArray === 'function' ? Array.isArray(value) :
                Object.prototype.toString.call(value) === "[object Array]";
        },
        /**
         * Merge to objects altogether in the first object argument
         * If the first argument is a boolean it will do a deep copy or not
         */
        extend  : function extend(/* deep, obj1, ... */) {
            var options, name, src, copy, copyIsArray, clone,
                target = arguments[0] || {},
                i = 1,
                length = arguments.length,
                deep = false;

            // Handle a deep copy situation
            if ( typeof target === "boolean" ) {
                deep = target;
                target = arguments[1] || {};
                // skip the boolean and the target
                i = 2;
            }

            // Handle case when target is a string or something (possible in deep copy)
            if ( typeof target !== 'object' && typeof target !== 'function') {
                target = {};
            }

            if ( length === i ) {
                target = this;
                --i;
            }

            for ( ; i < length; i++ ) {
                // Only deal with non-null/undefined values
                if ( (options = arguments[ i ]) != null ) {
                    // Extend the base object
                    for ( name in options ) {
                        //noinspection JSUnfilteredForInLoop
                        src = target[ name ];
                        //noinspection JSUnfilteredForInLoop
                        copy = options[ name ];

                        // Prevent never-ending loop
                        if ( target === copy ) {
                            continue;
                        }

                        // Recurse if we're merging plain objects or arrays
                        if ( deep && copy && ( util.isObject(copy) || (copyIsArray = util.isArray(copy)) ) ) {
                            if ( copyIsArray ) {
                                copyIsArray = false;
                                clone = src && util.isArray(src) ? src : [];

                            } else {
                                clone = src && util.isPlainObject(src) ? src : {};
                            }

                            // Never move original objects, clone them
                            //noinspection JSUnfilteredForInLoop
                            target[ name ] = util.extend( deep, clone, copy );

                            // Don't bring in undefined values
                        } else if ( copy !== undefined ) {
                            //noinspection JSUnfilteredForInLoop
                            target[ name ] = copy;
                        }
                    }
                }
            }
            // Return the modified object
            return target;
        },

        /*
         * 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
         *
         * Create a cookie with the given name and value and other optional parameters.
         *
         * @example util.cookie('the_cookie', 'the_value');
         * @desc Set the value of a cookie.
         * @example util.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
         * @desc Create a cookie with all available options.
         * @example util.cookie('the_cookie', 'the_value');
         * @desc Create a session cookie.
         * @example util.cookie('the_cookie', null);
         * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
         *       used when the cookie was set.
         *
         * @param String name The name of the cookie.
         * @param String value The value of the cookie.
         * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
         * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
         *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
         *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
         *                             when the the browser exits.
         * @option String path The value of the path attribute of the cookie (default: path of page that created the cookie).
         * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
         * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
         *                        require a secure protocol (like HTTPS).
         * @type undefined
         *
         * @name util.cookie
         * @cat Plugins/Cookie
         * @author Klaus Hartl/klaus.hartl@stilbuero.de
         *
         *
         * Get the value of a cookie with the given name.
         *
         * @example util.cookie('the_cookie');
         * @desc Get the value of a cookie.
         *
         * @param String name The name of the cookie.
         * @return The value of the cookie.
         * @type String
         *
         * @name util.cookie
         * @cat Plugins/Cookie
         * @author Klaus Hartl/klaus.hartl@stilbuero.de
         */
        cookie          :  function cookie(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
                }
                // CAUTION: Needed to parenthesize options.path and options.domain
                // in the following expressions, otherwise they evaluate to undefined
                // in the packed version for some reason...
                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 = cookies[i].toString().trim();
                        // 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;
            }
        },

        /*
         * Helper for util.param method
         * @param {String[]} output Output
         * @param {string} key Key
         * @param {*} value Value of the key
         */
        _param_add      : function addParam(output, key, value) {
            value = typeof value === 'function' ? value() : value;
            value = value === null ? '' : value === undefined ? '' : value;
            output.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
        },

        /*
         * Helper for util.param method
         * @param {String[]} output Output
         * @param {string} prefix Key
         * @param {*} obj Object
         */
        _param_build    : function buildParams(output, prefix, obj) {
            var i, len, key, rbracket = /\[\]$/;

            if (prefix) {
                if (util.isArray(obj)) {
                    for (i = 0, len = obj.length; i < len; i++) {
                        if (rbracket.test(prefix)) {
                            util._param_add(output, prefix, obj[i]);
                        } else {
                            util._param_build(output, prefix + '[' + (typeof obj[i] === 'object' ? i : '') + ']', obj[i]);
                        }
                    }
                } else if (obj && util.isObject(obj)) {
                    for (key in obj) {
                        if (obj.hasOwnProperty(key)) {
                            util._param_build(output, prefix + '[' + key + ']', obj[key]);
                        }
                    }
                } else {
                    util._param_add(output, prefix, obj);
                }
            } else if (util.isArray(obj)) {
                for (i = 0, len = obj.length; i < len; i++) {
                    util._param_add(output, obj[i].name, obj[i].value);
                }
            } else {
                for (key in obj) {
                    if (obj.hasOwnProperty(key)) {
                        util._param_build(output, key, obj[key]);
                    }
                }
            }
            return output;
        },

        /*
         * Build URL parameters using an object
         * @param abj
         * @returns {string}
         */
        param           : function param(abj) {
            return util._param_build([], '', abj).join('&').replace(/%20/g, '+');
        }
    };

    /**
     * DOM Utilities
     */
    dom = {
        /**
         * Indicates if the dom is ready
         */
        isReady: false,
        /**
         * Callback functions to execute when the dom is ready
         */
        callbacks: [],
        /**
         * Event triggered when the DOM is ready
         */
        onDomReady: function onDomReady() {
            if (this.isReady) {
                return;
            }
            this.isReady = true;
            var i, l;
            for (i = 0, l = this.callbacks.length; i < l; i += 1) {
                this.callbacks[i]();
            }
            this.callbacks.length = 0;
        },

        /**
         * Register a function to execute when the dom is ready
         * @param {Function} fn Function to register
         */
        ready: function ready(fn) {
            if (this.isReady) {
                fn();
                return;
            }
            this.callbacks.push(fn);
        },

        /**
         * Listen the dom ready event
         */
        listen: function listen() {
            function fireDomReady() {
                dom.onDomReady();
            }
            if (document.addEventListener) {
                document.addEventListener("DOMContentLoaded", fireDomReady, false);
            }
            else if (document.all && !window.opera) {
                document.write('<script type="text/javascript" id="contentloadtag" defer="defer" src="javascript:void(0)"><\/script>');
                var contentloadtag = document.getElementById("contentloadtag");
                contentloadtag.onreadystatechange = function onReadyState() {
                    if (this.readyState === "complete") {
                        fireDomReady();
                    }
                }
            } else {
                var backupOnLoad = window.onload;
                window.onload = function () {
                    setTimeout(fireDomReady, 0);
                    if (typeof backupOnLoad === "function") {
                        backupOnLoad();
                    }
                }
            }
        }
    };

    // ~ Return a dummy value to by pass the browser cache ~
    function getDummyValue() {
        var dt = new Date();
        return dt.getUTCDate() + "" + dt.getUTCMilliseconds();
    }

    //  Global error management
    function error(message) {
        var err = config('error');
        if (err && typeof (err) === "function") {
            err(message);
        } else {
            alert(message);
        }
    }

    //  Get url parameter
    // @param {String} name Name of parmeter to read
    // @return {String} Return the value of the parameter or ""
    function getUrlParameter(name) {
        if (!name || typeof (name) !== "string") {
            return "";
        }
        var rgExp = new RegExp(name + "=([^\\&]*)", "i"),
            arrResult = rgExp.exec(document.location.search);
        if (!arrResult) {
            return "";
        }
        if (arrResult.length < 2) {
            return "";
        }
        return arrResult[1];
    }

    //  Event when the config change
    // @param {Object} params Parameters to change
    function onConfigChange(params) {
        if (!params) {
            return;
        }
        var fromUrl, currentLocale;

        if (params.localeUrlParam) {
            currentLocale = config('locale');
            if (currentLocale === 'en') {
                fromUrl = getUrlParameter(config('localeUrlParam'));
                if (fromUrl && fromUrl !== currentLocale) {
                    config({
                        locale: fromUrl
                    });
                }
            }
        }

        if (params.languageUrlParam) {
           if (!configuration.language) {
               fromUrl = getUrlParameter(config('languageUrlParam'));
               if (fromUrl) {
                   config({
                       language : fromUrl
                   });
               }
           }
        }

        if (params.locale) {
            loadLocale(config('locale'));
        }
    }

    /**
     * Get or sets the configuration of the askiaVista
     *
     * Be careful, the configuration have to be specified before the execution of queries
     *
     *     // Set a configuration
     *     askiaVista.config({
     *        url : 'http://my.server.com/AskiaVistaReader/AjaxEmbedHandler.aspx',
     *        loadingMessage :'<img src="http://my.server.com/ajax-loader.gif" alt="Loading..." />',
     *        authenticityToken : '35f0461d-a1a2-4477-9c22-a008ae8839f3',
     *        cookie : {enable : false},
     *        survey : 'EX',
     *        locale : 'fr'
     *     });
     *
     *     // Get the entire configuration
     *     var config = askiaVista.config();
     *
     *     // Get the value of a given configuration key
     *     var language = askiaVista.config('locale');
     *
     * A change of the `locale` key in the configuration will load all localization files
     * (askiaVista.loadLocale() will be called internally)
     *
     * All keys available for queries like (settings, calculations, chart, tabStyle, subPopulation ...) could also be specified
     * and will be used as the default value of queries.
     *
     * Also see:
     *
     * - askiaVista.queries.config
     * - askiaVista#loadLocale
     *
     * @member askiaVista
     * @method config
     * @static
     * @param {Object|String} [params] An object to set the configuration or a string to obtain a configuration value
     * @return {askiaVista.queries.config|*} Returns the entire configuration or the value of the specified configuration key
     */
    function config(params) {
        if (!params) {
            return configuration;
        }
        if (!util.isObject(params)) {
            return configuration[params];
        }
        var key;
        for (key in params) {
            /* Don't set the unknown keys */
            if (params.hasOwnProperty(key) && ((key in configuration) || (key in parameters))) {
                if (util.isObject(configuration[key])) {
                    configuration[key] = util.extend(true, {}, configuration[key], params[key]);
                } else {
                    configuration[key] = params[key];
                    if (key === 'baseUrl') {
                        if (configuration.url === 'http://localhost/AskiaVistaReader.Net4/AjaxEmbedHandler.aspx') {
                            configuration.url = configuration.baseUrl + 'AjaxEmbedHandler.aspx';
                        }
                        if (configuration.loadingMessage === '<img src="http://localhost/AskiaVistaReader.Net4/ajax-loader.gif" alt="Loading..." />') {
                            configuration.loadingMessage = '<img src="' + configuration.baseUrl + 'ajax-loader.gif" alt="Loading..." />';
                        }
                    }
                }
            }
        }
        onConfigChange(params);
        return configuration;
    }

    /**
     *  Load localization file in order to translate messages, text of AskiaVista AJAX and all associated plugins.
     * The default locale is English (en).
     *
     * You can also use the askiaVista#config method or the askiaVista.configuration.localeUrlParam to manage it via url
     * The localization files will be loaded from the server-side at the following URL:
     * http://.../AskiaVistaReader/Scripts/locale/
     *
     *     askiaVista.loadLocale('fr');
     *
     *     // Equivalent to
     *     askiaVista.config({
     *         locale : 'fr'
     *     });
     *
     *     // OR
     *     index.html?locale=fr
     *
     * Also see:
     *
     * - askiaVista.configuration.locale
     * - askiaVista.configuration.localeUrlParam
     *
     * @member askiaVista
     * @method loadLocale
     * @static
     * @param {String} locale Shorthand of the language to use (`en` for English, `fr` for French ...)
     */
    function loadLocale(locale) {
        if (initializing || (!locale && typeof (locale) !== "string")) {
            return;
        }

        var pluginsWithLocale = plugins.getAllWithLocale(),
            i = 0,
            l = pluginsWithLocale.length,
            query = {
                action: action.loadLocale,
                locale: "askiavista-" + locale,
                dmy: getDummyValue(),
                async: false,
                dataType: "script"
            }, xhr;

        xhr = new XHR(query);
        xhr.execute();

        for (; i < l; i += 1) {
            query = {
                action: action.loadLocale,
                locale: pluginsWithLocale[i].localeFile + "-" + locale,
                dmy: getDummyValue(),
                async: false,
                dataType: "script"
            };
            xhr = new XHR(query);
            xhr.execute();
        }
    }

    //noinspection JSCommentMatchesSignature,JSValidateJSDoc
    /**
     * Translate a string by using his key identifier.
     *
     * The first parameter is a key string of the text to translate.
     * This key string represent the path to find the translation.
     * The translation is organized using this kind of structure:
     *
     *      i18n : {
     *          message : {
     *              hello : "Hello world!"
     *          }
     *      }
     *
     * The i18n (Internationalization) is the root of the translation.
     * The key string to obtain the message hello is: "message.hello"
     *
     *
     *     // According to the locale loaded, the following line will returns:
     *     //   - "Hello world!" for the locale "en"
     *     //   - "Salut tout le monde!" for the locale "fr"
     *     askiaVista.translate("message.hello");
     *
     * All remain arguments on askiaVista#translate method will be used for the text replacement.
     * It's using the C#-like syntax.
     *
     *
     *     i18n : {
     *         plugin : {
     *             info : "My plugin name is {0} and his version is {1}"
     *         }
     *     }
     *     askiaVista.translate("plugin.info","foo","1.0.0");
     *     // =>  "My plugin name is foo and his version is 1.0.0"
     *
     * Also see:
     *
     * - askiaVista.loadLocale
     *
     * @member askiaVista
     * @method translate
     * @static
     * @param {String} key Key to translate, indicates the `path` in the i18n to the text to translate
     * @param {String...|Number...} [args] Remain parameters to use for the text replacement
     * @returns {String} Returns the translation associated with the key or the key itself if the translation was not found
     */
    function translate(key) {
        if (typeof (key) !== "string") {
            return key;
        }
        var i, l, rg,
            isAvailableKey = /^[\S]+$/gi, /* Without spaces */
            undefinedTranslation = "[" + config('locale') + "] {" + key + "}",
            current = config('i18n'),
            map = key.split('.');

        if (!isAvailableKey.test(key)) { /* Plain text message */
            return key;
        }

        for (i = 0, l = map.length; i < l; i += 1) {
            if (!current[map[i]]) {
                return undefinedTranslation;
            }
            current = current[map[i]];
        }
        if (typeof (current) !== 'string') {
            return undefinedTranslation;
        }

        //Do a little formatting
        if (arguments.length > 1) {
            for (i = 1, l = arguments.length; i < l; i += 1) {
                rg = new RegExp("\\{" + (i - 1) + "\\}", "gi");
                current = current.replace(rg, arguments[i]);
            }
        }

        return current;
    }

    /**
     * Returns the current version of AskiaVista AJAX
     *
     *     alert('AskiaVista AJAX version: ' + askiaVista.version());
     *     // => 'AskiaVista AJAX version: 2.0.0'
     *
     * @member askiaVista
     * @method version
     * @static
     * @returns {string} The version of AskiaVista AJAX
     */
    function version() {
        return infos.version;
    }

    /**
     * Display an alert with the information about the AskiaVista AJAX and all associated plugins.
     *
     * If the `pluginName` parameter is specified it returns the information about the specified plugins
     *
     *     askiaVista.about(); // About AskiaVista AJAX
     *     askiaVista.about("jquery"); // About jQuery
     *     askiaVista.about("jquery.blockUI"); //About blockUI
     *
     * @member askiaVista
     * @method about
     * @static
     * @param {String} [pluginName] Name of the plugin
     */
    function about(pluginName) {
        plugins.refresh();
        pluginName = pluginName || 'askiaVista';
        var str = "", abouts, p;
        if (pluginName === 'askiaVista') {
            str = translate("about.message", infos.version);
            abouts = plugins.about();
            if (abouts.length > 0) {
                str += translate("about.enablePlugins");
            }
            str += abouts;
        } else if (pluginName === 'jquery') {
            str = " + jquery\r\n";
            str += translate("about.version", $.fn.jquery);
            str += translate("about.site", "http://www.jquery.com");
            str += translate("about.help", infos.jqueryHelpUrl);
        } else {
            p = plugins.get(pluginName);
            if (!p || !p.about) {
                return;
            }
            str = p.about(true);
        }
        if (str === "") {
            return;
        }
        str += "\r\n\r\njquery.askiaVista is distributed under the AskiaVistaSDK license\r\nCopyright Askia © 2011";
        alert(str);
    }

    /**
     * Open a new browser window with the documentation.
     *
     * If the `pluginName` parameter is specified it display the help of the specified plugin
     *
     *      askiaVista.help(); // Open a new window with the current help
     *      askiaVista.help("jquery"); // Open a new window with the documentation of jQuery
     *      askiaVista.help("jquery.blockUI"); // Open a new window with the documentation of blockUI
     *
     * @member askiaVista
     * @method help
     * @static
     * @param {String} [pluginName] Name of the plugin
     */
    function help(pluginName) {
        var url = infos.helpUrl,
            rg = /^https?:\/\//,
            plugin;
        pluginName = pluginName || 'askiaVista';
        if (pluginName === "jquery") {
            url = infos.jqueryHelpUrl;
        } else if (pluginName !== "askiaVista") {
            plugin = plugins.get(pluginName);
            if (!plugin) {
                return;
            }
            url = plugin.helpUrl || "";
            if (url === "") {
                url = plugin.website || "";
            }
        }

        if (url === "") {
            error(translate("error.cannotFoundHelpFor", pluginName));
            return;
        }
        if (!rg.test(url)) {
            return;
        }
        window.open(url);
    }

    /**
     * Abort all non-executed AskiaVista AJAX requests in the pool of requests. <br />
     * This method is mainly used to abort queries if the user cannot authenticate.
     *
     *     // Abort all remain queries
     *     askiaVista.abort();
     *
     * @member askiaVista
     * @method abort
     * @static
     */
    function abort() {
        queries.abort();
    }

    /**
     *  Encrypt the data using a symmetric algorithm name `Moonwalk` generated in the server-side.<br />
     *  This method is used internally to encrypt the password of the login() method before to send it to the server-side.
     *
     *       askiaVista.encrypt({
     *           value : 'secret',
     *           success : function (data, query) {
     *               console.log('`secret` has been encrypted to: ' + data);
     *           },
     *           error : function (message, query) {
     *               console.log(message);
     *           }
     *       });
     *
     * @member askiaVista
     * @method encrypt
     * @static
     *
     * @param {Object} query Query use for the encryption
     * @param {String} query.value String to encrypt
     * @param {Function} [query.success] Callback function to execute when the encryption succeed.
     * @param {String} query.success.data Encrypted string
     * @param {Object} query.success.query Original query used to keep the context
     * @param {Function} [query.error] Callback function to execute when the encryption failed
     * @param {String} query.error.message Error message
     * @param {Object} query.error.query Original query used to keep the context
     */
    function encrypt(query) {
        var key = '',
            isN,
            s = '',
            rnd = function (m, M) {
                var rv = m + (Math.random() * (M - m));
                return Math.round(rv);
            };
        while (key.length < 16) {
            isN = rnd(0, 1);
            if (isN) {
                key += s + rnd(0, 9);
            } else {
                key += s + String.fromCharCode(rnd(97, 122));
            }
        }
        $.ajax({
            url: config('url'),
            async: false,
            dataType: "script",
            data: util.param({ action: 'getEncAl', key: key, dmy: getDummyValue() }),
            success: function () {
                if (!window.moonWalk || typeof (window.moonWalk) !== "function") {
                    if (query.error) {
                        query.error(translate("error.unknowErrorDuringEncryption"), {});
                    }
                    return;
                }
                var value  = query.value,
                    output, i, l;

                if (util.isArray(value)) {
                    output = [];
                    for(i = 0, l = value.length; i < l; i += 1) {
                        output.push(key + '-' + window.moonWalk(value[i]));
                    }
                } else {
                    output = key + '-' + window.moonWalk(value);
                }

                window.moonWalk = null;
                if (query.success) {
                    query.success(output, {});
                }
            },
            error: function (data) {
                if (query.error) {
                    query.error(data, {});
                }
            }
        });
    }

    /**
     * Try to authenticate the user to allow him to execute queries.<br />
     * This method will automatically encrypt the password in the client browser before to send it to the server.
     *
     * When the session of the user has timed out, only send the password,
     * otherwise call the method #logout() first and then send the login and the password
     *
     * All queries in the stack will be executed once this method succeed.
     *
     *      // The login and password are read from HTML input
     *      askiaVista.login({
     *           login : document.getElementById('login').value,
     *           password : document.getElementById('password').value,
     *           success : function () {
     *              console.log('The user was successfully authenticated');
     *           },
     *           error : function (message, query) {
     *              document.getElementById('error_message').innerHTML = message;
     *           }
     *      });
     *
     * Also see:
     *
     * - askiaVista#logout
     * - askiaVista.queries.config#showLoginForm
     * - [Authentication in AskiaVista AJAX Framework](#!/guide/authentication)
     *
     * @member askiaVista
     * @method login
     * @static
     *
     * @param {Object} query Query to log the user in
     * @param {String} [query.login] Login of the user
     * @param {String} query.password Password of the user
     * @param {Function} [query.success] Callback function to execute when the log-in succeed
     * @param {String} query.success.data Empty string
     * @param {Object} query.success.query Original query used to keep the context
     * @param {Function} [query.error] Callback function to execute when the log-in failed
     * @param {String} query.error.message Error message
     * @param {Object} query.error.query Original query used to keep the context
     */
    function login(query) {
        query = query || {};
        query.dmy = getDummyValue();
        query.action = action.login;
        query.xhr = new XHR(query);

        if (query.password) {
            encrypt({
                value: query.password,
                success: function (data) {
                    query.password = data;
                    queries.executeNow(query);
                }
            });
        } else {
            queries.executeNow(query);
        }
    }

    /**
     * Logout the user.<br />
     * This method will clear the askiaVista.configuration.authenticityToken in the configuration
     * and remove cookies.
     *
     * - askiaVista#login
     * - [Authentication in AskiaVista AJAX Framework](#!/guide/authentication)
     *
     * @member askiaVista
     * @method logout
     * @static
     * @since 2.1.0
     *
     * @param {Object} query Query to log out the user
     * @param {Function} [query.success] Callback function to execute when the log-out succeed
     * @param {String} query.success.data Empty string
     * @param {Object} query.success.query Original query used to keep the context
     * @param {Function} [query.error] Callback function to execute when the log-out failed
     * @param {String} query.error.message Error message
     * @param {Object} query.error.query Original query used to keep the context
     */
    function logout(query) {
        query = query || {};
        query.dmy = getDummyValue();
        query.action = action.logout;
        query.xhr = new XHR(query);
        queries.executeNow(query);
        queries.logout();
    }

    /**
     * Clear the specified timer(s) or all timers
     *
     *        // Create a query with timer
     *        askiaVista.getSurveyStatus({
     *             survey : "EX",
     *             timer : {
     *                id      : "survey_status_timer",
     *                timeout : 300000 // each 5 minutes
     *             },
     *             success : function (data) {
     *                console.log(JSON.parse(data));
     *             }
     *        });
     *
     *        // Create another query with timer
     *        askiaVista.display({
     *            survey : "EX",
     *            timer : {
     *                id : "reload_crosstab",
     *                timeout : 300000
     *            },
     *            containerId : "result",
     *            rows : "gender"
     *        });
     *
     *        // ...
     *
     *        // Clear only one specified timer
     *        askiaVista.clearTimers("survey_status_timer");
     *
     *        // ...
     *
     *        // Clear several timers
     *        askiaVista.clearTimers("survey_status_timer", "reload_crosstab");
     *
     *        // ...
     *
     *        // Clear all timers
     *        askiaVista.clearTimers();
     *
     * Also see:
     *
     * - askiaVista#startTimers
     * - askiaVista#stopTimers
     *
     * @member askiaVista
     * @static
     * @param {String...} [id] Id(s) of the timer to clear
     */
    function clearTimers(id) {
        if (!arguments.length) {
            timers.each(function clearAll(timer) {
                timer.remove();
            });
            return;
        }
        var i, l, timer;
        for (i = 0, l = arguments.length; i < l; i += 1) {
            timer = timers.getTimer(arguments[i]);
            if (timer) {
                timer.remove();
            }
        }
    }

    /**
     * Stop the specified timer(s) or all timers
     * Stopped timers could be restarted using the askiaVista#startTimers methods
     *
     *
     *        // Create a query with timer
     *        askiaVista.getSurveyStatus({
     *             survey : "EX",
     *             timer : {
     *                id      : "survey_status_timer",
     *                timeout : 300000 // each 5 minutes
     *             },
     *             success : function (data) {
     *                console.log(JSON.parse(data));
     *             }
     *        });
     *
     *        // Create another query with timer
     *        askiaVista.display({
     *            survey : "EX",
     *            timer : {
     *                id : "reload_crosstab",
     *                timeout : 300000
     *            },
     *            containerId : "result",
     *            rows : "gender"
     *        });
     *
     *        // ...
     *
     *        // Stop only one specified timer
     *        askiaVista.stopTimers("survey_status_timer");
     *
     *        // ...
     *
     *        // Stop several timers
     *        askiaVista.stopTimers("survey_status_timer", "reload_crosstab");
     *
     *       // ..
     *
     *       // Stop all timers
     *        askiaVista.stopTimers();
     *
     * Also see:
     *
     * - askiaVista#startTimers
     * - askiaVista#clearTimers
     *
     * @member askiaVista
     * @static
     * @param {String...} [id] Id(s) of the timer to stop
     */
    function stopTimers(id) {
        if (!arguments.length) {
            timers.each(function stopAll(timer) {
                timer.stop();
            });
            return;
        }

        var i, l, timer;
        for (i = 0, l = arguments.length; i < l; i += 1) {
            timer = timers.getTimer(arguments[i]);
            if (timer) {
                timer.stop();
            }
        }
    }

    /**
     * Start the specified timer(s) or all timers
     *
     *        // Create a query with timer
     *        askiaVista.getSurveyStatus({
     *             survey : "EX",
     *             timer : {
     *                id      : "survey_status_timer",
     *                timeout : 300000 // each 5 minutes
     *             },
     *             success : function (data) {
     *                console.log(JSON.parse(data));
     *             }
     *        });
     *
     *        // Create another query with timer
     *        askiaVista.display({
     *            survey : "EX",
     *            timer : {
     *                id : "reload_crosstab",
     *                timeout : 300000
     *            },
     *            containerId : "result",
     *            rows : "gender"
     *        });
     *
     *        // ...
     *
     *        // Stop all timers
     *        askiaVista.stopTimers();
     *
     *        // ...
     *
     *        // Start one timer
     *        askiaVista.startTimers("survey_status_timer");
     *
     *        // ...
     *
     *        // Start several timers
     *        askiaVista.startTimers("survey_status_timer", "reload_crosstab");
     *
     *        // ...
     *
     *        // Start all timers
     *        askiaVista.startTimers();
     *
     * Also see:
     *
     * - askiaVista#stopTimers
     * - askiaVista#clearTimers
     *
     * @member askiaVista
     * @static
     * @param {String...} [id] Id(s) of the timer to start
     */
    function startTimers(id) {
        if (!arguments.length) {
            timers.each(function startAll(timer) {
                timer.start();
            });
            return;
        }
        var i, l, timer;
        for (i = 0, l = arguments.length; i < l; i += 1) {
            timer = timers.getTimer(arguments[i]);
            if (timer) {
                timer.start();
            }
        }
    }

    /**
     * Manage all timers
     *
     * @private
     * @ignore
     */
    timers = (function () {

        var timerCollection = {},
            lastId = 0,
            allowedActions = {
                display: true,
                getQuestions: true,
                getResponses: true,
                getLanguages : true,
                getSurveys: true,
                getSurveyStatus :true,
                getSurveySettings : true,
                getProfiles: true,
                getSubPopulation : true,
                getSubPopulations: true,
                getWaves: true,
                getUniverses: true,
                getWeightings: true,
                getLevels: true,
                getChartTemplates: true,
                getTabStyles: true,
                getXTabSettings: true,
                getUserInfo: true,
                getPortfolios: true,
                getPortfolioItems: true,
                getCalculatedQuestions: true,
                getCalculations: true,
                getPages: true,
                search: true,
                getInterviews: true,
                getSharings : true,
                getContacts   : true
            };

        /**
         * Timer object
         *
         * @param {askiaVista.abstracts.queryWithTimer|askiaVista.abstracts.queryVerboseWithTimer} query Query with timer
         * @returns {Timer}
         * @private
         * @ignore
         */
        function Timer(query) {
            if (!query || !query.timer || typeof query.timer !== "object") {
                return null;
            }
            if (!query.action || !allowedActions[query.action]) {
                return null;
            }
            // Already exist return the existing instance
            if (query.timer.id && timerCollection[query.timer.id]) {
                timerCollection[query.timer.id].query = query;
                return timerCollection[query.timer.id];
            }
            var timer = query.timer;

            // Update the id of the timer by reference
            timer.id = timer.id || timer.id || "timer_" + (++lastId);

            this.query = query;
            this.id = timer.id;
            this.timeout = (timer.timeout && timer.timeout > 5000) ? timer.timeout : 5000;
            this.maxAttempts = timer.maxAttempts || 5;
            this.maxExecutions = timer.maxExecutions;
            this.wasStopped = false;

            // Number of executions
            this.executionsCount = 0;

            // Number of errors
            this.errorCount = 0;

            // setTimeout id
            this.pid = null;

            timerCollection[this.id] = this;
            return timerCollection[this.id];
        }

        /**
         * Start the timer
         *
         * Mostly use after the query callbacks
         *
         * @param {Boolean} [isQueryError=false] Indicates if the query has failed
         */
        Timer.prototype.start = function timerStart(isQueryError) {
            this.wasStopped = false;

            // Already on timer
            if (this.pid) {
                return;
            }

            // Verify the query once again
            if (!this.query.action || !allowedActions[this.query.action]) {
                this.isRunning = false;
                return;
            }

            if (isQueryError) {
                this.errorCount++;
            } else {
                this.errorCount = 0;
            }

            // Remove the timer when max error reached
            if (this.errorCount >= this.maxAttempts) {
                this.remove();
                return;
            }

            this.executionsCount++;
            // Remove the timer when the number of executions was reached
            if (this.maxExecutions && this.executionsCount >= this.maxExecutions) {
                this.remove();
                return;
            }

            var self = this;
            this.pid = setTimeout(function onTimer() {
                if (self.wasStopped) {
                    return;
                }
                self.pid = null;
                self.query.dmy = getDummyValue(); // Override the timestamp
                queries.launcher.execute("AddQuery", self.query);
                if (queries.wasRunning) {
                    queries.execute();
                }
            }, this.timeout);
        };

        /**
         * Stop the timer
         */
        Timer.prototype.stop = function () {
            if (this.pid) {
                clearTimeout(this.pid);
            }
            this.pid = null;
            this.wasStopped = true;
        };

        /**
         * Stop the timer and remove it
         */
        Timer.prototype.remove = function () {
            this.stop();
            delete timerCollection[this.id];
        };

        return {
            /**
             * Create a timer for the specified query
             *
             * @static
             * @param {askiaVista.abstracts.queryWithTimer|askiaVista.abstracts.queryVerboseWithTimer} query Query with timer
             * @returns {Timer} Created timer
             */
            create : function createTimer(query) {
                if (!query || !query.timer || typeof query.timer !== "object") {
                    return null;
                }
                return new Timer(query);
            },

            /**
             * Returns the timer using his id
             *
             * @static
             * @param {String} id Id of the timer to obtain
             * @returns {Timer}
             */
            getTimer : function getTimer(id) {
                if (!id) {
                    return null;
                }
                return timerCollection[id];
            },

            /**
             * Iterate through all timers and execute the specified function
             *
             *      // Stop all timers
             *      Timer.each(function (timer) {
             *          timer.stop();
             *      });
             *
             * @static
             * @param {Function} fn Function to execute for each timer
             * @param {Timer} fn.timer Timer on the current iteration
             */
            each   : function (fn) {
               if (typeof fn !== 'function') {
                   return;
               }

                var id;
                for (id in timerCollection) {
                    if (timerCollection.hasOwnProperty(id)) {
                        fn(timerCollection[id]);
                    }
                }
            }
        };
    }());

    /**
     * A Javascript object to encode and/or decode html characters using HTML or Numeric entities that handles double or partial encoding
     * Author: R Reid
     * source: http://www.strictly-software.com/htmlencode
     * Licences: GPL, The MIT License (MIT)
     * Copyright: (c) 2011 Robert Reid - Strictly-Software.com
     *
     * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
     * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     *
     * Revision:
     *   2014-06-26, Mamadou Sy:
     *        - Cleanup the code
     *
     *
     * Revision:
     *  2011-07-14, Jacques-Yves Bleau:
     *       - fixed conversion error with capitalized accentuated characters
     *       + converted arr1 and arr2 to object property to remove redundancy
     *
     * Revision:
     *  2011-11-10, Ce-Yi Hio:
     *       - fixed conversion error with a number of capitalized entity characters
     *
     * Revision:
     *  2011-11-10, Rob Reid:
     *      - changed array format
     *
     * Revision:
     *  2012-09-23, Alex Oss:
     *      - replaced string concatonation in numEncode with string builder, push and join for peformance with ammendments by Rob Reid
     * @private
     * @ignore
     */
    htmlEncoder = (function (){

        //
        // Encoder
        //
        // param {"entity"|"numerical"} [encodeType="entity"] When encoding indicates the type to convert characters into html or numerical entities
        function Encoder(encodeType) {
            this.encodeType = encodeType || "entity";
            // arrays for conversion from HTML Entities to Numerical values
            this.arr1 = ['&nbsp;','&iexcl;','&cent;','&pound;','&curren;','&yen;','&brvbar;','&sect;','&uml;','&copy;','&ordf;','&laquo;','&not;','&shy;','&reg;','&macr;','&deg;','&plusmn;','&sup2;','&sup3;','&acute;','&micro;','&para;','&middot;','&cedil;','&sup1;','&ordm;','&raquo;','&frac14;','&frac12;','&frac34;','&iquest;','&Agrave;','&Aacute;','&Acirc;','&Atilde;','&Auml;','&Aring;','&AElig;','&Ccedil;','&Egrave;','&Eacute;','&Ecirc;','&Euml;','&Igrave;','&Iacute;','&Icirc;','&Iuml;','&ETH;','&Ntilde;','&Ograve;','&Oacute;','&Ocirc;','&Otilde;','&Ouml;','&times;','&Oslash;','&Ugrave;','&Uacute;','&Ucirc;','&Uuml;','&Yacute;','&THORN;','&szlig;','&agrave;','&aacute;','&acirc;','&atilde;','&auml;','&aring;','&aelig;','&ccedil;','&egrave;','&eacute;','&ecirc;','&euml;','&igrave;','&iacute;','&icirc;','&iuml;','&eth;','&ntilde;','&ograve;','&oacute;','&ocirc;','&otilde;','&ouml;','&divide;','&oslash;','&ugrave;','&uacute;','&ucirc;','&uuml;','&yacute;','&thorn;','&yuml;','&quot;','&amp;','&lt;','&gt;','&OElig;','&oelig;','&Scaron;','&scaron;','&Yuml;','&circ;','&tilde;','&ensp;','&emsp;','&thinsp;','&zwnj;','&zwj;','&lrm;','&rlm;','&ndash;','&mdash;','&lsquo;','&rsquo;','&sbquo;','&ldquo;','&rdquo;','&bdquo;','&dagger;','&Dagger;','&permil;','&lsaquo;','&rsaquo;','&euro;','&fnof;','&Alpha;','&Beta;','&Gamma;','&Delta;','&Epsilon;','&Zeta;','&Eta;','&Theta;','&Iota;','&Kappa;','&Lambda;','&Mu;','&Nu;','&Xi;','&Omicron;','&Pi;','&Rho;','&Sigma;','&Tau;','&Upsilon;','&Phi;','&Chi;','&Psi;','&Omega;','&alpha;','&beta;','&gamma;','&delta;','&epsilon;','&zeta;','&eta;','&theta;','&iota;','&kappa;','&lambda;','&mu;','&nu;','&xi;','&omicron;','&pi;','&rho;','&sigmaf;','&sigma;','&tau;','&upsilon;','&phi;','&chi;','&psi;','&omega;','&thetasym;','&upsih;','&piv;','&bull;','&hellip;','&prime;','&Prime;','&oline;','&frasl;','&weierp;','&image;','&real;','&trade;','&alefsym;','&larr;','&uarr;','&rarr;','&darr;','&harr;','&crarr;','&lArr;','&uArr;','&rArr;','&dArr;','&hArr;','&forall;','&part;','&exist;','&empty;','&nabla;','&isin;','&notin;','&ni;','&prod;','&sum;','&minus;','&lowast;','&radic;','&prop;','&infin;','&ang;','&and;','&or;','&cap;','&cup;','&int;','&there4;','&sim;','&cong;','&asymp;','&ne;','&equiv;','&le;','&ge;','&sub;','&sup;','&nsub;','&sube;','&supe;','&oplus;','&otimes;','&perp;','&sdot;','&lceil;','&rceil;','&lfloor;','&rfloor;','&lang;','&rang;','&loz;','&spades;','&clubs;','&hearts;','&diams;'];
            this.arr2 = ['&#160;','&#161;','&#162;','&#163;','&#164;','&#165;','&#166;','&#167;','&#168;','&#169;','&#170;','&#171;','&#172;','&#173;','&#174;','&#175;','&#176;','&#177;','&#178;','&#179;','&#180;','&#181;','&#182;','&#183;','&#184;','&#185;','&#186;','&#187;','&#188;','&#189;','&#190;','&#191;','&#192;','&#193;','&#194;','&#195;','&#196;','&#197;','&#198;','&#199;','&#200;','&#201;','&#202;','&#203;','&#204;','&#205;','&#206;','&#207;','&#208;','&#209;','&#210;','&#211;','&#212;','&#213;','&#214;','&#215;','&#216;','&#217;','&#218;','&#219;','&#220;','&#221;','&#222;','&#223;','&#224;','&#225;','&#226;','&#227;','&#228;','&#229;','&#230;','&#231;','&#232;','&#233;','&#234;','&#235;','&#236;','&#237;','&#238;','&#239;','&#240;','&#241;','&#242;','&#243;','&#244;','&#245;','&#246;','&#247;','&#248;','&#249;','&#250;','&#251;','&#252;','&#253;','&#254;','&#255;','&#34;','&#38;','&#60;','&#62;','&#338;','&#339;','&#352;','&#353;','&#376;','&#710;','&#732;','&#8194;','&#8195;','&#8201;','&#8204;','&#8205;','&#8206;','&#8207;','&#8211;','&#8212;','&#8216;','&#8217;','&#8218;','&#8220;','&#8221;','&#8222;','&#8224;','&#8225;','&#8240;','&#8249;','&#8250;','&#8364;','&#402;','&#913;','&#914;','&#915;','&#916;','&#917;','&#918;','&#919;','&#920;','&#921;','&#922;','&#923;','&#924;','&#925;','&#926;','&#927;','&#928;','&#929;','&#931;','&#932;','&#933;','&#934;','&#935;','&#936;','&#937;','&#945;','&#946;','&#947;','&#948;','&#949;','&#950;','&#951;','&#952;','&#953;','&#954;','&#955;','&#956;','&#957;','&#958;','&#959;','&#960;','&#961;','&#962;','&#963;','&#964;','&#965;','&#966;','&#967;','&#968;','&#969;','&#977;','&#978;','&#982;','&#8226;','&#8230;','&#8242;','&#8243;','&#8254;','&#8260;','&#8472;','&#8465;','&#8476;','&#8482;','&#8501;','&#8592;','&#8593;','&#8594;','&#8595;','&#8596;','&#8629;','&#8656;','&#8657;','&#8658;','&#8659;','&#8660;','&#8704;','&#8706;','&#8707;','&#8709;','&#8711;','&#8712;','&#8713;','&#8715;','&#8719;','&#8721;','&#8722;','&#8727;','&#8730;','&#8733;','&#8734;','&#8736;','&#8743;','&#8744;','&#8745;','&#8746;','&#8747;','&#8756;','&#8764;','&#8773;','&#8776;','&#8800;','&#8801;','&#8804;','&#8805;','&#8834;','&#8835;','&#8836;','&#8838;','&#8839;','&#8853;','&#8855;','&#8869;','&#8901;','&#8968;','&#8969;','&#8970;','&#8971;','&#9001;','&#9002;','&#9674;','&#9824;','&#9827;','&#9829;','&#9830;'];
        }

        Encoder.prototype = {

            isEmpty : function isEmpty(val) {
                if (val) {
                    return ((val === null) || val.length === 0 || /^\s+$/.test(val));
                } else {
                    return true;
                }
            },

            // Convert HTML entities into numerical entities
            html2Numerical : function html2Numerical(s) {
                return this.swapArrayVals(s, this.arr1, this.arr2);
            },

            // Convert Numerical entities into HTML entities
            numerical2Html : function numerical2Hml(s) {
                return this.swapArrayVals(s, this.arr2, this.arr1);
            },

            // Numerically encodes all unicode characters
            numEncode : function numEncode(s) {
                if(this.isEmpty(s)) {
                    return "";
                }

                var a = [],
                    i,l;

                for (i = 0, l = s.length; i < l; i++) {
                    var c = s.charAt(i);
                    if (c < " " || c > "~") {
                        a.push("&#");
                        a.push(c.charCodeAt()); //numeric value of code point
                        a.push(";");
                    } else {
                        a.push(c);
                    }
                }

                return a.join("");
            },

            // HTML Decode numerical and HTML entities back to original values
            htmlDecode : function htmlDecode(s) {
                var c, m, arr,
                    d = s,
                    x, l;

                if (this.isEmpty(d)) {
                    return "";
                }

                // convert HTML entities back to numerical entities first
                d = this.html2Numerical(d);

                // look for numerical entities &#34;
                arr = d.match(/&#[0-9]{1,5};/g);

                // if no matches found in string then skip
                if (arr !== null) {
                    for (x = 0, l = arr.length; x < l; x++) {
                        m = arr[x];
                        c = m.substring(2, m.length - 1); //get numeric part which is refernce to unicode character

                        // if its a valid number we can decode
                        if (c >= -32768 && c <= 65535) {
                            // decode every single match within string
                            d = d.replace(m, String.fromCharCode(c));
                        } else {
                            d = d.replace(m, ""); //invalid so replace with nada
                        }
                    }
                }

                return d;
            },

            // encode an input string into either numerical or HTML entities
            htmlEncode : function htmlEncode(s, dbl) {
                if (this.isEmpty(s)) {
                    return "";
                }

                // do we allow double encoding? E.g will &amp; be turned into &amp;amp;
                dbl = dbl || false; //default to prevent double encoding

                // if allowing double encoding we do ampersands first
                if (dbl) {
                    if (this.encodeType === "numerical") {
                        s = s.replace(/&/g, "&#38;");
                    } else {
                        s = s.replace(/&/g, "&amp;");
                    }
                }

                // convert the xss chars to numerical entities ' " < >
                s = this.xssEncode(s, false);

                if (this.EncodeType === "numerical" || !dbl) {
                    // Now call function that will convert any HTML entities to numerical codes
                    s = this.html2Numerical(s);
                }

                // Now encode all chars above 127 e.g unicode
                s = this.numEncode(s);

                // now we know anything that needs to be encoded has been converted to numerical entities we
                // can encode any ampersands & that are not part of encoded entities
                // to handle the fact that I need to do a negative check and handle multiple ampersands &&&
                // I am going to use a placeholder

                // if we don't want double encoded entities we ignore the & in existing entities
                if (!dbl) {
                    s = s.replace(/&#/g, "##AMPHASH##");

                    if (this.encodeType === "numerical") {
                        s = s.replace(/&/g, "&#38;");
                    } else {
                        s = s.replace(/&/g, "&amp;");
                    }

                    s = s.replace(/##AMPHASH##/g,"&#");
                }

                // replace any malformed entities
                s = s.replace(/&#\d*([^\d;]|$)/g, "$1");

                if (!dbl) {
                    // safety check to correct any double encoded &amp;
                    s = this.correctEncoding(s);
                }

                // now do we need to convert our numerical encoded string into entities
                if (this.encodeType === "entity") {
                    s = this.numerical2Html(s);
                }

                return s;
            },

            // Encodes the basic 4 characters used to malform HTML in XSS hacks
            xssEncode : function xssEncode(s, en) {
                if (!this.isEmpty(s)) {
                    en = en || true;
                    // do we convert to numerical or html entity?
                    if (en) {
                        s = s.replace(/\'/g,"&#39;"); //no HTML equivalent as &apos is not cross browser supported
                        s = s.replace(/\"/g,"&quot;");
                        s = s.replace(/</g,"&lt;");
                        s = s.replace(/>/g,"&gt;");
                    } else {
                        s = s.replace(/\'/g,"&#39;"); //no HTML equivalent as &apos is not cross browser supported
                        s = s.replace(/\"/g,"&#34;");
                        s = s.replace(/</g,"&#60;");
                        s = s.replace(/>/g,"&#62;");
                    }
                    return s;
                } else {
                    return "";
                }
            },

            // returns true if a string contains html or numerical encoded entities
            hasEncoded : function hasEncoded(s) {
                if (/&#[0-9]{1,5};/g.test(s)) {
                    return true;
                } else if (/&[A-Z]{2,6};/gi.test(s)) {
                    return true;
                } else {
                    return false;
                }
            },

            // will remove any unicode characters
            stripUnicode : function stripUnicode(s) {
                return s.replace(/[^\x20-\x7E]/g,"");
            },

            // corrects any double encoded &amp; entities e.g &amp;amp;
            correctEncoding : function correctEncoding(s) {
                return s.replace(/(&amp;)(amp;)+/,"$1");
            },

            // Function to loop through an array swaping each item with the value from another array e.g swap HTML entities with Numericals
            swapArrayVals : function swapArrayVals(s, arr1, arr2) {
                if (this.isEmpty(s)) {
                    return "";
                }

                var re, x, l;
                if (arr1 && arr2) {
                    //ShowDebug("in swapArrayVals arr1.length = " + arr1.length + " arr2.length = " + arr2.length)
                    // array lengths must match
                    if (arr1.length === arr2.length) {
                        for (x = 0, l = arr1.length; x < l; x++) {
                            re = new RegExp(arr1[x], 'g');
                            s = s.replace(re,arr2[x]); //swap arr1 item with matching item from arr2
                        }
                    }
                }
                return s;
            },

            inArray : function inArray (item, arr) {
                for (var i = 0, x = arr.length; i < x; i++) {
                    if ( arr[i] === item ){
                        return i;
                    }
                }
                return -1;
            }
        };


        return {
            /**
             * HTML encode the specified text.
             *
             * By default the queries should not contains any html piece of code to avoid the XSS.
             * If it contains sort of html fragment, the server side will reject that queries.
             *
             * But sometimes, you will really want to send html code on the server side,
             * like for the portfolio item section page with a WYSIWYG editor.
             *
             * In that special case the htmlEncode is needed and strongly recommend to use.
             *
             * But be careful, the server-side will not automatically htmlDecode values, it only allows that in certain cases.
             *
             *  * askiaVista#savePortfolioItem with section page item type
             *
             * @member askiaVista
             * @method htmlEncode
             * @static
             * @since 2.2.0
             * @param {String} text Text to encode
             * @param {Boolean} [doubleEncoding=false] Allow a double encoding. E.g will &amp; be turned into &amp;amp;
             * @param {"entity"|"numerical"} [encodeType="entity"] When encoding indicates the type to convert characters into html or numerical entities
             */
            htmlEncode : function htmlEncode(text, doubleEncoding, encodeType) {
                var encoder = new Encoder(encodeType);
                return encoder.htmlEncode(text, doubleEncoding)
                    .replace(/&#10;/g, '\r\n') // Break-line
                    .replace(/&#9;/g, '\t')    // Tab
                    .replace(/&#39;/g, "'");   // Apos
            },
            /**
             * HTML decode the specified text
             *
             * @param {String} text Text to decode
             * @ignore
             */
            htmlDecode : function htmlDecode(text) {
                var encoder = new Encoder();
                return encoder.htmlDecode(text);
            }
        };
    }());

    // Plugins management
    plugins = (function () {
        var byName = {}, byIndex = [];

        // Verify the chart category
        function verifyChartCategory(plugin) {
            if (!plugin.draw || typeof (plugin.draw) !== "function") {
                error(translate("error.undefinedDrawMethod", plugin.name));
                return false;
            }
            return true;
        }

        // Verify the plugin category
        function verifyPluginCategory(plugin) {
            if (!plugin.category) {
                return true;
            }
            if (plugin.category === "chart") {
                return verifyChartCategory(plugin);
            }
            return true;
        }

        // Verify the plugin
        function verifyPlugin(plugin) {
            if (!plugin.name) {
                error(translate("error.undefinedPluginName"));
                return false;
            }
            if (byName[plugin.name]) {
                return false;
            } /* Already added */
            return verifyPluginCategory(plugin);
        }

        // Initialize the deprecations of plugin
        function initPluginDeprecations(plugin) {
            if (!plugin.deprecatedMethods) {
                return;
            }
            var i, l;
            for (i = 0, l = plugin.deprecatedMethods.length; i < l; i += 1) {
                window.askiaVista.deprecate(plugin.deprecatedMethods[i]);
            }
        }

        // About text of plugin
        function initPluginAbout(plugin) {
            if (plugin.about && typeof (plugin.about) === "function") {
                return plugin;
            }
            var p = plugin;
            p.about = function (verbose) {
                var i, l, dName, dVersion, dRequire, str = " + " + this.name + "\r\n";
                if (this.category) {
                    str += translate("about.category", this.category);
                }
                if (this.version) {
                    str += translate("about.version", this.version);
                }
                if (this.date) {
                    str += translate("about.date", this.date);
                }
                if (this.author) {
                    str += translate("about.author", this.author);
                }
                if (this.website) {
                    str += translate("about.site", this.website);
                }
                if (!verbose) {
                    return str;
                } /* Stop here when not verbose */
                if (this.helpUrl) {
                    str += translate("about.help", this.helpUrl);
                }
                if (this.description) {
                    str += translate("about.description", this.description);
                }
                if (this.dependencies && this.dependencies.length) {
                    str += translate("about.dependencies");
                    for (i = 0, l = this.dependencies.length; i < l; i += 1) {
                        if (typeof (this.dependencies[i]) !== "function") {
                            dName = (typeof (this.dependencies[i]) === "string") ? this.dependencies[i] : "";
                            dVersion = "";
                            dRequire = true;
                            if (util.isObject(this.dependencies[i])) {
                                dName = this.dependencies[i].name || "";
                                dVersion = this.dependencies[i].version || "";
                                dRequire = (typeof (this.dependencies[i].require) === "boolean") ? this.dependencies[i].require : true;
                            }
                            if (dName !== "") {
                                if (dVersion !== "") {
                                    dVersion = " (" + dVersion + ")";
                                }
                                dRequire = (dRequire) ? "" : translate("about.optional");
                                str += "            * " + dName + dVersion + dRequire + "\r\n";
                            }
                        }
                    }
                }
                return str;
            };

            return p;
        }

        // Translation inside the plugin
        // @param {Object} plugin Plugin to update
        function initPluginTranslation(plugin) {
            if (plugin.translate && typeof (plugin.translate) === "function") {
                return plugin;
            }

            plugin.translate = function (key) {
                var fix_name = this.name.replace(/\s/gi, '_') + '.', i, l, args = [];
                if (key.indexOf(fix_name, 0) === -1) {
                    key = fix_name + key;
                }

                args.push(key);
                if (arguments.length > 1) {
                    for (i = 1, l = arguments.length; i < l; i += 1) {
                        args.push(arguments[i]);
                    }
                }
                return translate.apply(null, args);
            };

            return plugin;
        }

        // Initialize a plugin
        function initPlugin(plugin) {
            var p = plugin;
            initPluginDeprecations(p);
            p = initPluginAbout(p);
            p = initPluginTranslation(p);
            return p;
        }

        // Add plugin in collection
        function addPlugin(plugin) {
            var p = plugin;
            if (typeof (plugin) === "string") {
                p = { name: plugin };
            }
            if (!verifyPlugin(p)) {
                return;
            }
            p = initPlugin(p);
            byName[p.name] = p;
            byIndex.push(byName[p.name]);
            if (byName[p.name].init && typeof (byName[p.name].init) === "function") {
                byName[p.name].init();
            }
        }

        // Validate if the version is compatible
        function isCompatibleVersion(currentVersion, expectedVersion) {
            var computeVersion = function (version, appendComparator) {
                    var rg = /([><=]*)\s*([0-9.]+)[ -.]*(alpha|beta|rc)?[ -.]*([0-9]*)/,
                        r = rg.exec(version),
                        comp = r[1] || ">=",
                        vers = r[2].replace(/[.]/gi, ""),
                        sub,
                        ite,
                        dVer,
                        s = "";
                    while (vers.length < 3) {
                        vers += "0";
                    }
                    sub = r[3] || ".9"; //.9 for release all other is defined after
                    ite = r[4];
                    if (sub === "alpha") {
                        sub = ".1";
                    }
                    if (sub === "beta") {
                        sub = ".2";
                    }
                    if (sub === "rc") {
                        sub = ".3";
                    }
                    dVer = parseFloat(vers + s + sub + s + ite);
                    if (appendComparator) {
                        return comp + s + dVer;
                    }
                    return dVer + s;
                },
                evalVersion = function (expr) {
                    var rg = /([0-9.]+)([><=]+)([0-9.]+)/,
                        r = rg.exec(expr),
                        a = parseFloat(r[1]),
                        b = r[2],
                        c = parseFloat(r[3]);

                    switch (b) {
                        case "<":
                            return (a < c);
                        case "<=":
                            return (a <= c);
                        case ">":
                            return (a > c);
                        case ">=":
                            return (a >= c);
                        case "=":
                            return (a === c);
                        case "==":
                            return (a === c);
                        default:
                            return (a <= c);
                    }
                };

            return evalVersion("(" + computeVersion(currentVersion) + computeVersion(expectedVersion, true) + ")");
        }

        // Refresh the collection of plugins
        function refreshPlugins() {
            if ($.blockUI) {
                addPlugin({ name: "jquery.blockUI", author: "M. Alsup", category: "Windows and Overlays", website: "http://malsup.com/jquery/block/", version: $.blockUI.version, date: "06-JAN-2010" });
            }
        }

        // Validate the plugins dependencies
        function validateDependencies() {
            refreshPlugins();
            var arrErrors = [],
                i, l, plugin,
            /* Inner function */
                validatePluginDependencies = function (plugin) {
                    var i, l, result, dependentPluginName, dependentPluginVersion, dependentPluginRequire, currentVersion;
                    for (i = 0, l = plugin.dependencies.length; i < l; i += 1) {
                        dependentPluginName = "";
                        dependentPluginVersion = "";
                        dependentPluginRequire = true;
                        if (util.isObject(plugin.dependencies[i])) {
                            dependentPluginName = plugin.dependencies[i].name || "";
                            dependentPluginVersion = plugin.dependencies[i].version || "";
                            if (plugin.dependencies[i].require !== undefined && typeof (plugin.dependencies[i].require) === "boolean") {
                                dependentPluginRequire = plugin.dependencies[i].require;
                            }
                        }

                        if (typeof (plugin.dependencies[i]) === "string") {
                            dependentPluginName = plugin.dependencies[i];
                        }

                        if (typeof (plugin.dependencies[i]) === "function") {
                            /* Execute the custom validation */
                            result = plugin.dependencies[i]();
                            if (typeof (result) === "string" && result.length) {
                                arrErrors.push(result);
                            }
                        } else {

                            if (dependentPluginName !== "") {
                                if (!byName[dependentPluginName] && dependentPluginName !== "askiaVista" && dependentPluginName !== "jquery") {
                                    if (dependentPluginRequire) {
                                        arrErrors.push(translate("error.missingDependency", dependentPluginName, plugin.name));
                                    }
                                } else {
                                    currentVersion = "";
                                    switch (dependentPluginName) {
                                        case "askiaVista":
                                            currentVersion = infos.version;
                                            break;
                                        case "jquery":
                                            currentVersion = $.fn.jquery;
                                            break;
                                        default:
                                            currentVersion = byName[dependentPluginName].version;
                                            break;
                                    }

                                    if (currentVersion !== "" && dependentPluginVersion !== "") {
                                        if (!isCompatibleVersion(currentVersion, dependentPluginVersion)) {
                                            arrErrors.push(translate("error.incorrectVersionOfPlugin", dependentPluginVersion, dependentPluginName, plugin.name));
                                        }
                                    }
                                }
                            }
                        }
                    }
                };
            /* End of inner function */

            /* Validates the dependencies of askiaVista */
            validatePluginDependencies({ name: "askiaVista", version: infos.version, dependencies: infos.dependencies });
            for (i = 0, l = byIndex.length; i < l; i += 1) {
                plugin = byIndex[i];
                if (plugin.dependencies) {
                    validatePluginDependencies(plugin);
                }
            }

            if (arrErrors.length) {
                error(translate("error.pluginsExceptions") + arrErrors.join("\r\n"));
            }

        }

        // Returns the plugin by name
        function getPluginByName(name) {
            if (!byName[name]) {
                error(translate("error.cannotFoundPlugin", name));
                return false;
            }
            return byName[name];
        }

        // Returns the plugins by action
        function getPluginsByAction(action) {
            var arr = [], i, l;
            for (i = 0, l = byIndex.length; i < l; i += 1) {
                if (byIndex[i][action]) {
                    if (typeof (byIndex[i][action]) === "function") {
                        arr.push(byIndex[i]);
                    }
                }
            }
            return arr;
        }

        // Returns the plugins which have locale
        function getPluginsByLocale() {
            var arr = [], i, l;
            for (i = 0, l = byIndex.length; i < l; i += 1) {
                if (byIndex[i].localeFile && typeof (byIndex[i].localeFile) === "string") {
                    arr.push(byIndex[i]);
                }
            }
            return arr;
        }

        // Validate if the plugin exist
        function contains(name) {
            return (byName[name]) ? true : false;
        }

        // Returns the about string
        function getAboutText() {
            var str = '', i, l;
            for (i = 0, l = byIndex.length; i < l; i += 1) {
                if (str.length > 2 && str.substring(str.length - 2, str.length) !== "\r\n") {
                    str += "\r\n";
                }
                str += byIndex[i].about();
            }
            return str;
        }

        // Public interface of plugins
        return {
            add: addPlugin,
            get: getPluginByName,
            getAllByAction: getPluginsByAction,
            getAllWithLocale: getPluginsByLocale,
            contains: contains,
            refresh: refreshPlugins,
            validate: validateDependencies,
            about: getAboutText
        };
    } ());

    // Queries stack management
    queries = (function () {
        var queryStack = [],
            transactions = [],
            wasRunning = false,
            isRunning = false,
            authToken = "",
            explToken = "",
            wasAborted = false,

            // Invalidated SSO Key after logout
            invalidatedSSOKeys = {},

            // Inner launcher
            launcher = (function () {
                // Default actions
                var defaultActions = {
                    // Clear the transaction stack
                    executeBeginTransaction: function () {
                        transactions = [];
                    },

                    // Execute commit
                    executeCommit: function (options) {
                        if (!transactions.length) {
                            return;
                        }

                        var query = {
                            action: 'doTransaction',
                            transactions: []
                        }, i = 0, l = transactions.length, callbackSuccess;

                        if (options && util.isObject(options)) {
                            util.extend(true, query, options);
                        }

                        for (; i < l; i += 1) {
                            delete transactions[i].transaction; // Remove the transaction flag
                            query.transactions.push(transactions[i]);
                        }

                        query.xhr = new XHR(query);
                        callbackSuccess = query.success;

                        query.success = function (data) {
                            var i, l, d, action, options;
                            for (i = 0, l = query.transactions.length; i < l; i += 1) {

                                d = data[i];
                                if (d.stylesheet) {
                                    options = {
                                        stylesheet: d.stylesheet
                                    };
                                }
                                action = (d.success) ? "Success" : "Error";
                                queries.launcher.execute(action, d.data, query.transactions[i], options);
                            }
                            if (typeof callbackSuccess === 'function') {
                                callbackSuccess();
                            }
                        };
                        defaultActions.executeAddQuery(query);
                        if (queries.wasRunning) {
                            queries.execute();
                        }
                    },

                    //  Add query in stack
                    // @param {Object} query Query to add in stack
                    executeAddQuery: function (query) {
                        if (query.async === false && !query.transaction) {
                            queries.executeNow(query);
                        } else {
                            queries.add(query);
                        }
                    },

                    //  Abort a given query
                    // @param {Object} query Query to abort
                    executeAbort: function (query) {
                        // Remove the timer
                        if (query.timer && typeof query.timer === 'object' && query.timer.id) {
                            var timer = timers.getTimer(query.timer.id);
                            if (timer) {
                                timer.remove();
                            }
                        }
                        if (query.action !== action.display) {
                            return;
                        }
                        if (query.success) {
                            return;
                        }
                        if (!query.containerId) {
                            return;
                        }
                        document.getElementById(query.containerId).innerHTML = translate("aborted");
                    },

                    // Default behaviour when an error occured
                    // @param {String} message Error message
                    // @param {Object} query Original query for the context
                    executeError: function (message, query) {
                        message = translate(message);
                        if (query.error) {
                            query.error(message, query);
                        } else if (query.action === action.display) {
                            message = (message) ? message : translate("error.unhandleError");
                            document.getElementById(query.containerId).innerHTML = message;
                        } else if (query.action === action.login) {
                            error(message);
                        }
                    },

                    // Security error
                    // @param {String} message Error message
                    // @param {Object} query Original query for the context
                    executeSecurityError: function (message, query) {
                        message = translate(message);
                        error(message);
                    },

                    // Execute the default success event on query
                    // @param {String} data Data of success
                    // @param {Object} query Original query for the context
                    // @param {Number|Object} [options] Index of page to display (for the getPages) or object for extend configuration (like stylesheet...)
                    executeSuccess: function (data, query, options) {
                        if (query.success) {  // Execute the custom success
                            query.success(data, query, options);
                        } else { // Execute the implicit success (getPages, display, getInterviews)
                            execute('DisplayResult', data, query, options);
                            // defaultActions.executeDisplayResult(data, query, options);
                        }
                    },


                    // Display the results of cross-tab
                    // @param {String} data Data of success
                    // @param {Object} query Original query for the context
                    // @param {Number|Object} [options] Index of page to display (for the getPages) or object for extend configuration (like stylesheet...)
                    executeDisplayResult: function (data, query, options) {
                        var runDefault = true,
                            chartPlugin,
                            pages,
                            pageIndex = (typeof options === "number") ? options : (util.isObject(options) && ('page' in options)) ? (options.page || 0) : (query.page || 0),
                            stylesheet,
                            chart,
                            singlePage = false,
                            mockData  = data,
                            mockQuery = util.extend({}, query),
                            obj,
                            containerId = query.containerId,
                            portfolioData, i, l;

                        if (util.isObject(options)) {
                            if (options.stylesheet) {
                                stylesheet = options.stylesheet;
                            }
                            if (options.chart) {
                                chart = options.chart;
                            }
                            if (options.singlePage) {
                                singlePage = options.singlePage;
                            }
                        }

                        // Mock the query and the data of getPortfolioItem to act as getPages
                        if (query.action === action.getPortfolioItem) {
                            mockQuery = util.extend(true, {}, mockQuery, { action: action.getPages });
                            if (typeof (mockData) === "string") {
                                portfolioData = JSON.parse(mockData);
                            }
                            mockQuery = util.extend(true, mockQuery, portfolioData.definition || {});
                            mockData = portfolioData.results || [];
                        }

                        if (mockQuery.action === action.display ||
                            (mockQuery.action === action.getPages && mockQuery.containerId) ||
                            (mockQuery.action === action.getInterviews && mockQuery.containerId) ||
                            (mockQuery.action === action.getActivity && mockQuery.containerId) ||
                            (mockQuery.action === action.getActivityStats && mockQuery.containerId)) {

                            // Search the page
                            if (mockQuery.action === action.getPages) {
                                if (typeof (mockData) === "string") {
                                    pages = JSON.parse(mockData);
                                } else {
                                    pages = mockData;
                                }

                                if (pageIndex > pages.length) { // Fix the page index
                                    pageIndex = pages.length;
                                } else if (pageIndex < 0) {
                                    pageIndex = 0;
                                }
                            }

                            // Search the page
                            if (mockQuery.action === action.getInterviews) {
                                if (typeof mockData === 'string') {
                                    mockData = JSON.parse(data);
                                }
                                mockData = mockData.interviews;
                            }

                            // Search the page
                            if (mockQuery.action === action.getActivity
                                || mockQuery.action === action.getActivityStats) {
                                if (typeof mockData === 'string') {
                                    mockData = JSON.parse(data);
                                }
                                mockData = mockData.items;
                            }


                            // Use the chart in the options
                            if ((!mockQuery.chart || !util.isObject(mockQuery.chart)) && chart) {
                                mockQuery.chart = chart;
                            }

                            // Call the chart engine when it's necessary
                            if (mockQuery.chart && typeof (mockQuery.chart) !== 'string') {
                                if (mockQuery.chart.name) {
                                    chartPlugin = plugins.get(mockQuery.chart.name);
                                    if (!singlePage && chartPlugin) {
                                        if (mockQuery.action === action.getPages) {
                                            if (pages[pageIndex].type === "chart" && pages[pageIndex].output) {
                                                chartPlugin.draw(pages[pageIndex].output, mockQuery.chart.options, mockQuery);
                                                runDefault = false;
                                            }
                                        } else {
                                            chartPlugin.draw(mockData, mockQuery.chart.options, mockQuery);
                                            runDefault = false;
                                        }
                                    }
                                }
                            }

                            //Default behaviour
                            if (runDefault) {
                                if (mockQuery.action === action.getPages) {

                                    if (singlePage) {

                                        // Concatenate all in single page
                                        mockData = [];
                                        for (i = 0, l = pages.length; i < l; i += 1) {
                                            if (pages[i].type === "chart" && pages[i].output) {
                                                mockData.push('<div id="' + containerId + '_page' + i + '" class="askiavista-page"></div>');
                                            } else {
                                                mockData.push('<div id="' + containerId + '_page' + i + '" class="askiavista-page">');
                                                mockData.push(pages[i].output || pages[i].id + ". " + pages[i].name + " (" + pages[i].type + ")");
                                                mockData.push('</div>');
                                            }
                                        }
                                        mockData = mockData.join('');

                                    } else {

                                        // Use the current page
                                        mockData = pages[pageIndex].output ||
                                            pages[pageIndex].id + ". " + pages[pageIndex].name + " (" + pages[pageIndex].type + ")";
                                    }
                                }

                                // Then write the output
                                if (((mockQuery.action === action.getInterviews && pageIndex > 0) ||
                                    (mockQuery.action === action.getActivity && mockQuery.before > 0)) && mockQuery.lazyLoading ) {
                                    document.getElementById(containerId).querySelector('.askiatable.askia-rawdata tbody').insertAdjacentHTML("beforeEnd", mockData);
                                }
                                else if (mockQuery.action === action.getActivity && mockQuery.after > 0 && mockQuery.lazyLoading) {
                                    document.getElementById(containerId).querySelector('.askiatable.askia-rawdata tbody').insertAdjacentHTML("afterBegin", mockData);
                                }
                                else {

                                    // Add the stylesheet in the document first
                                    defaultActions.executeLoadStylesheet(stylesheet);

                                    document.getElementById(containerId).innerHTML = mockData;
                                }


                                // Display all charts
                                if (singlePage) {
                                    for (i = 0, l = pages.length; i < l; i += 1) {
                                        if (pages[i].type === "chart" && pages[i].output) {
                                            obj = util.extend({}, mockQuery, {
                                                containerId: containerId + '_page' + i
                                            });
                                            chartPlugin.draw(pages[i].output, mockQuery.chart.options, obj);
                                        }
                                    }
                                }
                            }
                        }
                    },

                    // Execute the default loadstylesheet event
                    // @param {Object} stylesheet Stylesheet object
                    // @param {String} stylesheet.root Root class for the table styles (clean name of the stylesheet)
                    // @param {String} stylesheet.definition CSS definition
                    executeLoadStylesheet: function (stylesheet) {
                        if (!stylesheet || typeof stylesheet.root !== "string" || typeof stylesheet.definition !== "string") {
                            return;
                        }
                        var doc = window.document,
                            style, textNode;

                        // Already loaded
                        if (doc.getElementById("tabstyle-" + stylesheet.root)) {
                            return;
                        }

                        style = doc.createElement('style');
                        style.setAttribute('type', 'text/css');
                        style.id = "tabstyle-" + stylesheet.root;
                        if (!style.styleSheet) { // Not IE
                            textNode = document.createTextNode(stylesheet.definition);
                            style.appendChild(textNode);
                        } else {
                            style.styleSheet.cssText = stylesheet.definition;
                        }
                        doc.getElementsByTagName("head")[0].appendChild(style);
                    }
                };

                // Execute an action
                function execute(action, data, query, options) {

                    var actionsBefore = plugins.getAllByAction("before" + action),
                        isExecute = true, i, l, result,

                        // Indicates if the object is the askiaVista query
                        isQuery = function (o) {
                            return (o && util.isObject(o) && o.action);
                        },

                        //  Returns the right askiaVista query
                         getQuery = function (data, query) {
                            if (isQuery(query)) {
                                return query;
                            }
                            if (isQuery(query)) {
                                return data;
                            }
                            return null;
                        },

                        //  Overwrite the askiaVista query
                         overwriteQuery = function (result) {
                            if (!result || !util.isObject(result)) {
                                return;
                            }
                            var newQuery = getQuery(data, query),
                                key;
                            if (!newQuery) {
                                return;
                            }
                            /* Merge parameter */
                            for (key in result) {
                                if (result.hasOwnProperty(key)) {
                                    newQuery[key] = result[key];
                                }
                            }
                            if (isQuery(query)) {
                                query = newQuery;
                            } else if (isQuery(data)) {
                                data = newQuery;
                            }
                        };


                    // Execute the actions before
                    for (i = 0, l = actionsBefore.length; i < l; i += 1) {
                        result = actionsBefore[i]["before" + action](data, query, options);
                        if (result !== undefined) {
                            if (typeof (result) === "boolean" && !result) {
                                isExecute = false;
                            }
                            overwriteQuery(result);
                        }
                    }

                    // Execute the default action and overwrite the query
                    if (isExecute) {
                        overwriteQuery(defaultActions["execute" + action](data, query, options));
                    }

                    // Execute the actions after
                    setTimeout(function () {
                        var actionsAfter = plugins.getAllByAction("after" + action), i, l, timer;
                        for (i = 0, l = actionsAfter.length; i < l; i += 1) {
                            overwriteQuery(actionsAfter[i]["after" + action](data, query, options));
                        }

                        // Start the timer right now only when action is success or error
                        if ((action === 'Success' || action === 'Error') && query.timer && typeof query.timer === 'object' && query.timer.id) {
                            timer = timers.getTimer(query.timer.id);
                            if (timer && !timer.wasStopped) {
                                timer.start((action === 'Error'));
                            }
                        }

                    }, 10);

                    return getQuery(data, query);
                }

                // Public interface of launcher
                return {
                    execute: execute,
                    executeSuccess: defaultActions.executeSuccess,
                    executeDisplayResult: function executeDisplayResult(data, query, options) {
                        return execute('DisplayResult', data, query, options);
                    },
                    executeLoadStylesheet: defaultActions.executeLoadStylesheet
                };
            } ());

        // Add query in stack
        // @param {Object} query Query to add at the end of the stack
        // @param {Boolean} onTop Indicates if the query should be add at the beginning of the stack
        function addQuery(query, onTop) {
            var stack = (query.transaction) ? transactions : queryStack;
            if (onTop) {
                stack.unshift(query);
            } else {
                stack.push(query);
            }
        }

        // Defines or returns the authenticity token according to the current config
        function authenticityToken(token) {
            var strToken,
                strParamAuthToken,
                cookieConfig = config('cookie'),
                fromCookie,
                cookieOptions = {};

            // Set the authenticity token
            if (token) {
                authToken = token;
                if (cookieConfig.enable) { //Try to write the token in the cookie
                    if (cookieConfig.secure) {
                        cookieOptions.secure = true;
                    }
                    util.cookie(cookieConfig.name, authToken, cookieOptions);
                }

                return authToken;
            }

            /* Search in the local variable first */
            if (authToken !== '') {
                return authToken;
            }

            /* Search in the config */
            strToken = config('authenticityToken');
            if (strToken !== '') {
                return strToken;
            }
            /* Search in the url parameter */
            strParamAuthToken = config('authenticityTokenUrlParam');
            strToken = getUrlParameter(strParamAuthToken);
            if (strToken !== '') {
                return strToken;
            }
            /* Still not found, then search in the cookie */
            /* Try to read the token inside the cookie */
            if (cookieConfig.enable) {
                fromCookie = util.cookie(cookieConfig.name);
                if (fromCookie) {
                    return fromCookie;
                }
            }
            /* Ok no way */
            return '';
        }

        // Defines or returns the explicit authenticity token
        function explicitToken(token) {
            var cookieConfig = config('cookie'), fromCookie, cookieOptions = {};

            // Set the authenticity token
            if (token) {
                explToken = token;
                // Write it in the cookie also
                if (cookieConfig.enable) { //Try to write the token in the cookie
                    if (cookieConfig.secure) {
                        cookieOptions.secure = true;
                    }
                    util.cookie('askiaVistaExplicit', explToken, cookieOptions);
                }
                return explToken;
            }

            /* Search in the local variable first */
            if (explToken !== '') {
                return explToken;
            }

            /* Search in the cookie */
            /* Try to read the token inside the cookie */
            if (cookieConfig.enable) {
                fromCookie = util.cookie('askiaVistaExplicit');
                if (fromCookie) {
                    return fromCookie;
                }
            }
            /* Ok no way */
            return '';
        }

        // Read the SSO Key in the url and return it
        function getSSOKey() {
            var ssoKey =  getUrlParameter('sso');
            return (!invalidatedSSOKeys[ssoKey]) ? ssoKey : '';
        }

        // Logout the user
        function logout() {
            authToken = '';
            explToken = '';
            config('authenticityToken', '');

            var cookieConfig = config('cookie');
            if (cookieConfig.enable) { //Try to write the token in the cookie
                util.cookie(cookieConfig.name, null);
                util.cookie('askiaVistaExplicit', null);
            }
            // Remove the SSOKey in URL parameter
            var ssoKey = getSSOKey();
            if (ssoKey) {
                invalidatedSSOKeys[ssoKey] = true;
            }
        }

        // Execute a query now
        function executeQueryNow(query) {
            if (wasAborted) {
                return;
            }
            if (query && query.xhr && query.xhr.execute) {
                query.xhr.execute();
            }
        }

        // Execute the next query
        function executeNextQuery(force) {
            if (wasAborted) {
                return;
            }
            if (force) {
                isRunning = false;
            }
            queries.wasRunning = true;
            if (isRunning) {
                return;
            }
            if (!queryStack.length) {
                return;
            }
            isRunning = true;
            var query = queryStack.shift();
            executeQueryNow(query);
        }

        // Abort all queries
        function abortQueries(fast) {
            wasAborted = true;
            timers.each(function removeAllTimers(timer) {
                timer.remove();
            });
            if (fast) {
                queryStack = [];
            }
            var query, i, l;
            for (i = 0, l = queryStack.length; i < l; i += 1) {
                query = queryStack[i];
                launcher.execute("Abort", query);
            }
        }

        // Public interface of queries
        return {
            authenticityToken: authenticityToken,
            explicitToken   : explicitToken,
            getSSOKey  : getSSOKey,
            logout: logout,
            wasRunning: wasRunning,
            add: addQuery,
            executeNow: executeQueryNow,
            execute: executeNextQuery,
            abort: abortQueries,
            launcher: launcher
        };
    } ());

    //  Creates a custom XMLHttpRequest for the AJAX query
    // This object is used to manage the query in coordination with the query stack
    XHR = (function () {
        // Enforce the execution of the query
        var FORCE = true;

        // Sanitize the parameter
        function sanitizeParam(obj) {
            var results = {}, prop, value, transactions = [], i, l;
            for (prop in obj) {
                if (!obj.hasOwnProperty(prop) ||
                    !parameters.hasOwnProperty(prop) ||
                    typeof (obj[prop]) === 'function' ||
                    obj[prop] === null ||
                    obj[prop] === undefined) {

                    continue;
                }

                value = obj[prop];

                // Format the string as table
                if (prop === parameters.rows || prop === parameters.columns || prop === parameters.edges ||
                    prop === parameters.questions || prop === parameters.calculations) {
                    if (typeof (value) === "string") {
                        value = value.split("|");
                    }
                }

                // Don't send the entire definition of the timer
                // it's not necessary for the server side
                if (prop === 'timer') {
                    value = true;
                }

                if (util.isObject(value) || util.isArray(value)) {

                    // Sanitize transactions
                    if (prop === parameters.transactions) {
                        for (i = 0, l = value.length; i < l; i += 1) {
                            transactions[i] = sanitizeParam(value[i]);
                        }
                        value = transactions;
                    }

                    // Sanitize the chart object
                    // only keep name and options keys
                    if (prop === parameters.chart) {
                        value = {};
                        if (obj.chart.name) {
                            value.name = obj.chart.name;
                        }
                        if (obj.chart.options) {
                            value.options = obj.chart.options;
                        }

                        // Fix the format of the output according to the chart parameter
                        if (!obj.format) {
                            if (obj.action === action.display) {
                                results.format = "json";
                            } else if (obj.action === action.getPages) {
                                results.format = {
                                    table: "html",
                                    chart: "json"
                                };
                            }
                        }
                    }

                    // Stringify to obtain only one parameters in the server side,
                    // for example obtain format="{table:html,char:json}"
                    // instead of format[table]="html"&format[chart]="json"
                    value = JSON.stringify(value);
                }
                results[prop] = value;
            }
            return results;
        }

        // Sanitize the query
        function sanitizeQuery(q) {
            var paramsToSend = sanitizeParam(q),
                explicitToken = queries.explicitToken(),
                ssoKey = queries.getSSOKey(),
                appName = config('appName'),
                appVersion = config('appVersion');

            paramsToSend[parameters.authenticityToken] = queries.authenticityToken();

            if (explicitToken) {
                paramsToSend[parameters.explicitAuthenticityToken] = explicitToken;
            }
            if (ssoKey) {
                paramsToSend[parameters.ssoKey] = ssoKey;
            }
            if (appName) {
                paramsToSend[parameters.appName] = appName;
            }
            if (appVersion) {
                paramsToSend[parameters.appVersion] = appVersion;
            }
            // Version of the API
            paramsToSend[parameters.ajaxApiVersion] = infos.version;
            // Time offset of the client
            paramsToSend[parameters.timeOffset] = infos.timeOffset;
            return paramsToSend;
        }

        // Transform the query to AJAX request
        function getAJAX(self) {
            var param = sanitizeQuery(self.query),

            // Assign the xhr object to the query
                request = {
                    url: config('url'),
                    async: self.query.async !== false,
                    data: util.param(param),
                    type: 'post',
                    originalData : param,
                    error: function (message, reason) {
                        if (reason === 'abort') { // Bypass the error
                            queries.execute(FORCE);
                            return;
                        }

                        // LoadLocale has different behaviour
                        if (self.query.action === action.loadLocale) {
                            //Execute error
                            if (self.query.error && typeof (self.query.error) === "function") {
                                self.query.error();
                            }

                            queries.execute(FORCE);
                            return;
                        }

                        try {
                            JSON.parse(message);
                        } catch (e) {
                            message = htmlEncoder.htmlEncode(message, true);
                        }
                        queries.launcher.execute("Error", message, self.query);

                        if (self.query.action === action.login) {
                            return;
                        }
                        queries.execute(FORCE);
                    },
                    success: function (data) {
                        if (self.aborted) {
                            this.error('', 'abort');
                            return;
                        }
                        var response, fn, options, subActionKey, subActionParam, subActionResult;

                        // LoadLocale has different behaviour
                        if (self.query.action === action.loadLocale) {
                            //Execute success
                            if (self.query.success && typeof (self.query.success) === "function") {
                                self.query.success();
                            }

                            queries.execute(FORCE);
                            return;
                        }

                        if (typeof data === 'string') {
                            response = JSON.parse(data);
                        } else  {
                            response = data;
                        }
                        response = response[0];

                        // Logout abort all subsequent queries
                        if (self.query.action === action.logout) {
                            queries.launcher.execute("Success", response.data, self.query);
                            return;
                        }
                        if ((!response.success && response.severity === SECURITY_EXCEPTION) || (response.token === "" &&
                            self.query.action !== action.login &&  self.query.action !== action.logout)) { //Security error
                            queries.launcher.execute("SecurityError", htmlEncoder.htmlEncode(response.data, true), self.query);
                            this.error(response.data);
                            return;
                        }

                        if (!response.success && response.severity !== INVALID_AUTHENTICITY_TOKEN_EXCEPTION) {
                            this.error(response.data);
                            return;
                        }

                        // With disconnection, we should clear the stack of queries
                        // and log the user out
                        if (response.token === 'sessionDisconnected') {
                            // Logout the queries (clear the cookie and tokens)
                            queries.logout();
                            // Clear the query stack
                            queries.abort(true);
                            // Call the disconnect function
                            fn = config('disconnect');
                            if (typeof fn === 'function') {
                                fn();
                            } else {
                                this.error(translate("error.sessionDisconnected"));
                            }
                            //Don't continue
                            return;
                        }

                        if (response.token === 'requireLogin' ||
                            response.severity === INVALID_AUTHENTICITY_TOKEN_EXCEPTION ||
                            response.token === 'sessionTimeout' || response.token === 'confirmSessionDisconnection') {
                            // Add explicit token if require for the next call
                            // Useful for the SSO management
                            if ((response.token === 'sessionTimeout' || response.token === 'confirmSessionDisconnection')
                                && response.explicitToken) {
                                queries.explicitToken(response.explicitToken);
                            }

                            subActionKey = (response.token !== 'confirmSessionDisconnection' || !response.explicitToken) ?
                                'showLoginForm' : 'confirmSessionDisconnection';
                            subActionParam = (subActionKey === 'showLoginForm') ? response.token : self.query;

                            /* Add again the query into the stack ... */
                            if (subActionKey !== 'confirmSessionDisconnection') {
                                queries.add(self.query, true);
                            }

                            /* ... and ask the login and password */
                            fn = config(subActionKey);
                            if (typeof (fn) === 'function') {
                                subActionResult = fn(subActionParam);
                                if (subActionKey === 'confirmSessionDisconnection' && typeof subActionResult === 'boolean') {
                                    // Confirm the session disconnection if it's not already done by the fn
                                    core.login({
                                        confirmSessionDisconnection : subActionResult,
                                        success : self.query.success,
                                        error  : self.query.error
                                    });
                                }
                            } else {
                                this.error(translate("error.authenticationRequire"));
                            }
                            //Don't continue
                            return;
                        }

                        //Set the token
                        if (response.token !== 'portfolioToken' && response.token !== 'portfolioItemToken') {
                            queries.authenticityToken(response.token);
                        }
                        // Explicit token
                        if (response.explicitToken) {
                            queries.explicitToken(response.explicitToken);
                        }

                        //Execute success
                        if (response.stylesheet) {
                            options = options || {};
                            options.stylesheet = response.stylesheet;
                        }
                        if (response.singlePage) {
                            options = options || {};
                            options.singlePage = response.singlePage;
                        }
                        if (response.chart) {
                            options = options || {};
                            options.chart = response.chart;
                        }

                        queries.launcher.execute("Success", response.data, self.query, options);
                        queries.execute(FORCE);
                    }
                };

            if (self.query.dataType) {
                request.dataType = self.query.dataType;
            }
            return request;
        }

        // Create inputs for a form in order to submit the query
        // return false when an error occurred
        // return true otherwise
        function appendQueryToInputForm(doc, form, data) {
            var prop,
                pair;

            // Returns the input string
            function addInput(name, value) {
                var input = doc.createElement('input');
                input.setAttribute('type', 'hidden');
                input.setAttribute('name', name);
                input.value = value;
                form.appendChild(input);
            }

            // Data can be string of parameters or object
            if (util.isObject(data)) {
                for (prop in data) {
                    if (data.hasOwnProperty(prop)) {
                        if (data[prop] === null || data[prop] === undefined) {
                            continue;
                        }
                        addInput(prop.toString(), data[prop].toString());
                    }
                }
            } else if (typeof (data) === "string") {
                // Split params into form inputs
                $.each(data.split('&'), function () {
                    pair = this.split('=');
                    addInput(pair[0], pair[1]);
                });
            } else {
                return false; // Error
            }
            return true;
        }

        // Execute a query using the iFrame
        // @param {IFrame} iFrame IFrame object
        // @param {Object} ajax AJAX query to execute
        function executeWithIFrame(iFrame, ajax) {
            var doc = iFrame.context.document,
                param = ajax.originalData;

            if (!appendQueryToInputForm(doc, iFrame.form[0], param)) {
                ajax.error(translate("error.incorrectIFrameArg"));
                return;
            }

            // Manage the callback of the iFrame
            iFrame.callback = function iFrameCallback(data) {
                // Manage the response
                ajax.success(data);

                // Reload the iFrame
                iFrame.reload();

                // Remove the additional callback function
                delete iFrame.callback;
            };
            iFrame.form.submit();
        }



        // Inner XHR
        function XHR(query) {
            this.query = query;

            // jQuery XHR object
            this.jqxhr = null;

            // Indicates if the query was aborted,
            // this variable is useful if the query is still
            // on the query stack and not already executed
            this.aborted = false;
        }

        //  Execute an ajax query
        XHR.prototype.execute = function executeXHR() {
            var ajax = getAJAX(this);

            // Execute the ajax through the iFrame
            if (this.query.fromIFrame) {
                if (!core.iFrames[this.query.fromIFrame]) {
                    ajax.error('error.couldNotFindTheIFrame');
                }
                executeWithIFrame(core.iFrames[this.query.fromIFrame], ajax);
                return;
            }

            if (!this.aborted) {
                this.jqxhr = $.ajax(ajax);
            } else {
                // Execute the error when the query was aborted
                ajax.error('', 'abort');
            }
        };

        //  Abort an AJAX request
        XHR.prototype.abort = function () {
            this.aborted = true;
            if (this.jqxhr && this.jqxhr.abort) {
                this.jqxhr.abort();
            }
        };

        // Statics
        XHR.sanitizeQuery = sanitizeQuery;
        XHR.appendQueryToInputForm = appendQueryToInputForm;

        return XHR;
    } ());

    // iFrame object
    IFrame = (function () {
        // IFrame constructor
        // @param {Object} options Options object
        // @constructor
        function IFrame(options) {
            options.action = action.createIFrame;
            this.options = options;
            this.id = options.id;
            $('<iframe id="' + options.id + '" src="' + this.getURL()  + '" style="display:none"></iframe>').appendTo('body');
            this.element = $('#' + options.id);
        }

        //  Set the context window
        // @param {Window} context Context of the iframe
        IFrame.prototype.setContext = function setContext(context) {
            this.context = context;
            this.form   = $(this.context.document).find('form');
            if (this.options.fileUploadName) {
                this.form.append('<input type="file" id="' + this.options.fileUploadName + '" name="' + this.options.fileUploadName + '" />');
            }
            if (typeof this.options.success === 'function') {
                this.options.success(this, this.options);
            }
        };

        //  Select file
        // @param {Object} [query] Query with pattern and callback
        // @param {RegExp} [query.pattern Pattern] to filter the selection
        // @param {String} [query,fileUploadName] Name of the input file
        // @param {Function} [query.success] Success method to call with the name of the file selected
        // @param {Function} [query.error] Error method when the selection doesn't match the pattern
        IFrame.prototype.selectFile = function selectFile(query) {
            query = query || {};
            var fileUploadName = query.fileUploadName || this.options.fileUploadName,
                input;

            if (!fileUploadName) {
                if (typeof query.error === 'function') {
                    query.error(translate('error.noFileUploadNameSpecified'), query);
                }
                return;
            }

            input = this.form.find('#' + fileUploadName);
            // Creates the input file right now if not found
            if (!input.length) {
                this.form.append('<input type="file" id="' + fileUploadName + '" name="' + fileUploadName + '" />');
                this.form.find('#' + fileUploadName);
            }
            if (!input.length) {
                if (typeof query.error === 'function') {
                    query.error(translate('error.couldNotFindInputFile'), query);
                }
                return;
            }


            // Verify the selected file and execute the callbacks
            input
                // Unbind the previous change event
                .unbind('change.askiavista')

                // Bind the change event
                .bind('change.askiavista', function onChange() {
                    var value = this.value,
                        re = /[\/\\]?([^\/\\]+)$/,
                        match;
                    if (value && query.pattern) {
                        if (!query.pattern.test(value)) {
                            this.value = '';
                            if (typeof query.error === 'function') {
                                query.error(translate('error.invalidFileExtension'), query);
                            }
                            return;
                        }
                    }

                    match = value.match(re);
                    if (match && match.length) {
                        value = match[1];
                    }
                    if (typeof query.success === 'function') {
                        query.success(value, query);
                    }
                })
                // Simulate the click on the input file
                .click();
        };

        //  Reset the form
        IFrame.prototype.reset = function reset() {
            if (this.form && this.form.length) {
                this.form[0].reset();
            }
        };

        // Get the url of the iFrame
        IFrame.prototype.getURL = function getURL() {
            var param = XHR.sanitizeQuery(this.options),
                url = [];
            url.push(config('url') + '?action=' + param.action);
            url.push('id=' + encodeURIComponent(this.options.id));
            url.push(parameters.authenticityToken + '=' + encodeURIComponent(param.authenticityToken));
            if (param.explicitAuthenticityToken) {
                url.push(parameters.explicitAuthenticityToken + '=' + encodeURIComponent(param.explicitAuthenticityToken));
            }
            url.push('dmy=' + getDummyValue());
            return  url.join('&');
        };

        //  Reload the iFrame
        IFrame.prototype.reload = function reload() {
            this.element.attr('src', this.getURL());
        };

        //  Destroy the previous reference
        IFrame.prototype.destroy = function destroy() {
            this.element.empty().remove();
            delete this.element;
            delete this.form;
            delete this.context;
            delete core.iFrames[this.options.id];
        };

        return IFrame;
    }());

    /**
     * # AskiaVista AJAX Framework - API documentation
     *
     * The AskiaVista AJAX is mainly based on the ajax calls,
     * that means that the browser (client-side) sends an ajax request to the server-side each time you invoke a method
     * (except some methods like abort(), about(), version() etc)
     *
     * To be more efficient, easy to use and easy to learn, the AskiaVista AJAX is very consistent and uses some spelling conventions.
     *
     * All methods and parameters use the lowerCamelCase syntax (first letter in lower case and the first letter of each other words in upper-case: useCamelCaseSyntax).
     *
     * In addition to the lowerCamelCase syntax, the methods and parameters makes the difference between the singular and plural form,
     * for example:
     *
     * - getSubPopulations() -> Obtain the list of sub-populations
     * - getSubPopulation() -> Obtain a single sub-population definition
     *
     * The AskiaVista AJAX is based on a single object/namespace `askiaVista` from where all methods will be invoked:
     * askiaVista.myMethod();
     *
     * Except some methods which not require a server side execution (abort(), about()...),
     * all methods accept a single argument which is the hash of pairs key/value.
     *
     * @class askiaVista
     */
    core = (function () {
        var fn = {},
            lastContainerId = 0,
            isTransaction = false;

        // Indicates if the action require the survey key
        function isRequireSurvey(actionName) {
            var actionWithoutSurvey = [action.getSurveys,
                action.loadLocale, action.login, action.getChartTemplates,
                action.getTabStyles, action.getCalculations,
                action.getUserInfo, action.saveUserInfo,
                action.getResources,
                action.getActivity, action.getActivityStats, action.getActivityFilters];

            return (actionWithoutSurvey.indexOf(actionName) === -1);
        }

        // Extend the query with additional keys
        function extendQuery(query, ignoreXhr) {
            var configKeysCommon      = [parameters.language],
                configKeysForCrossTab = [parameters.settings, parameters.calculations,
                    parameters.chart, parameters.tabStyle,
                    parameters.subPopulation, parameters.waves,
                    parameters.universe, parameters.weighting,
                    parameters.level, parameters.title,
                    parameters.width, parameters.height],
                i, l, key, val,
                entity = query.entity && query.entity.toLowerCase(),
                hasToken = query.portfolioToken || query.portfolioItemToken,
                isCrossTabEntity = (entity === 'crosstab' || entity === 'portfolio'),
                isCrossTabOrRawData = (query.action === action.getPages ||
                    query.action === action.display ||
                    query.action === action.getInterviews ||
                    (query.action === action.exportTo && (isCrossTabEntity || hasToken)));

            query.dmy = getDummyValue();
            if (isRequireSurvey(query.action) && !query.survey) {
                query.survey = config("survey");
            }

            // Add the XHR object on query
            if (!ignoreXhr) {
                if (!isTransaction) {
                    query.xhr = new XHR(query);
                } else {
                    query.transaction = true;
                }
            }

            // Auto add the verbose key when it's not defined
            // for the getPages when it contains the containerId
            if (query.action === action.getPages && query.containerId && (query.verbose === undefined || query.verbose === null)) {
                query.verbose = true;
            }
            // Merge with the keys in configuration
            if (query.action !== 'doTransaction') {
                for (i = 0, l = configKeysCommon.length; i < l; i += 1) {
                    key = configKeysCommon[i];
                    if (!query.hasOwnProperty(key)) {
                        val = config(key);
                        if (val !== undefined && val !== null) {
                            query[key] = val;
                        }
                    }
                }
            }

            if (isCrossTabOrRawData) {
                for (i = 0, l = configKeysForCrossTab.length; i < l; i += 1) {
                    key = configKeysForCrossTab[i];
                    if (!query.hasOwnProperty(key)) {
                        val = config(key);
                        if (val !== undefined && val !== null) {
                            query[key] = val;
                        }
                    }
                }
            }


            return query;
        }

        // Display the loading message for getPages and display method
        function displayLoadingMessage(query) {
            if (!query || (query.action !== action.display &&
                    query.action !== action.getPages &&
                    query.action !== action.getInterviews &&
                    query.action !== action.getActivity &&
                    query.action !== action.getActivityStats)) {
                return;
            }
            if ((query.action === action.getPages
                || query.action === action.getInterviews
                || query.action === action.getActivity
                || query.action === action.getActivityStats)
                && !query.containerId) {
                return;
            }

            var loadingMessage = (query.loadingMessage !== null && query.loadingMessage !== undefined) ? query.loadingMessage : config('loadingMessage'),
                strMessage = '';
            if (loadingMessage && typeof (loadingMessage) === "string") {
                strMessage = loadingMessage;
            }

            // When using the lazy loading, only allows the usage of the custom loading method function
            // Otherwise returned
            if ((query.action === action.getInterviews || query.action === action.getActivity)
                && query.lazyLoading && (query.page || query.before || query.after)) {
                /* Execute method for the loadingMessage */
                if (typeof (loadingMessage) === "function") {
                    loadingMessage(query);
                }
                return;
            }

            /* Creates the div container */
            if (!query.containerId) {
                lastContainerId += 1;
                query.containerId = "askiareport-" + lastContainerId;
                var elAutoContainer = document.createElement("div");
                elAutoContainer.setAttribute("id", query.containerId);
                elAutoContainer.innerHTML = strMessage;
                document.body.appendChild(elAutoContainer);
            } else if (strMessage) {
                dom.ready(function () {
                    document.getElementById(query.containerId).innerHTML = strMessage;
                });
            }

            /* Execute method for the loadingMessage */
            if (typeof (loadingMessage) === "function") {
                loadingMessage(query);
            }
        }

        // Add query in queries stack
        function addQuery(act, query) {
            query = query || {};
            query.action = act;
            extendQuery(query);

            // Register the query in the timer collection
            if (query.timer && typeof query.timer === 'object') {
                timers.create(query);
            }

            displayLoadingMessage(query);
            queries.launcher.execute("AddQuery", query);
            if (queries.wasRunning) {
                queries.execute();
            }
        }

        // Add a plugin
        // TODO::Document
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method addPlugin
         * @static
         * @param plugin
         */
        function addPlugin(plugin) {
            plugins.add(plugin);
        }

        // Get a plugin
        // TODO::Document
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method getPlugin
         * @static
         * @since 2.1.0
         * @param name
         */
        function getPlugin(name) {
            return plugins.get(name);
        }

        // Append the core method in fn
        function appendCoreMethod(action) {
            fn[action] = function (query) {
                addQuery(action, query);
            };
        }

        // Display an helper message for the deprecated methods
        // TODO::Document
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method deprecate
         * @static
         * @param query
         */
        function appendDeprecatedMethod(query) {
            var methodName = "", message = "";
            if (typeof (query) === "string") {
                methodName = query;
            }
            if (util.isObject(query)) {
                methodName = query.name || "";
                message = query.message || "";
            }
            if (methodName === "") {
                return;
            }
            if (message === "") {
                message = translate("error.deprecatedMethod", methodName);
            }
            fn[methodName] = function () {
                error(message);
            };
        }

        /**
         * Execute a transaction.
         *
         * This method aggregates several askiaVista queries to a single AJAX query.<br />
         * It's extremely useful for the:
         *
         * - Performance: it reduce the number of AJAX queries
         * - Synchronisation: all callbacks are treats without (AJAX) interruptions
         *
         * All askiaVista queries called inside the function passed in arguments will aggregated in the transaction.
         *
         *
         *      // Obtain all common survey properties in one AJAX query
         *      askiaVista.doTransaction(function () {
         *           askiaVista.getLevels({
         *               survey : "EX",
         *               success : function (data) {
         *                  console.log('levels', JSON.parse(data));
         *               }
         *           });
         *
         *           askiaVista.getSubPopulations({
         *               survey : "EX",
         *               success : function (data) {
         *                  console.log('subPopulations', JSON.parse(data));
         *               }
         *           });
         *
         *           askiaVista.getWeightings({
         *               survey : "EX",
         *               success : function (data) {
         *                  console.log('weightings', JSON.parse(data));
         *               }
         *           });
         *      });
         *
         *
         *      // Execute two cross-tabs
         *      askiaVista.doTransaction(function () {
         *           askiaVista.display({
         *               survey : "EX",
         *               rows : "gender",
         *               columns : "age",
         *               containerId : "result1"
         *           });
         *
         *           askiaVista.display({
         *               survey : "EX",
         *               rows : "gender",
         *               columns : "profession",
         *               containerId : "result2"
         *           });
         *      });
         *
         * @member askiaVista
         * @method doTransaction
         * @static
         * @since 2.1.0
         *
         * @param {Function} fn Function to encapsulate all askiaVista queries to aggregate in the transaction
         * @param {Object} options AJAX options
         * @param {Boolean} [options.async=true] Make the query synchronous or asynchronous
         * @param {Function} [options.success] Callback when the transaction itself succeed
         * @param {Function} [options.error] Callback when the transaction itself failed
         */
        function doTransaction(fn, options) {
            isTransaction = true;
            queries.launcher.execute('BeginTransaction');
            fn();
            isTransaction = false;
            queries.launcher.execute('Commit', options);
        }

        /**
         * Helper method to create a form to trigger the download of a file
         *
         * This method create an hidden form (with action="post") and submit it using
         * the target="_blank" to avoid the page to follow the url
         *
         * @member askiaVista
         * @method download
         * @static
         * @since 2.1.0
         * @param {String} url URL to download the data, it could be a link to a static file or dynamic page
         * @param {Object|String} data Flat object (key/value without nesting) or URL parameter in form of key=value&key1=value1
         */
        function download(url, data) {
            var form = document.createElement("form");
            form.setAttribute("name", "askiaVistaExportTo");
            form.setAttribute("action", url);
            form.setAttribute("method", "post");
            form.setAttribute("target", "_blank");
            form.style.display = "none";

            if (!XHR.appendQueryToInputForm(document, form, data)) {
                error(translate("error.incorrectExportDownloadDataArg"));
                return;
            }

            // Creates a temporary form to download the file
            $(form)
                .appendTo('body')
                .submit()
                .remove();
        }

        /**
         * Export an entity to a file to download.
         *
         * This method internally use the #download method.
         *
         * The available entities are:
         *
         * * {@link askiaVista.queries.exportTo.crosstab Cross-tab} : Execute a cross-tab and export it to Microsoft Excel file
         * * {@link askiaVista.queries.exportTo.interviews Interviews}: Get interviews and export it to Microsoft Excel file
         * * {@link askiaVista.queries.exportTo.portfolio Portfolio} : Execute all cross-tab within the portfolio and export them to Microsoft Excel file
         * * {@link askiaVista.queries.exportTo.tabStyle Table Style} : Generate a zip fie with the definition (CSS or LESS) of the table style
         * * {@link askiaVista.queries.exportTo.chartTemplate Chart Template} : Generate a zip file with the definition of the chart template
         *
         *       // Export a cross-tab result to MS Excel
         *       askiaVista.exportTo({
         *            entity : "crosstab",
         *            fileFormat : "Excel",
         *            fileName : "Gender_by_age.xlsx",
         *            rows : "i1. Gender",
         *            columns : "i2. Age"
         *       });
         *
         *       // Export interviews to MS Excel
         *       askiaVista.exportTo({
         *            entity : "interviews",
         *            fileFormat : "Excel",
         *            fileName : "verbatim.xlsx",
         *            questions : ["comment"]
         *       });
         *
         *       // Export the entire portfolio to MS Excel
         *       askiaVista.exportTo({
         *            entity : "portfolio",
         *            fileFormat : "Excel",
         *            fileName : "my_portfolio.xlsx",
         *            name : "my_portfolio"
         *       });
         *
         *       // Export a table style
         *       askiaVista.exportTo({
         *          entity : "tabStyle",
         *          fileFormat : "less",
         *          fileName   : "blue.zip",
         *          name : "Blue"
         *       });
         *
         *       // Export a chart template
         *       askiaVista.exportTo({
         *          entity : "chartTemplate",
         *          fileName   : "standard_column.zip",
         *          name : "Standard column"
         *       });
         *
         * @member askiaVista
         * @method exportTo
         * @static
         * @since 2.1.0
         * @param {askiaVista.queries.exportTo} query Query to export data to a file to download
         */
        function exportTo(query) {
            if (!util.isObject(query)) {
                error(translate("error.undefinedTypeOfQuery"));
                return;
            }
            var isUsingToken = query.portfolioToken || query.portfolioItemToken;
            if (!query.entity && !isUsingToken) {
                error(translate("error.expectedEntityParameter"));
                return;
            }
            if (!query.fileFormat) {
                error(translate("error.expectedFileFormatParameter"));
                return;
            }
            if (!isUsingToken && entities.indexOf(query.entity) === -1) {
                error(translate("error.invalidEntityParameter"));
                return;
            }

            // Update the query
            query.action = action.exportTo;
            query = XHR.sanitizeQuery(extendQuery(query));
            download(config("url"), query);
        }

        // Save the user information
        // TODO::Document
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method saveUserInfo
         * @static
         * @since 2.1.0
         * @param query
         */
        function saveUserInfo(query) {
            if (!query.password && !query.passwordConfirm && !query.passwordActual) {
                addQuery(action.saveUserInfo, query); // Normal flow
            } else {
                encrypt({
                    value    : [query.passwordActual || "", query.password || "", query.passwordConfirm || ""],
                    success  : function(data) {
                        query.passwordActual = data[0];
                        query.password = data[1];
                        query.passwordConfirm = data[2];
                        addQuery(action.saveUserInfo, query);
                    }
                });
            }
        }

        // Creates an iFrame to execute query through
        // TODO::Document
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method createIFrame
         * @static
         * @since 2.1.0
         * @param query
         * @returns {*}
         */
        function createIFrame(query) {
            if (!query.id) {
                error(translate("error.incompleteQuery"));
                return null;
            }
            // Remove the previous instance of the same iFrame
            if (core.iFrames[query.id] && typeof core.iFrames[query.id].destroy === 'function') {
                core.iFrames[query.id].destroy();
            }
            core.iFrames[query.id] = new IFrame(query);
            return core.iFrames[query.id];
        }

        // Extend the askiaVista
        // TODO::Document
        /**
         * @inheritdoc askiaVista.abstracts#docUnderConstruction
         * @member askiaVista
         * @method extend
         * @static
         * @param params
         */
        function extend(params) {
            if (!params) {
                return;
            }
            var key;
            if (util.isObject(params)) {
                for (key in params) {
                    if (params.hasOwnProperty(key)) {
                        /* Don't allow to overwrite the default methods */
                        if (!action[key]) {
                            fn[key] = params[key];
                        }
                    }
                }
            }
        }

        // Initialize the configuration using URL parameters
        function initConfigWithUrlParams() {
            // Change locale using the url parameter
            var localeFromUrl = getUrlParameter(config('localeUrlParam')),
                languageFromUrl = getUrlParameter(config('languageUrlParam'));

            if (localeFromUrl) {
                config({
                    locale: localeFromUrl
                });
            }
            if (languageFromUrl) {
                config({
                    language : languageFromUrl
                });
            }
        }

        // Initialize the object (dynamically add method using the actions)
        function init() {
            initConfigWithUrlParams();
            plugins.refresh();
            var query, method;
            for (query in action) {
                if (action.hasOwnProperty(query)) {
                    method = action[query];
                    if (!fn[method]) {
                        appendCoreMethod(method);
                    }
                }
            }

            /* Append the deprecated methods below */
            appendDeprecatedMethod({ name: "getProfile", message: "Sorry, but the method 'getProfile' was deprecated, please use the method 'getQuestions' instead\r\n or include the back-compatibility plugin (1.00) to re-activate this method" });
            initializing = false;
        }

        // Public interface of the core object
        fn = {
            // Enumerators
            action: action,
            parameter: parameters,

            // i18n
            loadLocale: loadLocale,
            translate: translate,

            // Configuration
            config: config,
            error: error,

            // Authentication and user info
            login: login,
            logout: logout,
            saveUserInfo : saveUserInfo,
            encrypt: encrypt,

            /**
             * @inheritdoc askiaVista.abstracts#docUnderConstruction
             * @member askiaVista
             * @method displayResult
             * @static
             * @since 2.1.0
             * @param query
             */
            displayResult: queries.launcher.executeDisplayResult,
            /**
             * @inheritdoc askiaVista.abstracts#docUnderConstruction
             * @member askiaVista
             * @method loadStylesheet
             * @static
             * @since 2.1.0
             * @param query
             */
            loadStylesheet: queries.launcher.executeLoadStylesheet,

            // Query managements
            /**
             * @inheritdoc askiaVista.abstracts#docUnderConstruction
             * @member askiaVista
             * @method sanitizeQuery
             * @static
             * @since 2.1.0
             * @param query
             */
            sanitizeQuery: XHR.sanitizeQuery,
            abort: abort,
            doTransaction: doTransaction,
            /**
             * @inheritdoc askiaVista.abstracts#docUnderConstruction
             * @member askiaVista
             * @method executeSuccess
             * @static
             * @since 2.1.0
             * @param query
             */
            executeSuccess: function (data, query, options) {
                queries.launcher.execute('Success', data, query, options);
            },
            /**
             * @inheritdoc askiaVista.abstracts#docUnderConstruction
             * @member askiaVista
             * @method executeError
             * @static
             * @since 2.1.0
             * @param query
             */
            executeError: function (message, query) {
                queries.launcher.execute('Error', message, query);
            },

            // Management of query through iFrame
            iFrames : {},
            createIFrame : createIFrame,

            // Download and exports
            exportTo: exportTo,
            download: download,

            // Extends askiaVista
            addPlugin: addPlugin,
            getPlugin: getPlugin,
            extend: extend,
            deprecate: appendDeprecatedMethod,

            // Timers
            startTimers  : startTimers,
            stopTimers   : stopTimers,
            clearTimers  : clearTimers,


            // HTML Encode
            htmlEncode   : htmlEncoder.htmlEncode,

            // Get extra information
            version: version,
            about: about,
            help: help
        };
        init();

        return fn;
    } ());

    // ~ Extend jQuery to read parameter in url ~
    util.extend($, {
        getUrlParameter: getUrlParameter
    });

    // ~ Expose the variable askiaVista ~
    window.askiaVista = core;
    dom.listen();


    function initAskiaVista() {
        // Begin the ajax requests when the dom is ready to use
        dom.ready(function () {
            core.loadLocale(config('locale'));
            plugins.validate();
            queries.execute();
        });
    }

    if (typeof define === "function" && define.amd) {
        define("askiaVista", ["module"], function defineAskiaVista(module) {
            var conf = module.config();
            if (util.isObject(conf)) {
                core.config(conf);
            }
            initAskiaVista();
            return core;
        });
    } else {
        initAskiaVista();
    }
} (window, jQuery));