<commit_before>/*
 * Copyright (C) 2012 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

Ext.define("viewer.FeatureInfo", {
    config: {
        actionBeanUrl: null,
        viewerController: null
    },
    constructor: function(config) {
        this.initConfig(config);
        if(this.config.actionbeanUrl == null) {
            this.config.actionbeanUrl = actionBeans["featureinfo"];
        }
    },
    getVisibleAppLayers: function() {
        var visibleLayerIds = this.viewerController.getVisibleLayers();

        var visibleAppLayers = {};

        for(var i in visibleLayerIds) {
            var id=visibleLayerIds[i];
            var appLayer = viewerController.getAppLayerById(id);
            if(appLayer != null) {
                visibleAppLayers[appLayer.id] = true;
            }
        }
        return visibleAppLayers;

    },
    featureInfoInternal: function(params, successFunction, failureFunction) {
        var me = this;
        params = Ext.apply(params, { application: this.viewerController.app.id });
        Ext.Ajax.request({
            url: this.config.actionbeanUrl,
            params: params,
            timeout: 40000,
            success: function(result) {
                var response = Ext.JSON.decode(result.responseText);

                for(var i in response) {
                    var r = response[i];
                    if(r.request.appLayer) {
                        r.appLayer = me.viewerController.app.appLayers[r.request.appLayer];
                    } else if(r.request.service) {
                        r.service = me.viewerController.app.services[r.request.service];
                    }
                }
                successFunction(response);
            },
            failure: function(result) {
                if(failureFunction != undefined) {
                    failureFunction("Ajax request failed with status " + result.status + " " + result.statusText + ": " + result.responseText);
                }
            }
        });
    },
    featureInfo: function(x, y, distance, successFunction, failureFunction) {
        var visibleAppLayers = this.getVisibleAppLayers();

        var queries = [];
        for(var id in visibleAppLayers) {
            var appLayer = this.viewerController.app.appLayers[id];
            var query = { appLayer: appLayer.id };
            if(appLayer.filter) {
                query.filter = appLayer.filter.getCQL();
            }
            queries.push(query);
        }

        var params = {featureInfo: true, x: x, y: y, distance: distance, queryJSON: Ext.JSON.encode(queries)};

        this.featureInfoInternal(params, successFunction, failureFunction);
    },
    layersFeatureInfo: function(x, y, distance, appLayers, successFunction, failureFunction) {

        var visibleAppLayers = this.getVisibleAppLayers();

        var queries = [];
        for(var i in appLayers) {
            var appLayer = appLayers[i];

            if(visibleAppLayers[appLayer.id] === true) {
                var query = { appLayer: appLayer.id };
                if(appLayer.filter) {
                    query.filter = appLayer.filter.getCQLWithoutType("GEOMETRY");
                }
                queries.push(query);
            }
        }

        var params = {featureInfo: true, x: x, y: y, distance: distance, queryJSON: Ext.JSON.encode(queries)};

        this.featureInfoInternal(params, successFunction, failureFunction);
    },
    editFeatureInfo: function(x, y, distance, appLayer, successFunction, failureFunction) {
        var query = [{appLayer: appLayer.id}];
        Ext.Ajax.request({
            url: this.config.actionbeanUrl,
            params: {application: this.viewerController.app.id, featureInfo: true, edit: true, arrays: true, x: x, y: y, distance: distance, queryJSON: Ext.JSON.encode(query)},
            timeout: 40000,
            success: function(result) {
                var response = Ext.JSON.decode(result.responseText)[0];

                if(response.error) {
                    failureFunction("Error finding feature to edit: " + response.error);
                } else {
                    successFunction(response.features);
                }
            },
            failure: function(result) {
                if(failureFunction != undefined) {
                    failureFunction("Ajax request failed with status " + result.status + " " + result.statusText + ": " + result.responseText);
                }
            }
        });
    }
});
<commit_msg>dont do request when no layers to query<commit_after>/*
 * Copyright (C) 2012 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

Ext.define("viewer.FeatureInfo", {
    config: {
        actionBeanUrl: null,
        viewerController: null
    },
    constructor: function(config) {
        this.initConfig(config);
        if(this.config.actionbeanUrl == null) {
            this.config.actionbeanUrl = actionBeans["featureinfo"];
        }
    },
    getVisibleAppLayers: function() {
        var visibleLayerIds = this.viewerController.getVisibleLayers();

        var visibleAppLayers = {};

        for(var i in visibleLayerIds) {
            var id=visibleLayerIds[i];
            var appLayer = viewerController.getAppLayerById(id);
            if(appLayer != null) {
                visibleAppLayers[appLayer.id] = true;
            }
        }
        return visibleAppLayers;

    },
    featureInfoInternal: function(params, successFunction, failureFunction) {
        var me = this;
        params = Ext.apply(params, { application: this.viewerController.app.id });
        Ext.Ajax.request({
            url: this.config.actionbeanUrl,
            params: params,
            timeout: 40000,
            success: function(result) {
                var response = Ext.JSON.decode(result.responseText);

                for(var i in response) {
                    var r = response[i];
                    if(r.request.appLayer) {
                        r.appLayer = me.viewerController.app.appLayers[r.request.appLayer];
                    } else if(r.request.service) {
                        r.service = me.viewerController.app.services[r.request.service];
                    }
                }
                successFunction(response);
            },
            failure: function(result) {
                if(failureFunction != undefined) {
                    failureFunction("Ajax request failed with status " + result.status + " " + result.statusText + ": " + result.responseText);
                }
            }
        });
    },
    featureInfo: function(x, y, distance, successFunction, failureFunction) {
        var visibleAppLayers = this.getVisibleAppLayers();

        var queries = [];
        for(var id in visibleAppLayers) {
            var appLayer = this.viewerController.app.appLayers[id];
            var query = { appLayer: appLayer.id };
            if(appLayer.filter) {
                query.filter = appLayer.filter.getCQL();
            }
            queries.push(query);
        }

        var params = {featureInfo: true, x: x, y: y, distance: distance, queryJSON: Ext.JSON.encode(queries)};

        this.featureInfoInternal(params, successFunction, failureFunction);
    },
    layersFeatureInfo: function(x, y, distance, appLayers, successFunction, failureFunction) {

        var visibleAppLayers = this.getVisibleAppLayers();

        var queries = [];
        for(var i in appLayers) {
            var appLayer = appLayers[i];

            if(visibleAppLayers[appLayer.id] === true) {
                var query = { appLayer: appLayer.id };
                if(appLayer.filter) {
                    query.filter = appLayer.filter.getCQLWithoutType("GEOMETRY");
                }
                queries.push(query);
            }
        }

        var params = {featureInfo: true, x: x, y: y, distance: distance, queryJSON: Ext.JSON.encode(queries)};
        if(queries.length > 0) {
            this.featureInfoInternal(params, successFunction, failureFunction);
        }
    },
    editFeatureInfo: function(x, y, distance, appLayer, successFunction, failureFunction) {
        var query = [{appLayer: appLayer.id}];
        Ext.Ajax.request({
            url: this.config.actionbeanUrl,
            params: {application: this.viewerController.app.id, featureInfo: true, edit: true, arrays: true, x: x, y: y, distance: distance, queryJSON: Ext.JSON.encode(query)},
            timeout: 40000,
            success: function(result) {
                var response = Ext.JSON.decode(result.responseText)[0];

                if(response.error) {
                    failureFunction("Error finding feature to edit: " + response.error);
                } else {
                    successFunction(response.features);
                }
            },
            failure: function(result) {
                if(failureFunction != undefined) {
                    failureFunction("Ajax request failed with status " + result.status + " " + result.statusText + ": " + result.responseText);
                }
            }
        });
    }
});
<|endoftext|>


<commit_before>module('users.timfelgentreff.babelsberg.src_transform_test').requires('lively.TestFramework', 'users.timfelgentreff.standalone.Compressor').toRun(function() {

TestCase.subclass('users.timfelgentreff.babelsberg.src_transform_test.TransformTest', {

    testAssignResult: function () {
        var src = "always: {store: c; a < b}";
        var result = new BabelsbergSrcTransform().transform(src);
        result = result.replace(/[ \n\r\t]/g,"");
        this.assert(result === "c=bbb.always({ctx:{c:c,a:a,b:b,_$_self:this.doitContext||this}},function(){returna<b;;});", result);
    },

    testObjectEditorTransform1: function () {
        var src = "always: {a < b}";
        var result = new BabelsbergSrcTransform().transform(src);
        result = result.replace(/[ \n\r\t]/g,"");
        this.assert(result === "bbb.always({ctx:{a:a,b:b,_$_self:this.doitContext||this}},function(){returna<b;;});", result);
    },
    testObjectEditorTransform2: function () {
        var src = "always: {solver: cassowary; priority: 'high'; a < b}";
        var result = new BabelsbergSrcTransform().transform(src);
        result = result.replace(/[ \n\r\t]/g,"");
        this.assert(result === "bbb.always({solver:cassowary,priority:\"high\",ctx:{cassowary:cassowary,a:a,b:b,_$_self:this.doitContext||this}},function(){returna<b;;});", result);
    },
    testOETransformWithLaterDeclarations: function () {
        var src = "always: { true }\n\
                    var late;\n";
        var result = new BabelsbergSrcTransform().transform(src);
        // asserts correct indenting, too
        this.assert(result === "bbb.always({\n" +
                               "    ctx: {\n" +
                               "        _$_self: this.doitContext || this\n" +
                               "    }\n" +
                               "}, function() {\n" +
                               "    return true;;\n" +
                               "});\n" +
                               "\n" +
                               "var late;", result);
    },
    testSCBTransformMulti: function () {
        var src = "always: {solver: cassowary; priority: 'high'; a < b}\n    always: {solver: cassowary; priority: 'high'; a < b}",
            panel = new lively.ide.BrowserPanel(pt(100,100)),
            editor = new lively.morphic.CodeEditor(rect(0,0,100,100), "    " + src);
        panel.addMorph(editor);
        editor.evalEnabled = false;

        cop.withLayers([ConstraintSyntaxLayer], function () {
            editor.doSave();
        });
        // asserts correct indenting, too
        result = "    bbb.always({\n" +
              "        solver: cassowary,\n" +
              "        priority: \"high\",\n" +
              "        ctx: {\n" +
              "            cassowary: cassowary,\n" +
              "            a: a,\n" +
              "            b: b,\n" +
              "            _$_self: this.doitContext || this\n" +
              "        }\n" +
              "    }, function() {\n" +
              "        return a < b;;\n" +
              "    });";
        result += "\n" + result;
        this.assert(editor.textString === result, editor.textString);
    },

    testSCBTransform: function () {
        var src = "always: {solver: cassowary; priority: 'high'; a < b}",
            panel = new lively.ide.BrowserPanel(pt(100,100)),
            editor = new lively.morphic.CodeEditor(rect(0,0,100,100), "    " + src);
        panel.addMorph(editor);
        editor.evalEnabled = false;

        cop.withLayers([ConstraintSyntaxLayer], function () {
            editor.doSave();
        });
        // asserts correct indenting, too
        this.assert(editor.textString === "    bbb.always({\n" +
                                          "        solver: cassowary,\n" +
                                          "        priority: \"high\",\n" +
                                          "        ctx: {\n" +
                                          "            cassowary: cassowary,\n" +
                                          "            a: a,\n" +
                                          "            b: b,\n" +
                                          "            _$_self: this.doitContext || this\n" +
                                          "        }\n" +
                                          "    }, function() {\n" +
                                          "        return a < b;;\n" +
                                          "    });", editor.textString);
    },
    testConvertAddScript: function() {
        var src = "this.addScript(function () { foo })";
        var result = new BabelsbergSrcTransform().transformAddScript(src);
        result = result.replace(/[ \n\r\t]/g,"");
        this.assert(result === "this.addScript(function(){foo;},\"function(){foo}\");", result);
    }
});
TestCase.subclass('users.timfelgentreff.babelsberg.src_transform_test.MinifyTest', {
    testBuildMinifiedJs: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["prototypejs", "core", "cassowary", "deltablue", "csp"], "babelsberg_mini_prototype");
    },
    testBuildMinifiedJs1: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["core", "cassowary", "deltablue", "csp"], "babelsberg_mini");
    },
    testBuildMinifiedJs2: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["core"], "babelsberg_core");
    },
    testBuildMinifiedJs3: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["deltablue"], "babelsberg_deltablue");
    },
    testBuildMinifiedJs4: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["cassowary"], "babelsberg_cassowary");
    },
    testBuildMinifiedJs5: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["csp"], "babelsberg_csp");
    },
    testBuildMinifiedJs6: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["sutherland"], "babelsberg_sutherland");
    },
    testBuildMinifiedJs7: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["reactive"], "babelsberg_reactive");
    },
    testBuildMinifiedJs8: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["z3"], "babelsberg_z3");
    },
});

}) // end of module
<commit_msg>add test for trigger transform<commit_after>module('users.timfelgentreff.babelsberg.src_transform_test').requires('lively.TestFramework', 'users.timfelgentreff.standalone.Compressor').toRun(function() {

TestCase.subclass('users.timfelgentreff.babelsberg.src_transform_test.TransformTest', {

    testAssignResult: function () {
        var src = "always: {store: c; a < b}";
        var result = new BabelsbergSrcTransform().transform(src);
        result = result.replace(/[ \n\r\t]/g,"");
        this.assert(result === "c=bbb.always({ctx:{c:c,a:a,b:b,_$_self:this.doitContext||this}},function(){returna<b;;});", result);
    },

    testObjectEditorTransform1: function () {
        var src = "always: {a < b}";
        var result = new BabelsbergSrcTransform().transform(src);
        result = result.replace(/[ \n\r\t]/g,"");
        this.assert(result === "bbb.always({ctx:{a:a,b:b,_$_self:this.doitContext||this}},function(){returna<b;;});", result);
    },
    testObjectEditorTransform2: function () {
        var src = "always: {solver: cassowary; priority: 'high'; a < b}";
        var result = new BabelsbergSrcTransform().transform(src);
        result = result.replace(/[ \n\r\t]/g,"");
        this.assert(result === "bbb.always({solver:cassowary,priority:\"high\",ctx:{cassowary:cassowary,a:a,b:b,_$_self:this.doitContext||this}},function(){returna<b;;});", result);
    },
    testObjectEditorTransformTrigger: function () {
        var src = "var c = when(function() {a < b}).trigger(function () { alert });";
        var result = new BabelsbergSrcTransform().transform(src);
        result = result.replace(/[ \n\r\t]/g,"");
        this.assert(result === "varc=bbb.when({ctx:{a:a,b:b,_$_self:this.doitContext||this}},function(){returna<b;;}).trigger(function(){alert});", result);
    },
    testOETransformWithLaterDeclarations: function () {
        var src = "always: { true }\n\
                    var late;\n";
        var result = new BabelsbergSrcTransform().transform(src);
        // asserts correct indenting, too
        this.assert(result === "bbb.always({\n" +
                               "    ctx: {\n" +
                               "        _$_self: this.doitContext || this\n" +
                               "    }\n" +
                               "}, function() {\n" +
                               "    return true;;\n" +
                               "});\n" +
                               "\n" +
                               "var late;", result);
    },
    testSCBTransformMulti: function () {
        var src = "always: {solver: cassowary; priority: 'high'; a < b}\n    always: {solver: cassowary; priority: 'high'; a < b}",
            panel = new lively.ide.BrowserPanel(pt(100,100)),
            editor = new lively.morphic.CodeEditor(rect(0,0,100,100), "    " + src);
        panel.addMorph(editor);
        editor.evalEnabled = false;

        cop.withLayers([ConstraintSyntaxLayer], function () {
            editor.doSave();
        });
        // asserts correct indenting, too
        result = "    bbb.always({\n" +
              "        solver: cassowary,\n" +
              "        priority: \"high\",\n" +
              "        ctx: {\n" +
              "            cassowary: cassowary,\n" +
              "            a: a,\n" +
              "            b: b,\n" +
              "            _$_self: this.doitContext || this\n" +
              "        }\n" +
              "    }, function() {\n" +
              "        return a < b;;\n" +
              "    });";
        result += "\n" + result;
        this.assert(editor.textString === result, editor.textString);
    },

    testSCBTransform: function () {
        var src = "always: {solver: cassowary; priority: 'high'; a < b}",
            panel = new lively.ide.BrowserPanel(pt(100,100)),
            editor = new lively.morphic.CodeEditor(rect(0,0,100,100), "    " + src);
        panel.addMorph(editor);
        editor.evalEnabled = false;

        cop.withLayers([ConstraintSyntaxLayer], function () {
            editor.doSave();
        });
        // asserts correct indenting, too
        this.assert(editor.textString === "    bbb.always({\n" +
                                          "        solver: cassowary,\n" +
                                          "        priority: \"high\",\n" +
                                          "        ctx: {\n" +
                                          "            cassowary: cassowary,\n" +
                                          "            a: a,\n" +
                                          "            b: b,\n" +
                                          "            _$_self: this.doitContext || this\n" +
                                          "        }\n" +
                                          "    }, function() {\n" +
                                          "        return a < b;;\n" +
                                          "    });", editor.textString);
    },
    testConvertAddScript: function() {
        var src = "this.addScript(function () { foo })";
        var result = new BabelsbergSrcTransform().transformAddScript(src);
        result = result.replace(/[ \n\r\t]/g,"");
        this.assert(result === "this.addScript(function(){foo;},\"function(){foo}\");", result);
    }
});
TestCase.subclass('users.timfelgentreff.babelsberg.src_transform_test.MinifyTest', {
    testBuildMinifiedJs: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["prototypejs", "core", "cassowary", "deltablue", "csp"], "babelsberg_mini_prototype");
    },
    testBuildMinifiedJs1: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["core", "cassowary", "deltablue", "csp"], "babelsberg_mini");
    },
    testBuildMinifiedJs2: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["core"], "babelsberg_core");
    },
    testBuildMinifiedJs3: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["deltablue"], "babelsberg_deltablue");
    },
    testBuildMinifiedJs4: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["cassowary"], "babelsberg_cassowary");
    },
    testBuildMinifiedJs5: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["csp"], "babelsberg_csp");
    },
    testBuildMinifiedJs6: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["sutherland"], "babelsberg_sutherland");
    },
    testBuildMinifiedJs7: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["reactive"], "babelsberg_reactive");
    },
    testBuildMinifiedJs8: function () {
        module("users.timfelgentreff.standalone.Compressor").load(true);
        users.timfelgentreff.standalone.Compressor.doAction(["z3"], "babelsberg_z3");
    },
});

}) // end of module
<|endoftext|>


<commit_before>/*! backbone-paginated-collection */
;(function (root) { function moduleDefinition(Backbone, _) {

function recalculatePagination() {
  var length = this.superset().length;
  var perPage = this.getPerPage();

  // If the # of objects can be exactly divided by the number
  // of pages, it would leave an empty last page if we took
  // the floor.
  var totalPages = length % perPage === 0 ?
    (length / perPage) : Math.floor(length / perPage) + 1;

  this._totalPages = totalPages;
  this.setPage(0);

  updatePagination.call(this);
}

function updatePagination() {
  var start = this.getPage() * this.getPerPage();
  var end = start + this.getPerPage();

  this._collection.reset(this.superset().toArray().slice(start, end));

  // A drawback is that we will have to update the length ourselves
  // every time we modify this collection.
  this.length = this._collection.length;
}

function onModelAdd() {
  console.log('add');
}

function onModelRemove() {
  console.log('remove');
}

function onReset() {
  console.log('reset');
}

function Paginated(superset, options) {
  // Save a reference to the original collection
  this._superset = superset;

  // The idea is to keep an internal backbone collection with the paginated
  // set, and expose limited functionality.
  this._collection = new Backbone.Collection(superset.toArray());
  this.setPerPage(options ? options.perPage: this._defaultPerPage);

  this._superset.on('add', onModelAdd, this);
  this._superset.on('remove', onModelRemove, this);
  this._superset.on('reset', onReset, this);
}

var methods = {

  _defaultPerPage: 20,

  setPerPage: function(perPage) {
    this._perPage = perPage;
    recalculatePagination.call(this);

    this.trigger('paginated:change:perPage', {
      perPage: perPage,
      numPages: this.getNumPages()
    });
  },

  setPage: function(page) {
    // The lowest page we could set
    var lowerLimit = 0;
    // The highest page we could set
    var upperLimit = this.getNumPages() - 1;

    // If the page is higher or lower than these limits,
    // set it to the limit.
    page = page > lowerLimit ? page : lowerLimit;
    page = page < upperLimit ? page : upperLimit;

    this._page = page;
    updatePagination.call(this);

    this.trigger('paginated:change:page', { page: page });
  },

  getPerPage: function() {
    return this._perPage;
  },

  getNumPages: function() {
    return this._totalPages;
  },

  getPage: function() {
    return this._page;
  },

  hasNextPage: function() {
    return this.getPage() < this.getNumPages() - 1;
  },

  hasPrevPage: function() {
    return this.getPage() > 0;
  },

  nextPage: function() {
    this.movePage(1);
  },

  prevPage: function() {
    this.movePage(-1);
  },

  movePage: function(delta) {
    this.setPage(this.getPage() + delta);
  },

  superset: function() {
    return this._superset;
  }

};

// Methods on `this._collection` we will expose to the outside world
var collectionMethods = [
  'toJSON', 'first', 'last', 'at', 'get', 'map',
  'each', 'slice', 'where', 'findWhere', 'contains',
  'indexOf', 'toArray', 'pluck'
];

_.each(collectionMethods, function(method) {
  methods[method] = function() {
    return Backbone.Collection.prototype[method].apply(this._collection, arguments);
  };
});

// Build up the prototype
_.extend(Paginated.prototype, methods, Backbone.Events);

return Paginated;

// ---------------------------------------------------------------------------
} if (typeof exports === 'object') {
  // node export
  module.exports = moduleDefinition(require('backbone'), require('underscore'));
} else if (typeof define === 'function' && define.amd) {
  // amd anonymous module registration
  define(['backbone', 'underscore'], moduleDefinition);
} else {
  // browser global
  root.PaginatedCollection = moduleDefinition(root.Backbone, root._);
}}(this));
<commit_msg>A bit more implementation. Still some failing tests.<commit_after>/*! backbone-paginated-collection */
;(function (root) { function moduleDefinition(Backbone, _) {

function recalculatePagination() {
  var length = this.superset().length;
  var perPage = this.getPerPage();

  // If the # of objects can be exactly divided by the number
  // of pages, it would leave an empty last page if we took
  // the floor.
  var totalPages = length % perPage === 0 ?
    (length / perPage) : Math.floor(length / perPage) + 1;

  this._totalPages = totalPages;
  updatePagination.call(this);
}

function updatePagination() {
  var start = this.getPage() * this.getPerPage();
  var end = start + this.getPerPage();

  this._collection.reset(this.superset().toArray().slice(start, end));

  // A drawback is that we will have to update the length ourselves
  // every time we modify this collection.
  this.length = this._collection.length;
}

function pipeEvents() {
  var args = _.toArray(arguments);

  // replace any references to `this._collection` with `this`
  for (var i = 1; i < args.length; i++) {
    // Is there a better way to check for this?
    // List all of the possible events?
    if (args[i].models && args[i].models.length === this._collection.models.length) {
      args[i] = this;
    }
  }

  this.trigger.apply(this, args);
}

function Paginated(superset, options) {
  // Save a reference to the original collection
  this._superset = superset;

  // The idea is to keep an internal backbone collection with the paginated
  // set, and expose limited functionality.
  this._collection = new Backbone.Collection(superset.toArray());
  this.setPerPage(options ? options.perPage: this._defaultPerPage);

  this.listenTo(this._superset, 'add', recalculatePagination);
  this.listenTo(this._superset, 'remove', recalculatePagination);
  this.listenTo(this._superset, 'reset', recalculatePagination);
  this.listenTo(this._collection, 'all', pipeEvents);
}

var methods = {

  _defaultPerPage: 20,

  setPerPage: function(perPage) {
    this._perPage = perPage;
    recalculatePagination.call(this);
    this.setPage(0);

    this.trigger('paginated:change:perPage', {
      perPage: perPage,
      numPages: this.getNumPages()
    });
  },

  setPage: function(page) {
    // The lowest page we could set
    var lowerLimit = 0;
    // The highest page we could set
    var upperLimit = this.getNumPages() - 1;

    // If the page is higher or lower than these limits,
    // set it to the limit.
    page = page > lowerLimit ? page : lowerLimit;
    page = page < upperLimit ? page : upperLimit;

    this._page = page;
    updatePagination.call(this);

    this.trigger('paginated:change:page', { page: page });
  },

  getPerPage: function() {
    return this._perPage;
  },

  getNumPages: function() {
    return this._totalPages;
  },

  getPage: function() {
    return this._page;
  },

  hasNextPage: function() {
    return this.getPage() < this.getNumPages() - 1;
  },

  hasPrevPage: function() {
    return this.getPage() > 0;
  },

  nextPage: function() {
    this.movePage(1);
  },

  prevPage: function() {
    this.movePage(-1);
  },

  movePage: function(delta) {
    this.setPage(this.getPage() + delta);
  },

  superset: function() {
    return this._superset;
  }

};

// Methods on `this._collection` we will expose to the outside world
var collectionMethods = [
  'toJSON', 'first', 'last', 'at', 'get', 'map',
  'each', 'slice', 'where', 'findWhere', 'contains',
  'indexOf', 'toArray', 'pluck'
];

_.each(collectionMethods, function(method) {
  methods[method] = function() {
    return Backbone.Collection.prototype[method].apply(this._collection, arguments);
  };
});

// Build up the prototype
_.extend(Paginated.prototype, methods, Backbone.Events);

return Paginated;

// ---------------------------------------------------------------------------
} if (typeof exports === 'object') {
  // node export
  module.exports = moduleDefinition(require('backbone'), require('underscore'));
} else if (typeof define === 'function' && define.amd) {
  // amd anonymous module registration
  define(['backbone', 'underscore'], moduleDefinition);
} else {
  // browser global
  root.PaginatedCollection = moduleDefinition(root.Backbone, root._);
}}(this));
<|endoftext|>


