<commit_before>// Highlight config
Highlight.configure({ classPrefix: '' });
Marked.setOptions({
    highlight: function (code) {
        return Highlight.highlightAuto(code).value;
    }
});

/**
 * validateField
 * This funciton validates the value by
 * providing the validators
 *
 * @name validateField
 * @function
 * @param {Anything} value the value that should be validated
 * @param {String} validators comma separated validators in this format:
 * "valitator1,validator2", e.g.: "string,non-empty"
 * @return {Boolean} if the value is valid, the function will return true. If
 * not, false will be returned
 */
function validateField (value, validators) {
    validators = validators.split(",");
    for (var i = 0; i < validators.length; ++i) {
        if (
            !Validators[validators[i]]
            || Validators[validators[i]](value) === false
        ) {
            return false;
        }
    }
    return true;
}

/**
 * getPost
 * Searches the post in the parsed resources and returns it
 *
 * @name getPost
 * @function
 * @param {Object|String} req The request object or the slug
 * @param {String|undefined} fileContent The file content that is passed to
 * handlePost function
 * @return {Object} The post object that comes from the parsed resources
 */
var getPost = Bloggify.post.fetch;

/**
 * handlePost
 * Attaches the additional fields that are used in the system.
 *
 * @name handlePost
 * @function
 * @param {Object} req The request object
 * @param {Object} cPost The post object from parsed resources
 * @param {String|undefined} postContent If it's a string, the content field
 * will be attached to the post object, being parsed by Marked module.
 * @return {Object} The post object that contains content, date and url fields
 * in addition to the other fields
 */
var handlePost = Bloggify.post.handle;

/**
 * fetchPosts
 * This function returns the posts via callback
 *
 * @name fetchPosts
 * @function
 * @param {Object} req The request object
 * @param {Number} skip How many posts should be skipped
 * @param {Number} limit How many posts to return
 * @param {Function} callback The callback function that will be called with an
 * error and the posts array
 * @return {undefined} Returns undefined
 */
function fetchPosts (req, skip, limit, callback) {

     var from = skip
       , to   = skip + limit - 1
       ;

     var posts = Utils.clone(Config.site.parsed.roots.posts)
       , result = []
       , complete = skip - 1
       ;

    if (to >= posts.length) {
        to = posts.length - 1;
    }

    if (from > to) {
        return callback(null, []);
    }

     for (var i = from, k = 0; i <= to; ++i, ++k) {
         (function (cPost, k) {

            if (!cPost) {
                if (++complete >= limit) {
                    callback(null, result);
                }
                return;
            }

            var pathToPost =
                Config.site.paths.roots.posts + "/" + cPost.id + ".md"
            ;

            Bloggify.file.read(pathToPost, function (err, postContent) {
                if (err) { return callback(err); }
                result[k] = handlePost(req, cPost, postContent);
                if (++complete >= to) {
                    callback(null, result);
                }
            });
         })(posts[i], k);
     }
}

/**
 * getFormData
 * Gets the form data sent via POST requests
 *
 * @name getFormData
 * @function
 * @param {Object} req The request object
 * @param {Function} callback the callback function
 * @return
 */
function getFormData (req, callback) {

    var formData = ""
      , error = ""
      ;

    req.on("data", function (data) {
        formData += data;
    });

    req.on("error", function (data) {
        error += data;
    });

    req.on("end", function (data) {
        if (error) { return callback(error); }
        callback(null, QueryString.parse(formData));
    });
}

/**
 * handlePageGet
 * This function handles the GET requests.
 *
 * @name handlePageGet
 * @function
 * @param {Object} req the request object
 * @param {Object} res the response object
 * @param {String} pathName the path name
 * @param {String} route the Statique route
 * @param {Array} the posts (if undefined and @isBlogPost is true the function
 * will be called again with the fetches posts)
 * @param {Boolean} isBlogPost shows if the route is to a blog post
 * @param {Boolean} isBlogPpage it's true if the page is a blog one
 * @return
 */
function handlePageGet (req, res, pathName, route, posts, isBlogPost, isBlogPage, sessionData) {

    var pageRoute = route.url
      , pages = Utils.clone(Config.site.parsed.roots.pages)
      , currentPage = pages[pathName.slice(0, -1)] || pages[pathName]
      ;

    if (currentPage && currentPage.loggedIn && !sessionData) {
        return Statique.error(req, res, 403);
    }

    // handle core pages, build the route
    if (pageRoute && pageRoute.indexOf(Config.site.paths.theme + "/core") !== 0) {
        pageRoute = Config.site.paths.roots.pages + pageRoute;
    }

    if (isBlogPage) {
        var pageNumber = parseInt((pathName.match(/[1-9]([0-9]*)/) || [])[0]);

        if (isNaN(pageNumber)) {
            pageNumber = 1;
        }
    }

    if (isBlogPage && !posts && !isBlogPost) {

        fetchPosts(
            req
          , (pageNumber - 1) * Config.site.blog.posts.limit
          , Config.site.blog.posts.limit
          , function (err, data) {

                if (err) {
                    Debug.log(err, "error");
                    return Statique.error(req, res, 500);
                }

                // no posts found
                if (!data || !data.length) {
                    return Statique.error(req, res, 404);
                }

                handlePageGet(req, res, pathName, route, data, isBlogPost, isBlogPage, sessionData);
            }
        )
        return;
    }

    // handle blog posts
    if (isBlogPost) {

        var postName = pathName.split("/")[2]
          , post = getPost(req, null, null, null, true)
          ;

        if (!post || !postName) {
            return Statique.error(req, res, 404);
        }

        pageRoute = Config.site.paths.roots.posts + "/" + post.id + ".md";

        if (req.url !== post.url) {
            return Statique.redirect(res, post.url);
        }
    }

    if (isBlogPage) {
        pageRoute = pages[
            Config.site.blog.url
        ].url;
    }

    // read file
    Bloggify.file.read(pageRoute, function (err, fileContent) {

        if (err) {
            Debug.log(err, "error");
            return Statique.error(req, res, 404);
        }

        // convert page object to array
        var pageArray = []
          , pageHtml = ""
          ;

        if (currentPage && currentPage.wrap === false) {
            return Statique.sendRes(res, 200, "text/html",
                Utils.mRender(fileContent, {
                    config: Config
                })
            );
        }

        if (isBlogPage) {
            currentPage = pages[
                Config.site.blog.url
            ];
        }

        for (var url in pages) {
            var cPage = Utils.clone(pages[url]);
            cPage.url = url;
            pageArray.push(cPage);
        }

        pageArray.sort(function (a, b) {
            return (a.order || 0) > (b.order || 0);
        });

        for (var i = 0; i < pageArray.length; ++i) {
            var cPageObj = pageArray[i];
            if (cPageObj.loggedIn && !sessionData) {
                cPageObj.visible = false;
            }
            if (!cPageObj.label || cPageObj.visible === false) { continue; }
            cPageObj.additionalClasses = "";
            if ("/" + cPageObj.slug + "/" === pathName
                || cPageObj.url + "/" === pathName
                || cPageObj.url === pathName) {
                cPageObj.additionalClasses = " current-page";
            }

            pageHtml += Utils.mRender(
                Config.site.parsed.roots.theme.blocks.page, cPageObj
            );
        }

        var postHtml = "";
        if (posts) {
            for (var i = 0; i < posts.length; ++i) {
                var cPostObj = posts[i];
                if (cPostObj.visible === false) { continue; }
                postHtml += Utils.mRender(
                    Config.site.parsed.roots.theme.blocks.post, cPostObj
                );
            }
        }

        var htmlTemplate = Config.site.parsed.roots.theme.single.page
          , tPost = null
          ;

        // add title
        if (isBlogPost) {
            htmlTemplate = Config.site.parsed.roots.theme.single.post
            tPost = getPost(req, null, fileContent)

            tPost.content += Utils.mRender(
                Marked(
                    Config.site.parsed.roots.theme.blocks.postEnd
                )
              , tPost
            );

            // success response
            return Statique.sendRes(res, 200, "text/html",
                Utils.mRender(htmlTemplate, {
                    data: {
                        post: tPost
                      , title: tPost.title
                    }
                  , config: Config
                })
            );
        }

        var data = {
            data: {
                pages: pageHtml
              , title: currentPage.label
              , page: {
                    content: Marked(fileContent)
                  , next: pageNumber + 1
                  , active: pageNumber
                  , previous: pageNumber - 1
                }
              , posts: postHtml
            }
          , config: Config
        };

        if (Config.site.blog) {
            data.data.page.number = Math.ceil(
                Config.site.parsed.roots.posts.length
                / Config.site.blog.posts.limit
            );
        }

        var page = data.data.page;

        if (page.next > page.number) {
            delete page.next;
        }

        if (page.previous <= 0) {
            delete page.previous;
        }

        if (typeof currentPage.template === "string") {
            return Bloggify.file.read(currentPage.template, function (err, template) {
                if (err) {
                    if (err.code === "ENOENT") {
                        return Statique.error(req, res, 404);
                    }
                    return Statique.error(req, res, 500);
                }

                // Success response
                Statique.sendRes(res, 200, "text/html",
                    Utils.mRender(template, data)
                );
            });
        }

        // Success response
        Statique.sendRes(res, 200, "text/html",
            Utils.mRender(htmlTemplate, data, { repeat: 2 })
        );
    });
}

/**
 * handlePagePost
 * This function handles the post requests
 *
 * @name handlePagePost
 * @function
 * @param {Object} req the request object
 * @param {Object} res the response object
 * @param {String} pathName the pathname
 * @param {Object} route the Statique route
 * @return
 */
function handlePagePost (req, res, pathName, route, posts, isBlogPost, isBlogPage, sessionData) {

    // get form data
    getFormData(req, function (err, formData) {

        if (err) {
            Debug.log(err, "error");
            return res.end ("Internal server error");
        }

        if (Object.keys(Bloggify.form).indexOf(formData.formId) !== -1) {
            var thisForm = Bloggify.form[formData.formId];
            if (typeof thisForm === "function") {
                return thisForm(req, res, formData);
            }

            if (thisForm.constructor.name === "Object") {
                if (
                    thisForm.validate
                    && thisForm.validate.constructor.name === "Object"
                ) {
                    for (var fieldName in thisForm.validate) {
                        if (!validateField(
                            formData[fieldName], thisForm.validate[fieldName])
                           ) {
                            return Statique.sendRes(
                                res, 400, "text", JSON.stringify({
                                    message: fieldName[0].toUpperCase()
                                           + fieldName.substring(1)
                                           + " is invalid."
                                })
                            );
                        }
                    }
                }

                thisForm.handler(req, res, formData);
            }

            return;
        }

        return Statique.sendRes(res, 400, "text", JSON.stringify({
            message: "Invalid or missing form id"
        }));
    });
}

