<commit_before>/* eslint-env mocha */
var chai = require('chai');
chai.use(require('chai-immutable'));
var expect = chai.expect;
var Immutable = require('immutable');

var transit = require('../');

var samples = Immutable.Map({

  "Immutable": Immutable.Map({

    "Maps": Immutable.Map({"abc": "def"}),

    "Maps with numeric keys": Immutable.Map().set(1, 2),

    "Maps in Maps": Immutable.Map()
      .set(1, Immutable.Map([['X', 'Y'], ['A', 'B']]))
      .set(2, Immutable.Map({a: 1, b: 2, c: 3})),

    "Lists": Immutable.List.of(1, 2, 3, 4, 5),

    "Long Lists": Immutable.Range(0, 100).toList(),

    "Lists in Maps": Immutable.Map().set(
      Immutable.List.of(1, 2),
      Immutable.List.of(1, 2, 3, 4, 5)
    ),

    "Sets": Immutable.Set.of(1, 2, 3, 3),

    "OrderedSets": Immutable.OrderedSet.of(1, 4, 3, 3),

    "Ordered Maps": Immutable.OrderedMap()
      .set(2, 'a')
      .set(3, 'b')
      .set(1, 'c')
  }),

  JS: Immutable.Map({

    "array": [1, 2, 3, 4, 5],

    "array of arrays": [
      [1, 2, 3],
      [4, 5, 6],
      [7, 8, 9, 10]
    ],

    "array of immutables": [
      Immutable.Map({1: 2}),
      Immutable.List.of(1, 2, 3)
    ],

    "object": {
      a: 1,
      b: 2
    },

    "object of immutables": {
      a: Immutable.Map({1: 2}),
      b: Immutable.Map({3: 4})
    }

  })

});

// This is a hack because records and maps are considered equivalent by
// chai-immutable.
// https://github.com/astorije/chai-immutable/issues/37
function expectRecordsEqual(r1, r2) {
  expect(r1).to.eql(r2);
  expect(r1.toString()).to.eql(r2.toString());
}

describe('transit', function() {
  samples.get('Immutable').forEach(function(data, desc) {
    describe(desc + " - " + data.inspect(), function() {
      it('should encode to JSON', function() {
        var json = transit.toJSON(data);
        expect(json).to.be.a('string');
        expect(JSON.parse(json)).to.not.eql(null);
      });
      it('should round-trip', function() {
        var roundTrip = transit.fromJSON(transit.toJSON(data));
        expect(roundTrip).to.be.an('object');
        expect(roundTrip).to.equal(data);
        expect(roundTrip).to.be.an.instanceOf(data.constructor);
      });
    });
  });

  samples.get('JS').forEach(function(data, desc) {
    describe(desc + " - " + JSON.stringify(data), function() {
      it('should encode to JSON', function() {
        var json = transit.toJSON(data);
        expect(json).to.be.a('string');
        expect(JSON.parse(json)).to.not.eql(null);
      });
      it('should round-trip', function() {
        var roundTrip = transit.fromJSON(transit.toJSON(data));
        expect(roundTrip).to.eql(data);
      });
    });
  });

  it('should ignore functions', function() {
    var input = Immutable.Map({ a: function abc(){} });
    var result = transit.fromJSON(transit.toJSON(input));
    expect(result.get('a')).to.eql(null);
  });

  describe('Records', function() {
    var FooRecord = Immutable.Record({
      a: 1,
      b: 2,
    }, 'foo');

    var BarRecord = Immutable.Record({
      c: '1',
      d: '2'
    }, 'bar');

    var NamelessRecord = Immutable.Record({});

    var recordTransit = transit.withRecords([FooRecord, BarRecord]);

    it('should round-trip simple records', function() {
      var data = Immutable.Map({
        myFoo: new FooRecord(),
        myBar: new BarRecord()
      });

      var roundTrip = recordTransit.fromJSON(recordTransit.toJSON(data));
      expectRecordsEqual(data, roundTrip);

      expect(roundTrip.get('myFoo').a).to.eql(1);
      expect(roundTrip.get('myFoo').b).to.eql(2);

      expect(roundTrip.get('myBar').c).to.eql('1');
      expect(roundTrip.get('myBar').d).to.eql('2');
    });

    it('should round-trip complex nested records', function() {
      var data = Immutable.Map({
        foo: new FooRecord({
          b: Immutable.List.of(BarRecord(), BarRecord({c: 22}))
        }),
        bar: new BarRecord()
      });

      var roundTrip = recordTransit.fromJSON(recordTransit.toJSON(data));
      expectRecordsEqual(data, roundTrip);
    });

    it('should serialize unspecified Record as a Map', function() {
      var data = Immutable.Map({
        myFoo: new FooRecord(),
        myBar: new BarRecord()
      });

      var oneRecordTransit = transit.withRecords([FooRecord]);
      var roundTripOneRecord = oneRecordTransit.fromJSON(
                                oneRecordTransit.toJSON(data));

      var equivalentMap = Immutable.fromJS({
        myFoo: new FooRecord(),
        myBar: {c: '1', d: '2'}
      });
      expectRecordsEqual(roundTripOneRecord, equivalentMap);

      var roundTripWithoutRecords = transit.fromJSON(transit.toJSON(data));

      expect(roundTripWithoutRecords).to.eql(
        Immutable.fromJS({
          myFoo: {a: 1, b: 2},
          myBar: {c: '1', d: '2'}
        })
      );
    });

    it('should roundtrip ES6-class-style records', function() {
      var ClassyBase = Immutable.Record({name: 'lindsey'}, 'ClassyRecord');
      function ClassyRecord(values){ ClassyBase.call(this, values); }
      ClassyRecord.prototype = Object.create(ClassyBase.prototype);
      ClassyRecord.prototype.constructor = ClassyRecord;

      var data = new ClassyRecord({name: 'jon'});
      var classyTransit = transit.withRecords([ClassyRecord]);
      var roundTrip = classyTransit.fromJSON(classyTransit.toJSON(data));
      expectRecordsEqual(data, roundTrip);
    });

    it('throws an error when it is passed a record with no name', function() {
      expect(function() {
        transit.withRecords([NamelessRecord]);
      }).to.throw();
    });

    it('throws an error when it reads an unknown record type', function() {
      var input = new FooRecord();

      var json = recordTransit.toJSON(input);

      var emptyRecordTransit = transit.withRecords([]);

      expect(function() {
        emptyRecordTransit.fromJSON(json);
      }).to.throw();
    });

    it('throws an error if two records have the same name', function() {
      var R1 = Immutable.Record({}, 'R1');
      var R1_2 = Immutable.Record({}, 'R1');

      expect(function() {
        transit.withRecords([R1, R1_2]);
      }).to.throw();
    });
  });

  describe('.withFilter(predicate)', function(){
    var filterFunction = function(val, key) {
      return key[0] !== '_';
    };
    var filter = transit.withFilter(filterFunction);

    it('can ignore Map entries', function() {
      var input = Immutable.Map({
        a: 'foo', _b: 'bar', c: Immutable.Map({d: 'deep', _e: 'hide'})
      });
      var result = filter.fromJSON(filter.toJSON(input));
      expect(result.get('a')).to.eql('foo');
      expect(result.get('_b')).to.eql(undefined);
      expect(result.getIn(['c', 'd'])).to.eql('deep');
      expect(result.getIn(['c', '_e'])).to.eql(undefined);
    });

    it('can ignore OrderedMap entries', function() {
      var input = Immutable.OrderedMap()
        .set('a', 'baz').set('_b', 'bar')
        .set('c', Immutable.OrderedMap({d: 'deep', _e: 'hide'}));
      var result = filter.fromJSON(filter.toJSON(input));
      expect(result.get('a')).to.eql('baz');
      expect(result.get('_b')).to.eql(undefined);
      expect(result.getIn(['c', 'd'])).to.eql('deep');
      expect(result.getIn(['c', '_e'])).to.eql(undefined);
    });

    it('can ignore Set entries', function() {
      var input = Immutable.OrderedSet.of(1, 2, 3, 3, 'a');
      filter = transit.withFilter(function(val) {
        return typeof val === 'number';
      });
      var result = filter.fromJSON(filter.toJSON(input));
      expect(result.includes('a')).to.eql(false);
    });

    it('can ignore OrderedSet entries', function() {
      var input = Immutable.Set.of(1, 2, 3, 3, 'a');
      filter = transit.withFilter(function(val) {
        return typeof val === 'number';
      });
      var result = filter.fromJSON(filter.toJSON(input));
      expect(result.includes('a')).to.eql(false);
    });

    it('can ignore List entries', function() {
      var input = Immutable.List.of(1, 2, 3, 3, 'a');
      var result = filter.fromJSON(filter.toJSON(input));
      expect(result.includes('a')).to.eql(false);
    });

    it('can ignore Maps nested in Records', function() {
      var MyRecord = Immutable.Record({
        a: null,
        _b: 'bar'
      }, 'myRecord');

      var input = new MyRecord({a: Immutable.Map({_c: 1, d: 2}), _b: 'baz' });
      var recordFilter = transit
                          .withRecords([MyRecord])
                          .withFilter(filterFunction);

      var result = recordFilter.fromJSON(recordFilter.toJSON(input));

      expect(result.getIn(['a', 'd'])).to.eql(2);
      expect(result.getIn(['a', '_c'])).to.eql(undefined);
      expect(result.get('_b')).to.eql('baz');

    });
  });

  describe('Unknown Input', function() {
    it('fails when an unrecognized object is passed', function() {
      var MyObject = function() {};
      var MyObjectInstance = new MyObject();

      expect(function() {
        transit.toJSON(MyObjectInstance);
      }).to.throw();
    });
  });

});
<commit_msg>Added test to ensure we're projected from record/map comparison<commit_after>/* eslint-env mocha */
var chai = require('chai');
chai.use(require('chai-immutable'));
var expect = chai.expect;
var Immutable = require('immutable');

var transit = require('../');

var samples = Immutable.Map({

  "Immutable": Immutable.Map({

    "Maps": Immutable.Map({"abc": "def"}),

    "Maps with numeric keys": Immutable.Map().set(1, 2),

    "Maps in Maps": Immutable.Map()
      .set(1, Immutable.Map([['X', 'Y'], ['A', 'B']]))
      .set(2, Immutable.Map({a: 1, b: 2, c: 3})),

    "Lists": Immutable.List.of(1, 2, 3, 4, 5),

    "Long Lists": Immutable.Range(0, 100).toList(),

    "Lists in Maps": Immutable.Map().set(
      Immutable.List.of(1, 2),
      Immutable.List.of(1, 2, 3, 4, 5)
    ),

    "Sets": Immutable.Set.of(1, 2, 3, 3),

    "OrderedSets": Immutable.OrderedSet.of(1, 4, 3, 3),

    "Ordered Maps": Immutable.OrderedMap()
      .set(2, 'a')
      .set(3, 'b')
      .set(1, 'c')
  }),

  JS: Immutable.Map({

    "array": [1, 2, 3, 4, 5],

    "array of arrays": [
      [1, 2, 3],
      [4, 5, 6],
      [7, 8, 9, 10]
    ],

    "array of immutables": [
      Immutable.Map({1: 2}),
      Immutable.List.of(1, 2, 3)
    ],

    "object": {
      a: 1,
      b: 2
    },

    "object of immutables": {
      a: Immutable.Map({1: 2}),
      b: Immutable.Map({3: 4})
    }

  })

});

// This is a hack because records and maps are considered equivalent by
// immutable.
// https://github.com/astorije/chai-immutable/issues/37
function expectImmutableEqual(r1, r2) {
  expect(r1).to.eql(r2);
  expect(r1.toString()).to.eql(r2.toString());
}
function expectNotImmutableEqual(r1, r2) {
  try {
    expectImmutableEqual(r1, r2);
  } catch (ex) {
    return true;
  }
  throw new chai.AssertionError('Expected ' + r1 + ' to differ from ' + r2);
}