<commit_before>/*
**  ComponentJS -- Component System for JavaScript <http://componentjs.com>
**  Copyright (c) 2009-2013 Ralf S. Engelschall <http://engelschall.com>
**
**  This Source Code Form is subject to the terms of the Mozilla Public
**  License, v. 2.0. If a copy of the MPL was not distributed with this
**  file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

cs.ns('app.ui.widget.grid')

app.ui.widget.grid.ctrl = cs.clazz({
    mixin: [ cs.marker.controller ],
    dynamics: {
        selectable: true
    },
    cons: function (selectable) {
        if (selectable === false) {
            this.selectable = selectable
        }
    },
    protos: {
        create: function () {
            var self = this

            cs(self).create('gridModel/view',
                app.ui.widget.grid.model,
                new app.ui.widget.grid.view(self.selectable)
            )

            cs(self).register({
                name: 'unshift', spool: 'created',
                func: function (trace) {
                    var tuples = cs(self, 'gridModel').value('data:rows')
                    tuples.unshift(trace)
                    cs(self, 'gridModel').value('data:rows', tuples)
                    cs(self, 'gridModel/view').call('unshift', trace)
                }
            })

            cs(self).register({
                name: 'save', spool: 'created',
                func: function () {
                    /* global btoa */
                    window.location = 'data:application/octet-stream;base64,'+
                        btoa(cs(self, 'gridModel').value('data:savable'))
                }
            })

            cs(self).register({
                name: 'tuples' , spool: 'created',
                func: function (tuples) {
                    if (tuples) {
                        cs(self, 'gridModel').value('data:rows', tuples, true)
                    } else {
                        return cs(self, 'gridModel').value('data:rows')
                    }
                }
            })

            cs(self).register({
                name: 'columns', spool: 'created',
                func: function (columns) {
                    cs(self, 'gridModel').value('data:columns', columns)
                }
            })

            cs(self).register({
                name: 'clear', spool: 'created',
                func: function () {
                    cs(self, 'gridModel').value('data:rows', [])
                }
            })

            cs(self).register({
                name: 'filter', spool: 'created',
                func: function (filter) {
                    cs(self, 'gridModel').value('state:filter', filter)
                }
            })

            cs(self, 'gridModel').observe({
                name: 'data:selected-obj', spool: '..:rendered',
                touch: true,
                func: function (ev, nVal) {
                    cs(self).publish('objectSelected', nVal)
                }
            })
        },
        destroy: function () {
            cs(this).unspool('created')
        }
    }
})

