<commit_before>/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */

var engine = require('caramel').engine('handlebars', (function () {
    return {
        partials: function (Handlebars) {
            var theme = caramel.theme();
            var partials = function (file) {
                (function register(prefix, file) {
                    var i, length, name, files;
                    if (file.isDirectory()) {
                        files = file.listFiles();
                        length = files.length;
                        for (i = 0; i < length; i++) {
                            file = files[i];
                            register(prefix ? prefix + '.' + file.getName() : file.getName(), file);
                        }
                    } else {
                        name = file.getName();
                        if (name.substring(name.length - 4) !== '.hbs') {
                            return;
                        }
                        file.open('r');
                        Handlebars.registerPartial(prefix.substring(0, prefix.length - 4), file.readAll());
                        file.close();
                    }
                })('', file);
            };
            //TODO : we don't need to register all partials in the themes dir.
            //Rather register only not overridden partials
            partials(new File(theme.__proto__.resolve.call(theme, 'partials')));
            partials(new File(theme.resolve('partials')));

            Handlebars.registerHelper('isAllowed', function(action, options) {
                if(caramel.meta().request.permissions != undefined && caramel.meta().request.permissions[action]) {
                    return options.fn(this);
                }
                return options.inverse(this);
            });

            Handlebars.registerHelper('ifCond', function (v1, operator, v2, options) {

                switch (operator) {
                    case '!=':
                        return (v1 != v2) ? options.fn(this) : options.inverse(this);
                    case '==':
                        return (v1 == v2) ? options.fn(this) : options.inverse(this);
                    case '===':
                        return (v1 === v2) ? options.fn(this) : options.inverse(this);
                    case '<':
                        return (v1 < v2) ? options.fn(this) : options.inverse(this);
                    case '<=':
                        return (v1 <= v2) ? options.fn(this) : options.inverse(this);
                    case '>':
                        return (v1 > v2) ? options.fn(this) : options.inverse(this);
                    case '>=':
                        return (v1 >= v2) ? options.fn(this) : options.inverse(this);
                    default:
                        return options.inverse(this);
                }
            });

            Handlebars.registerHelper('UnixConvert', function(unixtimestamp){
                var newDate = new Date();
                newDate.setTime(unixtimestamp);
                dateString = newDate.toUTCString();
                return dateString;
            });

            Handlebars.registerHelper('user', function(action, options) {
                if(caramel.meta().session.get("USER_NAME") != undefined ) {
                    return caramel.meta().session.get("USER_NAME");
                }
                return "";
            });

            Handlebars.registerHelper('domain', function(action, options) {
                if(caramel.meta().session.get("TENANT_DOMAIN") != undefined ) {
                    return caramel.meta().session.get("TENANT_DOMAIN");
                }
                return "";
            });
            Handlebars.registerHelper('tenantID', function(action, options) {
                if(caramel.meta().session.get("TENANT_ID") != undefined ) {
                    return caramel.meta().session.get("TENANT_ID");
                }
                return "";
            });

        }
    }
}()));
<commit_msg>Custom helper to check super tenant<commit_after>/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */

var engine = require('caramel').engine('handlebars', (function () {
    return {
        partials: function (Handlebars) {
            var theme = caramel.theme();
            var partials = function (file) {
                (function register(prefix, file) {
                    var i, length, name, files;
                    if (file.isDirectory()) {
                        files = file.listFiles();
                        length = files.length;
                        for (i = 0; i < length; i++) {
                            file = files[i];
                            register(prefix ? prefix + '.' + file.getName() : file.getName(), file);
                        }
                    } else {
                        name = file.getName();
                        if (name.substring(name.length - 4) !== '.hbs') {
                            return;
                        }
                        file.open('r');
                        Handlebars.registerPartial(prefix.substring(0, prefix.length - 4), file.readAll());
                        file.close();
                    }
                })('', file);
            };
            //TODO : we don't need to register all partials in the themes dir.
            //Rather register only not overridden partials
            partials(new File(theme.__proto__.resolve.call(theme, 'partials')));
            partials(new File(theme.resolve('partials')));

            Handlebars.registerHelper('isAllowed', function(action, options) {
                if(caramel.meta().request.permissions != undefined && caramel.meta().request.permissions[action]) {
                    return options.fn(this);
                }
                return options.inverse(this);
            });

            Handlebars.registerHelper('ifCond', function (v1, operator, v2, options) {

                switch (operator) {
                    case '!=':
                        return (v1 != v2) ? options.fn(this) : options.inverse(this);
                    case '==':
                        return (v1 == v2) ? options.fn(this) : options.inverse(this);
                    case '===':
                        return (v1 === v2) ? options.fn(this) : options.inverse(this);
                    case '<':
                        return (v1 < v2) ? options.fn(this) : options.inverse(this);
                    case '<=':
                        return (v1 <= v2) ? options.fn(this) : options.inverse(this);
                    case '>':
                        return (v1 > v2) ? options.fn(this) : options.inverse(this);
                    case '>=':
                        return (v1 >= v2) ? options.fn(this) : options.inverse(this);
                    default:
                        return options.inverse(this);
                }
            });

            Handlebars.registerHelper('UnixConvert', function(unixtimestamp){
                var newDate = new Date();
                newDate.setTime(unixtimestamp);
                dateString = newDate.toUTCString();
                return dateString;
            });

            Handlebars.registerHelper('user', function(action, options) {
                if(caramel.meta().session.get("USER_NAME") != undefined ) {
                    return caramel.meta().session.get("USER_NAME");
                }
                return "";
            });

            Handlebars.registerHelper('domain', function(action, options) {
                if(caramel.meta().session.get("TENANT_DOMAIN") != undefined ) {
                    return caramel.meta().session.get("TENANT_DOMAIN");
                }
                return "";
            });
            Handlebars.registerHelper('tenantID', function(action, options) {
                if(caramel.meta().session.get("TENANT_ID") != undefined ) {
                    return caramel.meta().session.get("TENANT_ID");
                }
                return "";
            });

            Handlebars.registerHelper('isSuperTenant', function (action, options) {
                if (caramel.meta().session.get("TENANT_ID") != undefined) {
                    if (caramel.meta().session.get("TENANT_ID") == -1234) {
                        return true;
                    }
                }
                return "";
            });
        }
    }
}()));
<|endoftext|>


<commit_before>/* global module, inject, chai */
"use strict";

var pageData = hqImport('hqwebapp/js/initial_page_data');