describe('transit', function() {
  samples.get('Immutable').forEach(function(data, desc) {
    describe(desc + " - " + data.inspect(), function() {
      it('should encode to JSON', function() {
        var json = transit.toJSON(data);
        expect(json).to.be.a('string');
        expect(JSON.parse(json)).to.not.eql(null);
      });
      it('should round-trip', function() {
        var roundTrip = transit.fromJSON(transit.toJSON(data));
        expect(roundTrip).to.be.an('object');
        expectImmutableEqual(roundTrip, data);
        expect(roundTrip).to.be.an.instanceOf(data.constructor);
      });
    });
  });

  samples.get('JS').forEach(function(data, desc) {
    describe(desc + " - " + JSON.stringify(data), function() {
      it('should encode to JSON', function() {
        var json = transit.toJSON(data);
        expect(json).to.be.a('string');
        expect(JSON.parse(json)).to.not.eql(null);
      });
      it('should round-trip', function() {
        var roundTrip = transit.fromJSON(transit.toJSON(data));
        expectImmutableEqual(roundTrip, data);
      });
    });
  });

  it('should ignore functions', function() {
    var input = Immutable.Map({ a: function abc(){} });
    var result = transit.fromJSON(transit.toJSON(input));
    expect(result.get('a')).to.eql(null);
  });

  describe('Records', function() {
    var FooRecord = Immutable.Record({
      a: 1,
      b: 2,
    }, 'foo');

    var BarRecord = Immutable.Record({
      c: '1',
      d: '2'
    }, 'bar');

    var NamelessRecord = Immutable.Record({});

    var ClassyBase = Immutable.Record({name: 'lindsey'}, 'ClassyRecord');
    function ClassyRecord(values) { ClassyBase.call(this, values); }
    ClassyRecord.prototype = Object.create(ClassyBase.prototype);
    ClassyRecord.prototype.constructor = ClassyRecord;

    var recordTransit = transit.withRecords([FooRecord, BarRecord]);

    it('should ensure maps and records compare differently', function() {
      expectNotImmutableEqual(new FooRecord(), Immutable.Map({a: 1, b: 2}));
    });

    it('should round-trip simple records', function() {
      var data = Immutable.Map({
        myFoo: new FooRecord(),
        myBar: new BarRecord()
      });

      var roundTrip = recordTransit.fromJSON(recordTransit.toJSON(data));
      expectImmutableEqual(data, roundTrip);

      expect(roundTrip.get('myFoo').a).to.eql(1);
      expect(roundTrip.get('myFoo').b).to.eql(2);

      expect(roundTrip.get('myBar').c).to.eql('1');
      expect(roundTrip.get('myBar').d).to.eql('2');
    });

    it('should round-trip complex nested records', function() {
      var data = Immutable.Map({
        foo: new FooRecord({
          b: Immutable.List.of(BarRecord(), BarRecord({c: 22}))
        }),
        bar: new BarRecord()
      });

      var roundTrip = recordTransit.fromJSON(recordTransit.toJSON(data));
      expectImmutableEqual(data, roundTrip);
    });

    it('should serialize unspecified Record as a Map', function() {
      var data = Immutable.Map({
        myFoo: new FooRecord(),
        myBar: new BarRecord()
      });

      var oneRecordTransit = transit.withRecords([FooRecord]);
      var roundTripOneRecord = oneRecordTransit.fromJSON(
                                oneRecordTransit.toJSON(data));

      expectImmutableEqual(roundTripOneRecord, Immutable.fromJS({
        myFoo: new FooRecord(),
        myBar: {c: '1', d: '2'}
      }));

      var roundTripWithoutRecords = transit.fromJSON(transit.toJSON(data));

      expectImmutableEqual(roundTripWithoutRecords, Immutable.fromJS({
        myFoo: {a: 1, b: 2},
        myBar: {c: '1', d: '2'}
      }));
    });

    it('should roundtrip ES6-class-style records', function() {
      var data = new ClassyRecord({name: 'jon'});

      var classyTransit = transit.withRecords([ClassyRecord]);
      var roundTrip = classyTransit.fromJSON(classyTransit.toJSON(data));

      expectImmutableEqual(data, roundTrip);
    });

    it('throws an error when it is passed a record with no name', function() {
      expect(function() {
        transit.withRecords([NamelessRecord]);
      }).to.throw();
    });

    it('throws an error when it reads an unknown record type', function() {
      var input = new FooRecord();

      var json = recordTransit.toJSON(input);

      var emptyRecordTransit = transit.withRecords([]);

      expect(function() {
        emptyRecordTransit.fromJSON(json);
      }).to.throw();
    });

    it('throws an error if two records have the same name', function() {
      var R1 = Immutable.Record({}, 'R1');
      var R1_2 = Immutable.Record({}, 'R1');

      expect(function() {
        transit.withRecords([R1, R1_2]);
      }).to.throw();
    });
  });

  describe('.withFilter(predicate)', function(){
    var filterFunction = function(val, key) {
      return key[0] !== '_';
    };
    var filter = transit.withFilter(filterFunction);

    it('can ignore Map entries', function() {
      var input = Immutable.Map({
        a: 'foo', _b: 'bar', c: Immutable.Map({d: 'deep', _e: 'hide'})
      });
      var result = filter.fromJSON(filter.toJSON(input));
      expect(result.get('a')).to.eql('foo');
      expect(result.get('_b')).to.eql(undefined);
      expect(result.getIn(['c', 'd'])).to.eql('deep');
      expect(result.getIn(['c', '_e'])).to.eql(undefined);
    });

    it('can ignore OrderedMap entries', function() {
      var input = Immutable.OrderedMap()
        .set('a', 'baz').set('_b', 'bar')
        .set('c', Immutable.OrderedMap({d: 'deep', _e: 'hide'}));
      var result = filter.fromJSON(filter.toJSON(input));
      expect(result.get('a')).to.eql('baz');
      expect(result.get('_b')).to.eql(undefined);
      expect(result.getIn(['c', 'd'])).to.eql('deep');
      expect(result.getIn(['c', '_e'])).to.eql(undefined);
    });

    it('can ignore Set entries', function() {
      var input = Immutable.OrderedSet.of(1, 2, 3, 3, 'a');
      filter = transit.withFilter(function(val) {
        return typeof val === 'number';
      });
      var result = filter.fromJSON(filter.toJSON(input));
      expect(result.includes('a')).to.eql(false);
    });

    it('can ignore OrderedSet entries', function() {
      var input = Immutable.Set.of(1, 2, 3, 3, 'a');
      filter = transit.withFilter(function(val) {
        return typeof val === 'number';
      });
      var result = filter.fromJSON(filter.toJSON(input));
      expect(result.includes('a')).to.eql(false);
    });

    it('can ignore List entries', function() {
      var input = Immutable.List.of(1, 2, 3, 3, 'a');
      var result = filter.fromJSON(filter.toJSON(input));
      expect(result.includes('a')).to.eql(false);
    });

    it('can ignore Maps nested in Records', function() {
      var MyRecord = Immutable.Record({
        a: null,
        _b: 'bar'
      }, 'myRecord');

      var input = new MyRecord({a: Immutable.Map({_c: 1, d: 2}), _b: 'baz' });
      var recordFilter = transit
                          .withRecords([MyRecord])
                          .withFilter(filterFunction);

      var result = recordFilter.fromJSON(recordFilter.toJSON(input));

      expect(result.getIn(['a', 'd'])).to.eql(2);
      expect(result.getIn(['a', '_c'])).to.eql(undefined);
      expect(result.get('_b')).to.eql('baz');
    });

  });

  describe('Unknown Input', function() {
    it('fails when an unrecognized object is passed', function() {
      var MyObject = function() {};
      var MyObjectInstance = new MyObject();

      expect(function() {
        transit.toJSON(MyObjectInstance);
      }).to.throw();
    });
  });

});
<|endoftext|>


<commit_before>/**
  @module ember-flexberry
*/

import Ember from 'ember';
import FlexberryBaseComponent from './flexberry-base-component';
import { translationMacro as t } from 'ember-i18n';
const { getOwner } = Ember;