app.ui.widget.grid.model = cs.clazz({
    mixin: [ cs.marker.model ],
    protos: {
        create: function () {
            var self = this

            var validTuplesSet = '[{ id?: number, time: number, source: string, sourceType: string,' +
                ' origin: string, originType: string, operation: string,' +
                ' parameters: any, result?: string, checks?: any }*]'

            /*  presentation model for items  */
            cs(self).model({
                'data:columns'      : { value: [],   valid: '[{ label: string, dataIndex: string, width?: number, align?:string, renderer?:any }*]' },
                'state:selection'   : { value: -1,   valid: 'number' },
                'state:filter'      : { value: '',   valid: 'string' },
                'data:selected-obj' : { value: null, valid: 'object' },
                'data:savable'      : { value: '',   valid: 'string' },
                'data:filtered'     : { value: [],   valid: validTuplesSet },
                'data:rows'         : { value: [],   valid: validTuplesSet }
            })

            cs(self).observe({
                name: 'data:rows', spool: 'created',
                touch: true,
                func: function (ev, nVal) {
                    cs(self).value('data:filtered', nVal, true)
                }
            })

            cs(self).observe({
                name: 'state:filter', spool: 'created',
                touch: true,
                func: function (ev, nVal) {
                    var unfiltered = cs(self).value('data:rows')
                    if (nVal === '')
                        cs(self).value('data:filtered', unfiltered)
                    else {
                        var result = []

                        var tmp = nVal.split(':')

                        for (var i = 0; i < unfiltered.length; i++) {
                            var tuple = unfiltered[i]
                            if (tmp.length === 2 && tuple[tmp[0]]) {
                                if (tuple[tmp[0]].toLowerCase().indexOf(tmp[1].toLowerCase()) !== -1)
                                    result.push(tuple)
                            }
                            else {
                                for (var key in tuple) {
                                    if (key === 'time' || key === 'id')
                                        continue;
                                    var val = tuple[key]
                                    if (key === 'parameters')
                                        val = JSON.stringify(val)
                                    if (val.toLowerCase().indexOf(nVal.toLowerCase()) !== -1) {
                                        result.push(tuple)
                                        break;
                                    }
                                }
                            }
                        }
                        cs(self).value('data:filtered', result)
                    }
                }
            })

            /*  calculate the savable content on demand  */
            cs(self).observe({
                name: 'data:savable', spool: 'created',
                operation: 'get',
                touch: true,
                func: function (ev) {
                    var result = ''
                    var rows = cs(self).value('data:filtered')

                    for (var i = 0; i < rows.length; i++) {
                        var row = rows[i]

                        /*  stringify parameters  */
                        var params = "";
                        var p = row.parameters;
                        for (var name in p) {
                            if (params !== "")
                                params += ", ";
                            params += name + ": " + JSON.stringify(p[name]);
                        }
                        if (params !== "")
                            params = "{ " + params + " }";
                        else
                            params = "{}";

                        result += '< ' +
                            row.time + ', ' +
                            row.source + ', ' +
                            row.sourceType + ', ' +
                            row.origin + ', ' +
                            row.originType + ', ' +
                            row.operation + ', ' +
                            params + ' > \n'
                    }
                    result = result.substr(0, result.length - 1)
                    ev.result(result)
                }
            })
        },
        destroy: function () {
            cs(this).unspool('created')
        }
    }
})