// public methods
module.exports["handlePage:GET"] = handlePageGet;
module.exports["handlePage:POST"] = handlePagePost;
<commit_msg>Send the invalid field<commit_after>// Highlight config
Highlight.configure({ classPrefix: '' });
Marked.setOptions({
    highlight: function (code) {
        return Highlight.highlightAuto(code).value;
    }
});

/**
 * validateField
 * This funciton validates the value by
 * providing the validators
 *
 * @name validateField
 * @function
 * @param {Anything} value the value that should be validated
 * @param {String} validators comma separated validators in this format:
 * "valitator1,validator2", e.g.: "string,non-empty"
 * @return {Boolean} if the value is valid, the function will return true. If
 * not, false will be returned
 */
function validateField (value, validators) {
    validators = validators.split(",");
    for (var i = 0; i < validators.length; ++i) {
        if (
            !Validators[validators[i]]
            || Validators[validators[i]](value) === false
        ) {
            return false;
        }
    }
    return true;
}

/**
 * getPost
 * Searches the post in the parsed resources and returns it
 *
 * @name getPost
 * @function
 * @param {Object|String} req The request object or the slug
 * @param {String|undefined} fileContent The file content that is passed to
 * handlePost function
 * @return {Object} The post object that comes from the parsed resources
 */
var getPost = Bloggify.post.fetch;

/**
 * handlePost
 * Attaches the additional fields that are used in the system.
 *
 * @name handlePost
 * @function
 * @param {Object} req The request object
 * @param {Object} cPost The post object from parsed resources
 * @param {String|undefined} postContent If it's a string, the content field
 * will be attached to the post object, being parsed by Marked module.
 * @return {Object} The post object that contains content, date and url fields
 * in addition to the other fields
 */
var handlePost = Bloggify.post.handle;

/**
 * fetchPosts
 * This function returns the posts via callback
 *
 * @name fetchPosts
 * @function
 * @param {Object} req The request object
 * @param {Number} skip How many posts should be skipped
 * @param {Number} limit How many posts to return
 * @param {Function} callback The callback function that will be called with an
 * error and the posts array
 * @return {undefined} Returns undefined
 */
function fetchPosts (req, skip, limit, callback) {

     var from = skip
       , to   = skip + limit - 1
       ;

     var posts = Utils.clone(Config.site.parsed.roots.posts)
       , result = []
       , complete = skip - 1
       ;

    if (to >= posts.length) {
        to = posts.length - 1;
    }

    if (from > to) {
        return callback(null, []);
    }

     for (var i = from, k = 0; i <= to; ++i, ++k) {
         (function (cPost, k) {

            if (!cPost) {
                if (++complete >= limit) {
                    callback(null, result);
                }
                return;
            }

            var pathToPost =
                Config.site.paths.roots.posts + "/" + cPost.id + ".md"
            ;

            Bloggify.file.read(pathToPost, function (err, postContent) {
                if (err) { return callback(err); }
                result[k] = handlePost(req, cPost, postContent);
                if (++complete >= to) {
                    callback(null, result);
                }
            });
         })(posts[i], k);
     }
}

/**
 * getFormData
 * Gets the form data sent via POST requests
 *
 * @name getFormData
 * @function
 * @param {Object} req The request object
 * @param {Function} callback the callback function
 * @return
 */
function getFormData (req, callback) {

    var formData = ""
      , error = ""
      ;

    req.on("data", function (data) {
        formData += data;
    });

    req.on("error", function (data) {
        error += data;
    });

    req.on("end", function (data) {
        if (error) { return callback(error); }
        callback(null, QueryString.parse(formData));
    });
}

/**
 * handlePageGet
 * This function handles the GET requests.
 *
 * @name handlePageGet
 * @function
 * @param {Object} req the request object
 * @param {Object} res the response object
 * @param {String} pathName the path name
 * @param {String} route the Statique route
 * @param {Array} the posts (if undefined and @isBlogPost is true the function
 * will be called again with the fetches posts)
 * @param {Boolean} isBlogPost shows if the route is to a blog post
 * @param {Boolean} isBlogPpage it's true if the page is a blog one
 * @return
 */
function handlePageGet (req, res, pathName, route, posts, isBlogPost, isBlogPage, sessionData) {

    var pageRoute = route.url
      , pages = Utils.clone(Config.site.parsed.roots.pages)
      , currentPage = pages[pathName.slice(0, -1)] || pages[pathName]
      ;

    if (currentPage && currentPage.loggedIn && !sessionData) {
        return Statique.error(req, res, 403);
    }

    // handle core pages, build the route
    if (pageRoute && pageRoute.indexOf(Config.site.paths.theme + "/core") !== 0) {
        pageRoute = Config.site.paths.roots.pages + pageRoute;
    }

    if (isBlogPage) {
        var pageNumber = parseInt((pathName.match(/[1-9]([0-9]*)/) || [])[0]);

        if (isNaN(pageNumber)) {
            pageNumber = 1;
        }
    }

    if (isBlogPage && !posts && !isBlogPost) {

        fetchPosts(
            req
          , (pageNumber - 1) * Config.site.blog.posts.limit
          , Config.site.blog.posts.limit
          , function (err, data) {

                if (err) {
                    Debug.log(err, "error");
                    return Statique.error(req, res, 500);
                }

                // no posts found
                if (!data || !data.length) {
                    return Statique.error(req, res, 404);
                }

                handlePageGet(req, res, pathName, route, data, isBlogPost, isBlogPage, sessionData);
            }
        )
        return;
    }

    // handle blog posts
    if (isBlogPost) {

        var postName = pathName.split("/")[2]
          , post = getPost(req, null, null, null, true)
          ;

        if (!post || !postName) {
            return Statique.error(req, res, 404);
        }

        pageRoute = Config.site.paths.roots.posts + "/" + post.id + ".md";

        if (req.url !== post.url) {
            return Statique.redirect(res, post.url);
        }
    }

    if (isBlogPage) {
        pageRoute = pages[
            Config.site.blog.url
        ].url;
    }

    // read file
    Bloggify.file.read(pageRoute, function (err, fileContent) {

        if (err) {
            Debug.log(err, "error");
            return Statique.error(req, res, 404);
        }

        // convert page object to array
        var pageArray = []
          , pageHtml = ""
          ;

        if (currentPage && currentPage.wrap === false) {
            return Statique.sendRes(res, 200, "text/html",
                Utils.mRender(fileContent, {
                    config: Config
                })
            );
        }

        if (isBlogPage) {
            currentPage = pages[
                Config.site.blog.url
            ];
        }

        for (var url in pages) {
            var cPage = Utils.clone(pages[url]);
            cPage.url = url;
            pageArray.push(cPage);
        }

        pageArray.sort(function (a, b) {
            return (a.order || 0) > (b.order || 0);
        });

        for (var i = 0; i < pageArray.length; ++i) {
            var cPageObj = pageArray[i];
            if (cPageObj.loggedIn && !sessionData) {
                cPageObj.visible = false;
            }
            if (!cPageObj.label || cPageObj.visible === false) { continue; }
            cPageObj.additionalClasses = "";
            if ("/" + cPageObj.slug + "/" === pathName
                || cPageObj.url + "/" === pathName
                || cPageObj.url === pathName) {
                cPageObj.additionalClasses = " current-page";
            }

            pageHtml += Utils.mRender(
                Config.site.parsed.roots.theme.blocks.page, cPageObj
            );
        }

        var postHtml = "";
        if (posts) {
            for (var i = 0; i < posts.length; ++i) {
                var cPostObj = posts[i];
                if (cPostObj.visible === false) { continue; }
                postHtml += Utils.mRender(
                    Config.site.parsed.roots.theme.blocks.post, cPostObj
                );
            }
        }

        var htmlTemplate = Config.site.parsed.roots.theme.single.page
          , tPost = null
          ;

        // add title
        if (isBlogPost) {
            htmlTemplate = Config.site.parsed.roots.theme.single.post
            tPost = getPost(req, null, fileContent)

            tPost.content += Utils.mRender(
                Marked(
                    Config.site.parsed.roots.theme.blocks.postEnd
                )
              , tPost
            );

            // success response
            return Statique.sendRes(res, 200, "text/html",
                Utils.mRender(htmlTemplate, {
                    data: {
                        post: tPost
                      , title: tPost.title
                    }
                  , config: Config
                })
            );
        }

        var data = {
            data: {
                pages: pageHtml
              , title: currentPage.label
              , page: {
                    content: Marked(fileContent)
                  , next: pageNumber + 1
                  , active: pageNumber
                  , previous: pageNumber - 1
                }
              , posts: postHtml
            }
          , config: Config
        };

        if (Config.site.blog) {
            data.data.page.number = Math.ceil(
                Config.site.parsed.roots.posts.length
                / Config.site.blog.posts.limit
            );
        }

        var page = data.data.page;

        if (page.next > page.number) {
            delete page.next;
        }

        if (page.previous <= 0) {
            delete page.previous;
        }

        if (typeof currentPage.template === "string") {
            return Bloggify.file.read(currentPage.template, function (err, template) {
                if (err) {
                    if (err.code === "ENOENT") {
                        return Statique.error(req, res, 404);
                    }
                    return Statique.error(req, res, 500);
                }

                // Success response
                Statique.sendRes(res, 200, "text/html",
                    Utils.mRender(template, data)
                );
            });
        }

        // Success response
        Statique.sendRes(res, 200, "text/html",
            Utils.mRender(htmlTemplate, data, { repeat: 2 })
        );
    });
}

/**
 * handlePagePost
 * This function handles the post requests
 *
 * @name handlePagePost
 * @function
 * @param {Object} req the request object
 * @param {Object} res the response object
 * @param {String} pathName the pathname
 * @param {Object} route the Statique route
 * @return
 */