/**
  @class OlvToolbar
  @extends FlexberryBaseComponent
*/
export default FlexberryBaseComponent.extend({
  modelController: null,

  /**
    Route for edit form by click row.

    @property editFormRoute
    @type String
  */
  editFormRoute: undefined,

  /**
    Service that triggers objectlistview events.

    @property objectlistviewEventsService
    @type Service
  */
  objectlistviewEventsService: Ember.inject.service('objectlistview-events'),

  /**
    Flag to use creation button at toolbar.

    @property createNewButton
    @type Boolean
    @default false
  */
  createNewButton: false,

  /**
    Flag to specify whether the create button is enabled.

    @property enableCreateNewButton
    @type Boolean
    @default true
  */
  enableCreateNewButton: true,

  /**
    Flag to use refresh button at toolbar.

    @property refreshButton
    @type Boolean
    @default false
  */
  refreshButton: false,

  /**
    Flag to use delete button at toolbar.

    @property deleteButton
    @type Boolean
    @default false
  */
  deleteButton: false,

  /**
    Flag to use colsConfigButton button at toolbar.

    @property colsConfigButton
    @type Boolean
    @default false
  */
  colsConfigButton: true,

  /**
    Flag to use filter button at toolbar.

    @property filterButton
    @type Boolean
    @default false
  */
  filterButton: false,

  /**
    Used to specify default 'filter by any match' field text.

    @property filterText
    @type String
    @default null
  */
  filterText: null,

  /**
    The flag to specify whether the delete button is enabled.

    @property enableDeleteButton
    @type Boolean
    @default true
  */
  enableDeleteButton: true,

  /**
    Name of action to send out, action triggered by click on user button.

    @property customButtonAction
    @type String
    @default 'customButtonAction'
  */
  customButtonAction: 'customButtonAction',

  /**
    Array of custom buttons of special structures [{ buttonName: ..., buttonAction: ..., buttonClasses: ... }, {...}, ...].

    @example
      ```
      {
        buttonName: '...', // Button displayed name.
        buttonAction: '...', // Action that is called from controller on this button click (it has to be registered at component).
        buttonClasses: '...' // Css classes for button.
      }
      ```

    @property customButtonsArray
    @type Array
  */
  customButtons: undefined,

  /**
    @property listUserSettings
  */
  listUserSettings: undefined,

  /**
    @property createSettitingTitle
    @type String
    @default t('components.olv-toolbar.create-setting-title')
  */
  createSettitingTitle: t('components.olv-toolbar.create-setting-title'),

  /**
    @property useSettitingTitle
    @type String
    @default t('components.olv-toolbar.use-setting-title')
  */
  useSettitingTitle: t('components.olv-toolbar.use-setting-title'),

  /**
    @property editSettitingTitle
    @type String
    @default t('components.olv-toolbar.edit-setting-title')
  */
  editSettitingTitle: t('components.olv-toolbar.edit-setting-title'),

  /**
    @property removeSettitingTitle
    @type String
    @default t('components.olv-toolbar.remove-setting-title')
  */
  removeSettitingTitle: t('components.olv-toolbar.remove-setting-title'),

  /**
    @property setDefaultSettitingTitle
    @type String
    @default t('components.olv-toolbar.set-default-setting-title')
  */
  setDefaultSettitingTitle: t('components.olv-toolbar.set-default-setting-title'),

  /**
    @property colsConfigMenu
    @type Service
  */
  colsConfigMenu: Ember.inject.service(),

  /**
    @property listUserSettings
  */
  listNamedSettings: null,

  /**
    @property colsSettingsItems
    @readOnly
  */
  colsSettingsItems:  Ember.computed(
    'createSettitingTitle',
    'setDefaultSettitingTitle',
    'useSettitingTitle',
    'editSettitingTitle',
    'removeSettitingTitle',
    'listNamedSettings',
    function() {
      let params = {
        createSettitingTitle: this.get('createSettitingTitle'),
        setDefaultSettitingTitle: this.get('setDefaultSettitingTitle'),
        useSettitingTitle: this.get('useSettitingTitle'),
        editSettitingTitle: this.get('editSettitingTitle'),
        removeSettitingTitle: this.get('removeSettitingTitle'),
        listNamedSettings: this.get('listNamedSettings'),
      };

      return this.get('userSettingsService').isUserSettingsServiceEnabled ?
        this.get('colsConfigMenu').resetMenu(params) :
        [];
    }
  ),

  /**
    Flag shows enable-state of delete button.
    If there are selected rows button is enabled. Otherwise - not.

    @property isDeleteButtonEnabled
    @type Boolean
    @default false
  */
  isDeleteButtonEnabled: false,

  /**
    Stores the text from "Filter by any match" input field.

    @property filterByAnyMatchText
    @type String
  */
  filterByAnyMatchText: Ember.computed.oneWay('filterText'),

  actions: {
    /**
      Handles action from object-list-view when no handler for this component is defined.

      @method actions.refresh
      @public
    */
    refresh() {
      this.get('modelController').send('refreshList');
    },

    /**
      Handles action from object-list-view when no handler for this component is defined.

      @method actions.createNew
      @public
    */
    createNew() {
      let editFormRoute = this.get('editFormRoute');
      let modelController = this.get('modelController');
      modelController.transitionToRoute(editFormRoute + '.new');
    },

    /**
      Delete selected rows.

      @method actions.delete
      @public
    */
    delete() {
      let confirmDeleteRows = this.get('confirmDeleteRows');
      if (confirmDeleteRows) {
        Ember.assert('Error: confirmDeleteRows must be a function.', typeof confirmDeleteRows === 'function');
        if (!confirmDeleteRows()) {
          return;
        }
      }

      let componentName = this.get('componentName');
      this.get('objectlistviewEventsService').deleteRowsTrigger(componentName, true);
    },

    /**
      Filters the content by "Filter by any match" field value.

      @method actions.filterByAnyMatch
      @public
    */
    filterByAnyMatch() {
      let componentName = this.get('componentName');
      this.get('objectlistviewEventsService').filterByAnyMatchTrigger(componentName, this.get('filterByAnyMatchText'));
    },

    /**
      Remove filter from url.

      @method actions.removeFilter
      @public
    */
    removeFilter() {
      this.set('filterText', null);
    },

    /**
      Action for custom button.

      @method actions.customButtonAction
      @public
      @param {String} actionName The name of action
    */
    customButtonAction(actionName) {
      this.sendAction('customButtonAction', actionName);
    },

    /**
      Action to show confis dialog.

      @method actions.showConfigDialog
      @public
    */
    showConfigDialog() {
      this.get('modelController').send('showConfigDialog');
    },

    /**
      Handler click on flexberry-menu.

      @method actions.onMenuItemClick
      @public
      @param {jQuery.Event} e jQuery.Event by click on menu item
    */
    onMenuItemClick(e) {
      let iTags = Ember.$(e.currentTarget).find('i');
      let namedSetingSpans = Ember.$(e.currentTarget).find('span');
      if (iTags.length <= 0 || namedSetingSpans.length <= 0) {
        return;
      }

      this._router = getOwner(this).lookup('router:main');
      let className = iTags.get(0).className;
      let namedSeting = namedSetingSpans.get(0).innerText;
      let moduleName  =   this._router.currentRouteName;
      let userSettingsService = this.get('userSettingsService');

      switch (className) {
        case 'table icon':
          this.send('showConfigDialog');
          break;
        case 'checkmark box icon':

          //TODO move this code and  _getSavePromise@addon/components/colsconfig-dialog-content.js to addon/components/colsconfig-dialog-content.js
          let colsConfig = this.listUserSettings[namedSeting];
          userSettingsService.saveUserSetting({
            moduleName: moduleName,
            settingName: 'DEFAULT',
            userSetting: colsConfig
          }).then(record => {
            if (this._router.location.location.href.indexOf('sort=') >= 0) { // sort parameter exist in URL (ugly - TODO find sort in query parameters)
              this._router.router.transitionTo(this._router.currentRouteName, { queryParams: { sort: null } }); // Show page without sort parameters
            } else {
              this._router.router.refresh();  //Reload current page and records (model) list
            }
          });
          break;
        case 'setting icon':
          this.send('showConfigDialog', namedSeting);
          break;
        case 'remove icon':
          userSettingsService.deleteUserSetting({
            moduleName: moduleName,
            settingName: namedSeting
          }).then(result => {
            this.get('colsConfigMenu').deleteNamedSettingTrigger(namedSeting);
            alert('Настройка ' + namedSeting + ' удалена');
          });
          break;
        case 'remove circle icon':
          userSettingsService.deleteUserSetting({
            moduleName: moduleName,
            settingName: 'DEFAULT'
          }).then(record => {
            if (this._router.location.location.href.indexOf('sort=') >= 0) { // sort parameter exist in URL (ugly - TODO find sort in query parameters)
              this._router.router.transitionTo(this._router.currentRouteName, { queryParams: { sort: null } }); // Show page without sort parameters
            } else {
              this._router.router.refresh();  //Reload current page and records (model) list
            }
          });
          break;
      }
    }
  },

  /**
    An overridable method called when objects are instantiated.
    For more information see [init](http://emberjs.com/api/classes/Ember.View.html#method_init) method of [Ember.View](http://emberjs.com/api/classes/Ember.View.html).
  */
  init() {
    this._super(...arguments);

    let componentName = this.get('componentName');
    if (this.get('deleteButton') === true && !componentName) {
      throw new Error('Name of flexberry-objectlictview component was not defined.');
    }

    this.get('objectlistviewEventsService').on('olvRowSelected', this, this._rowSelected);
    this.get('objectlistviewEventsService').on('olvRowsDeleted', this, this._rowsDeleted);

    this.get('colsConfigMenu').on('addNamedSetting', this, this._addNamedSetting);
    this.get('colsConfigMenu').on('deleteNamedSetting', this, this._deleteNamedSetting);
  },

  didReceiveAttrs() {
    this._super(...arguments);
    let listUserSettings = this.modelController.model.listUserSettings;
    if (listUserSettings && 'DEFAULT' in listUserSettings) {
      delete listUserSettings.DEFAULT;
    }

    this.listUserSettings = listUserSettings;
    Ember.set(this, 'listNamedSettings', {});
    if (listUserSettings) {
      for (let nameSetting in listUserSettings) {
        Ember.set(this.listNamedSettings, nameSetting, true);
      }
    }
  },

  /**
    Override to implement teardown.
    For more information see [willDestroy](http://emberjs.com/api/classes/Ember.Component.html#method_willDestroy) method of [Ember.Component](http://emberjs.com/api/classes/Ember.Component.html).
  */
  willDestroy() {
    this.get('objectlistviewEventsService').off('olvRowSelected', this, this._rowSelected);
    this.get('objectlistviewEventsService').off('olvRowsDeleted', this, this._rowsDeleted);
    this.get('colsConfigMenu').off('addNamedSetting', this, this._addNamedSetting);
    this.get('colsConfigMenu').off('deleteNamedSetting', this, this._deleteNamedSetting);
    this._super(...arguments);
  },

  /**
    Event handler for "row has been selected" event in objectlistview.

    @method _rowSelected
    @private

    @param {String} componentName The name of objectlistview component
    @param {DS.Model} record The model corresponding to selected row in objectlistview
    @param {Number} count Count of selected rows in objectlistview
  */
  _rowSelected(componentName, record, count) {
    if (componentName === this.get('componentName')) {
      this.set('isDeleteButtonEnabled', count > 0 && this.get('enableDeleteButton'));
    }
  },

  _addNamedSetting(namedSeting) {
    let listNamedSettings = JSON.parse(JSON.stringify(this.listNamedSettings));
    listNamedSettings[namedSeting] = true;
    Ember.set(this, 'listNamedSettings', listNamedSettings);
  },

  _deleteNamedSetting(namedSeting) {
    let listNamedSettings = JSON.parse(JSON.stringify(this.listNamedSettings));
    delete listNamedSettings[namedSeting];
    Ember.set(this, 'listNamedSettings', listNamedSettings);
  },
});
<commit_msg>Reset support edit named settings<commit_after>/**
  @module ember-flexberry
*/

import Ember from 'ember';
import FlexberryBaseComponent from './flexberry-base-component';
import { translationMacro as t } from 'ember-i18n';
const { getOwner } = Ember;