app.ui.widget.grid.view = cs.clazz({
    mixin: [ cs.marker.view ],
    dynamics: {
        selectable: true
    },
    cons: function (selectable) {
        if (selectable === false) {
            this.selectable = selectable
        }
    },
    protos: {
        render: function () {
            var self = this
            var grid = $.markup('grid')

            cs(self).plug(grid)

            cs(self).observe({
                name: 'data:columns', spool: 'rendered',
                touch: true,
                func: function (ev, nVal) {
                    for (var i = 0; i < nVal.length; i++) {
                        var vars = { label: nVal[i].label }
                        if (nVal[i].width)
                            vars.style = 'width: ' + nVal[i].width + 'px;'
                        $('.thead > .row', grid).markup('grid/column', vars)
                    }
                }
            })

            var fillRow = function (row, trace) {
                var columns = cs(self).value('data:columns')
                for (var x = 0; x < columns.length; x++) {
                    var vars = { style: '' }
                    if (columns[x].dataIndex === 'parameters')
                        vars.label = JSON.stringify(trace[columns[x].dataIndex])
                    else
                        if (columns[x].renderer)
                            vars.label = columns[x].renderer(trace[columns[x].dataIndex])
                        else
                            vars.label = trace[columns[x].dataIndex]
                    if (columns[x].width)
                        vars.style += 'width: ' + columns[x].width + 'px;'
                    if (columns[x].align)
                        vars.style += 'text-align: ' + columns[x].align + ';'
                    $(row).markup('grid/row/data', vars)
                }
            }

            cs(self).register({
                name: 'unshift', spool: 'rendered',
                func: function (trace) {
                    trace.style = ''
                    var i = $('.tbody > .row:first', grid).data('i')
                    if (typeof i === 'undefined')
                        i = -1
                    var row = $.markup('grid/row', { i: ++i })
                    fillRow(row, trace);
                    delete trace.style
                    $('.tbody', grid).prepend(row)
                    if (self.selectable) {
                        row.addClass('selectable')
                        row.click(function () {
                            var len = cs(self).value('data:rows').length
                            cs(self).value('state:selection', len - $(this).data('i') - 1)
                        })
                    }
                }
            })

            cs(self).observe({
                name: 'data:filtered', spool: 'rendered',
                touch: true,
                func: function (ev, nVal) {
                    $('.tbody tr', grid).remove()
                    for (var i = 0; i < nVal.length; i++) {
                        var row = $('.tbody', grid).markup('grid/row', { i: nVal.length - 1 - i })
                        fillRow(row, nVal[i])
                    }
                    cs(self).value('state:selection', -1)
                    if (self.selectable) {
                        var rows = $('.table > .tbody > .row', grid[2])
                        rows.addClass('selectable')
                        rows.click(function () {
                            var len = cs(self).value('data:rows').length
                            cs(self).value('state:selection', len - $(this).data('i') - 1)
                        })
                    }
                }
            })

            /*  react on selection change  */
            cs(self).observe({
                name: 'state:selection', spool: 'rendered',
                touch: true,
                func: function (ev, nVal) {
                    if (nVal !== -1) {
                        cs(self).value('data:selected-obj', cs(self).value('data:rows')[nVal])
                        $('.selected', grid).removeClass('selected')
                        $('.table > .tbody > .row', grid[2]).eq(nVal).addClass('selected')
                    }
                    else
                        cs(self).value('data:selected-obj', null)
                }
            })
        },
        release: function () {
            cs(this).unspool('rendered')
        }
    }
})
<commit_msg>Fixes #3 iterated over constraint checking results as well<commit_after>/*
**  ComponentJS -- Component System for JavaScript <http://componentjs.com>
**  Copyright (c) 2009-2013 Ralf S. Engelschall <http://engelschall.com>
**
**  This Source Code Form is subject to the terms of the Mozilla Public
**  License, v. 2.0. If a copy of the MPL was not distributed with this
**  file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