function handlePagePost (req, res, pathName, route, posts, isBlogPost, isBlogPage, sessionData) {

    // get form data
    getFormData(req, function (err, formData) {

        if (err) {
            Debug.log(err, "error");
            return res.end ("Internal server error");
        }

        if (Object.keys(Bloggify.form).indexOf(formData.formId) !== -1) {
            var thisForm = Bloggify.form[formData.formId];
            if (typeof thisForm === "function") {
                return thisForm(req, res, formData);
            }

            if (thisForm.constructor.name === "Object") {
                if (
                    thisForm.validate
                    && thisForm.validate.constructor.name === "Object"
                ) {
                    for (var fieldName in thisForm.validate) {
                        if (!validateField(
                            formData[fieldName], thisForm.validate[fieldName])
                           ) {
                            return Statique.sendRes(
                                res, 400, "text", JSON.stringify({
                                    message: fieldName[0].toUpperCase()
                                           + fieldName.substring(1)
                                           + " is invalid.",
                                    fields: [fieldName]
                                })
                            );
                        }
                    }
                }

                thisForm.handler(req, res, formData);
            }

            return;
        }

        return Statique.sendRes(res, 400, "text", JSON.stringify({
            message: "Invalid or missing form id"
        }));
    });
}

// public methods
module.exports["handlePage:GET"] = handlePageGet;
module.exports["handlePage:POST"] = handlePagePost;
<|endoftext|>


<commit_before>/*
 * 图表parse插件
 */

UE.parse.register('charts',function( utils ){

    var resourceRoot = this.rootPath,
        containers = this.root,
        sources = null;

    //不存在指定的根路径， 则直接退出
    if ( !resourceRoot ) {
        return;
    }

    if ( sources = parseSources() ) {

        loadResources();

    }

    function parseSources () {

        if ( !containers ) {
            return null;
        }

        return extractChartData( containers );

    }

    /**
     * 提取数据
     */
    function extractChartData ( rootNode ) {

        var data = [],
            tables = rootNode.getElementsByTagName( "table" );

        for ( var i = 0, tableNode; tableNode = tables[ i ]; i++ ) {

            if ( tableNode.hasAttribute( "data-chart" ) ) {

                data.push( formatData( tableNode ) );

            }

        }

        return data.length ? data : null;

    }

    function formatData ( tableNode ) {

        var meta = tableNode.getAttribute( "data-chart" ),
            metaConfig = {},
            data = [];

        //提取table数据
        for ( var i = 0, row; row = tableNode.rows[ i ]; i++ ) {

            var rowData = [];

            for ( var j = 0, cell; cell = row.cells[ j ]; j++ ) {

                rowData.push( ( cell.innerText || cell.textContent ) | 0 );

            }

            data.push( rowData );

        }

        //解析元信息
        meta = meta.split( ";" );
        for ( var i = 0, metaData; metaData = meta[ i ]; i++ ) {

            metaData = metaData.split( ":" );
            metaConfig[ metaData[ 0 ] ] = metaData[ 1 ];

        }

        return {
            table: tableNode,
            meta: metaConfig,
            data: data
        };

    }

    //加载资源
    function loadResources () {

        loadJQuery();

    }

    function loadJQuery () {

        //不存在jquery， 则加载jquery
        if ( !window.jQuery ) {

            utils.loadFile(document,{
                src : resourceRoot + "/third-party/jquery-1.10.2.min.js",
                tag : "script",
                type : "text/javascript",
                defer : "defer"
            },function(){

                loadHighcharts();

            });

        } else {

            loadHighcharts();

        }

    }

    function loadHighcharts () {

        //不存在Highcharts， 则加载Highcharts
        if ( !window.Highcharts ) {

            utils.loadFile(document,{
                src : resourceRoot + "/third-party/highcharts/highcharts.js",
                tag : "script",
                type : "text/javascript",
                defer : "defer"
            },function(){

                loadTypeConfig();

            });

        } else {

            loadTypeConfig();

        }

    }

    //加载图表差异化配置文件
    function loadTypeConfig () {

        utils.loadFile(document,{
            src : resourceRoot + "/dialogs/charts/chart.config.js",
            tag : "script",
            type : "text/javascript",
            defer : "defer"
        },function(){

            render();

        });

    }

    //渲染图表
    function render () {

        var config = null,
            chartConfig = null,
            container = null;

        for ( var i = 0, len = sources.length; i < len; i++ ) {

            config = sources[ i ];

            chartConfig = analysisConfig( config );

            container = createContainer( config.table );

            renderChart( container, typeConfig[ config.meta.chartType ], chartConfig );

        }

    }

    /*
     * 渲染图表
     * @param container 图表容器节点对象
     * @param typeConfig 图表类型配置
     * @param config 图表通用配置
     * */
    function renderChart ( container, typeConfig, config ) {

        $( container ).highcharts( $.extend( {}, typeConfig, {

            credits: {
                enabled: false
            },
            exporting: {
                enabled: false
            },
            title: {
                text: config.title,
                x: -20 //center
            },
            subtitle: {
                text: config.subTitle,
                x: -20
            },
            xAxis: {
                title: {
                    text: config.xTitle
                },
                categories: config.categories
            },
            yAxis: {
                title: {
                    text: config.yTitle
                },
                plotLines: [{
                    value: 0,
                    width: 1,
                    color: '#808080'
                }]
            },
            tooltip: {
                enabled: true,
                valueSuffix: config.suffix
            },
            legend: {
                layout: 'vertical',
                align: 'right',
                verticalAlign: 'middle',
                borderWidth: 1
            },
            series: config.series

        } ));

    }

    /*
     * 创建图表的容器
     * 新创建的容器会替换掉对应的table对象
     * */
    function createContainer ( tableNode ) {

        var container = document.createElement( "div" );
        container.className = "edui-chart-container";

        tableNode.parentNode.replaceChild( container, tableNode );

        return container;

    }

    //根据config解析出正确的类别和图表数据信息
    function analysisConfig ( config ) {

        var series = [],
        //数据类别
            categories = [],
            result = [],
            data = config.data,
            meta = config.meta;

        //数据对齐方式为相反的方式， 需要反转数据
        if ( meta.dataFormat != "1" ) {

            for ( var i = 0, len = data.length; i < len ; i++ ) {

                for ( var j = 0, jlen = data[ i ].length; j < jlen; j++ ) {

                    if ( !result[ j ] ) {
                        result[ j ] = [];
                    }

                    result[ j ][ i ] = data[ i ][ j ];

                }

            }

            data = result;

        }

        result = {};

        //普通图表
        if ( meta.chartType != typeConfig.length - 1 ) {

            categories = data[ 0 ].slice( 1 );

            for ( var i = 1, curData; curData = data[ i ]; i++ ) {
                series.push( {
                    name: curData[ 0 ],
                    data: curData.slice( 1 )
                } );
            }

            result.series = series;
            result.categories = categories;
            result.title = meta.title;
            result.subTitle = meta.subTitle;
            result.xTitle = meta.xTitle;
            result.yTitle = meta.yTitle;
            result.suffix = meta.suffix;

        } else {

            var curData = [];

            for ( var i = 1, len = data[ 0 ].length; i < len; i++ ) {

                curData.push( [ data[ 0 ][ i ], data[ 1 ][ i ] | 0 ] );

            }

            //饼图
            series[ 0 ] = {
                type: 'pie',
                name: meta.tip,
                data: curData
            };

            result.series = series;
            result.title = meta.title;
            result.suffix = meta.suffix;

        }

        return result;

    }

});<commit_msg>修复IE6下 hasAttribute的bug<commit_after>/*
 * 图表parse插件
 */

UE.parse.register('charts',function( utils ){

    var resourceRoot = this.rootPath,
        containers = this.root,
        sources = null;

    //不存在指定的根路径， 则直接退出
    if ( !resourceRoot ) {
        return;
    }

    if ( sources = parseSources() ) {

        loadResources();

    }

    function parseSources () {

        if ( !containers ) {
            return null;
        }

        return extractChartData( containers );

    }

    /**
     * 提取数据
     */
    function extractChartData ( rootNode ) {

        var data = [],
            tables = rootNode.getElementsByTagName( "table" );

        for ( var i = 0, tableNode; tableNode = tables[ i ]; i++ ) {

            if ( tableNode.getAttribute( "data-chart" ) !== null ) {

                data.push( formatData( tableNode ) );

            }

        }

        return data.length ? data : null;

    }

    function formatData ( tableNode ) {

        var meta = tableNode.getAttribute( "data-chart" ),
            metaConfig = {},
            data = [];

        //提取table数据
        for ( var i = 0, row; row = tableNode.rows[ i ]; i++ ) {

            var rowData = [];

            for ( var j = 0, cell; cell = row.cells[ j ]; j++ ) {

                rowData.push( ( cell.innerText || cell.textContent ) | 0 );

            }

            data.push( rowData );

        }

        //解析元信息
        meta = meta.split( ";" );
        for ( var i = 0, metaData; metaData = meta[ i ]; i++ ) {

            metaData = metaData.split( ":" );
            metaConfig[ metaData[ 0 ] ] = metaData[ 1 ];

        }

        return {
            table: tableNode,
            meta: metaConfig,
            data: data
        };

    }

    //加载资源
    function loadResources () {

        loadJQuery();

    }

    function loadJQuery () {

        //不存在jquery， 则加载jquery
        if ( !window.jQuery ) {

            utils.loadFile(document,{
                src : resourceRoot + "/third-party/jquery-1.10.2.min.js",
                tag : "script",
                type : "text/javascript",
                defer : "defer"
            },function(){

                loadHighcharts();

            });

        } else {

            loadHighcharts();

        }

    }

    function loadHighcharts () {

        //不存在Highcharts， 则加载Highcharts
        if ( !window.Highcharts ) {

            utils.loadFile(document,{
                src : resourceRoot + "/third-party/highcharts/highcharts.js",
                tag : "script",
                type : "text/javascript",
                defer : "defer"
            },function(){

                loadTypeConfig();

            });

        } else {

            loadTypeConfig();

        }

    }

    //加载图表差异化配置文件
    function loadTypeConfig () {

        utils.loadFile(document,{
            src : resourceRoot + "/dialogs/charts/chart.config.js",
            tag : "script",
            type : "text/javascript",
            defer : "defer"
        },function(){

            render();

        });

    }

    //渲染图表
    function render () {

        var config = null,
            chartConfig = null,
            container = null;

        for ( var i = 0, len = sources.length; i < len; i++ ) {

            config = sources[ i ];

            chartConfig = analysisConfig( config );

            container = createContainer( config.table );

            renderChart( container, typeConfig[ config.meta.chartType ], chartConfig );

        }

    }

    /*
     * 渲染图表
     * @param container 图表容器节点对象
     * @param typeConfig 图表类型配置
     * @param config 图表通用配置
     * */
    function renderChart ( container, typeConfig, config ) {

        $( container ).highcharts( $.extend( {}, typeConfig, {

            credits: {
                enabled: false
            },
            exporting: {
                enabled: false
            },
            title: {
                text: config.title,
                x: -20 //center
            },
            subtitle: {
                text: config.subTitle,
                x: -20
            },
            xAxis: {
                title: {
                    text: config.xTitle
                },
                categories: config.categories
            },
            yAxis: {
                title: {
                    text: config.yTitle
                },
                plotLines: [{
                    value: 0,
                    width: 1,
                    color: '#808080'
                }]
            },
            tooltip: {
                enabled: true,
                valueSuffix: config.suffix
            },
            legend: {
                layout: 'vertical',
                align: 'right',
                verticalAlign: 'middle',
                borderWidth: 1
            },
            series: config.series

        } ));

    }

    /*
     * 创建图表的容器
     * 新创建的容器会替换掉对应的table对象
     * */
    function createContainer ( tableNode ) {

        var container = document.createElement( "div" );
        container.className = "edui-chart-container";

        tableNode.parentNode.replaceChild( container, tableNode );

        return container;

    }

    //根据config解析出正确的类别和图表数据信息
    function analysisConfig ( config ) {

        var series = [],
        //数据类别
            categories = [],
            result = [],
            data = config.data,
            meta = config.meta;

        //数据对齐方式为相反的方式， 需要反转数据
        if ( meta.dataFormat != "1" ) {

            for ( var i = 0, len = data.length; i < len ; i++ ) {

                for ( var j = 0, jlen = data[ i ].length; j < jlen; j++ ) {

                    if ( !result[ j ] ) {
                        result[ j ] = [];
                    }

                    result[ j ][ i ] = data[ i ][ j ];

                }

            }

            data = result;

        }

        result = {};

        //普通图表
        if ( meta.chartType != typeConfig.length - 1 ) {

            categories = data[ 0 ].slice( 1 );

            for ( var i = 1, curData; curData = data[ i ]; i++ ) {
                series.push( {
                    name: curData[ 0 ],
                    data: curData.slice( 1 )
                } );
            }

            result.series = series;
            result.categories = categories;
            result.title = meta.title;
            result.subTitle = meta.subTitle;
            result.xTitle = meta.xTitle;
            result.yTitle = meta.yTitle;
            result.suffix = meta.suffix;

        } else {

            var curData = [];

            for ( var i = 1, len = data[ 0 ].length; i < len; i++ ) {

                curData.push( [ data[ 0 ][ i ], data[ 1 ][ i ] | 0 ] );

            }

            //饼图
            series[ 0 ] = {
                type: 'pie',
                name: meta.tip,
                data: curData
            };

            result.series = series;
            result.title = meta.title;
            result.suffix = meta.suffix;

        }

        return result;

    }

});<|endoftext|>