/**
  @class OlvToolbar
  @extends FlexberryBaseComponent
*/
export default FlexberryBaseComponent.extend({
  modelController: null,

  /**
    Route for edit form by click row.

    @property editFormRoute
    @type String
  */
  editFormRoute: undefined,

  /**
    Service that triggers objectlistview events.

    @property objectlistviewEventsService
    @type Service
  */
  objectlistviewEventsService: Ember.inject.service('objectlistview-events'),

  /**
    Flag to use creation button at toolbar.

    @property createNewButton
    @type Boolean
    @default false
  */
  createNewButton: false,

  /**
    Flag to specify whether the create button is enabled.

    @property enableCreateNewButton
    @type Boolean
    @default true
  */
  enableCreateNewButton: true,

  /**
    Flag to use refresh button at toolbar.

    @property refreshButton
    @type Boolean
    @default false
  */
  refreshButton: false,

  /**
    Flag to use delete button at toolbar.

    @property deleteButton
    @type Boolean
    @default false
  */
  deleteButton: false,

  /**
    Flag to use colsConfigButton button at toolbar.

    @property colsConfigButton
    @type Boolean
    @default false
  */
  colsConfigButton: true,

  /**
    Flag to use filter button at toolbar.

    @property filterButton
    @type Boolean
    @default false
  */
  filterButton: false,

  /**
    Used to specify default 'filter by any match' field text.

    @property filterText
    @type String
    @default null
  */
  filterText: null,

  /**
    The flag to specify whether the delete button is enabled.

    @property enableDeleteButton
    @type Boolean
    @default true
  */
  enableDeleteButton: true,

  /**
    Name of action to send out, action triggered by click on user button.

    @property customButtonAction
    @type String
    @default 'customButtonAction'
  */
  customButtonAction: 'customButtonAction',

  /**
    Array of custom buttons of special structures [{ buttonName: ..., buttonAction: ..., buttonClasses: ... }, {...}, ...].

    @example
      ```
      {
        buttonName: '...', // Button displayed name.
        buttonAction: '...', // Action that is called from controller on this button click (it has to be registered at component).
        buttonClasses: '...' // Css classes for button.
      }
      ```

    @property customButtonsArray
    @type Array
  */
  customButtons: undefined,

  /**
    @property listUserSettings
  */
  listUserSettings: undefined,

  /**
    @property createSettitingTitle
    @type String
    @default t('components.olv-toolbar.create-setting-title')
  */
  createSettitingTitle: t('components.olv-toolbar.create-setting-title'),

  /**
    @property useSettitingTitle
    @type String
    @default t('components.olv-toolbar.use-setting-title')
  */
  useSettitingTitle: t('components.olv-toolbar.use-setting-title'),

  /**
    @property editSettitingTitle
    @type String
    @default t('components.olv-toolbar.edit-setting-title')
  */
  editSettitingTitle: t('components.olv-toolbar.edit-setting-title'),

  /**
    @property removeSettitingTitle
    @type String
    @default t('components.olv-toolbar.remove-setting-title')
  */
  removeSettitingTitle: t('components.olv-toolbar.remove-setting-title'),

  /**
    @property setDefaultSettitingTitle
    @type String
    @default t('components.olv-toolbar.set-default-setting-title')
  */
  setDefaultSettitingTitle: t('components.olv-toolbar.set-default-setting-title'),

  /**
    @property colsConfigMenu
    @type Service
  */
  colsConfigMenu: Ember.inject.service(),

  /**
    @property listUserSettings
  */
  listNamedSettings: null,

  /**
    @property colsSettingsItems
    @readOnly
  */
  colsSettingsItems:  Ember.computed(
    'createSettitingTitle',
    'setDefaultSettitingTitle',
    'useSettitingTitle',
    'editSettitingTitle',
    'removeSettitingTitle',
    'listNamedSettings',
    function() {
      let params = {
        createSettitingTitle: this.get('createSettitingTitle'),
        setDefaultSettitingTitle: this.get('setDefaultSettitingTitle'),
        useSettitingTitle: this.get('useSettitingTitle'),
        editSettitingTitle: this.get('editSettitingTitle'),
        removeSettitingTitle: this.get('removeSettitingTitle'),
        listNamedSettings: this.get('listNamedSettings'),
      };

      return this.get('userSettingsService').isUserSettingsServiceEnabled ?
        this.get('colsConfigMenu').resetMenu(params) :
        [];
    }
  ),

  /**
    Flag shows enable-state of delete button.
    If there are selected rows button is enabled. Otherwise - not.

    @property isDeleteButtonEnabled
    @type Boolean
    @default false
  */
  isDeleteButtonEnabled: false,

  /**
    Stores the text from "Filter by any match" input field.

    @property filterByAnyMatchText
    @type String
  */
  filterByAnyMatchText: Ember.computed.oneWay('filterText'),

  actions: {
    /**
      Handles action from object-list-view when no handler for this component is defined.

      @method actions.refresh
      @public
    */
    refresh() {
      this.get('modelController').send('refreshList');
    },

    /**
      Handles action from object-list-view when no handler for this component is defined.

      @method actions.createNew
      @public
    */
    createNew() {
      let editFormRoute = this.get('editFormRoute');
      let modelController = this.get('modelController');
      modelController.transitionToRoute(editFormRoute + '.new');
    },

    /**
      Delete selected rows.

      @method actions.delete
      @public
    */
    delete() {
      let confirmDeleteRows = this.get('confirmDeleteRows');
      if (confirmDeleteRows) {
        Ember.assert('Error: confirmDeleteRows must be a function.', typeof confirmDeleteRows === 'function');
        if (!confirmDeleteRows()) {
          return;
        }
      }

      let componentName = this.get('componentName');
      this.get('objectlistviewEventsService').deleteRowsTrigger(componentName, true);
    },

    /**
      Filters the content by "Filter by any match" field value.

      @method actions.filterByAnyMatch
      @public
    */
    filterByAnyMatch() {
      let componentName = this.get('componentName');
      this.get('objectlistviewEventsService').filterByAnyMatchTrigger(componentName, this.get('filterByAnyMatchText'));
    },

    /**
      Remove filter from url.

      @method actions.removeFilter
      @public
    */
    removeFilter() {
      this.set('filterText', null);
    },

    /**
      Action for custom button.

      @method actions.customButtonAction
      @public
      @param {String} actionName The name of action
    */
    customButtonAction(actionName) {
      this.sendAction('customButtonAction', actionName);
    },

    /**
      Action to show confis dialog.

      @method actions.showConfigDialog
      @public
    */
    showConfigDialog(settingName) {
      this.get('modelController').send('showConfigDialog', settingName);
    },

    /**
      Handler click on flexberry-menu.

      @method actions.onMenuItemClick
      @public
      @param {jQuery.Event} e jQuery.Event by click on menu item
    */
    onMenuItemClick(e) {
      let iTags = Ember.$(e.currentTarget).find('i');
      let namedSettingSpans = Ember.$(e.currentTarget).find('span');
      if (iTags.length <= 0 || namedSettingSpans.length <= 0) {
        return;
      }

      this._router = getOwner(this).lookup('router:main');
      let className = iTags.get(0).className;
      let namedSetting = namedSettingSpans.get(0).innerText;
      let moduleName  =   this._router.currentRouteName;
      let userSettingsService = this.get('userSettingsService');

      switch (className) {
        case 'table icon':
          this.send('showConfigDialog');
          break;
        case 'checkmark box icon':

          //TODO move this code and  _getSavePromise@addon/components/colsconfig-dialog-content.js to addon/components/colsconfig-dialog-content.js
          let colsConfig = this.listUserSettings[namedSetting];
          userSettingsService.saveUserSetting({
            moduleName: moduleName,
            settingName: 'DEFAULT',
            userSetting: colsConfig
          }).then(record => {
            if (this._router.location.location.href.indexOf('sort=') >= 0) { // sort parameter exist in URL (ugly - TODO find sort in query parameters)
              this._router.router.transitionTo(this._router.currentRouteName, { queryParams: { sort: null } }); // Show page without sort parameters
            } else {
              this._router.router.refresh();  //Reload current page and records (model) list
            }
          });
          break;
        case 'setting icon':
          this.send('showConfigDialog', namedSetting);
          break;
        case 'remove icon':
          userSettingsService.deleteUserSetting({
            moduleName: moduleName,
            settingName: namedSetting
          }).then(result => {
            this.get('colsConfigMenu').deleteNamedSettingTrigger(namedSetting);
            alert('Настройка ' + namedSetting + ' удалена');
          });
          break;
        case 'remove circle icon':
          userSettingsService.deleteUserSetting({
            moduleName: moduleName,
            settingName: 'DEFAULT'
          }).then(record => {
            if (this._router.location.location.href.indexOf('sort=') >= 0) { // sort parameter exist in URL (ugly - TODO find sort in query parameters)
              this._router.router.transitionTo(this._router.currentRouteName, { queryParams: { sort: null } }); // Show page without sort parameters
            } else {
              this._router.router.refresh();  //Reload current page and records (model) list
            }
          });
          break;
      }
    }
  },

  /**
    An overridable method called when objects are instantiated.
    For more information see [init](http://emberjs.com/api/classes/Ember.View.html#method_init) method of [Ember.View](http://emberjs.com/api/classes/Ember.View.html).
  */
  init() {
    this._super(...arguments);

    let componentName = this.get('componentName');
    if (this.get('deleteButton') === true && !componentName) {
      throw new Error('Name of flexberry-objectlictview component was not defined.');
    }

    this.get('objectlistviewEventsService').on('olvRowSelected', this, this._rowSelected);
    this.get('objectlistviewEventsService').on('olvRowsDeleted', this, this._rowsDeleted);

    this.get('colsConfigMenu').on('addNamedSetting', this, this._addNamedSetting);
    this.get('colsConfigMenu').on('deleteNamedSetting', this, this._deleteNamedSetting);
  },

  didReceiveAttrs() {
    this._super(...arguments);
    let listUserSettings = this.modelController.model.listUserSettings;
    if (listUserSettings && 'DEFAULT' in listUserSettings) {
      delete listUserSettings.DEFAULT;
    }

    this.listUserSettings = listUserSettings;
    Ember.set(this, 'listNamedSettings', {});
    if (listUserSettings) {
      for (let nameSetting in listUserSettings) {
        Ember.set(this.listNamedSettings, nameSetting, true);
      }
    }
  },

  /**
    Override to implement teardown.
    For more information see [willDestroy](http://emberjs.com/api/classes/Ember.Component.html#method_willDestroy) method of [Ember.Component](http://emberjs.com/api/classes/Ember.Component.html).
  */
  willDestroy() {
    this.get('objectlistviewEventsService').off('olvRowSelected', this, this._rowSelected);
    this.get('objectlistviewEventsService').off('olvRowsDeleted', this, this._rowsDeleted);
    this.get('colsConfigMenu').off('addNamedSetting', this, this._addNamedSetting);
    this.get('colsConfigMenu').off('deleteNamedSetting', this, this._deleteNamedSetting);
    this._super(...arguments);
  },

  /**
    Event handler for "row has been selected" event in objectlistview.

    @method _rowSelected
    @private

    @param {String} componentName The name of objectlistview component
    @param {DS.Model} record The model corresponding to selected row in objectlistview
    @param {Number} count Count of selected rows in objectlistview
  */
  _rowSelected(componentName, record, count) {
    if (componentName === this.get('componentName')) {
      this.set('isDeleteButtonEnabled', count > 0 && this.get('enableDeleteButton'));
    }
  },

  _addNamedSetting(namedSetting) {
    let listNamedSettings = JSON.parse(JSON.stringify(this.listNamedSettings));
    listNamedSettings[namedSetting] = true;
    Ember.set(this, 'listNamedSettings', listNamedSettings);
  },

  _deleteNamedSetting(namedSetting) {
    let listNamedSettings = JSON.parse(JSON.stringify(this.listNamedSettings));
    delete listNamedSettings[namedSetting];
    Ember.set(this, 'listNamedSettings', listNamedSettings);
  },
});
<|endoftext|>


<commit_before>/*!
 * Module exports class Model
 */
module.exports = ModelBaseClass;

/*!
 * Module dependencies
 */

var util = require('util');
var jutil = require('./jutil');
var List = require('./list');
var Hookable = require('./hooks');
var validations = require('./validations');
var _extend = util._extend;

// Set up an object for quick lookup
var BASE_TYPES = {
  'String': true,
  'Boolean': true,
  'Number': true,
  'Date': true,
  'Text': true,
  'ObjectID': true
};

/**
 * Model class: base class for all persistent objects.
 *
 * `ModelBaseClass` mixes `Validatable` and `Hookable` classes methods
 *
 * @class
 * @param {Object} data Initial object data
 */
function ModelBaseClass(data, options) {
  options = options || {};
  if(!('applySetters' in options)) {
    // Default to true
    options.applySetters = true;
  }
  this._initProperties(data, options);
}

/**
 * Initialize the model instance with a list of properties
 * @param {Object} data The data object
 * @param {Object} options An object to control the instantiation
 * @property {Boolean} applySetters Controls if the setters will be applied
 * @property {Boolean} strict Set the instance level strict mode
 * @property {Boolean} persisted Whether the instance has been persisted
 * @private
 */