cs.ns('app.ui.widget.grid')

app.ui.widget.grid.ctrl = cs.clazz({
    mixin: [ cs.marker.controller ],
    dynamics: {
        selectable: true
    },
    cons: function (selectable) {
        if (selectable === false) {
            this.selectable = selectable
        }
    },
    protos: {
        create: function () {
            var self = this

            cs(self).create('gridModel/view',
                app.ui.widget.grid.model,
                new app.ui.widget.grid.view(self.selectable)
            )

            cs(self).register({
                name: 'unshift', spool: 'created',
                func: function (trace) {
                    var tuples = cs(self, 'gridModel').value('data:rows')
                    tuples.unshift(trace)
                    cs(self, 'gridModel').value('data:rows', tuples)
                    cs(self, 'gridModel/view').call('unshift', trace)
                }
            })

            cs(self).register({
                name: 'save', spool: 'created',
                func: function () {
                    /* global btoa */
                    window.location = 'data:application/octet-stream;base64,'+
                        btoa(cs(self, 'gridModel').value('data:savable'))
                }
            })

            cs(self).register({
                name: 'tuples' , spool: 'created',
                func: function (tuples) {
                    if (tuples) {
                        cs(self, 'gridModel').value('data:rows', tuples, true)
                    } else {
                        return cs(self, 'gridModel').value('data:rows')
                    }
                }
            })

            cs(self).register({
                name: 'columns', spool: 'created',
                func: function (columns) {
                    cs(self, 'gridModel').value('data:columns', columns)
                }
            })

            cs(self).register({
                name: 'clear', spool: 'created',
                func: function () {
                    cs(self, 'gridModel').value('data:rows', [])
                }
            })

            cs(self).register({
                name: 'filter', spool: 'created',
                func: function (filter) {
                    cs(self, 'gridModel').value('state:filter', filter)
                }
            })

            cs(self, 'gridModel').observe({
                name: 'data:selected-obj', spool: '..:rendered',
                touch: true,
                func: function (ev, nVal) {
                    cs(self).publish('objectSelected', nVal)
                }
            })
        },
        destroy: function () {
            cs(this).unspool('created')
        }
    }
})

app.ui.widget.grid.model = cs.clazz({
    mixin: [ cs.marker.model ],
    protos: {
        create: function () {
            var self = this

            var validTuplesSet = '[{ id?: number, time: number, source: string, sourceType: string,' +
                ' origin: string, originType: string, operation: string,' +
                ' parameters: any, result?: string, checks?: any }*]'

            /*  presentation model for items  */
            cs(self).model({
                'data:columns'      : { value: [],   valid: '[{ label: string, dataIndex: string, width?: number, align?:string, renderer?:any }*]' },
                'state:selection'   : { value: -1,   valid: 'number' },
                'state:filter'      : { value: '',   valid: 'string' },
                'data:selected-obj' : { value: null, valid: 'object' },
                'data:savable'      : { value: '',   valid: 'string' },
                'data:filtered'     : { value: [],   valid: validTuplesSet },
                'data:rows'         : { value: [],   valid: validTuplesSet }
            })

            cs(self).observe({
                name: 'data:rows', spool: 'created',
                touch: true,
                func: function (ev, nVal) {
                    cs(self).value('data:filtered', nVal, true)
                }
            })

            cs(self).observe({
                name: 'state:filter', spool: 'created',
                touch: true,
                func: function (ev, nVal) {
                    var unfiltered = cs(self).value('data:rows')
                    if (nVal === '')
                        cs(self).value('data:filtered', unfiltered)
                    else {
                        var result = []

                        var tmp = nVal.split(':')

                        for (var i = 0; i < unfiltered.length; i++) {
                            var tuple = unfiltered[i]
                            if (tmp.length === 2 && tuple[tmp[0]]) {
                                if (tuple[tmp[0]].toLowerCase().indexOf(tmp[1].toLowerCase()) !== -1)
                                    result.push(tuple)
                            }
                            else {
                                for (var key in tuple) {
                                    if (key === 'time' || key === 'id' || key === 'checks')
                                        continue;
                                    var val = tuple[key]
                                    if (key === 'parameters')
                                        val = JSON.stringify(val)
                                    if (val.toLowerCase().indexOf(nVal.toLowerCase()) !== -1) {
                                        result.push(tuple)
                                        break;
                                    }
                                }
                            }
                        }
                        cs(self).value('data:filtered', result)
                    }
                }
            })

            /*  calculate the savable content on demand  */
            cs(self).observe({
                name: 'data:savable', spool: 'created',
                operation: 'get',
                touch: true,
                func: function (ev) {
                    var result = ''
                    var rows = cs(self).value('data:filtered')

                    for (var i = 0; i < rows.length; i++) {
                        var row = rows[i]

                        /*  stringify parameters  */
                        var params = "";
                        var p = row.parameters;
                        for (var name in p) {
                            if (params !== "")
                                params += ", ";
                            params += name + ": " + JSON.stringify(p[name]);
                        }
                        if (params !== "")
                            params = "{ " + params + " }";
                        else
                            params = "{}";

                        result += '< ' +
                            row.time + ', ' +
                            row.source + ', ' +
                            row.sourceType + ', ' +
                            row.origin + ', ' +
                            row.originType + ', ' +
                            row.operation + ', ' +
                            params + ' > \n'
                    }
                    result = result.substr(0, result.length - 1)
                    ev.result(result)
                }
            })
        },
        destroy: function () {
            cs(this).unspool('created')
        }
    }
})

app.ui.widget.grid.view = cs.clazz({
    mixin: [ cs.marker.view ],
    dynamics: {
        selectable: true
    },
    cons: function (selectable) {
        if (selectable === false) {
            this.selectable = selectable
        }
    },
    protos: {
        render: function () {
            var self = this
            var grid = $.markup('grid')

            cs(self).plug(grid)

            cs(self).observe({
                name: 'data:columns', spool: 'rendered',
                touch: true,
                func: function (ev, nVal) {
                    for (var i = 0; i < nVal.length; i++) {
                        var vars = { label: nVal[i].label }
                        if (nVal[i].width)
                            vars.style = 'width: ' + nVal[i].width + 'px;'
                        $('.thead > .row', grid).markup('grid/column', vars)
                    }
                }
            })

            var fillRow = function (row, trace) {
                var columns = cs(self).value('data:columns')
                for (var x = 0; x < columns.length; x++) {
                    var vars = { style: '' }
                    if (columns[x].dataIndex === 'parameters')
                        vars.label = JSON.stringify(trace[columns[x].dataIndex])
                    else
                        if (columns[x].renderer)
                            vars.label = columns[x].renderer(trace[columns[x].dataIndex])
                        else
                            vars.label = trace[columns[x].dataIndex]
                    if (columns[x].width)
                        vars.style += 'width: ' + columns[x].width + 'px;'
                    if (columns[x].align)
                        vars.style += 'text-align: ' + columns[x].align + ';'
                    $(row).markup('grid/row/data', vars)
                }
            }

            cs(self).register({
                name: 'unshift', spool: 'rendered',
                func: function (trace) {
                    trace.style = ''
                    var i = $('.tbody > .row:first', grid).data('i')
                    if (typeof i === 'undefined')
                        i = -1
                    var row = $.markup('grid/row', { i: ++i })
                    fillRow(row, trace);
                    delete trace.style
                    $('.tbody', grid).prepend(row)
                    if (self.selectable) {
                        row.addClass('selectable')
                        row.click(function () {
                            var len = cs(self).value('data:rows').length
                            cs(self).value('state:selection', len - $(this).data('i') - 1)
                        })
                    }
                }
            })

            cs(self).observe({
                name: 'data:filtered', spool: 'rendered',
                touch: true,
                func: function (ev, nVal) {
                    $('.tbody tr', grid).remove()
                    for (var i = 0; i < nVal.length; i++) {
                        var row = $('.tbody', grid).markup('grid/row', { i: nVal.length - 1 - i })
                        fillRow(row, nVal[i])
                    }
                    cs(self).value('state:selection', -1)
                    if (self.selectable) {
                        var rows = $('.table > .tbody > .row', grid[2])
                        rows.addClass('selectable')
                        rows.click(function () {
                            var len = cs(self).value('data:rows').length
                            cs(self).value('state:selection', len - $(this).data('i') - 1)
                        })
                    }
                }
            })

            /*  react on selection change  */
            cs(self).observe({
                name: 'state:selection', spool: 'rendered',
                touch: true,
                func: function (ev, nVal) {
                    if (nVal !== -1) {
                        cs(self).value('data:selected-obj', cs(self).value('data:rows')[nVal])
                        $('.selected', grid).removeClass('selected')
                        $('.table > .tbody > .row', grid[2]).eq(nVal).addClass('selected')
                    }
                    else
                        cs(self).value('data:selected-obj', null)
                }
            })
        },
        release: function () {
            cs(this).unspool('rendered')
        }
    }
})
<|endoftext|>