<commit_before><commit_msg>Specifying a host for webpack-dev-server is optional<commit_after><|endoftext|>


<commit_before>var express = require('express');
var path = require("path");

exports.app = express();
var app = exports.app;

function createLink(key, adress){
	app.get(key,function (req,res){res.sendFile(path.join(__dirname, adress));});
}

createLink("/admin", "../client/admin/admin.html");
createLink("/login", "../newClient/login.html");
createLink("/loginJS", "../newClient/login.js");
createLink("/login/room", "../newClient/room.html");
createLink("/roomJS", "../newClient/roomJS.js");

app.get('/user/room',function (req,res){res.sendFile(path.join(__dirname+'../client/user/room/index.html'));});
app.get('/user/room/quizz',function (req,res){res.sendFile(path.join(__dirname+'../client/user/room/quizz/index.html'));});
app.get('/session-index', function (req, res, next) {
  req.session.index = (req.session.index || 0) + 1;
  res.write("Index : " + req.session.index + " : " + req.sessionID);
  res.end();
});

// Ce que j'aimerai bien faire :

/*
var react = require("react-dom");

app.get('/test', function(req, res){
  res.send(react.render("../newClient/login.js"));
});
*/

<commit_msg>app get pour la page de reponses<commit_after>var express = require('express');
var path = require("path");

exports.app = express();
var app = exports.app;

function createLink(key, adress){
	app.get(key,function (req,res){res.sendFile(path.join(__dirname, adress));});
}

createLink("/admin", "../client/admin/admin.html");
createLink("/login", "../newClient/login.html");
createLink("/loginJS", "../newClient/login.js");
createLink("/login/room", "../newClient/room.html");
createLink("/roomJS", "../newClient/roomJS.js");
createLink("/answers", "../newClient/answers-barchart.js");

app.get('/user/room',function (req,res){res.sendFile(path.join(__dirname+'../client/user/room/index.html'));});
app.get('/user/room/quizz',function (req,res){res.sendFile(path.join(__dirname+'../client/user/room/quizz/index.html'));});
app.get('/session-index', function (req, res, next) {
  req.session.index = (req.session.index || 0) + 1;
  res.write("Index : " + req.session.index + " : " + req.sessionID);
  res.end();
});

// Ce que j'aimerai bien faire :

/*
var react = require("react-dom");

app.get('/test', function(req, res){
  res.send(react.render("../newClient/login.js"));
});
*/

<|endoftext|>