ModelBaseClass.prototype._initProperties = function (data, options) {
  var self = this;
  var ctor = this.constructor;

  if(data instanceof ctor) {
    // Convert the data to be plain object to avoid pollutions
    data = data.toObject(false);
  }
  var properties = _extend({}, ctor.definition.properties);
  data = data || {};

  if (typeof ctor.applyProperties === 'function') {
    ctor.applyProperties(data);
  }

  options = options || {};
  var applySetters = options.applySetters;
  var strict = options.strict;

  if(strict === undefined) {
    strict = ctor.definition.settings.strict;
  }

  if (ctor.hideInternalProperties) {
    // Object.defineProperty() is expensive. We only try to make the internal
    // properties hidden (non-enumerable) if the model class has the
    // `hideInternalProperties` set to true
    Object.defineProperties(this, {
      __cachedRelations: {
        writable: true,
        enumerable: false,
        configurable: true,
        value: {}
      },

      __data: {
        writable: true,
        enumerable: false,
        configurable: true,
        value: {}
      },

      // Instance level data source
      __dataSource: {
        writable: true,
        enumerable: false,
        configurable: true,
        value: options.dataSource
      },

      // Instance level strict mode
      __strict: {
        writable: true,
        enumerable: false,
        configurable: true,
        value: strict
      },

      __persisted: {
        writable: true,
        enumerable: false,
        configurable: true,
        value: false
      }
    });
  } else {
    this.__cachedRelations = {};
    this.__data = {};
    this.__dataSource = options.dataSource;
    this.__strict = strict;
    this.__persisted = false;
  }

  if (options.persisted !== undefined) {
    this.__persisted = options.persisted === true;
  }

  if (data.__cachedRelations) {
    this.__cachedRelations = data.__cachedRelations;
  }

  var keys = Object.keys(data);

  if (Array.isArray(options.fields)) {
    keys = keys.filter(function(k) {
      return (options.fields.indexOf(k) != -1);
    });
  }

  var size = keys.length;
  var p, propVal;
  for (var k = 0; k < size; k++) {
    p = keys[k];
    propVal = data[p];
    if (typeof propVal === 'function') {
      continue;
    }
    if (properties[p]) {
      // Managed property
      if (applySetters || properties[p].id) {
        self[p] = propVal;
      } else {
        self.__data[p] = propVal;
      }
    } else if (ctor.relations[p]) {
      var relationType = ctor.relations[p].type;

      if (!properties[p]) {
        var modelTo = ctor.relations[p].modelTo || ModelBaseClass;
        var multiple = ctor.relations[p].multiple;
        var typeName = multiple ? 'Array' : modelTo.modelName;
        var propType = multiple ? [modelTo] : modelTo;
        properties[p] = { name: typeName, type: propType };
        this.setStrict(false);
      }

      // Relation
      if (relationType === 'belongsTo' && propVal != null) {
        // If the related model is populated
        self.__data[ctor.relations[p].keyFrom] = propVal[ctor.relations[p].keyTo];
      }
      self.__cachedRelations[p] = propVal;
    } else {
      // Un-managed property
      if (strict === false || self.__cachedRelations[p]) {
        self[p] = self.__data[p] =
          (propVal !== undefined) ? propVal : self.__cachedRelations[p];
      } else if (strict === 'throw') {
        throw new Error('Unknown property: ' + p);
      }
    }
  }

  keys = Object.keys(properties);

  if (Array.isArray(options.fields)) {
    keys = keys.filter(function(k) {
      return (options.fields.indexOf(k) != -1);
    });
  }

  size = keys.length;

  for (k = 0; k < size; k++) {
    p = keys[k];
    propVal = self.__data[p];

    // Set default values
    if (propVal === undefined) {
      var def = properties[p]['default'];
      if (def !== undefined) {
        if (typeof def === 'function') {
          if (def === Date) {
            // FIXME: We should coerce the value in general
            // This is a work around to {default: Date}
            // Date() will return a string instead of Date
            def = new Date();
          } else {
            def = def();
          }
        }
        // FIXME: We should coerce the value
        // will implement it after we refactor the PropertyDefinition
        self.__data[p] = def;
      }
    }

    // Handle complex types (JSON/Object)
    var type = properties[p].type;
    if (!BASE_TYPES[type.name]) {

      if (typeof self.__data[p] !== 'object' && self.__data[p]) {
        try {
          self.__data[p] = JSON.parse(self.__data[p] + '');
        } catch (e) {
          self.__data[p] = String(self.__data[p]);
        }
      }

      if (type.prototype instanceof ModelBaseClass) {
        if (!(self.__data[p] instanceof type)
          && typeof self.__data[p] === 'object'
          && self.__data[p] !== null ) {
          self.__data[p] = new type(self.__data[p]);
        }
      } else if (type.name === 'Array' || Array.isArray(type)) {
        if (!(self.__data[p] instanceof List)
          && self.__data[p] !== undefined
          && self.__data[p] !== null ) {
          self.__data[p] = List(self.__data[p], type, self);
        }
      }
    }
  }
  this.trigger('initialize');
};

/**
 * Define a property on the model.
 * @param {String} prop Property name
 * @param {Object} params Various property configuration
 */
ModelBaseClass.defineProperty = function (prop, params) {
  if(this.dataSource) {
    this.dataSource.defineProperty(this.modelName, prop, params);
  } else {
    this.modelBuilder.defineProperty(this.modelName, prop, params);
  }
};

ModelBaseClass.getPropertyType = function (propName) {
  var prop = this.definition.properties[propName];
  if (!prop) {
    // The property is not part of the definition
    return null;
  }
  if (!prop.type) {
    throw new Error('Type not defined for property ' + this.modelName + '.' + propName);
    // return null;
  }
  return prop.type.name;
};

ModelBaseClass.prototype.getPropertyType = function (propName) {
  return this.constructor.getPropertyType(propName);
};

/**
 * Return string representation of class
 * This overrides the default `toString()` method
 */
ModelBaseClass.toString = function () {
  return '[Model ' + this.modelName + ']';
};

/**
 * Convert model instance to a plain JSON object.
 * Returns a canonical object representation (no getters and setters).
 *
 * @param {Boolean} onlySchema Restrict properties to dataSource only.  Default is false.  If true, the function returns only properties defined in the schema;  Otherwise it returns all enumerable properties.
 */
ModelBaseClass.prototype.toObject = function (onlySchema, removeHidden) {
  if (onlySchema === undefined) {
    onlySchema = true;
  }
  var data = {};
  var self = this;
  var Model = this.constructor;

  // if it is already an Object
  if (Model === Object) {
    return self;
  }

  var strict = this.__strict;
  var schemaLess = (strict === false) || !onlySchema;

  var props = Model.definition.properties;
  var keys = Object.keys(props);
  var propertyName, val;
  for (var i = 0; i < keys.length; i++) {
    propertyName = keys[i];
    val = self[propertyName];

    // Exclude functions
    if (typeof val === 'function') {
      continue;
    }
    // Exclude hidden properties
    if (removeHidden && Model.isHiddenProperty(propertyName)) {
      continue;
    }

    if (val instanceof List) {
      data[propertyName] = val.toObject(!schemaLess, removeHidden);
    } else {
      if (val !== undefined && val !== null && val.toObject) {
        data[propertyName] = val.toObject(!schemaLess, removeHidden);
      } else {
        data[propertyName] = val;
      }
    }
  }

  if (schemaLess) {
    // Find its own properties which can be set via myModel.myProperty = 'myValue'.
    // If the property is not declared in the model definition, no setter will be
    // triggered to add it to __data
    keys = Object.keys(self);
    var size = keys.length;
    for (i = 0; i < size; i++) {
      propertyName = keys[i];
      if (props[propertyName]) {
        continue;
      }
      if (propertyName.indexOf('__') === 0) {
        continue;
      }
      if (removeHidden && Model.isHiddenProperty(propertyName)) {
        continue;
      }
      val = self[propertyName];
      if (val !== undefined && data[propertyName] === undefined) {
        if (typeof val === 'function') {
          continue;
        }
        if (val !== null && val.toObject) {
          data[propertyName] = val.toObject(!schemaLess, removeHidden);
        } else {
          data[propertyName] = val;
        }
      }
    }
    // Now continue to check __data
    keys = Object.keys(self.__data);
    size = keys.length;
    for (i = 0; i < size; i++) {
      propertyName = keys[i];
      if (propertyName.indexOf('__') === 0) {
        continue;
      }
      if (data[propertyName] === undefined) {
        if (removeHidden && Model.isHiddenProperty(propertyName)) {
          continue;
        }
        var ownVal = self[propertyName];
        // The ownVal can be a relation function
        val = (ownVal !== undefined && (typeof ownVal !== 'function'))
          ? ownVal : self.__data[propertyName];
        if (typeof val === 'function') {
          continue;
        }

        if (val !== undefined && val !== null && val.toObject) {
          data[propertyName] = val.toObject(!schemaLess, removeHidden);
        } else {
          data[propertyName] = val;
        }
      }
    }
  }

  return data;
};

ModelBaseClass.isHiddenProperty = function (propertyName) {
  var Model = this;
  var settings = Model.definition && Model.definition.settings;
  var hiddenProperties = settings && (settings.hiddenProperties || settings.hidden);
  if (Array.isArray(hiddenProperties)) {
    // Cache the hidden properties as an object for quick lookup
    settings.hiddenProperties = {};
    for (var i = 0; i < hiddenProperties.length; i++) {
      settings.hiddenProperties[hiddenProperties[i]] = true;
    }
    hiddenProperties = settings.hiddenProperties;
  }
  if (hiddenProperties) {
    return hiddenProperties[propertyName];
  } else {
    return false;
  }
}

ModelBaseClass.prototype.toJSON = function () {
  return this.toObject(false, true);
};

ModelBaseClass.prototype.fromObject = function (obj) {
  for (var key in obj) {
    this[key] = obj[key];
  }
};

/**
 * Reset dirty attributes.
 * This method does not perform any database operations; it just resets the object to its
 * initial state.
 */
ModelBaseClass.prototype.reset = function () {
  var obj = this;
  for (var k in obj) {
    if (k !== 'id' && !obj.constructor.dataSource.definitions[obj.constructor.modelName].properties[k]) {
      delete obj[k];
    }
  }
};

// Node v0.11+ allows custom inspect functions to return an object
// instead of string. That way options like `showHidden` and `colors`
// can be preserved.
var versionParts = process.versions.node
  .split(/\./g).map(function(v) { return +v; });

var INSPECT_SUPPORTS_OBJECT_RETVAL =
 versionParts[0] > 0 ||
 versionParts[1] > 11 ||
 (versionParts[0] === 11 && versionParts[1] >= 14);

ModelBaseClass.prototype.inspect = function (depth) {
  if (INSPECT_SUPPORTS_OBJECT_RETVAL)
     return this.__data;

  // Workaround for older versions
  // See also https://github.com/joyent/node/commit/66280de133
  return util.inspect(this.__data, {
    showHidden: false,
    depth: depth,
    colors: false
  });
};

ModelBaseClass.mixin = function (anotherClass, options) {
  if (typeof anotherClass === 'string') {
    this.modelBuilder.mixins.applyMixin(this, anotherClass, options);
  } else {
    if (anotherClass.prototype instanceof ModelBaseClass) {
      var props = anotherClass.definition.properties;
      for (var i in props) {
        if (this.definition.properties[i]) {
          continue;
        }
        this.defineProperty(i, props[i]);
      }
    }
    return jutil.mixin(this, anotherClass, options);
  }
};

ModelBaseClass.prototype.getDataSource = function () {
  return this.__dataSource || this.constructor.dataSource;
};

ModelBaseClass.getDataSource = function () {
  return this.dataSource;
};

ModelBaseClass.prototype.setStrict = function (strict) {
  this.__strict = strict;
};

jutil.mixin(ModelBaseClass, Hookable);
jutil.mixin(ModelBaseClass, validations.Validatable);
<commit_msg>Fix detection of `util.inspect` version<commit_after>/*!
 * Module exports class Model
 */
module.exports = ModelBaseClass;

/*!
 * Module dependencies
 */

var util = require('util');
var jutil = require('./jutil');
var List = require('./list');
var Hookable = require('./hooks');
var validations = require('./validations');
var _extend = util._extend;

// Set up an object for quick lookup
var BASE_TYPES = {
  'String': true,
  'Boolean': true,
  'Number': true,
  'Date': true,
  'Text': true,
  'ObjectID': true
};

/**
 * Model class: base class for all persistent objects.
 *
 * `ModelBaseClass` mixes `Validatable` and `Hookable` classes methods
 *
 * @class
 * @param {Object} data Initial object data
 */
function ModelBaseClass(data, options) {
  options = options || {};
  if(!('applySetters' in options)) {
    // Default to true
    options.applySetters = true;
  }
  this._initProperties(data, options);
}

/**
 * Initialize the model instance with a list of properties
 * @param {Object} data The data object
 * @param {Object} options An object to control the instantiation
 * @property {Boolean} applySetters Controls if the setters will be applied
 * @property {Boolean} strict Set the instance level strict mode
 * @property {Boolean} persisted Whether the instance has been persisted
 * @private
 */