<commit_before>function prop (map) {
  if('string' == typeof map) {
    var key = map
    return function (data) { return data[key] }
  }
  return map
}

function id (item) {
  return item
}

var k = 0
var map = exports.map =
function (read, map) {
  var _k = k++
  map = prop(map) || id
  return function (end, cb) {
    read(end, function (end, data) {
      var data = !end ? map(data) : null
      cb(end, data)
    })
  }
}

var filter = exports.filter =
function (read, test) {
  //regexp
  if('object' === typeof test
    && 'function' === typeof test.test)
    test = test.test.bind(test)
  test = prop(test) || id
  return function next (end, cb) {
    read(end, function (end, data) {
      if(!end && !test(data))
        return next(end, cb)
      cb(end, data)
    })
  }
}

var through = exports.through =
function (read, op) {
  return function (end, cb) {
    return read(end, function (end, data) {
      if(!end) op && op(data)
      cb(end, data)
    })
  }
}

var take = exports.take =
function (read, test) {
  var ended = false
  if('number' === typeof test) {
    var n = test; test = function () {
      return n-- > 0
    }
  }
  return function (end, cb) {
    if(end) {
      if(!ended) return ended = end, read(end, cb)
      cb(ended)
    }
    return read(null, function (end, data) {
      if(ended) return
      if(end) return cb(ended = end)
      //TODO, CHECK THAT END LOGIC IS CORRECT WITH TAKE!!!
      if(!test(data)) {
        ended = true
        nextTick(function () {
          read(true, function (){})
        })
        return cb(true)
      }
      return cb(null, data)
    })
  }
}

var unique = exports.unique = function (read, field, invert) {
  field = prop(field) || id
  var seen = {}
  return filter(read, function (data) {
    var key = field(data)
    if(seen[key]) return !!invert //false, by default
    else seen[key] = true
    return !invert //true by default
  })
}

var nonUnique = exports.nonUnique = function (read, field) {
  return unique(read, field, true)
}

var group = exports.group =
function (read, size) {
  var ended; size = size || 5
  var queue = []

  return function (end, cb) {
    //this means that the upstream is sending an error.
    if(end) return read(ended = end, cb)
    //this means that we read an end before.
    if(ended) return cb(ended)

    read(null, function next(end, data) {
      if(ended = ended || end) {
        if(!queue.length)
          return cb(ended)

        var _queue = queue; queue = []
        return cb(null, _queue)
      }
      queue.push(data)
      if(queue.length < size)
        return read(null, next)

      var _queue = queue; queue = []
      cb(null, _queue)
    })
  }
}

var nextTick = process.nextTick

var highWaterMark = exports.highWaterMark =
function (read, highWaterMark) {
  var buffer = [], waiting = [], ended, reading = false
  highWaterMark = highWaterMark || 10

  function readAhead () {
    while(waiting.length && (buffer.length || ended))
      waiting.shift()(ended, ended ? null : buffer.shift())
  }

  function next () {
    if(ended || reading || buffer.length >= highWaterMark)
      return
    reading = true
    return read(ended, function (end, data) {
      reading = false
      ended = ended || end
      if(data != null) buffer.push(data)

      next(); readAhead()
    })
  }

  nextTick(next)

  return function (end, cb) {
    ended = ended || end
    waiting.push(cb)

    next(); readAhead()
  }
}

<commit_msg>async-map<commit_after>function prop (map) {
  if('string' == typeof map) {
    var key = map
    return function (data) { return data[key] }
  }
  return map
}

function id (item) {
  return item
}

var k = 0
var map = exports.map =
function (read, map) {
  var _k = k++
  map = prop(map) || id
  return function (end, cb) {
    read(end, function (end, data) {
      var data = !end ? map(data) : null
      cb(end, data)
    })
  }
}

var asyncMap = exports.asyncMap =
function (read, map) {
  if(!map) return read
  return function (end, cb) {
    if(end) return read(end, cb) //abort
    read(null, function (end, data) {
      if(end) return cb(end, data)
      map(data, cb)
    })
  }
}

var filter = exports.filter =
function (read, test) {
  //regexp
  if('object' === typeof test
    && 'function' === typeof test.test)
    test = test.test.bind(test)
  test = prop(test) || id
  return function next (end, cb) {
    read(end, function (end, data) {
      if(!end && !test(data))
        return next(end, cb)
      cb(end, data)
    })
  }
}

var through = exports.through =
function (read, op) {
  return function (end, cb) {
    return read(end, function (end, data) {
      if(!end) op && op(data)
      cb(end, data)
    })
  }
}

var take = exports.take =
function (read, test) {
  var ended = false
  if('number' === typeof test) {
    var n = test; test = function () {
      return n-- > 0
    }
  }
  return function (end, cb) {
    if(end) {
      if(!ended) return ended = end, read(end, cb)
      cb(ended)
    }
    return read(null, function (end, data) {
      if(ended) return
      if(end) return cb(ended = end)
      //TODO, CHECK THAT END LOGIC IS CORRECT WITH TAKE!!!
      if(!test(data)) {
        ended = true
        nextTick(function () {
          read(true, function (){})
        })
        return cb(true)
      }
      return cb(null, data)
    })
  }
}

var unique = exports.unique = function (read, field, invert) {
  field = prop(field) || id
  var seen = {}
  return filter(read, function (data) {
    var key = field(data)
    if(seen[key]) return !!invert //false, by default
    else seen[key] = true
    return !invert //true by default
  })
}

var nonUnique = exports.nonUnique = function (read, field) {
  return unique(read, field, true)
}

var group = exports.group =
function (read, size) {
  var ended; size = size || 5
  var queue = []

  return function (end, cb) {
    //this means that the upstream is sending an error.
    if(end) return read(ended = end, cb)
    //this means that we read an end before.
    if(ended) return cb(ended)

    read(null, function next(end, data) {
      if(ended = ended || end) {
        if(!queue.length)
          return cb(ended)

        var _queue = queue; queue = []
        return cb(null, _queue)
      }
      queue.push(data)
      if(queue.length < size)
        return read(null, next)

      var _queue = queue; queue = []
      cb(null, _queue)
    })
  }
}

var nextTick = process.nextTick

var highWaterMark = exports.highWaterMark =
function (read, highWaterMark) {
  var buffer = [], waiting = [], ended, reading = false
  highWaterMark = highWaterMark || 10

  function readAhead () {
    while(waiting.length && (buffer.length || ended))
      waiting.shift()(ended, ended ? null : buffer.shift())
  }

  function next () {
    if(ended || reading || buffer.length >= highWaterMark)
      return
    reading = true
    return read(ended, function (end, data) {
      reading = false
      ended = ended || end
      if(data != null) buffer.push(data)

      next(); readAhead()
    })
  }

  nextTick(next)

  return function (end, cb) {
    ended = ended || end
    waiting.push(cb)

    next(); readAhead()
  }
}

<|endoftext|>


<commit_before>/**
 * A naive benchmark testing the performance hit when only using
 * events, thus defaulting to regular EventEmitter behaviour.
 */

var Benchmark      = require('benchmark');
var EventEmitter   = require('events').EventEmitter;
var PatternEmitter = require('../lib/patternEmitter');

var suite          = new Benchmark.Suite();
var eventEmitter   = new EventEmitter();
var patternEmitter = new PatternEmitter();

var i, j;

// Setup both emitters with 10 listeners on each of 100 events

for (i = 0; i < 10; i++) {
  for (j = 0; j < 10; j++) {
    eventEmitter.on('event:' + i, function() {
      // Do nothing
    });
  }
}

for (i = 0; i < 10; i++) {
  for (j = 0; j < 10; j++) {
    patternEmitter.on('event:' + i, function() {
      // Do nothing
    });
  }
}

suite.add('EventEmitter', function() {
  for (i = 0; i < 10; i++) {
    eventEmitter.emit('event:' + i);
  }
})
.add('PatternEmitter', function() {
  for (i = 0; i < 10; i++) {
    patternEmitter.emit('event:' + i);
  }
})
.on('cycle', function(event) {
  console.log(String(event.target));
})
.run({ 'async': true });
<commit_msg>Fix comment in benchmarks/eventEmitting<commit_after>/**
 * A naive benchmark testing the performance hit when only using
 * events, thus defaulting to regular EventEmitter behaviour.
 */

var Benchmark      = require('benchmark');
var EventEmitter   = require('events').EventEmitter;
var PatternEmitter = require('../lib/patternEmitter');

var suite          = new Benchmark.Suite();
var eventEmitter   = new EventEmitter();
var patternEmitter = new PatternEmitter();

var i, j;