<commit_before>developerKingdomModule.
	controller("guideCtrl", function guideCtrl($scope, $window, $sce, $http){

		$scope.sections = [{name: "Introduction", htmlText: "
This site is a guide to all developers wishing to contribute to or integrate with the inknote project.
"
								+ "
The aim of this project is to create a free, open source, browser based scoring program that will be both user and developer friendly.
"
		},
		{name: "Source code", htmlText: "
GitHub
"
			+ "
You can find the source code over here.
"
			+ "
If you see any bugs, or would like to improve the code or add some features, you are invited to help out with the project. Please go ahead and fork the code, pushing any changes.
"
			+ "
Once you have proved yourself trustworthy, by pushing sufficient good code or otherwise, you will be added as a contributor to the project to make things easier for you and give you more power over the code.
"
			+ "
If you have any questions regarding changes you would like to make, please go ahead and post them in the forum on this page."
			+ "
Licensing
"
			+ "
This project is entirely open source, so feel free to use any or all of it. You have every right to do so, so long as you do not try to sell the code you get from here as a product.
"
		},
		{name: "Debugging/Logging", htmlText: "
Turn it on
"
			+ "
To turn debugging mode on, go to
"
			+ "
Developers → Log → On
"
			+ "
Change style
"
			+ "
To change debugging style, go to
"
			+ "
Developers → Log → UI/Console
"
			+ "
UI mode will use alertify logs to display the log, while console will print the logs to the console. Please be aware that when using UI logging, there is no record of the logs.
"
		},
		{name: "Adding plugins", htmlText: "
Na na na na na nana heeeeeey jude

Hey judey judey jude
"}];

		$scope.getForumSections = function(){
			var additionalGuides = [];
			$http({method: "GET", url: "http://localhost:3000/guide"})
				.success(function(data, status){
					additionalGuides = data;

					for(var i = 0; i < additionalGuides.length; i++){
						$scope.sections.push(additionalGuides[i]);
					}
				})
				.error(function(data, status){
					additionalGuides = data || "Request failed";
					console.log(additionalGuides);
				});
		};

		$scope.getForumSections();

		$scope.currentSection = {};
		$scope.currentSectionOn = false;

		$scope.setSection = function(section){
			$scope.currentSection = section;
			$scope.currentSectionOn = true;
		}

		$scope.backToSections = function(){
			$scope.currentSectionOn = false;
		}

		$scope.to_trusted = function(html_code) {
		    return $sce.trustAsHtml(html_code);
		}

		$scope.getCurrentSectionIndex = function(){
			for(var i = 0; i < $scope.sections.length; i++){
				if($scope.sections[i] == $scope.currentSection){
					return i;
				}
			}
		}

		$scope.currentSectionIsFirst = function(){
			return $scope.getCurrentSectionIndex() == 0;
		}

		$scope.previousSection = function(){
			$scope.currentSection = $scope.sections[$scope.getCurrentSectionIndex() - 1];
		}

		$scope.currentSectionIsLast = function(){
			return $scope.getCurrentSectionIndex() == $scope.sections.length - 1;
		}

		$scope.nextSection = function(){
			$scope.currentSection = $scope.sections[$scope.getCurrentSectionIndex() + 1];
		}
	})
<commit_msg>Update guide.js<commit_after>developerKingdomModule.
	controller("guideCtrl", function guideCtrl($scope, $window, $sce, $http){

		$scope.sections = [];

		$scope.getForumSections = function(){
			var additionalGuides = [];
			$http({method: "GET", url: "http://localhost:3000/guide"})
				.success(function(data, status){
					additionalGuides = data;

					for(var i = 0; i < additionalGuides.length; i++){
						$scope.sections.push(additionalGuides[i]);
					}
				})
				.error(function(data, status){
					additionalGuides = data || "Request failed";
					console.log(additionalGuides);
				});
		};

		$scope.getForumSections();

		$scope.currentSection = {};
		$scope.currentSectionOn = false;

		$scope.setSection = function(section){
			$scope.currentSection = section;
			$scope.currentSectionOn = true;
		}

		$scope.backToSections = function(){
			$scope.currentSectionOn = false;
		}

		$scope.to_trusted = function(html_code) {
		    return $sce.trustAsHtml(html_code);
		}

		$scope.getCurrentSectionIndex = function(){
			for(var i = 0; i < $scope.sections.length; i++){
				if($scope.sections[i] == $scope.currentSection){
					return i;
				}
			}
		}

		$scope.currentSectionIsFirst = function(){
			return $scope.getCurrentSectionIndex() == 0;
		}

		$scope.previousSection = function(){
			$scope.currentSection = $scope.sections[$scope.getCurrentSectionIndex() - 1];
		}

		$scope.currentSectionIsLast = function(){
			return $scope.getCurrentSectionIndex() == $scope.sections.length - 1;
		}

		$scope.nextSection = function(){
			$scope.currentSection = $scope.sections[$scope.getCurrentSectionIndex() + 1];
		}
	})
<|endoftext|>


<commit_before>
/*
* Formatted fields - for number formats
* For all the fields that need to be formatted, create a
* FormattedField object.
* To assign a value to that field, use FormattedField.setFieldValue.
* Default FormattedField object uses currency format, subclasses use other formats.
*
* Requires jquery.
*
* Note that in Saleslogix 6.2.3+ you can use class = currDisplay to get a
* similar effect.
*/

(function () {

    /**********************************************/
    /* HELPER METHODS */
    /**********************************************/
    if (typeof (window.OpenSlx) == "undefined")
        window.OpenSlx = {};
    var OpenSlx = window.OpenSlx;
    var DECIMAL_SEPARATOR = ".";
    var THOUSAND_SEPARATOR = ",";
    var _fieldList = null;

    // Global values (used for formatting):
    // FormattedField.DECIMAL_SEPARATOR
    // FormattedField.THOUSAND_SEPARATOR
    function initGlobals() {
        var d = (2.2).toLocaleString();
        DECIMAL_SEPARATOR = d.substr(1, 1);
        d = (22222).toLocaleString();
        THOUSAND_SEPARATOR = d.substr(2, 1);
    }

    // locate a formatted field
    function findField(fieldObj) {
        if (!_fieldList)
            return null;
        for (var i = 0; i < _fieldList.length; i++) {
            if (_fieldList[i].field == fieldObj)
                return _fieldList[i];
        }
        return null;
    }

    // assign value to a field.
    // this makes sure value is formatted correctly.
    // pass field (field id or object)
    function setFieldValue(field, value) {
        var fieldObj = getRawObject(field);
        var fld = findField(fieldObj);
        if (fld)
            fld.setValue(value);
        else
            fieldObj.value = value;
    }

    // retrieve value from a field.
    // this makes sure value is formatted correctly.
    // pass field (field id or object)
    function getFieldValue(field) {
        var fieldObj = getRawObject(field);
        var fld = findField(fieldObj);
        if (fld)
            return fld.getValue();
        else
            return fieldObj.value;
    }

    function getRawObject(obj) {
        if (typeof obj == "string")
            return document.getElementById(obj);
        return obj;
    }

    // give amount as String
    function formatCurrency_wkh(amount) {
        if (amount.length <= 3) {
            return amount;
        } else {
            return formatCurrency_wkh(amount.substr(0, amount.length - 3)) +
                THOUSAND_SEPARATOR + amount.substr(amount.length - 3);
        }
    }

    function formatCurrency(amount, numDecimals, currencySymbol) {
        var acc = "";
        var b = Math.pow(10, numDecimals);
        if (typeof currencySymbol == "undefined")
            currencySymbol = "$";
        amount = Math.round(amount * b) / b;

        var intpart = Math.floor(amount);
        var floatpart = amount - intpart;

        floatpart = Math.round(floatpart * 100);
        if (floatpart < 10)
            floatpart = "0" + floatpart;

        if (intpart >= 1000) {
            acc = formatCurrency_wkh(intpart.toString());
        } else {
            acc = intpart;
        }

        acc = currencySymbol + acc;
        if (numDecimals > 0) {
            acc += DECIMAL_SEPARATOR + floatpart;
        }

        return acc;
    }

    // Keypress handler - return false if that wasnt a number
    function numberPlease(evt, allowDecimals) {
        var charCode = evt.which;

        if (typeof console != "undefined") {
            console.log("FormattedField: Char code: " + charCode + ", allowDecimals: " + allowDecimals);
        }
        // 40 and under: control chars
        // 44: comma, 46: decimal point
        // 48 to 57: number
        // we allow the comma in case they are on a european locale,
        // but it won't format correctly
        if ((charCode < 48 || charCode > 57) && // 0-9
        charCode > 0 &&  // special keys - arrows, tabs, etc
        (!allowDecimals || (DECIMAL_SEPARATOR == "." ? (charCode != 46) : (charCode != 44)))) {
            if (allowDecimals) {
                alert(OpenSlx.FormattedField.Strings.EnterOnlyNumbers);
            } else {
                alert(OpenSlx.FormattedField.Strings.EnterOnlyWholeNumbers);
            }
            return false;
        }
        return true;
    }

    /**********************************************/
    /* LOGIC - BASE CLASS */
    /**********************************************/

    // add field (an id or object) to the list of formatted field.
    // current name of field must be set.
    // current value of field must be set (to unformatted value).
    OpenSlx.FormattedField = function (field, numDecimals) {
        if (arguments.length > 0)
            this.init(field, numDecimals);
    }

    OpenSlx.FormattedField.setFieldValue = setFieldValue;
    OpenSlx.FormattedField.getFieldValue = getFieldValue;
    OpenSlx.FormattedField.formatCurrency = formatCurrency;

    // Default for localized strings.
    // They can be overridden either from Javascript code, or by defining the corresponding
    // resources for OpenSlx.
    OpenSlx.FormattedField.Strings =
    {
        EnterOnlyNumbers: "Enter only numbers in this field!",
        EnterOnlyWholeNumbers: "Enter only whole numbers, without cents!"
    };

    // constructor
    // create a hidden field and give it the name from this field,
    // then remove the name from the current field so that it does not get posted.
    OpenSlx.FormattedField.prototype.init = function (field, numDecimals) {
        var f = getRawObject(field);
        if (!f)
            return;
        if (!_fieldList)
            _fieldList = new Array();
        _fieldList.push(this);
        this.field = f;
        if (typeof (numDecimals) == "undefined")
            numDecimals = 2;
        this._numDecimals = numDecimals;
        var existingHids = $("[name=" + this.field.name + "][type=hidden]");
        var hid;
        if (existingHids.length > 0) {
            // reuse existing hidden control if it exists
            // (useful for ASP.NET updatepanels!)
            hid = existingHids[0];
        } else {
            hid = document.createElement("input");
            hid.type = "hidden";
            hid.name = this.field.name;
        }
        hid.value = this.field.value;
        hid.defaultValue = this.field.defaultValue;

        this.field.name = "";

        var r = this; // bind for closure
        var jqf = $(this.field);
        jqf.focus(function () { r.deformat(); this.select(); });
        jqf.blur(function () { r.reformat() });
        var allowDecimals = this._numDecimals > 0;
        var allowNonNumeric = !!this._allowNonNumeric;
        jqf.keypress(function (e) {
            if (e.which == 13)
            // save the value to the hidden field in case this will be used for a save
                r.setValue(r.field.value);
            if (!allowNonNumeric) {
                return numberPlease(e, allowDecimals);
            }
            return true;
        });
        this.hidden = this.field.parentNode.insertBefore(hid, this.field);
        this.setValue(hid.value);
    }

    // copy hid value into field
    OpenSlx.FormattedField.prototype.deformat = function () {
        this.field.value = this.hidden.value;
        this.isformatted = false;
    }

    OpenSlx.FormattedField.prototype.reformat = function () {
        this.setValue(this.field.value);
    }

    // override this to format the value
    OpenSlx.FormattedField.prototype.setValue = function (value) {
        var val = value;
        if (typeof value == "string") {
            val = parseFloat(value.replace(new RegExp("[\\$%\\" + THOUSAND_SEPARATOR + "]", "g"), ""));
        } else if (typeof value != "number") {
            throw "Invalid value for formatted field: " + value;
        }
        if (isNaN(val))
            val = 0;
        this.field.value = formatCurrency(val, this._numDecimals);
        this.hidden.value = val;
        this.isformatted = true;
    }

    // get the raw value
    OpenSlx.FormattedField.prototype.getValue = function () {
        var val;
        if (this.isformatted) {
            val = this.hidden.value;
        } else
            val = this.field.value;
        var ival = parseFloat(val);
        if (isNaN(ival))
            return 0.0;
        else
            return ival;
    }

    // get the formatted value
    OpenSlx.FormattedField.prototype.getFormattedValue = function () {
        var val;

        if (this.isformatted) {
            val = this.field.value;
        } else {
            this.reformat();
            val = this.field.value;
            this.deformat();
        }
        return val;
    }

    /**********************************************/
    /* PHONE FORMAT */
    /**********************************************/

    // Default keypress event handlers will prevent non-numeric keys.
    // Can be overridden to change that behavior
    OpenSlx.FormattedField.prototype.onKeyPress = function (e) {
    }

    /*
    * FormattedFieldPhone - phone number format (us format only at this point)
    * In Saleslogix 6.2.3+, use phoneDisplay class to get a similar effect
    * with less effort.
    */
    OpenSlx.FormattedFieldPhone = function (field) {
        if (arguments.length > 0)
            this.init(field);
    }
    OpenSlx.FormattedFieldPhone.prototype = new OpenSlx.FormattedField();
    OpenSlx.FormattedFieldPhone.prototype.constructor = OpenSlx.FormattedFieldPhone;
    OpenSlx.FormattedFieldPhone.superclass = OpenSlx.FormattedField.prototype;

    OpenSlx.FormattedFieldPhone.prototype.init = function (field) {
        this._allowNonNumeric = true;
        OpenSlx.FormattedFieldPhone.superclass.init.call(this, field);
    }

    OpenSlx.FormattedFieldPhone.prototype.setValue = function (value) {
        var formattedValue = "";

        if (value.length == 10) {
            formattedValue = "(" + value.substring(0, 3) + ") " +
			value.substring(3, 3) + "-" + value.substring(6, 4);
        } else if (value.length == 7) {
            formattedValue = value.substring(0, 3) + "-" + value.substring(3, 4);
        } else {
            formattedValue = value;
        }

        this.field.value = formattedValue;
        this.hidden.value = value;
        this.isformatted = true;
    }

    /**********************************************/
    /* PERCENT FORMAT */
    /**********************************************/

    /*
    * FormattedFieldPercent - percent format
    */
    OpenSlx.FormattedFieldPercent = function (field) {
        if (arguments.length > 0)
            this.init(field);
    }
    OpenSlx.FormattedFieldPercent.prototype = new OpenSlx.FormattedField();
    OpenSlx.FormattedFieldPercent.prototype.constructor = OpenSlx.FormattedFieldPercent;
    OpenSlx.FormattedFieldPercent.superclass = OpenSlx.FormattedField.prototype;

    OpenSlx.FormattedFieldPercent.prototype.init = function (field) {
        OpenSlx.FormattedFieldPercent.superclass.init.call(this, field);
    }

    OpenSlx.FormattedFieldPercent.prototype.setValue = function (value) {
        var val = parseFloat(value);
        if (isNaN(val))
            val = 0;
        if (val > 1)
            val = val / 100;
        this.field.value = (Math.round(val * 100)) + " %"
        this.hidden.value = val;
        this.isformatted = true;
    }

    // get the raw value
    OpenSlx.FormattedFieldPercent.prototype.getValue = function () {
        var val = OpenSlx.FormattedFieldPercent.superclass.getValue.call(this);
        if (val > 1)
            return val / 100;
        return val;
    }

    /**********************************************/
    /* NUMBER FORMAT */
    /**********************************************/

    /*
    * FormattedFieldDecimal - numeric format, arbitrary number of decimals
    */
    OpenSlx.FormattedFieldDecimal = function (field, numDecimals) {
        if (arguments.length > 0)
            this.init(field, numDecimals);
    }
    OpenSlx.FormattedFieldDecimal.prototype = new OpenSlx.FormattedField();
    OpenSlx.FormattedFieldDecimal.prototype.constructor = OpenSlx.FormattedFieldDecimal;
    OpenSlx.FormattedFieldDecimal.superclass = OpenSlx.FormattedField.prototype;

    OpenSlx.FormattedFieldDecimal.prototype.init = function (field, numDecimals) {
        OpenSlx.FormattedFieldDecimal.superclass.init.call(this, field, numDecimals);
    }

    OpenSlx.FormattedFieldDecimal.prototype.setValue = function (value) {
        var val = parseFloat(value);
        if (isNaN(val))
            val = 0;
        this.field.value = formatCurrency(val, this._numDecimals, "");
        this.hidden.value = val;
        this.isformatted = true;
    }

    initGlobals();
})();

// This is not needed when scripts are loaded via resource?
//if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
<commit_msg>Localization issue on Chrome<commit_after>
/*
* Formatted fields - for number formats
* For all the fields that need to be formatted, create a
* FormattedField object.
* To assign a value to that field, use FormattedField.setFieldValue.
* Default FormattedField object uses currency format, subclasses use other formats.
*
* Requires jquery.
*
* Note that in Saleslogix 6.2.3+ you can use class = currDisplay to get a
* similar effect.
*/

(function () {

    /**********************************************/
    /* HELPER METHODS */
    /**********************************************/
    if (typeof (window.OpenSlx) == "undefined")
        window.OpenSlx = {};
    var OpenSlx = window.OpenSlx;
    var DECIMAL_SEPARATOR = ".";
    var THOUSAND_SEPARATOR = ",";
    var _fieldList = null;

    // Global values (used for formatting):
    // FormattedField.DECIMAL_SEPARATOR
    // FormattedField.THOUSAND_SEPARATOR
    function initGlobals() {
        var d = (2.2).toLocaleString();
        DECIMAL_SEPARATOR = d.substr(1, 1);
        if (/\d/.test(DECIMAL_SEPARATOR))
            DECIMAL_SEPARATOR = ".";
        d = (22222).toLocaleString();
        THOUSAND_SEPARATOR = d.substr(2, 1);
        if (/\d/.test(THOUSAND_SEPARATOR))
            // fallback in case the browser does not include the 1000's sep
            // (Chrome)
            // TODO - use the globalization plugin from MS?
            THOUSAND_SEPARATOR = "";
    }

    // locate a formatted field
    function findField(fieldObj) {
        if (!_fieldList)
            return null;
        for (var i = 0; i < _fieldList.length; i++) {
            if (_fieldList[i].field == fieldObj)
                return _fieldList[i];
        }
        return null;
    }

    // assign value to a field.
    // this makes sure value is formatted correctly.
    // pass field (field id or object)
    function setFieldValue(field, value) {
        var fieldObj = getRawObject(field);
        var fld = findField(fieldObj);
        if (fld)
            fld.setValue(value);
        else
            fieldObj.value = value;
    }

    // retrieve value from a field.
    // this makes sure value is formatted correctly.
    // pass field (field id or object)
    function getFieldValue(field) {
        var fieldObj = getRawObject(field);
        var fld = findField(fieldObj);
        if (fld)
            return fld.getValue();
        else
            return fieldObj.value;
    }

    function getRawObject(obj) {
        if (typeof obj == "string")
            return document.getElementById(obj);
        return obj;
    }

    // give amount as String
    function formatCurrency_wkh(amount) {
        if (amount.length <= 3) {
            return amount;
        } else {
            return formatCurrency_wkh(amount.substr(0, amount.length - 3)) +
                THOUSAND_SEPARATOR + amount.substr(amount.length - 3);
        }
    }

    function formatCurrency(amount, numDecimals, currencySymbol) {
        var acc = "";
        var b = Math.pow(10, numDecimals);
        if (typeof currencySymbol == "undefined")
            currencySymbol = "$";
        amount = Math.round(amount * b) / b;

        var intpart = Math.floor(amount);
        var floatpart = amount - intpart;

        floatpart = Math.round(floatpart * 100);
        if (floatpart < 10)
            floatpart = "0" + floatpart;

        if (intpart >= 1000) {
            acc = formatCurrency_wkh(intpart.toString());
        } else {
            acc = intpart;
        }

        acc = currencySymbol + acc;
        if (numDecimals > 0) {
            acc += DECIMAL_SEPARATOR + floatpart;
        }

        return acc;
    }

    // Keypress handler - return false if that wasnt a number
    function numberPlease(evt, allowDecimals) {
        var charCode = evt.which;

        if (typeof console != "undefined") {
            console.log("FormattedField: Char code: " + charCode + ", allowDecimals: " + allowDecimals);
        }
        // 40 and under: control chars
        // 44: comma, 46: decimal point
        // 48 to 57: number
        // we allow the comma in case they are on a european locale,
        // but it won't format correctly
        if ((charCode < 48 || charCode > 57) && // 0-9
        charCode > 0 &&  // special keys - arrows, tabs, etc
        (!allowDecimals || (DECIMAL_SEPARATOR == "." ? (charCode != 46) : (charCode != 44)))) {
            if (allowDecimals) {
                alert(OpenSlx.FormattedField.Strings.EnterOnlyNumbers);
            } else {
                alert(OpenSlx.FormattedField.Strings.EnterOnlyWholeNumbers);
            }
            return false;
        }
        return true;
    }

    /**********************************************/
    /* LOGIC - BASE CLASS */
    /**********************************************/

    // add field (an id or object) to the list of formatted field.
    // current name of field must be set.
    // current value of field must be set (to unformatted value).
    OpenSlx.FormattedField = function (field, numDecimals) {
        if (arguments.length > 0)
            this.init(field, numDecimals);
    }

    OpenSlx.FormattedField.setFieldValue = setFieldValue;
    OpenSlx.FormattedField.getFieldValue = getFieldValue;
    OpenSlx.FormattedField.formatCurrency = formatCurrency;

    // Default for localized strings.
    // They can be overridden either from Javascript code, or by defining the corresponding
    // resources for OpenSlx.
    OpenSlx.FormattedField.Strings =
    {
        EnterOnlyNumbers: "Enter only numbers in this field!",
        EnterOnlyWholeNumbers: "Enter only whole numbers, without cents!"
    };

    // constructor
    // create a hidden field and give it the name from this field,
    // then remove the name from the current field so that it does not get posted.
    OpenSlx.FormattedField.prototype.init = function (field, numDecimals) {
        var f = getRawObject(field);
        if (!f)
            return;
        if (!_fieldList)
            _fieldList = new Array();
        _fieldList.push(this);
        this.field = f;
        if (typeof (numDecimals) == "undefined")
            numDecimals = 2;
        this._numDecimals = numDecimals;
        var existingHids = $("[name=" + this.field.name + "][type=hidden]");
        var hid;
        if (existingHids.length > 0) {
            // reuse existing hidden control if it exists
            // (useful for ASP.NET updatepanels!)
            hid = existingHids[0];
        } else {
            hid = document.createElement("input");
            hid.type = "hidden";
            hid.name = this.field.name;
        }
        hid.value = this.field.value;
        hid.defaultValue = this.field.defaultValue;

        this.field.name = "";

        var r = this; // bind for closure
        var jqf = $(this.field);
        jqf.focus(function () { r.deformat(); this.select(); });
        jqf.blur(function () { r.reformat() });
        var allowDecimals = this._numDecimals > 0;
        var allowNonNumeric = !!this._allowNonNumeric;
        jqf.keypress(function (e) {
            if (e.which == 13)
            // save the value to the hidden field in case this will be used for a save
                r.setValue(r.field.value);
            if (!allowNonNumeric) {
                return numberPlease(e, allowDecimals);
            }
            return true;
        });
        this.hidden = this.field.parentNode.insertBefore(hid, this.field);
        this.setValue(hid.value);
    }

    // copy hid value into field
    OpenSlx.FormattedField.prototype.deformat = function () {
        this.field.value = this.hidden.value;
        this.isformatted = false;
    }

    OpenSlx.FormattedField.prototype.reformat = function () {
        this.setValue(this.field.value);
    }

    // override this to format the value
    OpenSlx.FormattedField.prototype.setValue = function (value) {
        var val = value;
        if (typeof value == "string") {
            val = parseFloat(value.replace(new RegExp("[\\$%\\" + THOUSAND_SEPARATOR + "]", "g"), ""));
        } else if (typeof value != "number") {
            throw "Invalid value for formatted field: " + value;
        }
        if (isNaN(val))
            val = 0;
        this.field.value = formatCurrency(val, this._numDecimals);
        this.hidden.value = val;
        this.isformatted = true;
    }

    // get the raw value
    OpenSlx.FormattedField.prototype.getValue = function () {
        var val;
        if (this.isformatted) {
            val = this.hidden.value;
        } else
            val = this.field.value;
        var ival = parseFloat(val);
        if (isNaN(ival))
            return 0.0;
        else
            return ival;
    }

    // get the formatted value
    OpenSlx.FormattedField.prototype.getFormattedValue = function () {
        var val;

        if (this.isformatted) {
            val = this.field.value;
        } else {
            this.reformat();
            val = this.field.value;
            this.deformat();
        }
        return val;
    }

    /**********************************************/
    /* PHONE FORMAT */
    /**********************************************/

    // Default keypress event handlers will prevent non-numeric keys.
    // Can be overridden to change that behavior
    OpenSlx.FormattedField.prototype.onKeyPress = function (e) {
    }

    /*
    * FormattedFieldPhone - phone number format (us format only at this point)
    * In Saleslogix 6.2.3+, use phoneDisplay class to get a similar effect
    * with less effort.
    */
    OpenSlx.FormattedFieldPhone = function (field) {
        if (arguments.length > 0)
            this.init(field);
    }
    OpenSlx.FormattedFieldPhone.prototype = new OpenSlx.FormattedField();
    OpenSlx.FormattedFieldPhone.prototype.constructor = OpenSlx.FormattedFieldPhone;
    OpenSlx.FormattedFieldPhone.superclass = OpenSlx.FormattedField.prototype;

    OpenSlx.FormattedFieldPhone.prototype.init = function (field) {
        this._allowNonNumeric = true;
        OpenSlx.FormattedFieldPhone.superclass.init.call(this, field);
    }

    OpenSlx.FormattedFieldPhone.prototype.setValue = function (value) {
        var formattedValue = "";

        if (value.length == 10) {
            formattedValue = "(" + value.substring(0, 3) + ") " +
			value.substring(3, 3) + "-" + value.substring(6, 4);
        } else if (value.length == 7) {
            formattedValue = value.substring(0, 3) + "-" + value.substring(3, 4);
        } else {
            formattedValue = value;
        }

        this.field.value = formattedValue;
        this.hidden.value = value;
        this.isformatted = true;
    }

    /**********************************************/
    /* PERCENT FORMAT */
    /**********************************************/

    /*
    * FormattedFieldPercent - percent format
    */
    OpenSlx.FormattedFieldPercent = function (field) {
        if (arguments.length > 0)
            this.init(field);
    }
    OpenSlx.FormattedFieldPercent.prototype = new OpenSlx.FormattedField();
    OpenSlx.FormattedFieldPercent.prototype.constructor = OpenSlx.FormattedFieldPercent;
    OpenSlx.FormattedFieldPercent.superclass = OpenSlx.FormattedField.prototype;

    OpenSlx.FormattedFieldPercent.prototype.init = function (field) {
        OpenSlx.FormattedFieldPercent.superclass.init.call(this, field);
    }

    OpenSlx.FormattedFieldPercent.prototype.setValue = function (value) {
        var val = parseFloat(value);
        if (isNaN(val))
            val = 0;
        if (val > 1)
            val = val / 100;
        this.field.value = (Math.round(val * 100)) + " %"
        this.hidden.value = val;
        this.isformatted = true;
    }

    // get the raw value
    OpenSlx.FormattedFieldPercent.prototype.getValue = function () {
        var val = OpenSlx.FormattedFieldPercent.superclass.getValue.call(this);
        if (val > 1)
            return val / 100;
        return val;
    }

    /**********************************************/
    /* NUMBER FORMAT */
    /**********************************************/

    /*
    * FormattedFieldDecimal - numeric format, arbitrary number of decimals
    */
    OpenSlx.FormattedFieldDecimal = function (field, numDecimals) {
        if (arguments.length > 0)
            this.init(field, numDecimals);
    }
    OpenSlx.FormattedFieldDecimal.prototype = new OpenSlx.FormattedField();
    OpenSlx.FormattedFieldDecimal.prototype.constructor = OpenSlx.FormattedFieldDecimal;
    OpenSlx.FormattedFieldDecimal.superclass = OpenSlx.FormattedField.prototype;

    OpenSlx.FormattedFieldDecimal.prototype.init = function (field, numDecimals) {
        OpenSlx.FormattedFieldDecimal.superclass.init.call(this, field, numDecimals);
    }

    OpenSlx.FormattedFieldDecimal.prototype.setValue = function (value) {
        var val = parseFloat(value);
        if (isNaN(val))
            val = 0;
        this.field.value = formatCurrency(val, this._numDecimals, "");
        this.hidden.value = val;
        this.isformatted = true;
    }

    initGlobals();
})();

// This is not needed when scripts are loaded via resource?
//if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
<|endoftext|>


<commit_before><commit_msg>Add voltearAlIrAIzquierda property to SaltarHaciaAdelante action.<commit_after><|endoftext|>


<commit_before>/*
 * 图表parse插件
 */

UE.parse.register('charts',function( utils ){

    var resourceRoot = this.rootPath,
        containers = this.root,
        sources = null;

    //不存在指定的根路径， 则直接退出
    if ( !resourceRoot ) {
        return;
    }

    if ( sources = parseSources() ) {

        loadResources();

    }

    function parseSources () {

        if ( !containers ) {
            return null;
        }

        return extractChartData( containers );

    }

    /**
     * 提取数据
     */
    function extractChartData ( rootNode ) {

        var data = [],
            tables = rootNode.getElementsByTagName( "table" );

        for ( var i = 0, tableNode; tableNode = tables[ i ]; i++ ) {

            if ( tableNode.getAttribute( "data-chart" ) !== null ) {

                data.push( formatData( tableNode ) );

            }

        }

        return data.length ? data : null;

    }

    function formatData ( tableNode ) {

        var meta = tableNode.getAttribute( "data-chart" ),
            metaConfig = {},
            data = [];

        //提取table数据
        for ( var i = 0, row; row = tableNode.rows[ i ]; i++ ) {

            var rowData = [];

            for ( var j = 0, cell; cell = row.cells[ j ]; j++ ) {

                //trace 3730
                var value = ( cell.innerText || cell.textContent );
                rowData.push( cell.tagName == 'TH' ? value:(value | 0) );

            }

            data.push( rowData );

        }

        //解析元信息
        meta = meta.split( ";" );
        for ( var i = 0, metaData; metaData = meta[ i ]; i++ ) {

            metaData = metaData.split( ":" );
            metaConfig[ metaData[ 0 ] ] = metaData[ 1 ];

        }

        return {
            table: tableNode,
            meta: metaConfig,
            data: data
        };

    }

    //加载资源
    function loadResources () {

        loadJQuery();

    }

    function loadJQuery () {

        //不存在jquery， 则加载jquery
        if ( !window.jQuery ) {

            utils.loadFile(document,{
                src : resourceRoot + "/third-party/jquery-1.10.2.min.js",
                tag : "script",
                type : "text/javascript",
                defer : "defer"
            },function(){

                loadHighcharts();

            });

        } else {

            loadHighcharts();

        }

    }

    function loadHighcharts () {

        //不存在Highcharts， 则加载Highcharts
        if ( !window.Highcharts ) {

            utils.loadFile(document,{
                src : resourceRoot + "/third-party/highcharts/highcharts.js",
                tag : "script",
                type : "text/javascript",
                defer : "defer"
            },function(){

                loadTypeConfig();

            });

        } else {

            loadTypeConfig();

        }

    }

    //加载图表差异化配置文件
    function loadTypeConfig () {

        utils.loadFile(document,{
            src : resourceRoot + "/dialogs/charts/chart.config.js",
            tag : "script",
            type : "text/javascript",
            defer : "defer"
        },function(){

            render();

        });

    }

    //渲染图表
    function render () {

        var config = null,
            chartConfig = null,
            container = null;

        for ( var i = 0, len = sources.length; i < len; i++ ) {

            config = sources[ i ];

            chartConfig = analysisConfig( config );

            container = createContainer( config.table );

            renderChart( container, typeConfig[ config.meta.chartType ], chartConfig );

        }

    }

    /*
     * 渲染图表
     * @param container 图表容器节点对象
     * @param typeConfig 图表类型配置
     * @param config 图表通用配置
     * */
    function renderChart ( container, typeConfig, config ) {

        $( container ).highcharts( $.extend( {}, typeConfig, {

            credits: {
                enabled: false
            },
            exporting: {
                enabled: false
            },
            title: {
                text: config.title,
                x: -20 //center
            },
            subtitle: {
                text: config.subTitle,
                x: -20
            },
            xAxis: {
                title: {
                    text: config.xTitle
                },
                categories: config.categories
            },
            yAxis: {
                title: {
                    text: config.yTitle
                },
                plotLines: [{
                    value: 0,
                    width: 1,
                    color: '#808080'
                }]
            },
            tooltip: {
                enabled: true,
                valueSuffix: config.suffix
            },
            legend: {
                layout: 'vertical',
                align: 'right',
                verticalAlign: 'middle',
                borderWidth: 1
            },
            series: config.series

        } ));

    }

    /*
     * 创建图表的容器
     * 新创建的容器会替换掉对应的table对象
     * */
    function createContainer ( tableNode ) {

        var container = document.createElement( "div" );
        container.className = "edui-chart-container";

        tableNode.parentNode.replaceChild( container, tableNode );

        return container;

    }

    //根据config解析出正确的类别和图表数据信息
    function analysisConfig ( config ) {

        var series = [],
        //数据类别
            categories = [],
            result = [],
            data = config.data,
            meta = config.meta;

        //数据对齐方式为相反的方式， 需要反转数据
        if ( meta.dataFormat != "1" ) {

            for ( var i = 0, len = data.length; i < len ; i++ ) {

                for ( var j = 0, jlen = data[ i ].length; j < jlen; j++ ) {

                    if ( !result[ j ] ) {
                        result[ j ] = [];
                    }

                    result[ j ][ i ] = data[ i ][ j ];

                }

            }

            data = result;

        }

        result = {};

        //普通图表
        if ( meta.chartType != typeConfig.length - 1 ) {

            categories = data[ 0 ].slice( 1 );

            for ( var i = 1, curData; curData = data[ i ]; i++ ) {
                series.push( {
                    name: curData[ 0 ],
                    data: curData.slice( 1 )
                } );
            }

            result.series = series;
            result.categories = categories;
            result.title = meta.title;
            result.subTitle = meta.subTitle;
            result.xTitle = meta.xTitle;
            result.yTitle = meta.yTitle;
            result.suffix = meta.suffix;

        } else {

            var curData = [];

            for ( var i = 1, len = data[ 0 ].length; i < len; i++ ) {

                curData.push( [ data[ 0 ][ i ], data[ 1 ][ i ] | 0 ] );

            }

            //饼图
            series[ 0 ] = {
                type: 'pie',
                name: meta.tip,
                data: curData
            };

            result.series = series;
            result.title = meta.title;
            result.suffix = meta.suffix;

        }

        return result;

    }

});<commit_msg>修复charts取内容为空时判断失败的bug<commit_after>/*
 * 图表parse插件
 */

UE.parse.register('charts',function( utils ){

    var resourceRoot = this.rootPath,
        containers = this.root,
        sources = null;

    //不存在指定的根路径， 则直接退出
    if ( !resourceRoot ) {
        return;
    }

    if ( sources = parseSources() ) {

        loadResources();

    }

    function parseSources () {

        if ( !containers ) {
            return null;
        }

        return extractChartData( containers );

    }

    /**
     * 提取数据
     */
    function extractChartData ( rootNode ) {

        var data = [],
            tables = rootNode.getElementsByTagName( "table" );

        for ( var i = 0, tableNode; tableNode = tables[ i ]; i++ ) {

            if ( tableNode.getAttribute( "data-chart" ) !== null ) {

                data.push( formatData( tableNode ) );

            }

        }

        return data.length ? data : null;

    }

    function formatData ( tableNode ) {

        var meta = tableNode.getAttribute( "data-chart" ),
            metaConfig = {},
            data = [];

        //提取table数据
        for ( var i = 0, row; row = tableNode.rows[ i ]; i++ ) {

            var rowData = [];

            for ( var j = 0, cell; cell = row.cells[ j ]; j++ ) {

                var value = ( cell.innerText || cell.textContent || '' );
                rowData.push( cell.tagName == 'TH' ? value:(value | 0) );

            }

            data.push( rowData );

        }

        //解析元信息
        meta = meta.split( ";" );
        for ( var i = 0, metaData; metaData = meta[ i ]; i++ ) {

            metaData = metaData.split( ":" );
            metaConfig[ metaData[ 0 ] ] = metaData[ 1 ];

        }

        return {
            table: tableNode,
            meta: metaConfig,
            data: data
        };

    }

    //加载资源
    function loadResources () {

        loadJQuery();

    }

    function loadJQuery () {

        //不存在jquery， 则加载jquery
        if ( !window.jQuery ) {

            utils.loadFile(document,{
                src : resourceRoot + "/third-party/jquery-1.10.2.min.js",
                tag : "script",
                type : "text/javascript",
                defer : "defer"
            },function(){

                loadHighcharts();

            });

        } else {

            loadHighcharts();

        }

    }

    function loadHighcharts () {

        //不存在Highcharts， 则加载Highcharts
        if ( !window.Highcharts ) {

            utils.loadFile(document,{
                src : resourceRoot + "/third-party/highcharts/highcharts.js",
                tag : "script",
                type : "text/javascript",
                defer : "defer"
            },function(){

                loadTypeConfig();

            });

        } else {

            loadTypeConfig();

        }

    }

    //加载图表差异化配置文件
    function loadTypeConfig () {

        utils.loadFile(document,{
            src : resourceRoot + "/dialogs/charts/chart.config.js",
            tag : "script",
            type : "text/javascript",
            defer : "defer"
        },function(){

            render();

        });

    }

    //渲染图表
    function render () {

        var config = null,
            chartConfig = null,
            container = null;

        for ( var i = 0, len = sources.length; i < len; i++ ) {

            config = sources[ i ];

            chartConfig = analysisConfig( config );

            container = createContainer( config.table );

            renderChart( container, typeConfig[ config.meta.chartType ], chartConfig );

        }

    }

    /*
     * 渲染图表
     * @param container 图表容器节点对象
     * @param typeConfig 图表类型配置
     * @param config 图表通用配置
     * */
    function renderChart ( container, typeConfig, config ) {

        $( container ).highcharts( $.extend( {}, typeConfig, {

            credits: {
                enabled: false
            },
            exporting: {
                enabled: false
            },
            title: {
                text: config.title,
                x: -20 //center
            },
            subtitle: {
                text: config.subTitle,
                x: -20
            },
            xAxis: {
                title: {
                    text: config.xTitle
                },
                categories: config.categories
            },
            yAxis: {
                title: {
                    text: config.yTitle
                },
                plotLines: [{
                    value: 0,
                    width: 1,
                    color: '#808080'
                }]
            },
            tooltip: {
                enabled: true,
                valueSuffix: config.suffix
            },
            legend: {
                layout: 'vertical',
                align: 'right',
                verticalAlign: 'middle',
                borderWidth: 1
            },
            series: config.series

        } ));

    }

    /*
     * 创建图表的容器
     * 新创建的容器会替换掉对应的table对象
     * */
    function createContainer ( tableNode ) {

        var container = document.createElement( "div" );
        container.className = "edui-chart-container";

        tableNode.parentNode.replaceChild( container, tableNode );

        return container;

    }

    //根据config解析出正确的类别和图表数据信息
    function analysisConfig ( config ) {

        var series = [],
        //数据类别
            categories = [],
            result = [],
            data = config.data,
            meta = config.meta;

        //数据对齐方式为相反的方式， 需要反转数据
        if ( meta.dataFormat != "1" ) {

            for ( var i = 0, len = data.length; i < len ; i++ ) {

                for ( var j = 0, jlen = data[ i ].length; j < jlen; j++ ) {

                    if ( !result[ j ] ) {
                        result[ j ] = [];
                    }

                    result[ j ][ i ] = data[ i ][ j ];

                }

            }

            data = result;

        }

        result = {};

        //普通图表
        if ( meta.chartType != typeConfig.length - 1 ) {

            categories = data[ 0 ].slice( 1 );

            for ( var i = 1, curData; curData = data[ i ]; i++ ) {
                series.push( {
                    name: curData[ 0 ],
                    data: curData.slice( 1 )
                } );
            }

            result.series = series;
            result.categories = categories;
            result.title = meta.title;
            result.subTitle = meta.subTitle;
            result.xTitle = meta.xTitle;
            result.yTitle = meta.yTitle;
            result.suffix = meta.suffix;

        } else {

            var curData = [];

            for ( var i = 1, len = data[ 0 ].length; i < len; i++ ) {

                curData.push( [ data[ 0 ][ i ], data[ 1 ][ i ] | 0 ] );

            }

            //饼图
            series[ 0 ] = {
                type: 'pie',
                name: meta.tip,
                data: curData
            };

            result.series = series;
            result.title = meta.title;
            result.suffix = meta.suffix;

        }

        return result;

    }

});<|endoftext|>


<commit_before>import path from 'path';
import { match } from './providers/react-router';
import PrettyError from 'pretty-error';

import createStore from '../shared/create';
import configure from '../configure';
import html from './html';
import getTools from './tools';

global.__CLIENT__ = false;
global.__SERVER__ = true;
global.__DISABLE_SSR__ = false;  // <----- DISABLES SERVER SIDE RENDERING FOR ERROR DEBUGGING
global.__DEVELOPMENT__ = process.env.NODE_ENV !== 'production';

export default (projectConfig, projectToolsConfig) => {
  const tools = getTools(projectConfig, projectToolsConfig);
  const config = configure(projectConfig);
  const rootComponentPath = config.rootServerComponent || config.rootComponent || __dirname + '/root';
  const rootServerComponent = require(path.resolve(rootComponentPath)).default;
  const getRoutes = require(path.resolve(config.routes)).default;
  const pretty = new PrettyError();

  const dynamicMiddleware = (originalUrl, headers, send, redirect) => {
    if (__DEVELOPMENT__) {
      // Do not cache webpack stats: the script file would change since
      // hot module replacement is enabled in the development env
      tools.refresh();
    }

    const middleware = config.redux.middleware ? require(path.resolve(config.redux.middleware)).default : [];
    const store = createStore(middleware);
    const routes = getRoutes(store);

    if (__DISABLE_SSR__) {
      const content = html(config, tools.assets(), store, headers);
      return new Promise(resolve => send(200, content, resolve)).then(() => {
      });
    }
    return new Promise((resolve) => {
      match(routes, originalUrl, store, (error, redirectLocation, renderProps) => {
        if (redirectLocation) {
          redirect(redirectLocation.pathname + redirectLocation.search, resolve);
        } else if (error) {
          console.error('ROUTER ERROR:', pretty.render(error));
          send(500, resolve);
        } else if (renderProps) {
          rootServerComponent(store, renderProps, config.providers)
            .then(({ root }) => {
              const content = html(config, tools.assets(), store, headers, root);
              send(200, content, resolve);
            })
            .catch((err) => {
              console.log('ERROR GENERATING ROOT COMPONENT', err, err.stack);
              send(500, err, resolve);
            });
        } else {
          send(404, 'Not found', resolve);
        }
      });
    }).then(() => {
    });
  };

  function *koaMiddleware() {
    yield dynamicMiddleware(this.request.originalUrl,
      this.request.headers,
      (status, body, resolve) => {
        this.status = status;
        this.body = body;
        resolve();
      },
      (url, resolve) => {
        this.response.redirect(url);
        resolve();
      });
  }

  switch (config.server.webFramework) {
    case 'koa': {
      return koaMiddleware;
    }
    default:
    case 'express': {
      return (req, res) => {
        dynamicMiddleware(req.originalUrl,
          res._headers,
          (status, body) => res.status(status).send(body),
          (url) => res.redirect(url));
      };
    }
  }
};
<commit_msg>remove extra whitespace<commit_after>import path from 'path';
import { match } from './providers/react-router';
import PrettyError from 'pretty-error';

import createStore from '../shared/create';
import configure from '../configure';
import html from './html';
import getTools from './tools';

global.__CLIENT__ = false;
global.__SERVER__ = true;
global.__DISABLE_SSR__ = false;  // <----- DISABLES SERVER SIDE RENDERING FOR ERROR DEBUGGING
global.__DEVELOPMENT__ = process.env.NODE_ENV !== 'production';

export default (projectConfig, projectToolsConfig) => {
  const tools = getTools(projectConfig, projectToolsConfig);
  const config = configure(projectConfig);
  const rootComponentPath = config.rootServerComponent || config.rootComponent || __dirname + '/root';
  const rootServerComponent = require(path.resolve(rootComponentPath)).default;
  const getRoutes = require(path.resolve(config.routes)).default;
  const pretty = new PrettyError();

  const dynamicMiddleware = (originalUrl, headers, send, redirect) => {
    if (__DEVELOPMENT__) {
      // Do not cache webpack stats: the script file would change since
      // hot module replacement is enabled in the development env
      tools.refresh();
    }

    const middleware = config.redux.middleware ? require(path.resolve(config.redux.middleware)).default : [];
    const store = createStore(middleware);
    const routes = getRoutes(store);

    if (__DISABLE_SSR__) {
      const content = html(config, tools.assets(), store, headers);
      return new Promise(resolve => send(200, content, resolve)).then(() => {
      });
    }
    return new Promise((resolve) => {
      match(routes, originalUrl, store, (error, redirectLocation, renderProps) => {
        if (redirectLocation) {
          redirect(redirectLocation.pathname + redirectLocation.search, resolve);
        } else if (error) {
          console.error('ROUTER ERROR:', pretty.render(error));
          send(500, resolve);
        } else if (renderProps) {
          rootServerComponent(store, renderProps, config.providers)
            .then(({ root }) => {
              const content = html(config, tools.assets(), store, headers, root);
              send(200, content, resolve);
            })
            .catch((err) => {
              console.log('ERROR GENERATING ROOT COMPONENT', err, err.stack);
              send(500, err, resolve);
            });
        } else {
          send(404, 'Not found', resolve);
        }
      });
    }).then(() => {
    });
  };

  function *koaMiddleware() {
    yield dynamicMiddleware(this.request.originalUrl,
      this.request.headers,
      (status, body, resolve) => {
        this.status = status;
        this.body = body;
        resolve();
      },
      (url, resolve) => {
        this.response.redirect(url);
        resolve();
      });
  }

  switch (config.server.webFramework) {
    case 'koa': {
      return koaMiddleware;
    }
    default:
    case 'express': {
      return (req, res) => {
        dynamicMiddleware(req.originalUrl,
          res._headers,
          (status, body) => res.status(status).send(body),
          (url) => res.redirect(url));
      };
    }
  }
};
<|endoftext|>


<commit_before><commit_msg>Stop self referencers trying to cheat ~popular [Fixes #47]<commit_after><|endoftext|>