ModelBaseClass.prototype._initProperties = function (data, options) {
  var self = this;
  var ctor = this.constructor;

  if(data instanceof ctor) {
    // Convert the data to be plain object to avoid pollutions
    data = data.toObject(false);
  }
  var properties = _extend({}, ctor.definition.properties);
  data = data || {};

  if (typeof ctor.applyProperties === 'function') {
    ctor.applyProperties(data);
  }

  options = options || {};
  var applySetters = options.applySetters;
  var strict = options.strict;

  if(strict === undefined) {
    strict = ctor.definition.settings.strict;
  }

  if (ctor.hideInternalProperties) {
    // Object.defineProperty() is expensive. We only try to make the internal
    // properties hidden (non-enumerable) if the model class has the
    // `hideInternalProperties` set to true
    Object.defineProperties(this, {
      __cachedRelations: {
        writable: true,
        enumerable: false,
        configurable: true,
        value: {}
      },

      __data: {
        writable: true,
        enumerable: false,
        configurable: true,
        value: {}
      },

      // Instance level data source
      __dataSource: {
        writable: true,
        enumerable: false,
        configurable: true,
        value: options.dataSource
      },

      // Instance level strict mode
      __strict: {
        writable: true,
        enumerable: false,
        configurable: true,
        value: strict
      },

      __persisted: {
        writable: true,
        enumerable: false,
        configurable: true,
        value: false
      }
    });
  } else {
    this.__cachedRelations = {};
    this.__data = {};
    this.__dataSource = options.dataSource;
    this.__strict = strict;
    this.__persisted = false;
  }

  if (options.persisted !== undefined) {
    this.__persisted = options.persisted === true;
  }

  if (data.__cachedRelations) {
    this.__cachedRelations = data.__cachedRelations;
  }

  var keys = Object.keys(data);

  if (Array.isArray(options.fields)) {
    keys = keys.filter(function(k) {
      return (options.fields.indexOf(k) != -1);
    });
  }

  var size = keys.length;
  var p, propVal;
  for (var k = 0; k < size; k++) {
    p = keys[k];
    propVal = data[p];
    if (typeof propVal === 'function') {
      continue;
    }
    if (properties[p]) {
      // Managed property
      if (applySetters || properties[p].id) {
        self[p] = propVal;
      } else {
        self.__data[p] = propVal;
      }
    } else if (ctor.relations[p]) {
      var relationType = ctor.relations[p].type;

      if (!properties[p]) {
        var modelTo = ctor.relations[p].modelTo || ModelBaseClass;
        var multiple = ctor.relations[p].multiple;
        var typeName = multiple ? 'Array' : modelTo.modelName;
        var propType = multiple ? [modelTo] : modelTo;
        properties[p] = { name: typeName, type: propType };
        this.setStrict(false);
      }

      // Relation
      if (relationType === 'belongsTo' && propVal != null) {
        // If the related model is populated
        self.__data[ctor.relations[p].keyFrom] = propVal[ctor.relations[p].keyTo];
      }
      self.__cachedRelations[p] = propVal;
    } else {
      // Un-managed property
      if (strict === false || self.__cachedRelations[p]) {
        self[p] = self.__data[p] =
          (propVal !== undefined) ? propVal : self.__cachedRelations[p];
      } else if (strict === 'throw') {
        throw new Error('Unknown property: ' + p);
      }
    }
  }

  keys = Object.keys(properties);

  if (Array.isArray(options.fields)) {
    keys = keys.filter(function(k) {
      return (options.fields.indexOf(k) != -1);
    });
  }

  size = keys.length;

  for (k = 0; k < size; k++) {
    p = keys[k];
    propVal = self.__data[p];

    // Set default values
    if (propVal === undefined) {
      var def = properties[p]['default'];
      if (def !== undefined) {
        if (typeof def === 'function') {
          if (def === Date) {
            // FIXME: We should coerce the value in general
            // This is a work around to {default: Date}
            // Date() will return a string instead of Date
            def = new Date();
          } else {
            def = def();
          }
        }
        // FIXME: We should coerce the value
        // will implement it after we refactor the PropertyDefinition
        self.__data[p] = def;
      }
    }

    // Handle complex types (JSON/Object)
    var type = properties[p].type;
    if (!BASE_TYPES[type.name]) {

      if (typeof self.__data[p] !== 'object' && self.__data[p]) {
        try {
          self.__data[p] = JSON.parse(self.__data[p] + '');
        } catch (e) {
          self.__data[p] = String(self.__data[p]);
        }
      }

      if (type.prototype instanceof ModelBaseClass) {
        if (!(self.__data[p] instanceof type)
          && typeof self.__data[p] === 'object'
          && self.__data[p] !== null ) {
          self.__data[p] = new type(self.__data[p]);
        }
      } else if (type.name === 'Array' || Array.isArray(type)) {
        if (!(self.__data[p] instanceof List)
          && self.__data[p] !== undefined
          && self.__data[p] !== null ) {
          self.__data[p] = List(self.__data[p], type, self);
        }
      }
    }
  }
  this.trigger('initialize');
};

/**
 * Define a property on the model.
 * @param {String} prop Property name
 * @param {Object} params Various property configuration
 */
ModelBaseClass.defineProperty = function (prop, params) {
  if(this.dataSource) {
    this.dataSource.defineProperty(this.modelName, prop, params);
  } else {
    this.modelBuilder.defineProperty(this.modelName, prop, params);
  }
};

ModelBaseClass.getPropertyType = function (propName) {
  var prop = this.definition.properties[propName];
  if (!prop) {
    // The property is not part of the definition
    return null;
  }
  if (!prop.type) {
    throw new Error('Type not defined for property ' + this.modelName + '.' + propName);
    // return null;
  }
  return prop.type.name;
};

ModelBaseClass.prototype.getPropertyType = function (propName) {
  return this.constructor.getPropertyType(propName);
};

/**
 * Return string representation of class
 * This overrides the default `toString()` method
 */
ModelBaseClass.toString = function () {
  return '[Model ' + this.modelName + ']';
};

/**
 * Convert model instance to a plain JSON object.
 * Returns a canonical object representation (no getters and setters).
 *
 * @param {Boolean} onlySchema Restrict properties to dataSource only.  Default is false.  If true, the function returns only properties defined in the schema;  Otherwise it returns all enumerable properties.
 */
ModelBaseClass.prototype.toObject = function (onlySchema, removeHidden) {
  if (onlySchema === undefined) {
    onlySchema = true;
  }
  var data = {};
  var self = this;
  var Model = this.constructor;

  // if it is already an Object
  if (Model === Object) {
    return self;
  }

  var strict = this.__strict;
  var schemaLess = (strict === false) || !onlySchema;

  var props = Model.definition.properties;
  var keys = Object.keys(props);
  var propertyName, val;
  for (var i = 0; i < keys.length; i++) {
    propertyName = keys[i];
    val = self[propertyName];

    // Exclude functions
    if (typeof val === 'function') {
      continue;
    }
    // Exclude hidden properties
    if (removeHidden && Model.isHiddenProperty(propertyName)) {
      continue;
    }

    if (val instanceof List) {
      data[propertyName] = val.toObject(!schemaLess, removeHidden);
    } else {
      if (val !== undefined && val !== null && val.toObject) {
        data[propertyName] = val.toObject(!schemaLess, removeHidden);
      } else {
        data[propertyName] = val;
      }
    }
  }

  if (schemaLess) {
    // Find its own properties which can be set via myModel.myProperty = 'myValue'.
    // If the property is not declared in the model definition, no setter will be
    // triggered to add it to __data
    keys = Object.keys(self);
    var size = keys.length;
    for (i = 0; i < size; i++) {
      propertyName = keys[i];
      if (props[propertyName]) {
        continue;
      }
      if (propertyName.indexOf('__') === 0) {
        continue;
      }
      if (removeHidden && Model.isHiddenProperty(propertyName)) {
        continue;
      }
      val = self[propertyName];
      if (val !== undefined && data[propertyName] === undefined) {
        if (typeof val === 'function') {
          continue;
        }
        if (val !== null && val.toObject) {
          data[propertyName] = val.toObject(!schemaLess, removeHidden);
        } else {
          data[propertyName] = val;
        }
      }
    }
    // Now continue to check __data
    keys = Object.keys(self.__data);
    size = keys.length;
    for (i = 0; i < size; i++) {
      propertyName = keys[i];
      if (propertyName.indexOf('__') === 0) {
        continue;
      }
      if (data[propertyName] === undefined) {
        if (removeHidden && Model.isHiddenProperty(propertyName)) {
          continue;
        }
        var ownVal = self[propertyName];
        // The ownVal can be a relation function
        val = (ownVal !== undefined && (typeof ownVal !== 'function'))
          ? ownVal : self.__data[propertyName];
        if (typeof val === 'function') {
          continue;
        }

        if (val !== undefined && val !== null && val.toObject) {
          data[propertyName] = val.toObject(!schemaLess, removeHidden);
        } else {
          data[propertyName] = val;
        }
      }
    }
  }

  return data;
};

ModelBaseClass.isHiddenProperty = function (propertyName) {
  var Model = this;
  var settings = Model.definition && Model.definition.settings;
  var hiddenProperties = settings && (settings.hiddenProperties || settings.hidden);
  if (Array.isArray(hiddenProperties)) {
    // Cache the hidden properties as an object for quick lookup
    settings.hiddenProperties = {};
    for (var i = 0; i < hiddenProperties.length; i++) {
      settings.hiddenProperties[hiddenProperties[i]] = true;
    }
    hiddenProperties = settings.hiddenProperties;
  }
  if (hiddenProperties) {
    return hiddenProperties[propertyName];
  } else {
    return false;
  }
}

ModelBaseClass.prototype.toJSON = function () {
  return this.toObject(false, true);
};

ModelBaseClass.prototype.fromObject = function (obj) {
  for (var key in obj) {
    this[key] = obj[key];
  }
};

/**
 * Reset dirty attributes.
 * This method does not perform any database operations; it just resets the object to its
 * initial state.
 */
ModelBaseClass.prototype.reset = function () {
  var obj = this;
  for (var k in obj) {
    if (k !== 'id' && !obj.constructor.dataSource.definitions[obj.constructor.modelName].properties[k]) {
      delete obj[k];
    }
  }
};

// Node v0.11+ allows custom inspect functions to return an object
// instead of string. That way options like `showHidden` and `colors`
// can be preserved.
var versionParts = process.versions && process.versions.node ?
  process.versions.node.split(/\./g).map(function(v) { return +v; }) :
  [1, 0, 0]; // browserify ships 1.0-compatible version of util.inspect

var INSPECT_SUPPORTS_OBJECT_RETVAL =
 versionParts[0] > 0 ||
 versionParts[1] > 11 ||
 (versionParts[0] === 11 && versionParts[1] >= 14);

ModelBaseClass.prototype.inspect = function (depth) {
  if (INSPECT_SUPPORTS_OBJECT_RETVAL)
     return this.__data;

  // Workaround for older versions
  // See also https://github.com/joyent/node/commit/66280de133
  return util.inspect(this.__data, {
    showHidden: false,
    depth: depth,
    colors: false
  });
};

ModelBaseClass.mixin = function (anotherClass, options) {
  if (typeof anotherClass === 'string') {
    this.modelBuilder.mixins.applyMixin(this, anotherClass, options);
  } else {
    if (anotherClass.prototype instanceof ModelBaseClass) {
      var props = anotherClass.definition.properties;
      for (var i in props) {
        if (this.definition.properties[i]) {
          continue;
        }
        this.defineProperty(i, props[i]);
      }
    }
    return jutil.mixin(this, anotherClass, options);
  }
};

ModelBaseClass.prototype.getDataSource = function () {
  return this.__dataSource || this.constructor.dataSource;
};

ModelBaseClass.getDataSource = function () {
  return this.dataSource;
};

ModelBaseClass.prototype.setStrict = function (strict) {
  this.__strict = strict;
};

jutil.mixin(ModelBaseClass, Hookable);
jutil.mixin(ModelBaseClass, validations.Validatable);
<|endoftext|>