// Setup both emitters with 10 listeners on each of 10 events

for (i = 0; i < 10; i++) {
  for (j = 0; j < 10; j++) {
    eventEmitter.on('event:' + i, function() {
      // Do nothing
    });
  }
}

for (i = 0; i < 10; i++) {
  for (j = 0; j < 10; j++) {
    patternEmitter.on('event:' + i, function() {
      // Do nothing
    });
  }
}

suite.add('EventEmitter', function() {
  for (i = 0; i < 10; i++) {
    eventEmitter.emit('event:' + i);
  }
})
.add('PatternEmitter', function() {
  for (i = 0; i < 10; i++) {
    patternEmitter.emit('event:' + i);
  }
})
.on('cycle', function(event) {
  console.log(String(event.target));
})
.run({ 'async': true });
<|endoftext|>


<commit_before>/**
 * @file   common/js/xml_js_filter.js
 * @author taggon (taggon@gmail.com)
 * @brief  xml filter (validator) plugin
 *
 * A rule is a method validate one field.
 * A filter is made up of one or more rules.
 **/
(function($){

var messages  = [];
var rules     = [];
var filters   = [];
var callbacks = [];

var Validator = xe.createApp('Validator', {
	init : function() {
		// {{{ add filters
		// email
		var regEmail = /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)*$/;
		this.cast('ADD_RULE', ['email', regEmail]);
		this.cast('ADD_RULE', ['email_address', regEmail]);

		// userid
		var regUserid = /^[a-z]+[\w-]*[a-z0-9]+$/i;
		this.cast('ADD_RULE', ['userid', regUserid]);
		this.cast('ADD_RULE', ['user_id', regUserid]);

		// url
		var regUrl = /^(https?|ftp|mms):\/\/[0-9a-z-]+(\.[_0-9a-z-\/\~]+)+(:[0-9]{2,4})*$/;
		this.cast('ADD_RULE', ['url', regUrl]);
		this.cast('ADD_RULE', ['homepage', regUrl]);

		// korean
		var regKor = /^[가-힣]*$/;
		this.cast('ADD_RULE', ['korean', regKor]);

		// korean_number
		var regKorNum = /^[가-힣0-9]*$/;
		this.cast('ADD_RULE', ['korean_number', regKorNum]);

		// alpha
		var regAlpha = /^[a-z]*$/i;
		this.cast('ADD_RULE', ['alpha', regAlpha]);

		// alpha_number
		var regAlphaNum = /^[a-z][a-z0-9_]*$/i;
		this.cast('ADD_RULE', ['alpha_number', regAlphaNum]);

		// number
		var regNum = /^[0-9]*$/i;
		this.cast('ADD_RULE', ['number', regNum]);
		// }}} add filters
	},
	// run validator
	run : function(oForm) {
		var filter = '';

		if (oForm._filter) filter = oForm._filter.value;

		return this.cast('VALIDATE', [oForm, filter]);
	},
	API_ONREADY : function() {
		var self = this;

		// hook form submit event
		$('form')
			.each(function(){
				if (this.onsubmit) {
					this['xe:onsubmit'] = this.onsubmit;
					this.onsubmit = null;
				}
			})
			.submit(function(){
				var legacyFn = this['xe:onsubmit'];
				var hasLegacyFn = $.isFunction(legacyFn);
				var bResult = hasLegacyFn?legacyFn.apply(this):self.run(this);

				return false;
			});
	},
	API_VALIDATE : function(sender, params) {
		var self = this, result = true, form = params[0], filter=null, callback=null;

		if (form.elements['_filter']) filter = form.elements['_filter'].value;
		if (!filter) return true;
		if ($.isFunction(callbacks[filter])) callback = callbacks[filter];
		filter = filters[filter.toLowerCase()] || null;

		$.each(filter, function(name) {
			var _el = form.elements[name];

			if (!_el) return true;

			var el = $(_el), val = $.trim(get_value(el));
			var minlen = parseInt(this.minlen) || 0;
			var maxlen = parseInt(this.maxlen) || 0;
			var rule   = (this.rule || '').split(',');

			if (this.required && !val) return (result = (!!self.cast('ALERT', [form, name, 'isnull']) && false));
			if (!this.required && !val) return (result = true);
			if ((minlen && maxlen) && (val.length < minlen || val.length > maxlen)) return (result = (!!self.cast('ALERT', [form, name, 'outofrange', minlen, maxlen]) && false));

			if (this.equalto) {
				var eq_val = get_value($(form.elements[this.equalto]));
				if (eq_val != val) return (result = (!!self.cast('ALERT', [form, name, 'equalto']) && false));
			}

			$.each(rule, function() {
				var ret = self.cast('APPLY_RULE', [this, val]);
				if (!ret) {
					self.cast('ALERT', [form, name, 'invalid_'+this]);
					return (result = false);
				}
			});

			if (!result) return false;
		});

		if (!result) return false;
		if ($.isFunction(callback)) return callback(form);

		return true;
	},
	API_ADD_RULE : function(sender, params) {
		var name = params[0].toLowerCase();
		rules[name] = params[1];
	},
	API_DEL_RULE : function(sender, params) {
		var name = params[0].toLowerCase();
		delete rules[name];
	},
	API_GET_RULE : function(sender, params) {
		var name = params[0].toLowerCase();

		if (rules[name]) {
			return rules[name];
		} else {
			return null;
		}
	},
	API_ADD_FILTER : function(sender, params) {
		var name   = params[0].toLowerCase();
		var filter = params[1];

		filters[name] = filter;
	},
	API_DEL_FILTER : function(sender, params) {
		var name = params[0].toLowerCase();
		delete filters[name];
	},
	API_GET_FILTER : function(sender, params) {
		var name = params[0].toLowerCase();

		if (filters[name]) {
			return filters[name];
		} else {
			return null;
		}
	},
	API_APPLY_RULE : function(sender, params) {
		var name  = params[0].toLowerCase();
		var value = params[1];

		if (typeof(rules[name]) == 'undefined') return true; // no filter
		if ($.isFunction(rules[name])) return rules[name](value);
		if (rules[name] instanceof RegExp) return rules[name].test(value);

		return true;
	},
	API_ALERT : function(sender, params) {
		var form = params[0];
		var field_name = params[1];
		var msg_code = params[2];
		var minlen   = params[3];
		var maxlen   = params[4];

		var field_msg = this.cast('GET_MESSAGE', [field_name]);
		var msg = this.cast('GET_MESSAGE', [msg_code]);

		if (msg != msg_code) msg = (msg.indexOf('%s')<0)?(field_msg+msg):(msg.replace('%s',field_msg));
		if (typeof(minlen)!='undefined' && typeof(maxlen)!='undefined') msg += '('+minlen+'~'+maxlen+')';

		this.cast('SHOW_ALERT', [msg]);

		// set focus
		$(form.elements[field_name]).focus();
	},
	API_SHOW_ALERT : function(sender, params) {
		alert(params[0]);
	},
	API_ADD_MESSAGE : function(sender, params) {
		var msg_code = params[0];
		var msg_str  = params[1];

		messages[msg_code] = msg_str;
	},
	API_GET_MESSAGE : function(sender, params) {
		var msg_code = params[0];

		return messages[msg_code] || msg_code;
	},
	API_ADD_CALLBACK : function(sender, params) {
		var name = params[0];
		var func = params[1];

		callbacks[name] = func;
	},
	API_REMOVE_CALLBACK : function(sender, params) {
		var name = params[0];

		delete callbacks[name];
	}
});

var oValidator = new Validator;

// register validator
xe.registerApp(oValidator);

// 호환성을 위해 추가한 플러그인 - 에디터에서 컨텐트를 가져와서 설정한다.
var EditorStub = xe.createPlugin('editor_stub', {
	API_BEFORE_VALIDATE : function(sender, params) {
		var form = params[0];
		var seq  = form.getAttribute('editor_sequence');

		if (seq) {
			form.content.value = editorGetContentTextarea_xe(seq) || '';
		}
	}
});
oValidator.registerPlugin(new EditorStub);

// functions
function get_value(elem) {
	if (elem.is(':radio')){
		return elem.filter(':checked').val();
	} else if (elem.is(':checkbox')) {
		var vals = [];
		elem.filter(':checked').each(function(){
			vals.push(this.value);
		});
		return vals.join('|@|');
	} else {
		return elem.val();
	}
}

})(jQuery);

/**
 * @function filterAlertMessage
 * @brief ajax로 서버에 요청후 결과를 처리할 callback_function을 지정하지 않았을 시 호출되는 기본 함수
 **/