describe('Navigation Directive', function () {

    pageData.registerUrl('icds-ng-template', 'template');
    pageData.registerUrl('icds_locations', 'icds_locations');

    var $rootScope, $compile, $httpBackend, controller;

    var myScope;
    beforeEach(module('icdsApp'));

    beforeEach(inject(function (_$rootScope_, _$compile_, _$httpBackend_) {
        $compile = _$compile_;
        $httpBackend = _$httpBackend_;
        $rootScope = _$rootScope_.$new();

        $httpBackend.expectGET('template').respond(200, '

');
        var element = window.angular.element("<navigation></navigation>");
        var compiled = $compile(element)($rootScope);

        $httpBackend.flush();
        $rootScope.$digest();
        controller = compiled.controller("navigation", {$scope: $rootScope});
        myScope = element.isolateScope();
    }));

    it('tests instantiate the controller properly', function () {
        chai.expect(controller).not.to.be.a('undefined');
    });

    it('tests get empty page path', function () {
        var result = myScope.goToStep("test", {});
        var expected = "#/test";
        assert.equal(result, expected);
    });

    it('tests get page path with one arguments', function () {
        var result = myScope.goToStep("test", {'one': 1});

        var expected = "#/test?one=1&";
        assert.equal(result, expected);
    });

    it('tests get page path with two arguments', function () {
        var result = myScope.goToStep("test", {'one': 1, 'two': 2});

        var expected = "#/test?one=1&two=2&";
        assert.equal(result, expected);
    });
});<commit_msg>fix tests<commit_after>/* global module, inject, chai */
"use strict";

var pageData = hqImport('hqwebapp/js/initial_page_data');

describe('Navigation Directive', function () {

    pageData.registerUrl('icds-ng-template', 'template');
    pageData.registerUrl('icds_locations', 'icds_locations');

    var $rootScope, $compile, $httpBackend, controller;

    var myScope;

    beforeEach(module('icdsApp', function ($provide) {
        $provide.constant("stateLevelAccess", false);
        $provide.constant("haveAccessToAllLocations", false);
    }));

    beforeEach(inject(function (_$rootScope_, _$compile_, _$httpBackend_) {
        $compile = _$compile_;
        $httpBackend = _$httpBackend_;
        $rootScope = _$rootScope_.$new();

        $httpBackend.expectGET('template').respond(200, '

');
        var element = window.angular.element("<navigation></navigation>");
        var compiled = $compile(element)($rootScope);

        $httpBackend.flush();
        $rootScope.$digest();
        controller = compiled.controller("navigation", {$scope: $rootScope});
        myScope = element.isolateScope();
    }));

    it('tests instantiate the controller properly', function () {
        chai.expect(controller).not.to.be.a('undefined');
    });

    it('tests get empty page path', function () {
        var result = myScope.goToStep("test", {});
        var expected = "#/test";
        assert.equal(result, expected);
    });

    it('tests get page path with one arguments', function () {
        var result = myScope.goToStep("test", {'one': 1});

        var expected = "#/test?one=1&";
        assert.equal(result, expected);
    });

    it('tests get page path with two arguments', function () {
        var result = myScope.goToStep("test", {'one': 1, 'two': 2});

        var expected = "#/test?one=1&two=2&";
        assert.equal(result, expected);
    });
});<|endoftext|>


<commit_before>const _ = require('underscore');
const $ = require('jquery');
const CoreView = require('backbone/core-view');
const Utils = require('builder/helpers/utils');
const template = require('./editable-tags.tpl');

/**
 *  Editable tags
 */
module.exports = CoreView.extend({
  events: {
    'click .js-add-btn': '_edit',
    'click .js-field-input': 'killEvent',
    'keydown .js-field-input': '_keyPressed',
    'blur .js-field-input': '_cancelEditing'
  },

  initialize: function () {
    this.editable = this.options.editable;

    // Backbone's className won't work here because we are providing an el
    this.$el.addClass('EditableField');
  },

  render: function () {
    const tags = this.model.get('tags') || [];

    this.$el.html(template({
      tags: _.compact(tags),
      tagsCount: tags.length,
      editable: this.editable,
      router: this.options.router
    }));

    return this;
  },

  _edit: function (event) {
    this.killEvent(event);
    this.$el.addClass('is-editing');
    this.$('.js-field-input').val('').focus();
  },

  _keyPressed: function (event) {
    const enterPressed = event.keyCode === $.ui.keyCode.ENTER;
    const escapePressed = event.keyCode === $.ui.keyCode.ESCAPE;

    if (enterPressed) {
      this._save();
    } else if (escapePressed) {
      this._cancelEditing();
    }
  },

  _save: function () {
    let tags = this.$('.js-field-input')
      .val()
      .split(',')
      .map(tag => Utils.stripHTML(tag.trim()));

    tags = _.chain(tags).compact().uniq().value();

    this.model.save({
      tags: tags
    });
    this.$el.removeClass('is-editing');
    this.render();
  },

  _cancelEditing: function (ev) {
    this.$el.removeClass('is-editing');
  }
});
<commit_msg>this.options.router => this.options.routerModel<commit_after>const _ = require('underscore');
const $ = require('jquery');
const CoreView = require('backbone/core-view');
const Utils = require('builder/helpers/utils');
const template = require('./editable-tags.tpl');

/**
 *  Editable tags
 */
module.exports = CoreView.extend({
  events: {
    'click .js-add-btn': '_edit',
    'click .js-field-input': 'killEvent',
    'keydown .js-field-input': '_keyPressed',
    'blur .js-field-input': '_cancelEditing'
  },

  initialize: function () {
    this.editable = this.options.editable;

    // Backbone's className won't work here because we are providing an el
    this.$el.addClass('EditableField');
  },

  render: function () {
    const tags = this.model.get('tags') || [];

    this.$el.html(template({
      tags: _.compact(tags),
      tagsCount: tags.length,
      editable: this.editable,
      router: this.options.routerModel
    }));

    return this;
  },

  _edit: function (event) {
    this.killEvent(event);
    this.$el.addClass('is-editing');
    this.$('.js-field-input').val('').focus();
  },

  _keyPressed: function (event) {
    const enterPressed = event.keyCode === $.ui.keyCode.ENTER;
    const escapePressed = event.keyCode === $.ui.keyCode.ESCAPE;

    if (enterPressed) {
      this._save();
    } else if (escapePressed) {
      this._cancelEditing();
    }
  },

  _save: function () {
    let tags = this.$('.js-field-input')
      .val()
      .split(',')
      .map(tag => Utils.stripHTML(tag.trim()));

    tags = _.chain(tags).compact().uniq().value();

    this.model.save({
      tags: tags
    });
    this.$el.removeClass('is-editing');
    this.render();
  },

  _cancelEditing: function (ev) {
    this.$el.removeClass('is-editing');
  }
});
<|endoftext|>


<commit_before><commit_msg>Replace ref to attributes with get()<commit_after><|endoftext|>


<commit_before><commit_msg>Revert "Avoids policy query on the server"<commit_after><|endoftext|>


<commit_before>FaultedEarth = Ext.extend(gxp.Viewer, {

    legendTabTitle: "Legend",
	summaryId: null,

    constructor: function(config) {

        Ext.Window.prototype.shadow = false;

        // property names for FeatureEditor and FeatureGrid
        var propertyNames = {
            // custom fied names for the fault summary table
            "fault_name": "Fault Name",
            "sec_name": "Fault Section Name",
            "episodi_is": "Episodic behaviour (yes/no)",
            "episodi_ac": "Episodic behaviour (active/inactive)",
            "length": "Length (km, pref, min, max)",
            "u_sm_d_min": "Upper seismogenic depth min (km)",
            "u_sm_d_max": "Upper seismogenic depth max (km)",
            "u_sm_d_pre": "Upper seismogenic depth pref (km)",
            "u_sm_d_com": "Upper seismogenic completeness (1, 2, 3, or 4)",
            "low_d_min": "Lower seismogenic depth min (km)",
            "low_d_max": "Lower seismogenic depth max (km)",
            "low_d_pref": "Lower seismogenic depth pref (km)",
            "low_d_com": "Lower seismogenic completeness (1, 2, 3, or 4)",
            "strike": "Strike (...\u00B0)",
            "dip_min": "Dip min (...\u00B0)",
            "dip_max": "Dip max (...\u00B0)",
            "dip_pref": "Dip pref (...\u00B0)",
            "dip_com": "Dip data completeness factor (1, 2, 3, or 4)",
            "dip_dir": "Dip direction (...\u00B0)",
            "down_thro": "Downthrown side (N, S, W, E or NW etc.)",
            "slip_typ": "Slip type (Reverse etc.)",
            "slip_com": "Slip type completeness (1, 2, 3, or 4)",
            "slip_r_min": "Slip rate min (mm/yr)",
            "slip_r_max": "Slip rate max (mm/yr)",
            "slip_r_pre": "Slip rate pref (mm/yr)",
            "slip_r_com": "Slip rate completeness (1, 2, 3, or 4)",
            "aseis_slip": "Aseismic-slip factor (0-1)",
            "aseis_com": "Aseismic-slip completeness (1, 2, 3, or 4)",
            "dis_min": "Displacement min (m)",
            "dis_max": "Displacement max (m)",
            "dis_pref": "Displacement pref (m)",
            "re_int_min": "Recurrence interval min (yr)",
            "re_int_max": "Recurrence interval max (yr)",
            "re_int_pre": "Recurrence interval pref (yr)",
            "re_int_com": "Recurrence interval common (yr)",
            "mov_min": "Age of last movement min (yr BP)",
            "mov_max": "Age of last movement max (yr BP)",
            "mov_pref": "Age of last movement pref (yr BP)",
            "all_com": "Overall data completeness (1, 2, 3, or 4)",
            "created": "Date created (date)",
            "compiler": "Compiled by (name)",
            "contrib": "Contributed by (name)",
            // custom fied names for the observations table
            "observationType": "Observation Type",
            "slipType": "Slip Type",
            "hv_ratio": "H:V Ratio",
            "rake": "Rake (deg)",
            "net_slip_rate_min": "Net Slip Rate Min (mm/yr)",
            "net_slip_rate_max": "Net Slip Rate Max (mm/yr)",
            "net_slip_rate_pref": "Net Slip Rate Pref (mm/yr)",
            "dip_slip_rate_min": "Dip Slip Rate Min (mm/yr)",
            "dip_slip_rate_max": "Dip Slip Rate Max (mm/yr)",
            "dip_slip_rate_pref": "Dip Slip Rate Pref (mm/yr)",
            "marker_age": "Marker Age (yrs BP)",
            "slip_rate_category": "Slip Rate Category",
            "strike_slip_rate_min": "Strike Slip Rate Min (mm/yr)",
            "strike_slip_rate_max": "Strike Slip Rate Max (mm/yr)",
            "strike_slip_rate_pref": "Strike Slip Rate Pref (mm/yr)",
            "vertical_slip_rate_min": "Vertical Slip Rate Min (mm/yr)",
            "vertical_slip_rate_max": "Vertical Slip Rate Max (mm/yr)",
            "vertical_slip_rate_pref": "Vertical Slip Rate Pref (mm/yr)",
            "site": "Site",
            "notes": "Notes",
            "summary_id": "Fault Section Summary ID",
            // custom fied names for fault trace form
            "section_name": "Fault Section Name",
            "loc_meth": "Location Method",
            "scale": "Scale",
            "accuracy": "Accuracy",
            "geomor_exp": "Geomorphic Expression",
            "notes": "Notes",
            "fault_section_id": "Fault Section Id",
            "t_feature": "Trace Feature",
	        "s_feature": "Site Feature",
	        // custom field names for fault source form
    	    "source_nm": "Fault Source Name",
    	    "width": "Width",
    	    "area": "Area",
    	    "rake_min": "Rake Min",
    	    "rake_max": "Rake Max",
    	    "rake_pref": "Rake Pref",
    	    "rake_com": "Rake Common",
    	    "magnitude": "Magnitude",
    	    "length_min": "Length Min",
    	    "length_max": "Length Max",
    	    "length_pre": "Length Pref"
        };

        Ext.applyIf(config, {
            proxy: "/proxy?url=",

            mapItems: [{
                xtype: "gx_zoomslider",
                vertical: true,
                height: 100
            }, {
                xtype: "gxp_scaleoverlay"
            }],
            portalItems: [{
                region: "center",
                layout: "border",
                tbar: {
                    id: "paneltbar",
                    items: ["-"]
                },
                items: [{
                    id: "west",
                    region: "west",
                    layout: "accordion",
                    width: 280,
                    split: true,
                    collapsible: true,
                    collapseMode: "mini",
                    header: false,
                    border: false,
                    defaults: {
                       hideBorders: true,
                       autoScroll: true

                    },
                    items: [{
                        id: "tree",
                        title: "Layers"
                    }, {
                        id: 'trace',
                        title: "Trace Form",
                        padding: 10
                    }, {
                		id: 'summary',
                		title: "Neotectonic Section Summary",
                		padding: 10
                	}, {
                        id: 'site',
                        title: "Site Observation Form",
                        padding: 10
                    },/* {
                        id: 'observations',
                        title: "Observations",
                        layout: "fit",
                        autoScroll: false
                    },*/ {
                		id: "fault",
                		title: "Neotectonic Fault Form"
                    }, {
                		id: "simple_geometry",
                		title: "Simple Fault Geometry"
                    }, {
                    	id: "source",
                    	title: "Fault Source"
                    }]
                },
		"map", {
                    id: "featuregrid",
                    layout: "fit",
                    region: "south",
                    border: false,
                    height: 200,
                    split: true,
                    collapseMode: "mini",
                }]
            }],

            tools: [{
                actionTarget: {target: "paneltbar", index: 0},
                outputAction: 0,
                outputConfig: {
                    title: "Login",
                    width: 900,
                    height: 500,
                    modal: true,
                    bodyCfg: {
                        tag: "iframe",
                        src: "http://178.79.185.190/",
                        style: {border: 0}
                    }
                },
                actions: [{
                    iconCls: "icon-geoexplorer",
                    text: "Login",
                }]
            },{
                ptype: "gxp_layertree",
                outputTarget: "tree",
            }, {
                ptype: "gxp_featuremanager",
                id: "featuremanager",
                autoLoadFeatures: true,
                autoSetLayer: false,
                paging: false,
                maxFeatures: 100
            }, {
                ptype: "gxp_featuregrid",
                alwaysDisplayOnMap: true,
                selectOnMap: true,
                displayMode: "selected",
                featureManager: "featuremanager",
                outputTarget: "featuregrid",
                outputConfig: {
                    id: "grid",
                    propertyNames: propertyNames
                },
                controlOptions: {
                    multiple: true,
                }
            }, {
                ptype: "app_summaryform",
                id: "summaryform",
                featureManager: "featuremanager",
                featureEditor: "featureeditor",
                outputTarget: "summary"
            }, {
                ptype: "gxp_featureeditor",
                id: "featureeditor",
                featureManager: "featuremanager",
                modifyOnly: true,
                actionTarget: "summaryform_tooltarget",
                //createFeatureActionText: "Draw",
                editFeatureActionText: "Modify",
				snappingAgent: "snapping-agent",
                outputConfig: {
                    propertyNames: propertyNames
                }
            }, {
                ptype: "app_traceform",
                id: "traceform",
                featureManager: "featuremanager",
                featureEditor: "featureeditor",
                outputTarget: "trace"
            }, {
                ptype: "gxp_featureeditor",
                id: "featureeditor",
                featureManager: "featuremanager",
                actionTarget: "traceform_tooltarget",
                autoLoadFeatures: true,
                createFeatureActionText: "Draw",
                editFeatureActionText: "Modify",
		        snappingAgent: "snapping-agent",
                outputConfig: {
                    propertyNames: propertyNames
                }
            }, {
                ptype: "app_siteform",
                id: "siteform",
                featureManager: "featuremanager",
                featureEditor: "featureeditor",
                outputTarget: "site"
            }, {
                ptype: "gxp_featureeditor",
                id: "featureeditor",
                featureManager: "featuremanager",
                actionTarget: "siteform_tooltarget",
                createFeatureActionText: "Draw",
                editFeatureActionText: "Modify",
                snappingAgent: "snapping-agent",
                autoLoadFeatures: true,
                outputConfig: {
                    propertyNames: propertyNames
                }
            }, {
                ptype: "app_faultform",
                id: "faultform",
                featureManager: "featuremanager",
                featureEditor: "featureeditor",
                outputTarget: "fault"
            }, {
                ptype: "gxp_featureeditor",
                id: "featureeditor",
                featureManager: "featuremanager",
                actionTarget: "faultform_tooltarget",
                modifyOnly: true,
                //createFeatureActionText: "Draw",
                editFeatureActionText: "Modify",
		        snappingAgent: "snapping-agent",
		        autoLoadFeatures: true,
                outputConfig: {
                    propertyNames: propertyNames
                }
            }, {
                ptype: "app_simplegeometryform",
                id: "simplegeometryform",
                featureManager: "featuremanager",
                featureEditor: "featureeditor",
                outputTarget: "simple_geometry"
            }, {
                ptype: "gxp_featureeditor",
                id: "featureeditor",
                featureManager: "featuremanager",
                actionTarget: "simplegeometryform_tooltarget",
                createFeatureActionText: "Draw",
                editFeatureActionText: "Modify",
		        snappingAgent: "snapping-agent",
		        autoLoadFeatures: true,
                outputConfig: {
                    propertyNames: propertyNames
                }
            }, {
                ptype: "app_sourceform",
                id: "sourceform",
                featureManager: "featuremanager",
                featureEditor: "featureeditor",
                outputTarget: "source"
            }, {
                ptype: "gxp_featureeditor",
                id: "featureeditor",
                featureManager: "featuremanager",
                actionTarget: "sourceform_tooltarget",
                createFeatureActionText: "Draw",
                editFeatureActionText: "Modify",
		        snappingAgent: "snapping-agent",
		        autoLoadFeatures: true,
                outputConfig: {
                    propertyNames: propertyNames
                }
            }, {
		         ptype: "gxp_wmsgetfeatureinfo",
	             outputConfig: {
	                 width: 400
	                 }
	         },/*{
        		ptype: "app_observations",
        		featureManager: "featuremanager",
        		outputTarget: "observations"
        	    },*/{
        		ptype: "gxp_legend",
        		outputTarget: "west",
        		outputConfig: {
        		    title: this.legendTabTitle,
        		    autoScroll: true
        		}
        	}, {
            	ptype: "gxp_measure",
            	actionTarget: {target: "map.tbar", index: 6},
            	toggleGroup: "main"
            }, {
            	ptype: "gxp_zoomtoextent",
            	actionTarget: "map.tbar"
            }, {
            	ptype: "gxp_zoom",
            	actionTarget: "map.tbar"
            }, {
            	ptype: "gxp_navigationhistory",
            	actionTarget: "map.tbar"
            }, {
                ptype: "gxp_zoomtoselectedfeatures",
                featureManager: "featuremanager",
                actionTarget: "map.tbar",
                tooltip: "Zoom to selected closure"
            }, {
                ptype: "gxp_selectedfeatureactions",
                featureManager: "featuremanager",
                actions: [{
                    menuText: "Feature context demo",
                    text: "Feature context demo",
                    urlTemplate: "/geoserver/wms/reflect?layers={layer}&width=377&height=328&format=application/openlayers&featureid={fid}"
                }],
                actionTarget: ["grid.contextMenu", "grid.bbar"],
                outputConfig: {
                    width: 410,
                    height: 410
                }
            },{
                ptype: "gxp_googlegeocoder",
                outputTarget: "paneltbar",
                outputConfig: {
                    emptyText: "Search for a location ..."
                }
            }, {
            	ptype: "gxp_snappingagent",
            	id: "snapping-agent",
            	targets: [{
            		source: "local",
            		name: "geonode:trace"
            	}]
    	     }]
        });

        FaultedEarth.superclass.constructor.apply(this, arguments);
    }

});
<commit_msg>try to sove the clone issue by bracking out a feature manager for the trace layer<commit_after>FaultedEarth = Ext.extend(gxp.Viewer, {

    legendTabTitle: "Legend",
	summaryId: null,

    constructor: function(config) {

        Ext.Window.prototype.shadow = false;

        // property names for FeatureEditor and FeatureGrid
        var propertyNames = {
            // custom fied names for the fault summary table
            "fault_name": "Fault Name",
            "sec_name": "Fault Section Name",
            "episodi_is": "Episodic behaviour (yes/no)",
            "episodi_ac": "Episodic behaviour (active/inactive)",
            "length": "Length (km, pref, min, max)",
            "u_sm_d_min": "Upper seismogenic depth min (km)",
            "u_sm_d_max": "Upper seismogenic depth max (km)",
            "u_sm_d_pre": "Upper seismogenic depth pref (km)",
            "u_sm_d_com": "Upper seismogenic completeness (1, 2, 3, or 4)",
            "low_d_min": "Lower seismogenic depth min (km)",
            "low_d_max": "Lower seismogenic depth max (km)",
            "low_d_pref": "Lower seismogenic depth pref (km)",
            "low_d_com": "Lower seismogenic completeness (1, 2, 3, or 4)",
            "strike": "Strike (...\u00B0)",
            "dip_min": "Dip min (...\u00B0)",
            "dip_max": "Dip max (...\u00B0)",
            "dip_pref": "Dip pref (...\u00B0)",
            "dip_com": "Dip data completeness factor (1, 2, 3, or 4)",
            "dip_dir": "Dip direction (...\u00B0)",
            "down_thro": "Downthrown side (N, S, W, E or NW etc.)",
            "slip_typ": "Slip type (Reverse etc.)",
            "slip_com": "Slip type completeness (1, 2, 3, or 4)",
            "slip_r_min": "Slip rate min (mm/yr)",
            "slip_r_max": "Slip rate max (mm/yr)",
            "slip_r_pre": "Slip rate pref (mm/yr)",
            "slip_r_com": "Slip rate completeness (1, 2, 3, or 4)",
            "aseis_slip": "Aseismic-slip factor (0-1)",
            "aseis_com": "Aseismic-slip completeness (1, 2, 3, or 4)",
            "dis_min": "Displacement min (m)",
            "dis_max": "Displacement max (m)",
            "dis_pref": "Displacement pref (m)",
            "re_int_min": "Recurrence interval min (yr)",
            "re_int_max": "Recurrence interval max (yr)",
            "re_int_pre": "Recurrence interval pref (yr)",
            "re_int_com": "Recurrence interval common (yr)",
            "mov_min": "Age of last movement min (yr BP)",
            "mov_max": "Age of last movement max (yr BP)",
            "mov_pref": "Age of last movement pref (yr BP)",
            "all_com": "Overall data completeness (1, 2, 3, or 4)",
            "created": "Date created (date)",
            "compiler": "Compiled by (name)",
            "contrib": "Contributed by (name)",
            // custom fied names for the observations table
            "observationType": "Observation Type",
            "slipType": "Slip Type",
            "hv_ratio": "H:V Ratio",
            "rake": "Rake (deg)",
            "net_slip_rate_min": "Net Slip Rate Min (mm/yr)",
            "net_slip_rate_max": "Net Slip Rate Max (mm/yr)",
            "net_slip_rate_pref": "Net Slip Rate Pref (mm/yr)",
            "dip_slip_rate_min": "Dip Slip Rate Min (mm/yr)",
            "dip_slip_rate_max": "Dip Slip Rate Max (mm/yr)",
            "dip_slip_rate_pref": "Dip Slip Rate Pref (mm/yr)",
            "marker_age": "Marker Age (yrs BP)",
            "slip_rate_category": "Slip Rate Category",
            "strike_slip_rate_min": "Strike Slip Rate Min (mm/yr)",
            "strike_slip_rate_max": "Strike Slip Rate Max (mm/yr)",
            "strike_slip_rate_pref": "Strike Slip Rate Pref (mm/yr)",
            "vertical_slip_rate_min": "Vertical Slip Rate Min (mm/yr)",
            "vertical_slip_rate_max": "Vertical Slip Rate Max (mm/yr)",
            "vertical_slip_rate_pref": "Vertical Slip Rate Pref (mm/yr)",
            "site": "Site",
            "notes": "Notes",
            "summary_id": "Fault Section Summary ID",
            // custom fied names for fault trace form
            "section_name": "Fault Section Name",
            "loc_meth": "Location Method",
            "scale": "Scale",
            "accuracy": "Accuracy",
            "geomor_exp": "Geomorphic Expression",
            "notes": "Notes",
            "fault_section_id": "Fault Section Id",
            "t_feature": "Trace Feature",
	        "s_feature": "Site Feature",
	        // custom field names for fault source form
    	    "source_nm": "Fault Source Name",
    	    "width": "Width",
    	    "area": "Area",
    	    "rake_min": "Rake Min",
    	    "rake_max": "Rake Max",
    	    "rake_pref": "Rake Pref",
    	    "rake_com": "Rake Common",
    	    "magnitude": "Magnitude",
    	    "length_min": "Length Min",
    	    "length_max": "Length Max",
    	    "length_pre": "Length Pref"
        };

        Ext.applyIf(config, {
            proxy: "/proxy?url=",

            mapItems: [{
                xtype: "gx_zoomslider",
                vertical: true,
                height: 100
            }, {
                xtype: "gxp_scaleoverlay"
            }],
            portalItems: [{
                region: "center",
                layout: "border",
                tbar: {
                    id: "paneltbar",
                    items: ["-"]
                },
                items: [{
                    id: "west",
                    region: "west",
                    layout: "accordion",
                    width: 280,
                    split: true,
                    collapsible: true,
                    collapseMode: "mini",
                    header: false,
                    border: false,
                    defaults: {
                       hideBorders: true,
                       autoScroll: true

                    },
                    items: [{
                        id: "tree",
                        title: "Layers"
                    }, {
                        id: 'trace',
                        title: "Trace Form",
                        padding: 10
                    }, {
                		id: 'summary',
                		title: "Neotectonic Section Summary",
                		padding: 10
                	}, {
                        id: 'site',
                        title: "Site Observation Form",
                        padding: 10
                    },/* {
                        id: 'observations',
                        title: "Observations",
                        layout: "fit",
                        autoScroll: false
                    },*/ {
                		id: "fault",
                		title: "Neotectonic Fault Form"
                    }, {
                		id: "simple_geometry",
                		title: "Simple Fault Geometry"
                    }, {
                    	id: "source",
                    	title: "Fault Source"
                    }]
                },
		"map", {
                    id: "featuregrid",
                    layout: "fit",
                    region: "south",
                    border: false,
                    height: 200,
                    split: true,
                    collapseMode: "mini",
                }]
            }],

            tools: [{
                actionTarget: {target: "paneltbar", index: 0},
                outputAction: 0,
                outputConfig: {
                    title: "Login",
                    width: 900,
                    height: 500,
                    modal: true,
                    bodyCfg: {
                        tag: "iframe",
                        src: "http://178.79.185.190/",
                        style: {border: 0}
                    }
                },
                actions: [{
                    iconCls: "icon-geoexplorer",
                    text: "Login",
                }]
            },{
                ptype: "gxp_layertree",
                outputTarget: "tree",
            }, {
                ptype: "gxp_featuremanager",
                id: "featuremanager",
                autoLoadFeatures: true,
                autoSetLayer: false,
                paging: false,
                maxFeatures: 100
            }, {
                ptype: "gxp_featuremanager",
                id: "trace_featuremanager",
                autoLoadFeatures: true,
                autoSetLayer: false,
                paging: false,
                maxFeatures: 100
            }, {
                ptype: "gxp_featuregrid",
                alwaysDisplayOnMap: true,
                selectOnMap: true,
                displayMode: "selected",
                featureManager: "featuremanager",
                outputTarget: "featuregrid",
                outputConfig: {
                    id: "grid",
                    propertyNames: propertyNames
                },
                controlOptions: {
                    multiple: true,
                }
            }, {
                ptype: "app_summaryform",
                id: "summaryform",
                featureManager: "featuremanager",
                featureEditor: "featureeditor",
                outputTarget: "summary"
            }, {
                ptype: "gxp_featureeditor",
                id: "featureeditor",
                featureManager: "featuremanager",
                modifyOnly: true,
                actionTarget: "summaryform_tooltarget",
                //createFeatureActionText: "Draw",
                editFeatureActionText: "Modify",
				snappingAgent: "snapping-agent",
                outputConfig: {
                    propertyNames: propertyNames
                }
            }, {
                ptype: "app_traceform",
                id: "traceform",
                featureManager: "trace_featuremanager",
                featureEditor: "featureeditor",
                outputTarget: "trace"
            }, {
                ptype: "gxp_featureeditor",
                id: "featureeditor",
                featureManager: "trace_featuremanager",
                actionTarget: "traceform_tooltarget",
                autoLoadFeatures: true,
                createFeatureActionText: "Draw",
                editFeatureActionText: "Modify",
		        snappingAgent: "snapping-agent",
                outputConfig: {
                    propertyNames: propertyNames
                }
            }, {
                ptype: "app_siteform",
                id: "siteform",
                featureManager: "featuremanager",
                featureEditor: "featureeditor",
                outputTarget: "site"
            }, {
                ptype: "gxp_featureeditor",
                id: "featureeditor",
                featureManager: "featuremanager",
                actionTarget: "siteform_tooltarget",
                createFeatureActionText: "Draw",
                editFeatureActionText: "Modify",
                snappingAgent: "snapping-agent",
                autoLoadFeatures: true,
                outputConfig: {
                    propertyNames: propertyNames
                }
            }, {
                ptype: "app_faultform",
                id: "faultform",
                featureManager: "featuremanager",
                featureEditor: "featureeditor",
                outputTarget: "fault"
            }, {
                ptype: "gxp_featureeditor",
                id: "featureeditor",
                featureManager: "featuremanager",
                actionTarget: "faultform_tooltarget",
                modifyOnly: true,
                //createFeatureActionText: "Draw",
                editFeatureActionText: "Modify",
		        snappingAgent: "snapping-agent",
		        autoLoadFeatures: true,
                outputConfig: {
                    propertyNames: propertyNames
                }
            }, {
                ptype: "app_simplegeometryform",
                id: "simplegeometryform",
                featureManager: "featuremanager",
                featureEditor: "featureeditor",
                outputTarget: "simple_geometry"
            }, {
                ptype: "gxp_featureeditor",
                id: "featureeditor",
                featureManager: "featuremanager",
                actionTarget: "simplegeometryform_tooltarget",
                createFeatureActionText: "Draw",
                editFeatureActionText: "Modify",
		        snappingAgent: "snapping-agent",
		        autoLoadFeatures: true,
                outputConfig: {
                    propertyNames: propertyNames
                }
            }, {
                ptype: "app_sourceform",
                id: "sourceform",
                featureManager: "featuremanager",
                featureEditor: "featureeditor",
                outputTarget: "source"
            }, {
                ptype: "gxp_featureeditor",
                id: "featureeditor",
                featureManager: "featuremanager",
                actionTarget: "sourceform_tooltarget",
                createFeatureActionText: "Draw",
                editFeatureActionText: "Modify",
		        snappingAgent: "snapping-agent",
		        autoLoadFeatures: true,
                outputConfig: {
                    propertyNames: propertyNames
                }
            }, {
		         ptype: "gxp_wmsgetfeatureinfo",
	             outputConfig: {
	                 width: 400
	                 }
	         },/*{
        		ptype: "app_observations",
        		featureManager: "featuremanager",
        		outputTarget: "observations"
        	    },*/{
        		ptype: "gxp_legend",
        		outputTarget: "west",
        		outputConfig: {
        		    title: this.legendTabTitle,
        		    autoScroll: true
        		}
        	}, {
            	ptype: "gxp_measure",
            	actionTarget: {target: "map.tbar", index: 6},
            	toggleGroup: "main"
            }, {
            	ptype: "gxp_zoomtoextent",
            	actionTarget: "map.tbar"
            }, {
            	ptype: "gxp_zoom",
            	actionTarget: "map.tbar"
            }, {
            	ptype: "gxp_navigationhistory",
            	actionTarget: "map.tbar"
            }, {
                ptype: "gxp_zoomtoselectedfeatures",
                featureManager: "featuremanager",
                actionTarget: "map.tbar",
                tooltip: "Zoom to selected closure"
            }, {
                ptype: "gxp_selectedfeatureactions",
                featureManager: "featuremanager",
                actions: [{
                    menuText: "Feature context demo",
                    text: "Feature context demo",
                    urlTemplate: "/geoserver/wms/reflect?layers={layer}&width=377&height=328&format=application/openlayers&featureid={fid}"
                }],
                actionTarget: ["grid.contextMenu", "grid.bbar"],
                outputConfig: {
                    width: 410,
                    height: 410
                }
            },{
                ptype: "gxp_googlegeocoder",
                outputTarget: "paneltbar",
                outputConfig: {
                    emptyText: "Search for a location ..."
                }
            }, {
            	ptype: "gxp_snappingagent",
            	id: "snapping-agent",
            	targets: [{
            		source: "local",
            		name: "geonode:trace"
            	}]
    	     }]
        });

        FaultedEarth.superclass.constructor.apply(this, arguments);
    }

});
<|endoftext|>


<commit_before>/*global define*/

define([
  'jquery',
  'underscore',
  'backbone',
  'templates',
  'orgModel',
  'provinceModel',
  'officialCollection',
  'orgCollection',
  'provinceCollection',
  'municipalCollection',
  'dongCollection',
  './officials'
], function ($, _, Backbone, JST, OrgModel, ProvinceModel, Officials, Orgs, Provinces, Municipals, Dongs, OfficialsView) {
  'use strict'

  var SearchView = Backbone.View.extend({
    template: JST['app/scripts/templates/search.ejs'],

    el: '#search',

    events: {
      'change #selected-orgs'            : 'selectOrgs',
      'change #selected-years'           : 'selectYears',
      'change #selected-provinces'       : 'selectProvince',
      'change #selected-municipals'      : 'selectMunicipal',
      'submit form#form-search-default'  : 'submitDefaultSearch',
      'submit form#form-search-election' : 'submitElectionSearch',
      'click .chip > i'                  : 'closeAChip'
    },

    initialize: function (params) {
      var self = this
      this.params = params

      this.orgs = new Orgs()
      this.provinces = new Provinces()

      this.orgs.model = OrgModel
      this.provinces.model = ProvinceModel

      this.orgs.fetch({success: function() {
        self.provinces.fetch({success: function() {
          self.render()
        }})
      }})
    },

    render: function () {
      this.$el.html(this.template())
      this.afterRender()
    },

    afterRender: function() {
      // initialize tabs
      $('#search-tabs > ul.tabs').tabs();
      this.setInitSelectOptions()
      this.drawForms()

      if (!_.isEmpty(this.params)) {
        this.setParams()
        this.getResult(this.params)

        /**
         * if use request with default search option
         */
        if (this.params['keyword'] !== undefined) {
          this.resetTags('default', 'orgs', $('#selected-orgs > option:selected'))
          this.resetTags('default', 'years', $('#selected-years > option:selected'))
        } else if (this.params['election'] !== undefined) {
          /**
         * if use request with election cadidates search option
         */
          $('#search-tabs > ul.tabs').tabs('select_tab', 'search-election');
          this.setParams()
          this.getResult(this.params)
        }
      } else {
        this.hideLoadingDiv()
      }

    },

    showLoadingDiv: function() {
      $('#page-search .search-loading').show()
    },

    hideLoadingDiv: function() {
      $('#page-search .search-loading').hide()
    },

    setInitSelectOptions: function() {
      var self = this

      this.orgs.models.forEach(function(m) {
        $('#selected-orgs').append($('<option>', {
          id: 'option-orgs-id-' + m.get('id'),
          value: m.get('title'),
          text: m.get('title')
        }))
      })

      this.provinces.models.forEach(function(p) {
        $('#selected-provinces').append($('<option>', {
          id: 'option-provinces-id-' + p.get('id'),
          value: p.get('name'),
          text: p.get('name')
        }))
      })
    },

    /**
     * [setParams description]
     * set options in form if url has parameters like keyword, provinces, and so on
     */
    setParams: function() {
      var self = this
      var params = this.params

      if (params.org) {
        var orgOps = $('#selected-orgs > option')

        if (typeof params.org === 'string') {
          params.org = params.org.split(',')
        }

        for (var i = 0; i < orgOps.length; i++) {
          if (params.org.indexOf($(orgOps[i]).val()) > -1) $(orgOps[i]).attr('selected', 'selected')
        }
      }

      if (params.year) {
        var yearOps = $('#selected-years > option')

        if (typeof params.year === 'string') {
          params.year = params.year.split(',')
        }

        for (var i = 0; i < yearOps.length; i++) {
          if (params.year.indexOf($(yearOps[i]).val()) > -1) $(yearOps[i]).attr('selected', 'selected')
        }
      }

      if (params.election) {
        if (params.keyword) {
          $('#selected-keyword-election').val(params.keyword)
        }

        var provinceOps = $('#selected-provinces > option:not(:disabled)')

        for (var i = 0; i < provinceOps.length; i++) {
          if (params.province === $(provinceOps[i]).val()) {
            $(provinceOps[i]).prop('selected', true)
            $('#selected-provinces').material_select()
            break;
          }
        }

        this.selectProvince(function() {
          var municipalOps = $('#selected-municipals > option:not(:disabled)')

          for (var i = 0; i < municipalOps.length; i++) {
            if (params.municipal === $(municipalOps[i]).val()) {
              $(municipalOps[i]).prop('selected', true)
              $('#selected-municipals').material_select()
              break;
            }
          }

          self.selectMunicipal(function() {
            var dongOps = $('#selected-dongs > option:not(:disabled)')

            for (var i = 0; i < dongOps.length; i++) {
              if (params.dong === $(dongOps[i]).val()) {
                $(dongOps[i]).prop('selected', true)
                $('#selected-dongs').material_select()
                break;
              }
            }

          })
        })
      }
    },
    /**
     * end of setParams
     */

    drawForms: function() {
      $('#selected-orgs').material_select();
      $('#selected-years').material_select();
      $('#selected-provinces').material_select();
      $('#selected-municipals').material_select();
      $('#selected-dongs').material_select();
    },

    selectOrgs: function(e) {
      this.resetTags('default', 'orgs', $('#selected-orgs > option:selected'))
    },

    selectYears: function() {
      this.resetTags('default', 'years', $('#selected-years > option:selected'))
    },

    selectProvince: function(callback) {
      var self = this
      var cb = callback ? callback : function(){}
      // this.resetTags('election', 'provinces', $('#selected-provinces > option:selected'))

      self.initRegionOptions($('#selected-municipals'))
      self.initRegionOptions($('#selected-dongs'))

      this.municipals = new Municipals()
      this.municipals.fetch({data: 'province=' + $('#selected-provinces').val(), success: function() {
        self.municipals.models.forEach(function(m) {
          $('#selected-municipals').append($('<option>', {
            id: 'option-municipals-id-' + m.get('id'),
            value: m.get('name'),
            text: m.get('name')
          }))
        })

        $('#selected-municipals').material_select()

        cb()
      }})
    },

    selectMunicipal: function(callback) {
      var self = this
      var cb = callback ? callback : function(){}
      // this.resetTags('election', 'municipals', $('#selected-municipals > option:selected'))
      self.initRegionOptions($('#selected-dongs'))

      this.dongs = new Dongs()
      this.dongs.fetch({data: 'municipal=' + $('#selected-municipals').val(), success: function() {
        self.dongs.models.forEach(function(m) {
          $('#selected-dongs').append($('<option>', {
            id: 'option-dongs-id-' + m.get('id'),
            value: m.get('name'),
            text: m.get('name')
          }))
        })

        $('#selected-dongs').material_select()
        cb()
      }})
    },

    initRegionOptions: function(target) {
      var text = target.attr('id') === 'selected-municipals' ? '시/군/구를 선택하세요' : '읍/면/동을 선택하세요'
      target.html('')

      target.append($('<option>', {
        selected: true,
        disabled: true,
        value: text,
        text: text
      }))

      target.material_select()
    },

    submitDefaultSearch: function(e) {
      var self = this

      // if user click the submit button
      if (e) e.preventDefault()

      var params = {}
      params.org = $('#selected-orgs').val()
      params.year = $('#selected-years').val()
      params.keyword = $('#selected-keyword').val()

      // set current url with query parameters
      Backbone.history.navigate('?' + this.fixEncodeURI($.param(params)))
      // find results
      this.getResult(params)
    },

    submitElectionSearch: function(e) {
      var self = this

      // if user click the submit button
      if (e) e.preventDefault()

      var params = {}
      if ($('#selected-provinces').val()) {
        params.province = $('#selected-provinces').val()
      }

      if ($('#selected-municipals').val()) {
        params.municipal = $('#selected-municipals').val()
      }

      if ($('#selected-dongs').val()) {
        params.dong = $('#selected-dongs').val()
      }

      if ($('#selected-keyword-election').val()) {
        params.keyword = $('#selected-keyword-election').val()
      }

      params.election = 1

      // set current url with query parameters
      Backbone.history.navigate('?' + this.fixEncodeURI($.param(params)))
      // find results
      this.getResult(params)
    },

    fixEncodeURI: function(param) {
      return param.replace(/%5B/g, '').replace(/%5D/g, '');
    },

    getResult: function(params) {
      if (this.resultView) {
        this.resultView.destroy()
      }

      // show results in the active tab
      // between #search-default and #search-election
      params.el = $('#search-tabs li.tab > a.active').attr('href') + '-result'
      this.resultView = new OfficialsView(params)
    },

    resetTags: function(category, subcategory, values) {
      if (category === 'default') {
        var valLength = values.length - 1
        var initNum = 1
      } else {
        var valLength = values.length
        var initNum = 0
      }
      var chips = $('#tags-' + category + ' > .col > .chip.chip-' + subcategory)

      if (valLength > chips.length) {
        // if user added a tag
        for (; initNum < values.length; initNum++) {
          var id = $(values[initNum]).attr('id').split('-')[3]

          if ($('#chip-' + subcategory + '-id-' + id).length === 0) {
            $('#tags-' + category + ' > .col').append('' + $(values[initNum]).val() + 'close')
          }
        }
      } else {
        // if user removed a tag
        for (var i = 0; i < chips.length; i++) {
          var id = $(chips[i]).attr('id').split('-')[3]

          if ($('#option-' + subcategory + '-id-' + id).prop('selected') === false) {
             $('#chip-' + subcategory + '-id-' + id).remove()
          }
        }
      }
    },

    closeAChip: function(e) {
      var id = 'option-' + $(e.target).closest('.chip').attr('id').split('-').slice(1).join('-')

      $('option#' + id).prop('selected', false)
      $('#selected-' + $(e.target).closest('.chip').attr('id').split('-')[1]).material_select()
    },

    destroy: function() {
      this.undelegateEvents();
      this.$el.empty();
      this.stopListening();
      return this;
    }
  })

  return SearchView
})
<commit_msg>add check error status<commit_after>/*global define*/

define([
  'jquery',
  'underscore',
  'backbone',
  'templates',
  'orgModel',
  'provinceModel',
  'officialCollection',
  'orgCollection',
  'provinceCollection',
  'municipalCollection',
  'dongCollection',
  './officials'
], function ($, _, Backbone, JST, OrgModel, ProvinceModel, Officials, Orgs, Provinces, Municipals, Dongs, OfficialsView) {
  'use strict'

  var SearchView = Backbone.View.extend({
    template: JST['app/scripts/templates/search.ejs'],

    el: '#search',

    events: {
      'change #selected-orgs'            : 'selectOrgs',
      'change #selected-years'           : 'selectYears',
      'change #selected-provinces'       : 'selectProvince',
      'change #selected-municipals'      : 'selectMunicipal',
      'submit form#form-search-default'  : 'submitDefaultSearch',
      'submit form#form-search-election' : 'submitElectionSearch',
      'click .chip > i'                  : 'closeAChip'
    },

    initialize: function (params) {
      var self = this
      this.params = params

      this.orgs = new Orgs()
      this.provinces = new Provinces()

      this.orgs.model = OrgModel
      this.provinces.model = ProvinceModel

      this.checkBackboneError()

      this.orgs.fetch({success: function() {
        self.provinces.fetch({success: function() {
          self.render()
        }})
      }})
    },

    render: function () {
      this.$el.html(this.template())
      this.afterRender()
    },

    afterRender: function() {
      // initialize tabs
      $('#search-tabs > ul.tabs').tabs();
      this.setInitSelectOptions()
      this.drawForms()

      if (!_.isEmpty(this.params)) {
        this.setParams()
        this.getResult(this.params)

        /**
         * if use request with default search option
         */
        if (this.params['keyword'] !== undefined) {
          this.resetTags('default', 'orgs', $('#selected-orgs > option:selected'))
          this.resetTags('default', 'years', $('#selected-years > option:selected'))
        } else if (this.params['election'] !== undefined) {
          /**
         * if use request with election cadidates search option
         */
          $('#search-tabs > ul.tabs').tabs('select_tab', 'search-election');
          this.setParams()
          this.getResult(this.params)
        }
      } else {
        this.hideLoadingDiv()
      }

    },

    checkBackboneError: function() {
      if (!OrgModel || !ProvinceModel || !Orgs || !Provinces) {
        window.location.reload()
      }
    },

    showLoadingDiv: function() {
      $('#page-search .search-loading').show()
    },

    hideLoadingDiv: function() {
      $('#page-search .search-loading').hide()
    },

    setInitSelectOptions: function() {
      var self = this

      this.orgs.models.forEach(function(m) {
        $('#selected-orgs').append($('<option>', {
          id: 'option-orgs-id-' + m.get('id'),
          value: m.get('title'),
          text: m.get('title')
        }))
      })

      this.provinces.models.forEach(function(p) {
        $('#selected-provinces').append($('<option>', {
          id: 'option-provinces-id-' + p.get('id'),
          value: p.get('name'),
          text: p.get('name')
        }))
      })
    },

    /**
     * [setParams description]
     * set options in form if url has parameters like keyword, provinces, and so on
     */
    setParams: function() {
      var self = this
      var params = this.params

      if (params.org) {
        var orgOps = $('#selected-orgs > option')

        if (typeof params.org === 'string') {
          params.org = params.org.split(',')
        }

        for (var i = 0; i < orgOps.length; i++) {
          if (params.org.indexOf($(orgOps[i]).val()) > -1) $(orgOps[i]).attr('selected', 'selected')
        }
      }

      if (params.year) {
        var yearOps = $('#selected-years > option')

        if (typeof params.year === 'string') {
          params.year = params.year.split(',')
        }

        for (var i = 0; i < yearOps.length; i++) {
          if (params.year.indexOf($(yearOps[i]).val()) > -1) $(yearOps[i]).attr('selected', 'selected')
        }
      }

      if (params.election) {
        if (params.keyword) {
          $('#selected-keyword-election').val(params.keyword)
        }

        var provinceOps = $('#selected-provinces > option:not(:disabled)')

        for (var i = 0; i < provinceOps.length; i++) {
          if (params.province === $(provinceOps[i]).val()) {
            $(provinceOps[i]).prop('selected', true)
            $('#selected-provinces').material_select()
            break;
          }
        }

        this.selectProvince(function() {
          var municipalOps = $('#selected-municipals > option:not(:disabled)')

          for (var i = 0; i < municipalOps.length; i++) {
            if (params.municipal === $(municipalOps[i]).val()) {
              $(municipalOps[i]).prop('selected', true)
              $('#selected-municipals').material_select()
              break;
            }
          }

          self.selectMunicipal(function() {
            var dongOps = $('#selected-dongs > option:not(:disabled)')

            for (var i = 0; i < dongOps.length; i++) {
              if (params.dong === $(dongOps[i]).val()) {
                $(dongOps[i]).prop('selected', true)
                $('#selected-dongs').material_select()
                break;
              }
            }

          })
        })
      }
    },
    /**
     * end of setParams
     */

    drawForms: function() {
      $('#selected-orgs').material_select();
      $('#selected-years').material_select();
      $('#selected-provinces').material_select();
      $('#selected-municipals').material_select();
      $('#selected-dongs').material_select();
    },

    selectOrgs: function(e) {
      this.resetTags('default', 'orgs', $('#selected-orgs > option:selected'))
    },

    selectYears: function() {
      this.resetTags('default', 'years', $('#selected-years > option:selected'))
    },

    selectProvince: function(callback) {
      var self = this
      var cb = callback ? callback : function(){}
      // this.resetTags('election', 'provinces', $('#selected-provinces > option:selected'))

      self.initRegionOptions($('#selected-municipals'))
      self.initRegionOptions($('#selected-dongs'))

      this.municipals = new Municipals()
      this.municipals.fetch({data: 'province=' + $('#selected-provinces').val(), success: function() {
        self.municipals.models.forEach(function(m) {
          $('#selected-municipals').append($('<option>', {
            id: 'option-municipals-id-' + m.get('id'),
            value: m.get('name'),
            text: m.get('name')
          }))
        })

        $('#selected-municipals').material_select()

        cb()
      }})
    },

    selectMunicipal: function(callback) {
      var self = this
      var cb = callback ? callback : function(){}
      // this.resetTags('election', 'municipals', $('#selected-municipals > option:selected'))
      self.initRegionOptions($('#selected-dongs'))

      this.dongs = new Dongs()
      this.dongs.fetch({data: 'municipal=' + $('#selected-municipals').val(), success: function() {
        self.dongs.models.forEach(function(m) {
          $('#selected-dongs').append($('<option>', {
            id: 'option-dongs-id-' + m.get('id'),
            value: m.get('name'),
            text: m.get('name')
          }))
        })

        $('#selected-dongs').material_select()
        cb()
      }})
    },

    initRegionOptions: function(target) {
      var text = target.attr('id') === 'selected-municipals' ? '시/군/구를 선택하세요' : '읍/면/동을 선택하세요'
      target.html('')

      target.append($('<option>', {
        selected: true,
        disabled: true,
        value: text,
        text: text
      }))

      target.material_select()
    },

    submitDefaultSearch: function(e) {
      var self = this

      // if user click the submit button
      if (e) e.preventDefault()

      var params = {}
      params.org = $('#selected-orgs').val()
      params.year = $('#selected-years').val()
      params.keyword = $('#selected-keyword').val()

      // set current url with query parameters
      Backbone.history.navigate('?' + this.fixEncodeURI($.param(params)))
      // find results
      this.getResult(params)
    },

    submitElectionSearch: function(e) {
      var self = this

      // if user click the submit button
      if (e) e.preventDefault()

      var params = {}
      if ($('#selected-provinces').val()) {
        params.province = $('#selected-provinces').val()
      }

      if ($('#selected-municipals').val()) {
        params.municipal = $('#selected-municipals').val()
      }

      if ($('#selected-dongs').val()) {
        params.dong = $('#selected-dongs').val()
      }

      if ($('#selected-keyword-election').val()) {
        params.keyword = $('#selected-keyword-election').val()
      }

      params.election = 1

      // set current url with query parameters
      Backbone.history.navigate('?' + this.fixEncodeURI($.param(params)))
      // find results
      this.getResult(params)
    },

    fixEncodeURI: function(param) {
      return param.replace(/%5B/g, '').replace(/%5D/g, '');
    },

    getResult: function(params) {
      if (this.resultView) {
        this.resultView.destroy()
      }

      // show results in the active tab
      // between #search-default and #search-election
      params.el = $('#search-tabs li.tab > a.active').attr('href') + '-result'
      this.resultView = new OfficialsView(params)
    },

    resetTags: function(category, subcategory, values) {
      if (category === 'default') {
        var valLength = values.length - 1
        var initNum = 1
      } else {
        var valLength = values.length
        var initNum = 0
      }
      var chips = $('#tags-' + category + ' > .col > .chip.chip-' + subcategory)

      if (valLength > chips.length) {
        // if user added a tag
        for (; initNum < values.length; initNum++) {
          var id = $(values[initNum]).attr('id').split('-')[3]

          if ($('#chip-' + subcategory + '-id-' + id).length === 0) {
            $('#tags-' + category + ' > .col').append('' + $(values[initNum]).val() + 'close')
          }
        }
      } else {
        // if user removed a tag
        for (var i = 0; i < chips.length; i++) {
          var id = $(chips[i]).attr('id').split('-')[3]

          if ($('#option-' + subcategory + '-id-' + id).prop('selected') === false) {
             $('#chip-' + subcategory + '-id-' + id).remove()
          }
        }
      }
    },

    closeAChip: function(e) {
      var id = 'option-' + $(e.target).closest('.chip').attr('id').split('-').slice(1).join('-')

      $('option#' + id).prop('selected', false)
      $('#selected-' + $(e.target).closest('.chip').attr('id').split('-')[1]).material_select()
    },

    destroy: function() {
      this.undelegateEvents();
      this.$el.empty();
      this.stopListening();
      return this;
    }
  })

  return SearchView
})
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.TextArea.extend({
  tagName: "textarea",
  attributeBindings: [ "name", "type", "value", "disabled", "required",
    "parentDiv" ],
  disabled: false,

  valueChanged: function(){
    var textarea = this.element;
    if(textarea) {
      // auto-resize height of textarea $('textarea')[0].
      Ember.$(textarea)
        .css({'height':'auto','overflow-y':'hidden'})
        .height(textarea.scrollHeight - 15);

      var parent = this.get('parentDiv');
      var grandParentDiv = Ember.$("." + parent).closest(".review_item ");
      if(grandParentDiv.length === 0) {
        // auto-move textarea by chaning margin of parentDiv
        Ember.$("." + parent)
          .css({'margin-bottom': textarea.scrollHeight - 50 });

        // scrolling down to bottom of page
        if(this.get("value") !== ""){
          Ember.$('html, body').stop(true, false).animate({
            scrollTop: Ember.$(document).height()
          }, 'fast');
        }
      }
    }
  }.observes('value'),

});
<commit_msg>GCW-534 fix IE error by removing "value" from attribute bindings<commit_after>import Ember from 'ember';

export default Ember.TextArea.extend({
  tagName: "textarea",
  attributeBindings: ["disabled"],
  disabled: false,

  valueChanged: function(){
    var textarea = this.element;
    if(textarea) {
      // auto-resize height of textarea $('textarea')[0].
      Ember.$(textarea)
        .css({'height':'auto','overflow-y':'hidden'})
        .height(textarea.scrollHeight - 15);

      var parent = this.get('parentDiv');
      var grandParentDiv = Ember.$("." + parent).closest(".review_item ");
      if(grandParentDiv.length === 0) {
        // auto-move textarea by chaning margin of parentDiv
        Ember.$("." + parent)
          .css({'margin-bottom': textarea.scrollHeight - 50 });

        // scrolling down to bottom of page
        if(this.get("value") !== ""){
          Ember.$('html, body').stop(true, false).animate({
            scrollTop: Ember.$(document).height()
          }, 'fast');
        }
      }
    }
  }.observes('value'),

});
<|endoftext|>


<commit_before>App.cfg.modelChatUser = {
    url: '/um/lib/chat/user',
    fields:[
    {
        name: 'id',
        type: 'string',
        persist: false
    }
    ],
    columns:[
    {
        dataIndex:'id',
        flex: 1
    }
    ]
}

Ext.define('App.model.userman.chatUser',{
    extend: App.model.BaseCRUD,
    fields: App.cfg.modelChatUser.fields
})
<commit_msg>cfg.modelChatUser: use CRUD model's ID === _id as id<commit_after>App.cfg.modelChatUser = {
    url: '/um/lib/chat/user',
    fields:[
    {
        name: '_id',
        type: 'string'
    }
    ],
    columns:[
    {
        dataIndex: '_id',
        flex: 1
    }
    ]
}

Ext.define('App.model.userman.chatUser',{
    extend: App.model.BaseCRUD,
    fields: App.cfg.modelChatUser.fields
})
<|endoftext|>


<commit_before>(function( window, document ) {
  var PI2 = 2 * Math.PI;

  var canvas = document.getElementById( 'canvas' );
  var context = canvas.getContext( '2d' );

  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;

  context.fillRect( 0, 0, canvas.width, canvas.height );

  var config = {
    player: {
      color: 'rgba(0, 255, 0, 1.0)',
      radius: 10
    },
    zombie: {
      color: 'rgba(255, 0, 0, 1.0)',
      radius: 10
    },
    civilian: {
      color: 'rgba(255, 255, 255, 1.0)',
      radius: 10
    },
    entity: {
      color: 'rgba(255, 0, 255, 1.0)'
    },
    bullet: {
      color: 'rgba(255, 255, 0, 1.0)'
    }
  };

  var keys = {};

  var zombies     = [],
      civilians   = [],
      projectiles = [],
      player;

  var zombieHeatMap = document.createElement( 'canvas' ),
      civilianHeatMap = document.createElement( 'canvas' );

  var zombieHeatMapCtx = zombieHeatMap.getContext( '2d' ),
      civilianHeatMapCtx = civilianHeatMap.getContext( '2d' );

  zombieHeatMap.width = canvas.width;
  zombieHeatMap.height = canvas.height;

  civilianHeatMap.width = canvas.width;
  civilianHeatMap.height = canvas.height;

  // Draw heat map template pattern
  var heatMapTemplate = document.createElement( 'canvas' ),
      heatMapTemplateCtx = heatMapTemplate.getContext( '2d' );

  var heatMapRadius = 25,
      heatMapSize = 2 * heatMapRadius;

  heatMapTemplate.width = heatMapSize;
  heatMapTemplate.height = heatMapSize;

  var heatMapGrad = heatMapTemplateCtx.createRadialGradient(
    heatMapRadius, heatMapRadius, 1,
    heatMapRadius, heatMapRadius, heatMapRadius
  );

  heatMapGrad.addColorStop( 0, 'white' );
  heatMapGrad.addColorStop( 1, 'transparent' );

  heatMapTemplateCtx.fillStyle = heatMapGrad;
  heatMapTemplateCtx.fillRect( 0, 0, heatMapSize, heatMapSize );

  var prevTime = Date.now(),
      currTime,
      running = true;

  function tick() {
    if ( !running ) {
      return;
    }

    update();
    draw( context );
    window.requestAnimationFrame( tick );
  }

  function draw( ctx ) {
    ctx.fillStyle = 'black';
    ctx.fillRect( 0, 0, canvas.width, canvas.height );

    ctx.globalAlpha = 0.2;
    ctx.drawImage( civilianHeatMap, 0, 0, canvas.width, canvas.height );
    ctx.globalAlpha = 1.0;

    projectiles.forEach(function( projectile ) {
      projectile.draw( ctx );
    });

    zombies.forEach(function( zombie ) {
      zombie.draw( ctx );
    });

    civilians.forEach(function( civilian ) {
      civilian.draw( ctx );
    });

    player.draw( ctx );
  }

  function updateHeatMaps() {
    zombieHeatMapCtx.fillStyle = 'black';
    zombieHeatMapCtx.fillRect( 0, 0, zombieHeatMap.width, zombieHeatMap.height );

    civilianHeatMapCtx.fillStyle = 'black';
    civilianHeatMapCtx.fillRect( 0, 0, civilianHeatMap.width, civilianHeatMap.height );

    var x, y;
    zombies.forEach(function( zombie ) {
      x = zombie.x;
      y = zombie.y;

      zombieHeatMapCtx.drawImage(
        heatMapTemplate,
        x - heatMapRadius, y - heatMapRadius,
        heatMapSize, heatMapSize
      );
    });

    civilians.forEach(function( civilian ) {
      x = civilian.x;
      y = civilian.y;

      civilianHeatMapCtx.drawImage(
        heatMapTemplate,
        x - heatMapRadius, y - heatMapRadius,
        heatMapSize, heatMapSize
      );
    });
  }

  function update() {
    currTime = Date.now();
    var dt = currTime - prevTime;
    prevTime = currTime;

    if ( dt > 1e2 ) {
      dt = 1e2;
    }

    dt *= 1e-3;

    updateHeatMaps();

    projectiles.forEach(function( projectile ) {
      projectile.update( dt );
    });

    zombies.forEach(function( zombie ) {
      zombie.update( dt );
    });

    civilians.forEach(function( civilian ) {
      civilian.update( dt );
    });

    player.update( dt );
  }

  /**
   * Entity.
   */
  function Entity( x, y, width, height  ) {
    this.x = x || 0.0;
    this.y = y || 0.0;
    this.width = width || 0.0;
    this.height = height || 0.0;

    this.vx = 0.0;
    this.vy = 0.0;
  }

  Entity.prototype.update = function( dt ) {
    this.x += this.vx * dt;
    this.y += this.vy * dt;

    if ( 0 > this.x ) {
      this.x = 0;
    }

    if ( this.x > canvas.width ) {
      this.x = canvas.width;
    }

    if ( 0 > this.y ) {
      this.y = 0;
    }

    if ( this.y > canvas.height ) {
      this.y = canvas.height;
    }
  };

  Entity.prototype.draw = function( ctx ) {
    ctx.fillStyle = config.entity.color;
    ctx.fillRect( this.x - 0.5 * this.width, this.y - 0.5 * this.height, this.width, this.height );
  };

  /**
   * Bullet.
   */
  function Bullet( x, y, vx, vy ) {
    Entity.call( this, x, y, 1, 1 );
    this.vx = vx || 0.0;
    this.vy = vy || 0.0;
  }

  Bullet.prototype.draw = function( ctx ) {
    ctx.fillStyle = config.bullet.color;
    ctx.fillRect( this.x, this.y, this.width, this.height );
  };

  Bullet.prototype.update = function( dt ) {
    Entity.prototype.update.call( this, dt );

    if ( this.x === 0 || this.x === canvas.width ||
         this.y === 0 || this.y === canvas.height ) {
      var index = projectiles.indexOf( this );
      if ( index !== -1 ) {
        projectiles.splice( index, 1 );
      }
    }
  };

  /**
   * Character.
   */
  function Character( x, y ) {
    Entity.call( this, x, y, 2, 2 );
  }

  Character.prototype = new Entity();
  Character.prototype.constructor = Character;

  /**
   * Zombie.
   */
  function Zombie( x, y ) {
    Character.call( this, x, y );
  }

  Zombie.prototype = new Character();
  Zombie.prototype.constructor = Zombie;

  Zombie.prototype.draw = function( ctx ) {
    ctx.fillStyle = config.zombie.color;
    ctx.fillRect( this.x - 2, this.y - 2, this.width + 4, this.height + 4 );
  };

  Zombie.prototype.update = function( dt ) {
    Character.prototype.update.call( this, dt );
    var data = civilianHeatMapCtx.getImageData( this.x - 1, this.y - 1, 3, 3 ).data;
    // This is super hacky.
    var topLeft     = data[ 0 * 4 ];
    var top         = data[ 1 * 4 ];
    var topRight    = data[ 2 * 4 ];
    var left        = data[ 3 * 4 ];
    var center      = data[ 4 * 4 ];
    var right       = data[ 5 * 4 ];
    var bottomLeft  = data[ 6 * 4 ];
    var bottom      = data[ 7 * 4 ];
    var bottomRight = data[ 8 * 4 ];

    var dx = topLeft * -1 + left * -1 + bottomLeft * -1 + topRight * 1 + right * 1 + bottomRight * 1;
    var dy = topLeft * -1 + top * -1 + topRight * -1 + bottomLeft * 1 + bottom * 1 + bottomRight * 1;

    if ( dx === 0 ) {
      dx = Math.random() * 50 - 25;
    }

    if ( dy === 0 ) {
      dy = Math.random() * 50 - 25;
    }

    this.vx = dx;
    this.vy = dy;
  };

  /**
   * Civilian.
   */
  function Civilian( x, y ) {
    Character.call( this, x, y );
  }

  Civilian.prototype = new Character();
  Civilian.prototype.constructor = Civilian;

  Civilian.prototype.draw = function( ctx ) {
    ctx.fillStyle = config.civilian.color;
    ctx.fillRect( this.x, this.y, this.width, this.height );
  };

  Civilian.prototype.update = function( dt ) {
    Character.prototype.update.call( this, dt );
    this.vx = Math.random() * 100 - 50;
    this.vy = Math.random() * 100 - 50;
  };

  /**
   * Zombie.
   */
  function Player( x, y ) {
    Character.call( this, x, y );
  }

  Player.prototype = new Character();
  Player.prototype.constructor = Player;

  Player.prototype.draw = function( ctx ) {
    ctx.fillStyle = config.player.color;
    ctx.fillRect( this.x - 2, this.y - 2, this.width + 5, this.height + 5 );
  };

  Player.prototype.update = function( dt ) {
    var dx = 0,
        dy = 0;

    dx += keys[ 65 ] ? -1 : 0; // A.
    dx += keys[ 68 ] ?  1 : 0; // D.

    dy += keys[ 87 ] ? -1 : 0; // W.
    dy += keys[ 83 ] ?  1 : 0; // S.

    this.vx = dx * 30;
    this.vy = dy * 30;

    Character.prototype.update.call( this, dt );

    // Start shooting.
    var bx = 0,
        by = 0;

    bx += keys[ 37 ] ? -1 : 0; // Left.
    bx += keys[ 39 ] ?  1 : 0; // Right.

    by += keys[ 38 ] ? -1 : 0; // Top.
    by += keys[ 40 ] ?  1 : 0;  // Bottom.

    if ( !bx && !by ) {
      return;
    }

    bx *= 200;
    by *= 200;

    projectiles.push( new Bullet( this.x, this.y, bx, by ) );
  };

  function randomInt( min, max ) {
    return Math.round( min + Math.random() * ( max - min ) );
  }

  function init() {
    var width  = canvas.width,
        height = canvas.height;

    var civilianCount = 100;
    var i;
    for ( i = 0; i < civilianCount; i++ ) {
      civilians.push( new Civilian( randomInt( 0, width ), randomInt( 0, height ) ) );
    }

    var zombieCount = 5;
    for ( i = 0; i < zombieCount; i++ ) {
      zombies.push( new Zombie( randomInt( 0, width ), randomInt( 0, height ) ) );
    }

    player = new Player( randomInt( 0, width ), randomInt( 0, height ) );

    tick();
  }

  function onKeyDown( event ) {
    // console.log( event.which );
    keys[ event.which ] = true;
    // ESC.
    if ( event.which === 27 ) {
      running = false;
    }
  }

  function onKeyUp( event ) {
    // console.log( event.which );
    keys[ event.which ] = false;
  }

  document.addEventListener( 'keydown', onKeyDown );
  document.addEventListener( 'keyup', onKeyUp );

  init();
}) ( window, document );
<commit_msg>Infection. Bullets hurt now. Simple AI, without heatmaps.<commit_after>(function( window, document ) {
  var PI2 = 2 * Math.PI;

  var canvas = document.getElementById( 'canvas' );
  var context = canvas.getContext( '2d' );

  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;

  context.fillRect( 0, 0, canvas.width, canvas.height );

  var config = {
    player: {
      color: 'rgba(0, 255, 0, 1.0)',
      health: 100,
      speed: 15,
      frequency: 1000 / 10, // Number of ms to fire n bullets/second.
      hitFrequency: 1000 / 40 // Number of ms between player injuries.
    },
    zombie: {
      color: 'rgba(255, 0, 0, 1.0)',
      speed: 20,
      radiusSquared: 75 * 75,
      health: 10
    },
    civilian: {
      color: 'rgba(255, 255, 255, 1.0)',
      radiusSquared: 100 * 100,
      speed: 25
    },
    entity: {
      color: 'rgba(255, 0, 255, 1.0)'
    },
    bullet: {
      color: 'rgba(255, 255, 0, 1.0)'
    }
  };

  var keys = {};

  var zombies     = [],
      civilians   = [],
      projectiles = [],
      player;

  var prevTime = Date.now(),
      currTime,
      running = true;

  function tick() {
    if ( !running ) {
      return;
    }

    update();
    draw( context );
    window.requestAnimationFrame( tick );
  }

  function draw( ctx ) {
    ctx.fillStyle = 'black';
    ctx.fillRect( 0, 0, canvas.width, canvas.height );

    projectiles.forEach(function( projectile ) {
      projectile.draw( ctx );
    });

    ctx.beginPath();
    zombies.forEach(function( zombie ) {
      zombie.draw( ctx );
    });
    ctx.fillStyle = config.zombie.color;
    ctx.fill();

    ctx.beginPath();
    civilians.forEach(function( civilian ) {
      if ( !( civilian instanceof Player ) ) {
        civilian.draw( ctx );
      }
    });
    ctx.fillStyle = config.civilian.color;
    ctx.fill();

    player.draw( ctx );

    ctx.font = '14px Helvetica, Arial';
    ctx.fillStyle = 'white';
    ctx.fillText( player.health, 20, 20 );
  }

  function update() {
    currTime = Date.now();
    var dt = currTime - prevTime;
    prevTime = currTime;

    if ( dt > 1e2 ) {
      dt = 1e2;
    }

    dt *= 1e-3;

    projectiles.forEach(function( projectile ) {
      projectile.update( dt );
    });

    zombies.forEach(function( zombie ) {
      zombie.update( dt );
    });

    civilians.forEach(function( civilian ) {
      civilian.update( dt );
    });

    player.update( dt );
  }

  function distanceSquared( x0, y0, x1, y1 ) {
    var dx = x1 - x0,
        dy = y1 - y0;

    return dx * dx + dy * dy;
  }

  function distance( x0, y0, x1, y1 ) {
    return Math.sqrt( distanceSquared( x0, y0, x1, y1 ) );
  }

  /**
   * Returns the angle that a character at (x0, y0) would need to travel along
   * to reach (x1, y1);
   */
  function angleTo( x0, y0, x1, y1 ) {
    return Math.atan2( y1 - y0, x1 - x0 );
  }

  /**
   * Entity.
   */
  function Entity( x, y, width, height  ) {
    this.x = x || 0.0;
    this.y = y || 0.0;
    this.width = width || 0.0;
    this.height = height || 0.0;

    this.vx = 0.0;
    this.vy = 0.0;
  }

  Entity.prototype.update = function( dt ) {
    this.x += this.vx * dt;
    this.y += this.vy * dt;

    if ( 0 > this.x ) {
      this.x = 0;
      this.vx = -this.vx;
    }

    if ( this.x > canvas.width ) {
      this.x = canvas.width;
      this.vx = -this.vx;
    }

    if ( 0 > this.y ) {
      this.y = 0;
      this.vy = -this.vy;
    }

    if ( this.y > canvas.height ) {
      this.y = canvas.height;
      this.vy = -this.vy;
    }
  };

  Entity.prototype.draw = function( ctx ) {
    ctx.fillStyle = config.entity.color;
    ctx.fillRect( this.x - 0.5 * this.width, this.y - 0.5 * this.height, this.width, this.height );
  };

  /**
   * Bullet.
   */
  function Bullet( x, y, vx, vy ) {
    Entity.call( this, x, y, 1, 1 );
    this.vx = vx || 0.0;
    this.vy = vy || 0.0;
  }

  Bullet.prototype.draw = function( ctx ) {
    ctx.fillStyle = config.bullet.color;
    ctx.fillRect( this.x, this.y, this.width, this.height );
  };

  Bullet.prototype.update = function( dt ) {
    Entity.prototype.update.call( this, dt );

    var x = this.x,
        y = this.y;

    if ( x === 0 || x === canvas.width ||
         y === 0 || y === canvas.height ) {
      var index = projectiles.indexOf( this );
      if ( index !== -1 ) {
        projectiles.splice( index, 1 );
      }
    }

    var minDistanceSquared = Number.POSITIVE_INFINITY,
        currDistanceSquared,
        min;

    zombies.forEach(function( zombie ) {
      var currDistanceSquared = distanceSquared( x, y, zombie.x, zombie.y );
      if ( currDistanceSquared < minDistanceSquared ) {
        minDistanceSquared = currDistanceSquared;
        min = zombie;
      }
    });

    if ( min && minDistanceSquared < 4 ) {
      var index = zombies.indexOf( min );
      if ( index !== -1 ) {
        zombies.splice( index, 1 );

        index = projectiles.indexOf( this );
        if ( index !== -1 ) {
          projectiles.splice( index, 1 );
        }
      }
    }
  };

  /**
   * Character.
   */
  function Character( x, y ) {
    Entity.call( this, x, y, 2, 2 );
    this.speed = 0;
  }

  Character.prototype = new Entity();
  Character.prototype.constructor = Character;

  /**
   * Zombie.
   */
  function Zombie( x, y ) {
    Character.call( this, x, y );
    this.speed = ( Math.random() + 0.5 ) * config.zombie.speed;
  }

  Zombie.prototype = new Character();
  Zombie.prototype.constructor = Zombie;

  Zombie.prototype.draw = function( ctx ) {
    ctx.rect( this.x, this.y, this.width, this.height );
  };

  Zombie.prototype.update = function( dt ) {
    Character.prototype.update.call( this, dt );

    var x = this.x,
        y = this.y;

    var minDistanceSquared = Number.POSITIVE_INFINITY,
        currDistanceSquared,
        min;

    civilians.forEach(function( civilian ) {
      currDistanceSquared = distanceSquared( x, y, civilian.x, civilian.y );
      if ( currDistanceSquared < config.zombie.radiusSquared &&
           currDistanceSquared < minDistanceSquared ) {
        minDistanceSquared = currDistanceSquared;
        min = civilian;
      }
    });

    if ( minDistanceSquared < 1 ) {
      min.infect();
    } else {
      var angle;
      if ( min ) {
        angle = angleTo( x, y, min.x, min.y );
      } else {
        angle = Math.random() * PI2;
      }

      this.vx = Math.cos( angle ) * this.speed;
      this.vy = Math.sin( angle ) * this.speed;
    }
  };

  /**
   * Civilian.
   */
  function Civilian( x, y ) {
    Character.call( this, x, y );
    this.speed = ( Math.random() + 0.5 ) * config.civilian.speed;
  }

  Civilian.prototype = new Character();
  Civilian.prototype.constructor = Civilian;

  Civilian.prototype.draw = function( ctx ) {
    ctx.rect( this.x, this.y, this.width, this.height );
  };

  Civilian.prototype.update = function( dt ) {
    Character.prototype.update.call( this, dt );

    var x = this.x,
        y = this.y;

    var minDistanceSquared = Number.POSITIVE_INFINITY,
        currDistanceSquared,
        min;

    zombies.forEach(function( zombie ) {
      currDistanceSquared = distanceSquared( x, y, zombie.x, zombie.y );
      if ( currDistanceSquared < config.civilian.radiusSquared &&
           currDistanceSquared < minDistanceSquared ) {
        minDistanceSquared = currDistanceSquared;
        min = zombie;
      }
    });

    var angle;
    if ( min ) {
      angle = angleTo( x, y, min.x, min.y ) + Math.PI;
    } else {
      angle = Math.random() * PI2;
    }

    this.vx = Math.cos( angle ) * this.speed;
    this.vy = Math.sin( angle ) * this.speed;
  };

  Civilian.prototype.infect = function() {
    var index = civilians.indexOf( this );
    if ( index !== -1 ) {
      civilians.splice( index, 1 );
      zombies.push( new Zombie( this.x, this.y ) );
    }
  };

  /**
   * Player.
   */
  function Player( x, y ) {
    Character.call( this, x, y );
    this.canFire = true;

    this.health = config.player.health;
    this.living = true;
    this.injured = false;
  }

  Player.prototype = new Character();
  Player.prototype.constructor = Player;

  Player.prototype.draw = function( ctx ) {
    ctx.fillStyle = config.player.color;
    ctx.fillRect( this.x - 2, this.y - 2, this.width + 5, this.height + 5 );
  };

  Player.prototype.update = function( dt ) {
    var dx = 0,
        dy = 0;

    dx += keys[ 65 ] ? -1 : 0; // A.
    dx += keys[ 68 ] ?  1 : 0; // D.

    dy += keys[ 87 ] ? -1 : 0; // W.
    dy += keys[ 83 ] ?  1 : 0; // S.

    this.vx = dx * 30;
    this.vy = dy * 30;

    Character.prototype.update.call( this, dt );

    // Start shooting.
    var bx = 0,
        by = 0;

    bx += keys[ 37 ] ? -1 : 0; // Left.
    bx += keys[ 39 ] ?  1 : 0; // Right.

    by += keys[ 38 ] ? -1 : 0; // Top.
    by += keys[ 40 ] ?  1 : 0;  // Bottom.

    if ( !bx && !by || !this.canFire ) {
      return;
    }

    this.canFire = false;
    setTimeout(function() {
      this.canFire = true;
    }.bind( this ), config.player.frequency );

    bx *= 200;
    by *= 200;

    projectiles.push( new Bullet( this.x, this.y, bx, by ) );
  };

  Player.prototype.infect = function() {
    if ( !this.living ) {
      return;
    }

    if ( !this.injured ) {
      this.health--;
      this.injured = true;

      setTimeout(function() {
        this.injured = false;
      }.bind( this ), config.player.hitFrequency );
    }

    if ( !this.health ) {
      console.log( 'You\'re dead!' );
      this.living = false;
    }
  };

  function randomInt( min, max ) {
    return Math.round( min + Math.random() * ( max - min ) );
  }

  function init() {
    var width  = canvas.width,
        height = canvas.height;

    civilians.push( player = new Player( randomInt( 0, width ), randomInt( 0, height ) ) );
    var civilianCount = 500;
    var i;
    for ( i = 0; i < civilianCount; i++ ) {
      civilians.push( new Civilian( randomInt( 0, width ), randomInt( 0, height ) ) );
    }

    var zombieCount = 20;
    for ( i = 0; i < zombieCount; i++ ) {
      zombies.push( new Zombie( randomInt( 0, width ), randomInt( 0, height ) ) );
    }

    tick();
  }

  function onKeyDown( event ) {
    // console.log( event.which );
    keys[ event.which ] = true;
    // ESC.
    if ( event.which === 27 ) {
      running = false;
    }
  }

  function onKeyUp( event ) {
    // console.log( event.which );
    keys[ event.which ] = false;
  }

  document.addEventListener( 'keydown', onKeyDown );
  document.addEventListener( 'keyup', onKeyUp );

  init();
}) ( window, document );
<|endoftext|>