<commit_before>/**
 *  Author: Ido Green @greenido
 *  date: Sep 2013
 */

// TODO - move to their own object.
var map;
var markersArray = [];
var bounds = new google.maps.LatLngBounds();
var gotTheData = false;

/**
 * Initialize our map obj.
 * @returns {undefined}
 */
function initialize() {
  var mapOptions = {
    center: new google.maps.LatLng(31.7, 35.1),
    zoom: 10,
    streetViewControl: true,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  map = new google.maps.Map(document.getElementById("map_canvas"),
          mapOptions);
}

/**
 * Fetching the stations geo points and other data from our google sheet in JSON baby!
 * @returns {undefined}
 */
function fetchPoints() {
  $.ajax({
    type: 'GET',
    dataType: 'json',
    url: 'https://spreadsheets.google.com/feeds/list/0Ass6q5sTeDKidDlKY3BUU0NoSnk4UUZIQ2NuUDYtTHc/od7/public/basic?alt=json',
    success: function(response, status, xhr) {
      if (gotTheData) {
        return;
      }
      if (response !== "") {
        gotTheData = true;
        for (var i = 0; i < response.feed.entry.length; i++) {
          //console.log("data: " + response.feed.entry[i].content.$t);
          //console.log("waze link: " + response.feed.entry[i].title.$t);
          var tmpData = response.feed.entry[i].content.$t.split(":");
          tmpData[4] = tmpData[4].replace("city", "");
          tmpData[5] = tmpData[5].replace(", hours", "");
          tmpData[3] = tmpData[3].replace(", address", "");
          var address = tmpData[4] + " " + tmpData[5];
          $("#maintable").append(
                  '

' +
                  '' +
                  address +
                  '

' +
                  '

' +
                  'לחץ לניווט

' +
                  '

' +
                  tmpData[6] +'

'
                  );
          addStation(tmpData);
        }
        map.fitBounds(bounds);
        $(".wazeButton").buttonMarkup( "refresh" );
      }
      else {
        console.error("ERR: blagan... we didn't get any response from our google sheet JSON obj. Status"+status + " XHR:"+xhr);
      }
    }
  });
}

/**
 * Adding the station to our map
 * @param {type} tmpData
 * @returns {undefined}
 */
function addStation(tmpData) {
    var station = new Object;
    var stationText = tmpData[4] + "
"  + tmpData[6];
    station.long = tmpData[1].replace(", geolong", "");
    station.lang = tmpData[2].replace(", geopoint", "");
    station.title = tmpData[5] ; // TODO - change it
    station.contentString = "
"+  station.title +
            "
" + stationText + "
";

    var infowindow = new google.maps.InfoWindow();
    var tmpPos = new google.maps.LatLng(station.long,station.lang);
    var marker = new google.maps.Marker({
      position: tmpPos,
      map: map
    });
    bounds.extend(tmpPos);
    google.maps.event.addListener(marker, 'click', (function(marker, i) {
      return function() {
        infowindow.setContent(station.contentString); //"תחנת חלוקה
" +  tmpData[4]
        infowindow.open(map, marker);
      }
    })(marker));

}

/**
 * Clear all the markers
 * @returns {undefined}
 */
function clearOverlays() {
  if (markersArray) {
    for (i in markersArray) {
      markersArray[i].setMap(null);
    }
  }
}

/**
 * Start the party
 */
$(document).on('pageinit', '[data-role=page]', function() {
  console.log("--start the map party--");

  initialize();
  $.mobile.touchOverflowEnabled = true;
  fetchPoints();

  $("#reload").click(function() {
    clearOverlays();
  });

});<commit_msg>remove the old jQuery1.1 hack on touchOverflow for fixed headers<commit_after>/**
 *  Author: Ido Green @greenido
 *  date: Sep 2013
 */

// TODO - move to their own object.
var map;
var markersArray = [];
var bounds = new google.maps.LatLngBounds();
var gotTheData = false;

/**
 * Initialize our map obj.
 * @returns {undefined}
 */
function initialize() {
  var mapOptions = {
    center: new google.maps.LatLng(31.7, 35.1),
    zoom: 10,
    streetViewControl: true,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  map = new google.maps.Map(document.getElementById("map_canvas"),
          mapOptions);
}

/**
 * Fetching the stations geo points and other data from our google sheet in JSON baby!
 * @returns {undefined}
 */
function fetchPoints() {
  $.ajax({
    type: 'GET',
    dataType: 'json',
    url: 'https://spreadsheets.google.com/feeds/list/0Ass6q5sTeDKidDlKY3BUU0NoSnk4UUZIQ2NuUDYtTHc/od7/public/basic?alt=json',
    success: function(response, status, xhr) {
      if (gotTheData) {
        return;
      }
      if (response !== "") {
        gotTheData = true;
        for (var i = 0; i < response.feed.entry.length; i++) {
          //console.log("data: " + response.feed.entry[i].content.$t);
          //console.log("waze link: " + response.feed.entry[i].title.$t);
          var tmpData = response.feed.entry[i].content.$t.split(":");
          tmpData[4] = tmpData[4].replace("city", "");
          tmpData[5] = tmpData[5].replace(", hours", "");
          tmpData[3] = tmpData[3].replace(", address", "");
          var address = tmpData[4] + " " + tmpData[5];
          $("#maintable").append(
                  '

' +
                  '' +
                  address +
                  '

' +
                  '

' +
                  'לחץ לניווט

' +
                  '

' +
                  tmpData[6] +'

'
                  );
          addStation(tmpData);
        }
        map.fitBounds(bounds);
        $(".wazeButton").buttonMarkup( "refresh" );
      }
      else {
        console.error("ERR: blagan... we didn't get any response from our google sheet JSON obj. Status"+status + " XHR:"+xhr);
      }
    }
  });
}

/**
 * Adding the station to our map
 * @param {type} tmpData
 * @returns {undefined}
 */
function addStation(tmpData) {
    var station = new Object;
    var stationText = tmpData[4] + "
"  + tmpData[6];
    station.long = tmpData[1].replace(", geolong", "");
    station.lang = tmpData[2].replace(", geopoint", "");
    station.title = tmpData[5] ; // TODO - change it
    station.contentString = "
"+  station.title +
            "
" + stationText + "
";

    var infowindow = new google.maps.InfoWindow();
    var tmpPos = new google.maps.LatLng(station.long,station.lang);
    var marker = new google.maps.Marker({
      position: tmpPos,
      map: map
    });
    bounds.extend(tmpPos);
    google.maps.event.addListener(marker, 'click', (function(marker, i) {
      return function() {
        infowindow.setContent(station.contentString); //"תחנת חלוקה
" +  tmpData[4]
        infowindow.open(map, marker);
      }
    })(marker));

}

/**
 * Clear all the markers
 * @returns {undefined}
 */
function clearOverlays() {
  if (markersArray) {
    for (i in markersArray) {
      markersArray[i].setMap(null);
    }
  }
}

/**
 * Start the party
 */
$(document).on('pageinit', '[data-role=page]', function() {
  console.log("--start the map party--");

  initialize();
  fetchPoints();

  $("#reload").click(function() {
    clearOverlays();
  });

});
<|endoftext|>


<commit_before>$('#old-contrast').affix(
        {
            offset: {
                top: function() {
                    var header = $('#header').height()
                    var setUpForm = $('#set-up-form').height()
                    return (this.top = header + setUpForm + 135)
                }
            }
        })
<commit_msg>Remove sticky "old colors" banner (affix.js)<commit_after>/*$('#old-contrast').affix(
    {
        offset: {
            top: function() {
                var header = $('#header').height()
                var setUpForm = $('#set-up-form').height()
                return (this.top = header + setUpForm + 135)
            }
        }
    })*/
<|endoftext|>


<commit_before>'use strict';

const {Client}           = require ('_debugger');
const {spawn}            = require ('child_process');
const watt               = require ('watt');
const escapeStringRegexp = require ('escape-string-regexp');
const path               = require ('path');

const linesExtractor = require ('./lines-extractor.js');

class Wannabe {
  /**
   * Construct the Wannabe object.
   *
   * @param {string} script - Test script.
   * @param {string|RegExp} regtest - Tests cases to grep.
   */
  constructor (script, regtest) {
    this._frames  = {};
    this._script  = script;
    this._client  = new Client ();
    this._regtest = regtest;

    watt.wrapAll (this);
  }

  * init (next) {
    yield this._spawn (next);

    let skip = true;
    this._client.on ('break', () => {
      if (skip) {
        skip = false;
        return;
      }
      this.inspect (() => {
        this._client.reqContinue (() => {});
      });
    });

    this._client.on ('error', (err) => {
      // console.error (err);
    });

    this._client.connect (5858);
  }

  /**
   * Spawn mocha with the node debugger.
   */
  _spawn (next) {
    const regex = this._regtest instanceof RegExp ?
                  this._regtest.toString ().replace (/^\/(.*)\/.?$/, '$1') :
                  escapeStringRegexp (this._regtest);

    const mocha = spawn ('node', [
      '--debug',
      '--debug-brk',
      path.join (__dirname, './mocha.js'),
      this._script,
      regex
    ], {
      detached: false,
      stdio: ['ignore', 'ignore', 'pipe']
    });

    mocha.unref ();

    mocha.stderr.on ('data', (data) => {
      if (/Debugger listening/.test (data.toString ())) {
        // HACK: it's not really listening when it's printed;
        //       then wait for 100ms :-(
        setTimeout (next, 100);
      }
    });

    mocha.on ('close', () => {});
    mocha.on ('error', (err) => {
      console.error (err);
    });
  }

  /**
   * Inspect the frame on the current breakpoint.
   *
   * It populates this._frames with the local variables.
   * The key of this._frames is the line number.
   *
   * NOTE: setBreakpoint is slow!
   */
  * inspect (next) {
    const {frames} = yield this._client.reqBacktrace (next);

    this._frames[`${frames[0].line}`] = [];
    frames[0].locals.forEach ((local) => {
      this._frames[`${frames[0].line}`].push ({
        name:  local.name,
        value: local.value.value
      });
    });
  }

  /**
   * Set one or more breakpoints according to the current script.
   *
   * @param {number[]} lines - Lines where put the breakpoints.
   */
  * setBreakpoints (lines, next) {
    for (const line of lines) {
      this._client.setBreakpoint ({
        type:   'script',
        target: this._script,
        line:   line
      }, next.parallel ());
    }

    yield next.sync ();
  }

  /**
   * Run Wannabe.
   *
   * @returns all frames.
   */
  * run (next) {
    const promise = new Promise ((resolve) => {
      this._client.on ('error', (err) => {
        resolve (this._frames);
      });

      this._client.on ('close', () => {
        resolve (this._frames);
      });
    });

    yield this._client.reqContinue (next);
    return yield promise;
  }
}

watt (function * (next) {
  const script = path.join (__dirname, '../test/sample.js');
  const lines = linesExtractor.byFile (script, 'it', 'a.1');

  const wannabe = new Wannabe (script, 'a.1');
  yield wannabe.init ();
  yield wannabe.setBreakpoints (lines);
  const frames = yield wannabe.run ();

  Object.keys (frames).forEach ((line) => {
    const frame = frames[line];
    console.log (`line:${line}`);
    frame.forEach ((local) => {
      console.log (` -> ${local.name}:${local.value}`);
    });
  });
  console.log ();
}) ();
<commit_msg>Coametic: move a method<commit_after>'use strict';

const {Client}           = require ('_debugger');
const {spawn}            = require ('child_process');
const watt               = require ('watt');
const escapeStringRegexp = require ('escape-string-regexp');
const path               = require ('path');

const linesExtractor = require ('./lines-extractor.js');

class Wannabe {
  /**
   * Construct the Wannabe object.
   *
   * @param {string} script - Test script.
   * @param {string|RegExp} regtest - Tests cases to grep.
   */
  constructor (script, regtest) {
    this._frames  = {};
    this._script  = script;
    this._client  = new Client ();
    this._regtest = regtest;

    watt.wrapAll (this);
  }

  /**
   * Spawn mocha with the node debugger.
   */
  _spawn (next) {
    const regex = this._regtest instanceof RegExp ?
                  this._regtest.toString ().replace (/^\/(.*)\/.?$/, '$1') :
                  escapeStringRegexp (this._regtest);

    const mocha = spawn ('node', [
      '--debug',
      '--debug-brk',
      path.join (__dirname, './mocha.js'),
      this._script,
      regex
    ], {
      detached: false,
      stdio: ['ignore', 'ignore', 'pipe']
    });

    mocha.unref ();

    mocha.stderr.on ('data', (data) => {
      if (/Debugger listening/.test (data.toString ())) {
        // HACK: it's not really listening when it's printed;
        //       then wait for 100ms :-(
        setTimeout (next, 100);
      }
    });

    mocha.on ('close', () => {});
    mocha.on ('error', (err) => {
      console.error (err);
    });
  }

  /**
   * Inspect the frame on the current breakpoint.
   *
   * It populates this._frames with the local variables.
   * The key of this._frames is the line number.
   *
   * NOTE: setBreakpoint is slow!
   */
  * inspect (next) {
    const {frames} = yield this._client.reqBacktrace (next);

    this._frames[`${frames[0].line}`] = [];
    frames[0].locals.forEach ((local) => {
      this._frames[`${frames[0].line}`].push ({
        name:  local.name,
        value: local.value.value
      });
    });
  }

  * init (next) {
    yield this._spawn (next);

    let skip = true;
    this._client.on ('break', () => {
      if (skip) {
        skip = false;
        return;
      }
      this.inspect (() => {
        this._client.reqContinue (() => {});
      });
    });

    this._client.on ('error', (err) => {
      // console.error (err);
    });

    this._client.connect (5858);
  }

  /**
   * Set one or more breakpoints according to the current script.
   *
   * @param {number[]} lines - Lines where put the breakpoints.
   */
  * setBreakpoints (lines, next) {
    for (const line of lines) {
      this._client.setBreakpoint ({
        type:   'script',
        target: this._script,
        line:   line
      }, next.parallel ());
    }

    yield next.sync ();
  }

  /**
   * Run Wannabe.
   *
   * @returns all frames.
   */
  * run (next) {
    const promise = new Promise ((resolve) => {
      this._client.on ('error', (err) => {
        resolve (this._frames);
      });

      this._client.on ('close', () => {
        resolve (this._frames);
      });
    });

    yield this._client.reqContinue (next);
    return yield promise;
  }
}

watt (function * (next) {
  const script = path.join (__dirname, '../test/sample.js');
  const lines = linesExtractor.byFile (script, 'it', 'a.1');

  const wannabe = new Wannabe (script, 'a.1');
  yield wannabe.init ();
  yield wannabe.setBreakpoints (lines);
  const frames = yield wannabe.run ();

  Object.keys (frames).forEach ((line) => {
    const frame = frames[line];
    console.log (`line:${line}`);
    frame.forEach ((local) => {
      console.log (` -> ${local.name}:${local.value}`);
    });
  });
  console.log ();
}) ();
<|endoftext|>


<commit_before>var Namespace = function(name, owner) {
    this.name = name;
    this.owner = owner;
    this.methods = Object.create(null);
    this.remoteMethods = [];
    this.listeners = null;
};

Namespace.prototype = {
    isMethodProvided: function(methodName) {
        return methodName in this.methods;
    },
    provide: function(methodName, fn) {
        if (typeof methodName === 'string') {
            if (typeof fn === 'function') {
                this.methods[methodName] = fn;
                this.owner.scheduleProvidedMethodsUpdate();
            }
        } else {
            var methods = methodName;
            for (methodName in methods) {
                if (this.isMethodProvided(methodName) &&
                    typeof methods[methodName] === 'function') {
                    this.methods[methodName] = methods[methodName];
                    this.owner.scheduleProvidedMethodsUpdate();
                }
            }
        }
    },
    revoke: function(methodName) {
        if (Array.isArray(methodName)) {
            methodName.forEach(this.revoke, this);
        } else {
            if (this.isMethodProvided(methodName)) {
                delete this.methods[methodName];
                this.owner.scheduleProvidedMethodsUpdate();
            }
        }
    },

    isRemoteMethodExists: function(methodName) {
        return this.remoteMethods.indexOf(methodName) !== -1;
    },
    callRemote: function(method/*, ...args, callback*/) {
        var args = Array.prototype.slice.call(arguments, 1);
        var callback = null;

        if (args.length && typeof args[args.length - 1] === 'function') {
            callback = args.pop();
        }

        Namespace.send(this.owner, [{
            type: 'call',
            ns: this.name,
            method: method,
            args: args
        }, callback]);
    },

    onRemoteMethodsChanged: function(callback) {
        var listener = {
            event: 'remoteMethodsChanged',
            callback: callback,
            listeners: this.listeners
        };

        this.listeners = listener;

        callback(this.remoteMethods.slice());

        return function() {
            var cursor = this.listeners;
            var prev = this;

            while (cursor !== null) {
                if (cursor === listener) {
                    prev.listeners = cursor.listeners;
                    break;
                }

                prev = cursor;
                cursor = cursor.listeners;
            }
        }.bind(this);
    }
};

Namespace.invoke = function invoke(namespace, method, args, callback) {
    // add a callback to args even if no callback, to avoid extra checking
    // that callback is passed by remote side
    args = args.concat(typeof callback === 'function' ? callback : function() {});

    // invoke the provided remote method
    namespace.methods[method].apply(null, args);
};

Namespace.notifyRemoteMethodsChanged = function(namespace) {
    var cursor = namespace.listeners;

    while (cursor !== null) {
        if (cursor.event === 'remoteMethodsChanged') {
            cursor.callback.call(null, namespace.remoteMethods.slice());
        }
        cursor = cursor.listeners;
    }
};

Namespace.send = function send(owner, args) {
    owner.channels.forEach(function(channel) {
        channel.send.apply(null, args);
    });
};

module.exports = Namespace;
<commit_msg>fix Namespace#provide() when invoked for define several methods<commit_after>var hasOwnProperty = Object.prototype.hasOwnProperty;

var Namespace = function(name, owner) {
    this.name = name;
    this.owner = owner;
    this.methods = Object.create(null);
    this.remoteMethods = [];
    this.listeners = null;
};

Namespace.prototype = {
    isMethodProvided: function(methodName) {
        return methodName in this.methods;
    },
    provide: function(methodName, fn) {
        if (typeof methodName === 'string') {
            if (typeof fn === 'function') {
                this.methods[methodName] = fn;
                this.owner.scheduleProvidedMethodsUpdate();
            }
        } else {
            var methods = methodName;
            for (methodName in methods) {
                if (hasOwnProperty.call(methods, methodName) &&
                    typeof methods[methodName] === 'function') {
                    this.methods[methodName] = methods[methodName];
                    this.owner.scheduleProvidedMethodsUpdate();
                }
            }
        }
    },
    revoke: function(methodName) {
        if (Array.isArray(methodName)) {
            methodName.forEach(this.revoke, this);
        } else {
            if (this.isMethodProvided(methodName)) {
                delete this.methods[methodName];
                this.owner.scheduleProvidedMethodsUpdate();
            }
        }
    },

    isRemoteMethodExists: function(methodName) {
        return this.remoteMethods.indexOf(methodName) !== -1;
    },
    callRemote: function(method/*, ...args, callback*/) {
        var args = Array.prototype.slice.call(arguments, 1);
        var callback = null;

        if (args.length && typeof args[args.length - 1] === 'function') {
            callback = args.pop();
        }

        Namespace.send(this.owner, [{
            type: 'call',
            ns: this.name,
            method: method,
            args: args
        }, callback]);
    },

    onRemoteMethodsChanged: function(callback) {
        var listener = {
            event: 'remoteMethodsChanged',
            callback: callback,
            listeners: this.listeners
        };

        this.listeners = listener;

        callback(this.remoteMethods.slice());

        return function() {
            var cursor = this.listeners;
            var prev = this;

            while (cursor !== null) {
                if (cursor === listener) {
                    prev.listeners = cursor.listeners;
                    break;
                }

                prev = cursor;
                cursor = cursor.listeners;
            }
        }.bind(this);
    }
};

Namespace.invoke = function invoke(namespace, method, args, callback) {
    // add a callback to args even if no callback, to avoid extra checking
    // that callback is passed by remote side
    args = args.concat(typeof callback === 'function' ? callback : function() {});

    // invoke the provided remote method
    namespace.methods[method].apply(null, args);
};

Namespace.notifyRemoteMethodsChanged = function(namespace) {
    var cursor = namespace.listeners;

    while (cursor !== null) {
        if (cursor.event === 'remoteMethodsChanged') {
            cursor.callback.call(null, namespace.remoteMethods.slice());
        }
        cursor = cursor.listeners;
    }
};

Namespace.send = function send(owner, args) {
    owner.channels.forEach(function(channel) {
        channel.send.apply(null, args);
    });
};

module.exports = Namespace;
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed 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.
 */

CLASS({
  package: 'foam.graphics',
  name:  'Circle',

  extendsModel: 'foam.graphics.CView',

  properties: [
    {
      name:  'border',
      label: 'Border Color',
      type:  'String',
      defaultValue: undefined
    },
    {
      name:  'borderWidth',
      type:  'int',
      defaultValue: 1
    },
    {
      name: 'r',
      label: 'Radius',
      type: 'int',
      defaultValue: 20
    }
  ],

  methods: {
    paintSelf: function() {
      var c = this.canvas;
      if ( ! c ) return;

      c.globalAlpha = this.alpha;

      if ( this.border && this.r ) {
        c.lineWidth = this.borderWidth;
        c.strokeStyle = this.border;
        c.beginPath();
        c.arc(0, 0, this.r, 0, Math.PI*2, true);
        c.closePath();
        c.stroke();
      }

      if ( this.color ) {
        c.fillStyle = this.color;

        c.beginPath();
        c.arc(0, 0, this.r, 0, Math.PI*2, true);
        c.closePath();
        c.fill();
      }
    }
  }
});
<commit_msg>Added startAngle and endAngle to Circle.<commit_after>/**
 * @license
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed 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.
 */

CLASS({
  package: 'foam.graphics',
  name:  'Circle',

  extendsModel: 'foam.graphics.CView',

  properties: [
    {
      name:  'border',
      label: 'Border Color',
      type:  'String',
      defaultValue: undefined
    },
    {
      name:  'borderWidth',
      type:  'int',
      defaultValue: 1
    },
    {
      name: 'r',
      label: 'Radius',
      type: 'int',
      defaultValue: 20
    },
    {
      name: 'startAngle',
      defaultValue: 0
    },
    {
      name: 'endAngle',
      label: 'Radius',
      type: 'int',
      defaultValue: Math.PI*2
    }
  ],

  methods: {
    paintSelf: function() {
      var c = this.canvas;
      if ( ! c ) return;

      c.globalAlpha = this.alpha;

      if ( ! this.r ) return;

      if ( this.color) {
        c.beginPath();
        c.moveTo(0,0);
        c.arc(0, 0, this.r, -this.endAngle, -this.startAngle, false);
        c.closePath();

        c.fillStyle = this.color;
        c.fill();
      }
      if ( this.border ) {
        c.lineWidth = this.borderWidth;

        c.beginPath();
        c.arc(0, 0, this.r+this.borderWidth/2-0.1, -this.endAngle, -this.startAngle, false);
        c.closePath();

        c.strokeStyle = this.border;
        c.stroke();
      }
    }
  }
});
<|endoftext|>