function filterAlertMessage(ret_obj) {
    var error = ret_obj["error"];
    var message = ret_obj["message"];
    var act = ret_obj["act"];
    var redirect_url = ret_obj["redirect_url"];
    var url = location.href;

    if(typeof(message)!="undefined"&&message&&message!="success") alert(message);

    if(typeof(act)!="undefined" && act) url = current_url.setQuery("act", act);
    else if(typeof(redirect_url)!="undefined" && redirect_url) url = redirect_url;

    if(url == location.href) url = url.replace(/#(.*)$/,'');

    location.href = url;
}

/**
 * @brief Function to process filters
 * @deprecated
 */
function procFilter(fo_obj, filter_func)
{
	filter_func(fo_obj);
	return false;
}
<commit_msg>#18578550 #18578544 폼 전송이 안되던 문제 수정<commit_after>/**
 * @file   common/js/xml_js_filter.js
 * @author taggon (taggon@gmail.com)
 * @brief  xml filter (validator) plugin
 *
 * A rule is a method validate one field.
 * A filter is made up of one or more rules.
 **/
(function($){

var messages  = [];
var rules     = [];
var filters   = [];
var callbacks = [];

var Validator = xe.createApp('Validator', {
	init : function() {
		// {{{ add filters
		// email
		var regEmail = /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)*$/;
		this.cast('ADD_RULE', ['email', regEmail]);
		this.cast('ADD_RULE', ['email_address', regEmail]);

		// userid
		var regUserid = /^[a-z]+[\w-]*[a-z0-9]+$/i;
		this.cast('ADD_RULE', ['userid', regUserid]);
		this.cast('ADD_RULE', ['user_id', regUserid]);

		// url
		var regUrl = /^(https?|ftp|mms):\/\/[0-9a-z-]+(\.[_0-9a-z-\/\~]+)+(:[0-9]{2,4})*$/;
		this.cast('ADD_RULE', ['url', regUrl]);
		this.cast('ADD_RULE', ['homepage', regUrl]);

		// korean
		var regKor = /^[가-힣]*$/;
		this.cast('ADD_RULE', ['korean', regKor]);

		// korean_number
		var regKorNum = /^[가-힣0-9]*$/;
		this.cast('ADD_RULE', ['korean_number', regKorNum]);

		// alpha
		var regAlpha = /^[a-z]*$/i;
		this.cast('ADD_RULE', ['alpha', regAlpha]);

		// alpha_number
		var regAlphaNum = /^[a-z][a-z0-9_]*$/i;
		this.cast('ADD_RULE', ['alpha_number', regAlphaNum]);

		// number
		var regNum = /^[0-9]*$/i;
		this.cast('ADD_RULE', ['number', regNum]);
		// }}} add filters
	},
	// run validator
	run : function(oForm) {
		var filter = '';

		if (oForm._filter) filter = oForm._filter.value;

		return this.cast('VALIDATE', [oForm, filter]);
	},
	API_ONREADY : function() {
		var self = this;

		// hook form submit event
		$('form')
			.each(function(){
				if (this.onsubmit) {
					this['xe:onsubmit'] = this.onsubmit;
					this.onsubmit = null;
				}
			})
			.submit(function(){
				var legacyFn = this['xe:onsubmit'];
				var hasLegacyFn = $.isFunction(legacyFn);
				var bResult = hasLegacyFn?legacyFn.apply(this):self.run(this);

				return bResult;
			});
	},
	API_VALIDATE : function(sender, params) {
		var self = this, result = true, form = params[0], filter=null, callback=null;

		if (form.elements['_filter']) filter = form.elements['_filter'].value;
		if (!filter) return true;
		if ($.isFunction(callbacks[filter])) callback = callbacks[filter];
		filter = filters[filter.toLowerCase()] || null;

		$.each(filter, function(name) {
			var _el = form.elements[name];

			if (!_el) return true;

			var el = $(_el), val = $.trim(get_value(el));
			var minlen = parseInt(this.minlen) || 0;
			var maxlen = parseInt(this.maxlen) || 0;
			var rule   = (this.rule || '').split(',');

			if (this.required && !val) return (result = (!!self.cast('ALERT', [form, name, 'isnull']) && false));
			if (!this.required && !val) return (result = true);
			if ((minlen && maxlen) && (val.length < minlen || val.length > maxlen)) return (result = (!!self.cast('ALERT', [form, name, 'outofrange', minlen, maxlen]) && false));

			if (this.equalto) {
				var eq_val = get_value($(form.elements[this.equalto]));
				if (eq_val != val) return (result = (!!self.cast('ALERT', [form, name, 'equalto']) && false));
			}

			$.each(rule, function() {
				var ret = self.cast('APPLY_RULE', [this, val]);
				if (!ret) {
					self.cast('ALERT', [form, name, 'invalid_'+this]);
					return (result = false);
				}
			});

			if (!result) return false;
		});

		if (!result) return false;
		if ($.isFunction(callback)) return callback(form);

		return true;
	},
	API_ADD_RULE : function(sender, params) {
		var name = params[0].toLowerCase();
		rules[name] = params[1];
	},
	API_DEL_RULE : function(sender, params) {
		var name = params[0].toLowerCase();
		delete rules[name];
	},
	API_GET_RULE : function(sender, params) {
		var name = params[0].toLowerCase();

		if (rules[name]) {
			return rules[name];
		} else {
			return null;
		}
	},
	API_ADD_FILTER : function(sender, params) {
		var name   = params[0].toLowerCase();
		var filter = params[1];

		filters[name] = filter;
	},
	API_DEL_FILTER : function(sender, params) {
		var name = params[0].toLowerCase();
		delete filters[name];
	},
	API_GET_FILTER : function(sender, params) {
		var name = params[0].toLowerCase();

		if (filters[name]) {
			return filters[name];
		} else {
			return null;
		}
	},
	API_APPLY_RULE : function(sender, params) {
		var name  = params[0].toLowerCase();
		var value = params[1];

		if (typeof(rules[name]) == 'undefined') return true; // no filter
		if ($.isFunction(rules[name])) return rules[name](value);
		if (rules[name] instanceof RegExp) return rules[name].test(value);

		return true;
	},
	API_ALERT : function(sender, params) {
		var form = params[0];
		var field_name = params[1];
		var msg_code = params[2];
		var minlen   = params[3];
		var maxlen   = params[4];

		var field_msg = this.cast('GET_MESSAGE', [field_name]);
		var msg = this.cast('GET_MESSAGE', [msg_code]);

		if (msg != msg_code) msg = (msg.indexOf('%s')<0)?(field_msg+msg):(msg.replace('%s',field_msg));
		if (typeof(minlen)!='undefined' && typeof(maxlen)!='undefined') msg += '('+minlen+'~'+maxlen+')';

		this.cast('SHOW_ALERT', [msg]);

		// set focus
		$(form.elements[field_name]).focus();
	},
	API_SHOW_ALERT : function(sender, params) {
		alert(params[0]);
	},
	API_ADD_MESSAGE : function(sender, params) {
		var msg_code = params[0];
		var msg_str  = params[1];

		messages[msg_code] = msg_str;
	},
	API_GET_MESSAGE : function(sender, params) {
		var msg_code = params[0];

		return messages[msg_code] || msg_code;
	},
	API_ADD_CALLBACK : function(sender, params) {
		var name = params[0];
		var func = params[1];

		callbacks[name] = func;
	},
	API_REMOVE_CALLBACK : function(sender, params) {
		var name = params[0];

		delete callbacks[name];
	}
});

var oValidator = new Validator;

// register validator
xe.registerApp(oValidator);

// 호환성을 위해 추가한 플러그인 - 에디터에서 컨텐트를 가져와서 설정한다.
var EditorStub = xe.createPlugin('editor_stub', {
	API_BEFORE_VALIDATE : function(sender, params) {
		var form = params[0];
		var seq  = form.getAttribute('editor_sequence');

		if (seq) {
			try {
				editorRelKeys[seq].content.value = editorGetContentTextarea_xe(seq) || '';
			} catch(e) { }
		}
	}
});
oValidator.registerPlugin(new EditorStub);

// functions
function get_value(elem) {
	if (elem.is(':radio')){
		return elem.filter(':checked').val();
	} else if (elem.is(':checkbox')) {
		var vals = [];
		elem.filter(':checked').each(function(){
			vals.push(this.value);
		});
		return vals.join('|@|');
	} else {
		return elem.val();
	}
}

})(jQuery);

/**
 * @function filterAlertMessage
 * @brief ajax로 서버에 요청후 결과를 처리할 callback_function을 지정하지 않았을 시 호출되는 기본 함수
 **/
function filterAlertMessage(ret_obj) {
    var error = ret_obj["error"];
    var message = ret_obj["message"];
    var act = ret_obj["act"];
    var redirect_url = ret_obj["redirect_url"];
    var url = location.href;

    if(typeof(message)!="undefined"&&message&&message!="success") alert(message);

    if(typeof(act)!="undefined" && act) url = current_url.setQuery("act", act);
    else if(typeof(redirect_url)!="undefined" && redirect_url) url = redirect_url;

    if(url == location.href) url = url.replace(/#(.*)$/,'');

    location.href = url;
}

/**
 * @brief Function to process filters
 * @deprecated
 */
function procFilter(fo_obj, filter_func)
{
	filter_func(fo_obj);
	return false;
}
<|endoftext|>