<commit_before>// ==========================================================================
// Project:   SproutCore - JavaScript Application Framework
// Copyright: ©2006-2009 Apple, Inc. and contributors.
// License:   Licened under MIT license (see license.js)
// ==========================================================================
/*globals module ok equals same test MyApp */

// test querying through findAll on the store
var MyApp;
module("SC.Query querying findAll on a store", {
  setup: function() {
    SC.RunLoop.begin();
    // setup dummy app and store
    MyApp = SC.Object.create({});

    // setup data source that just returns cached storeKeys
    MyApp.DataSource = SC.DataSource.create({

      storeKeys: null,

      fetch: function(store, fetchKey, params) {
        return this.storeKeys;
      },

      destroyRecord: function(store, storeKey){
        store.dataSourceDidDestroy(storeKey);
        return YES;
      }

    });

    MyApp.store = SC.Store.create().from(MyApp.DataSource);

    // setup a dummy model
    MyApp.Foo = SC.Record.extend({});
    MyApp.Faa = SC.Record.extend({});

    var records = [
      { guid: 1, firstName: "John", lastName: "Doe", married: true },
      { guid: 2, firstName: "Jane", lastName: "Doe", married: false },
      { guid: 3, firstName: "Emily", lastName: "Parker", bornIn: 1975, married: true },
      { guid: 4, firstName: "Johnny", lastName: "Cash", married: true },
      { guid: 5, firstName: "Bert", lastName: "Berthold", married: true }
    ];

    // load some data
    MyApp.DataSource.storeKeys = MyApp.store.loadRecords(MyApp.Foo, records);

    // for sanity check, load two record types
    MyApp.store.loadRecords(MyApp.Faa, records);

    SC.RunLoop.end();

  }

});

// ..........................................................
// RECORD PROPERTIES
//

test("should find records based on boolean", function() {
  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"married=true"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 4, 'record length should be 4');

});

test("should find records based on query string", function() {

  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'John'"});
  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 1, 'record length should be 1');
  equals(records.objectAt(0).get('firstName'), 'John', 'name should be John');

});

test("should find records based on SC.Query", function() {

  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'Jane'"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 1, 'record length should be 1');
  equals(records.objectAt(0).get('firstName'), 'Jane', 'name should be Jane');

});

test("should find records based on SC.Query without recordType", function() {

  var q = SC.Query.create({conditions:"lastName = 'Doe'"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 2, 'record length should be 2');
  equals(records.objectAt(0).get('firstName'), 'John', 'name should be John');
  equals(records.objectAt(1).get('firstName'), 'Jane', 'name should be Jane');

});

test("should find records within a passed record array", function() {

  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'Emily'"});

  var recArray = MyApp.store.findAll(MyApp.Foo);
  var records = MyApp.store.findAll(q, null, recArray);

  equals(records.get('length'), 1, 'record length should be 1');
  equals(records.objectAt(0).get('firstName'), 'Emily', 'name should be Emily');

});

test("changing the original store key array from data source should propagate to record array", function() {

  var records = MyApp.store.findAll(MyApp.Foo);

  equals(records.get('length'), 5, 'record length should be 5');

  var newStoreKeys = MyApp.DataSource.storeKeys;
  newStoreKeys.pop();

  // .replace() will call .enumerableContentDidChange()
  MyApp.DataSource.storeKeys.replace(0,100,newStoreKeys);

  equals(records.get('length'), 4, 'record length should be 4');

});

test("loading more data into the store should propagate to record array", function() {

  var records = MyApp.store.findAll(MyApp.Foo);

  equals(records.get('length'), 5, 'record length before should be 5');

  var newStoreKeys = MyApp.store.loadRecords(MyApp.Foo, [
    { guid: 10, firstName: "John", lastName: "Johnson" }
  ]);

  MyApp.DataSource.storeKeys.replace(0,0,newStoreKeys);

  equals(records.get('length'), 6, 'record length after should be 6');

});

test("loading more data into the store should propagate to record array with query", function() {
  SC.RunLoop.begin();
  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'John'"});

  var records = MyApp.store.findAll(q);

  equals(records.get('length'), 1, 'record length before should be 1');

  var newStoreKeys = MyApp.store.loadRecords(MyApp.Foo, [
    { guid: 10, firstName: "John", lastName: "Johnson" }
  ]);

  // .replace() will call .enumerableContentDidChange()
  // and should fire original SC.Query again

  MyApp.DataSource.storeKeys.replace(0,0,newStoreKeys);
  SC.RunLoop.end();
  equals(records.get('length'), 2, 'record length after should be 2');

  // subsequent updates to store keys should also work
  SC.RunLoop.begin();
  var newStoreKeys2 = MyApp.store.loadRecords(MyApp.Foo, [
    { guid: 11, firstName: "John", lastName: "Norman" }
  ]);

  MyApp.DataSource.storeKeys.replace(0,0,newStoreKeys2);
  SC.RunLoop.end();

  equals(records.get('length'), 3, 'record length after should be 3');

});

test("SC.Query returned from fetchRecords() should return result set", function() {

  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'John'"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 1, 'record length should be 1');
  equals(records.objectAt(0).get('firstName'), 'John', 'name should be John');

});

test("Loading records after SC.Query is returned in fetchRecords() should show up", function() {

  SC.RunLoop.begin();
  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'John'"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 1, 'record length should be 1');
  equals(records.objectAt(0).get('firstName'), 'John', 'name should be John');

  var recordsToLoad = [
    { guid: 20, firstName: "John", lastName: "Johnson" },
    { guid: 21, firstName: "John", lastName: "Anderson" },
    { guid: 22, firstName: "Barbara", lastName: "Jones" }
  ];

  MyApp.store.loadRecords(MyApp.Foo, recordsToLoad);
  SC.RunLoop.end();

  equals(records.get('length'), 3, 'record length should be 3');

  equals(records.objectAt(0).get('firstName'), 'John', 'name should be John');
  equals(records.objectAt(1).get('firstName'), 'John', 'name should be John');
  equals(records.objectAt(2).get('firstName'), 'John', 'name should be John');

});

test("Loading records after getting empty record array based on SC.Query should update", function() {

  SC.RunLoop.begin();
  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'Maria'"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 0, 'record length should be 0');

  var recordsToLoad = [
    { guid: 20, firstName: "Maria", lastName: "Johnson" }
  ];

  MyApp.store.loadRecords(MyApp.Foo, recordsToLoad);
  SC.RunLoop.end();

  equals(records.get('length'), 1, 'record length should be 1');

  equals(records.objectAt(0).get('firstName'), 'Maria', 'name should be Maria');

});

test("Changing a record should make it show up in RecordArrays based on SC.Query", function() {

  SC.RunLoop.begin();

  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'Maria'"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 0, 'record length should be 0');

  var record = MyApp.store.find(MyApp.Foo, 1);
  record.set('firstName', 'Maria');

  SC.RunLoop.end();

  equals(records.get('length'), 1, 'record length should be 1');

  equals(records.objectAt(0).get('firstName'), 'Maria', 'name should be Maria');

});

test("Deleting a record should make the RecordArray based on SC.Query update accordingly", function() {

  SC.RunLoop.begin();
  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'John'"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 1, 'record length should be 1');

  MyApp.store.destroyRecord(MyApp.Foo, 1);
  SC.RunLoop.end();

  equals(records.get('length'), 0, 'record length should be 0');

});

test("Using findAll with SC.Query on store with no data source should work", function() {

  SC.RunLoop.begin();
  // create a store with no data source
  MyApp.store3 = SC.Store.create();

  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'John'"});

  var records = MyApp.store3.findAll(q);
  equals(records.get('length'), 0, 'record length should be 0');

  var recordsToLoad = [
    { guid: 20, firstName: "John", lastName: "Johnson" },
    { guid: 21, firstName: "John", lastName: "Anderson" },
    { guid: 22, firstName: "Barbara", lastName: "Jones" }
  ];

  MyApp.store3.loadRecords(MyApp.Foo, recordsToLoad);

  SC.RunLoop.end();

  equals(records.get('length'), 2, 'record length should be 2');

});

test("Using orderBy in SC.Query returned from findAll()", function() {

  var q = SC.Query.create({recordType: MyApp.Foo, orderBy:"firstName ASC"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 5, 'record length should be 5');

  same(records.getEach('firstName'), ["Bert", "Emily", "Jane", "John", "Johnny"], 'first name should be properly sorted');

});

test("Using orderBy in SC.Query returned from findAll() and loading more records to original store key array", function() {

  SC.RunLoop.begin();
  var q = SC.Query.create({recordType: MyApp.Foo, orderBy:"firstName ASC"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 5, 'record length should be 5');

  equals(records.objectAt(0).get('firstName'), 'Bert', 'name should be Bert');
  equals(records.objectAt(4).get('firstName'), 'Johnny', 'name should be Johnny');

  var newStoreKeys2 = MyApp.store.loadRecords(MyApp.Foo, [
    { guid: 11, firstName: "Anna", lastName: "Petterson" }
  ]);

  MyApp.DataSource.storeKeys.replace(0,0,newStoreKeys2);
  SC.RunLoop.end();

  equals(records.objectAt(0).get('firstName'), 'Anna', 'name should be Anna');
  equals(records.objectAt(1).get('firstName'), 'Bert', 'name should be Bert');
  equals(records.objectAt(5).get('firstName'), 'Johnny', 'name should be Johnny');

});

test("Using orderBy in SC.Query and loading more records to the store", function() {

  SC.RunLoop.begin();
  var q = SC.Query.create({recordType: MyApp.Foo, orderBy:"firstName ASC"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 5, 'record length should be 5');
  equals(records.objectAt(0).get('firstName'), 'Bert', 'name should be Bert');

  MyApp.store.loadRecords(MyApp.Foo, [
    { guid: 11, firstName: "Anna", lastName: "Petterson" }
  ]);
  SC.RunLoop.end();

  equals(records.get('length'), 6, 'record length should be 6');

  equals(records.objectAt(0).get('firstName'), 'Anna', 'name should be Anna');
  equals(records.objectAt(5).get('firstName'), 'Johnny', 'name should be Johnny');

});

test("Chaining findAll() queries", function() {

  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"lastName='Doe'"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 2, 'record length should be 2');

  var q2 = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName='John'"});

  var records2 = records.findAll(q2);

  equals(records2.get('length'), 1, 'record length should be 1');

  equals(records2.objectAt(0).get('firstName'), 'John', 'name should be John');

});

test("Chaining findAll() queries and loading more records", function() {

  SC.RunLoop.begin();
  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"lastName='Doe'"});
  var q2 = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName='John'"});

  var records = MyApp.store.findAll(q).findAll(q2);
  equals(records.get('length'), 1, 'record length should be 1');

  MyApp.store.loadRecords(MyApp.Foo, [
    { guid: 11, firstName: "John", lastName: "Doe" }
  ]);
  SC.RunLoop.end();

  equals(records.get('length'), 2, 'record length should be 2');

});
<commit_msg>Runloop fixes to SC.Store and related tests<commit_after>// ==========================================================================
// Project:   SproutCore - JavaScript Application Framework
// Copyright: ©2006-2009 Apple, Inc. and contributors.
// License:   Licened under MIT license (see license.js)
// ==========================================================================
/*globals module ok equals same test MyApp */

// test querying through findAll on the store
var MyApp;
module("SC.Query querying findAll on a store", {
  setup: function() {
    SC.RunLoop.begin();
    // setup dummy app and store
    MyApp = SC.Object.create({});

    // setup data source that just returns cached storeKeys
    MyApp.DataSource = SC.DataSource.create({

      storeKeys: null,

      fetch: function(store, fetchKey, params) {
        return this.storeKeys;
      },

      destroyRecord: function(store, storeKey){
        store.dataSourceDidDestroy(storeKey);
        return YES;
      }

    });

    MyApp.store = SC.Store.create().from(MyApp.DataSource);

    // setup a dummy model
    MyApp.Foo = SC.Record.extend({});
    MyApp.Faa = SC.Record.extend({});

    var records = [
      { guid: 1, firstName: "John", lastName: "Doe", married: true },
      { guid: 2, firstName: "Jane", lastName: "Doe", married: false },
      { guid: 3, firstName: "Emily", lastName: "Parker", bornIn: 1975, married: true },
      { guid: 4, firstName: "Johnny", lastName: "Cash", married: true },
      { guid: 5, firstName: "Bert", lastName: "Berthold", married: true }
    ];

    // load some data
    MyApp.DataSource.storeKeys = MyApp.store.loadRecords(MyApp.Foo, records);
    SC.RunLoop.end();

    SC.RunLoop.begin();
    // for sanity check, load two record types
    MyApp.store.loadRecords(MyApp.Faa, records);
    SC.RunLoop.end();

  }

});

// ..........................................................
// RECORD PROPERTIES
//

test("should find records based on boolean", function() {
  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"married=true"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 4, 'record length should be 4');

});

test("should find records based on query string", function() {

  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'John'"});
  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 1, 'record length should be 1');
  equals(records.objectAt(0).get('firstName'), 'John', 'name should be John');

});

test("should find records based on SC.Query", function() {

  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'Jane'"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 1, 'record length should be 1');
  equals(records.objectAt(0).get('firstName'), 'Jane', 'name should be Jane');

});

test("should find records based on SC.Query without recordType", function() {

  var q = SC.Query.create({conditions:"lastName = 'Doe'"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 2, 'record length should be 2');
  equals(records.objectAt(0).get('firstName'), 'John', 'name should be John');
  equals(records.objectAt(1).get('firstName'), 'Jane', 'name should be Jane');

});

test("should find records within a passed record array", function() {

  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'Emily'"});

  var recArray = MyApp.store.findAll(MyApp.Foo);
  var records = MyApp.store.findAll(q, null, recArray);

  equals(records.get('length'), 1, 'record length should be 1');
  equals(records.objectAt(0).get('firstName'), 'Emily', 'name should be Emily');

});

test("changing the original store key array from data source should propagate to record array", function() {

  var records = MyApp.store.findAll(MyApp.Foo);

  equals(records.get('length'), 5, 'record length should be 5');

  var newStoreKeys = MyApp.DataSource.storeKeys;
  newStoreKeys.pop();

  // .replace() will call .enumerableContentDidChange()
  MyApp.DataSource.storeKeys.replace(0,100,newStoreKeys);

  equals(records.get('length'), 4, 'record length should be 4');

});

test("loading more data into the store should propagate to record array", function() {

  var records = MyApp.store.findAll(MyApp.Foo);

  equals(records.get('length'), 5, 'record length before should be 5');

  var newStoreKeys = MyApp.store.loadRecords(MyApp.Foo, [
    { guid: 10, firstName: "John", lastName: "Johnson" }
  ]);

  MyApp.DataSource.storeKeys.replace(0,0,newStoreKeys);

  equals(records.get('length'), 6, 'record length after should be 6');

});

test("loading more data into the store should propagate to record array with query", function() {
  SC.RunLoop.begin();
  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'John'"});

  var records = MyApp.store.findAll(q);

  equals(records.get('length'), 1, 'record length before should be 1');

  var newStoreKeys = MyApp.store.loadRecords(MyApp.Foo, [
    { guid: 10, firstName: "John", lastName: "Johnson" }
  ]);

  // .replace() will call .enumerableContentDidChange()
  // and should fire original SC.Query again

  MyApp.DataSource.storeKeys.replace(0,0,newStoreKeys);
  SC.RunLoop.end();
  equals(records.get('length'), 2, 'record length after should be 2');

  // subsequent updates to store keys should also work
  SC.RunLoop.begin();
  var newStoreKeys2 = MyApp.store.loadRecords(MyApp.Foo, [
    { guid: 11, firstName: "John", lastName: "Norman" }
  ]);

  MyApp.DataSource.storeKeys.replace(0,0,newStoreKeys2);
  SC.RunLoop.end();

  equals(records.get('length'), 3, 'record length after should be 3');

});

test("SC.Query returned from fetchRecords() should return result set", function() {

  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'John'"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 1, 'record length should be 1');
  equals(records.objectAt(0).get('firstName'), 'John', 'name should be John');

});

test("Loading records after SC.Query is returned in fetchRecords() should show up", function() {

  SC.RunLoop.begin();
  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'John'"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 1, 'record length should be 1');
  equals(records.objectAt(0).get('firstName'), 'John', 'name should be John');

  var recordsToLoad = [
    { guid: 20, firstName: "John", lastName: "Johnson" },
    { guid: 21, firstName: "John", lastName: "Anderson" },
    { guid: 22, firstName: "Barbara", lastName: "Jones" }
  ];

  MyApp.store.loadRecords(MyApp.Foo, recordsToLoad);
  SC.RunLoop.end();

  equals(records.get('length'), 3, 'record length should be 3');

  equals(records.objectAt(0).get('firstName'), 'John', 'name should be John');
  equals(records.objectAt(1).get('firstName'), 'John', 'name should be John');
  equals(records.objectAt(2).get('firstName'), 'John', 'name should be John');

});

test("Loading records after getting empty record array based on SC.Query should update", function() {

  SC.RunLoop.begin();
  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'Maria'"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 0, 'record length should be 0');

  var recordsToLoad = [
    { guid: 20, firstName: "Maria", lastName: "Johnson" }
  ];

  MyApp.store.loadRecords(MyApp.Foo, recordsToLoad);
  SC.RunLoop.end();

  equals(records.get('length'), 1, 'record length should be 1');

  equals(records.objectAt(0).get('firstName'), 'Maria', 'name should be Maria');

});

test("Changing a record should make it show up in RecordArrays based on SC.Query", function() {

  SC.RunLoop.begin();

  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'Maria'"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 0, 'record length should be 0');

  var record = MyApp.store.find(MyApp.Foo, 1);
  record.set('firstName', 'Maria');

  SC.RunLoop.end();

  equals(records.get('length'), 1, 'record length should be 1');

  equals(records.objectAt(0).get('firstName'), 'Maria', 'name should be Maria');

});

test("Deleting a record should make the RecordArray based on SC.Query update accordingly", function() {

  SC.RunLoop.begin();
  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'John'"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 1, 'record length should be 1');

  MyApp.store.destroyRecord(MyApp.Foo, 1);
  SC.RunLoop.end();

  equals(records.get('length'), 0, 'record length should be 0');

});

test("Using findAll with SC.Query on store with no data source should work", function() {

  SC.RunLoop.begin();
  // create a store with no data source
  MyApp.store3 = SC.Store.create();

  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName = 'John'"});

  var records = MyApp.store3.findAll(q);
  equals(records.get('length'), 0, 'record length should be 0');

  var recordsToLoad = [
    { guid: 20, firstName: "John", lastName: "Johnson" },
    { guid: 21, firstName: "John", lastName: "Anderson" },
    { guid: 22, firstName: "Barbara", lastName: "Jones" }
  ];

  MyApp.store3.loadRecords(MyApp.Foo, recordsToLoad);

  SC.RunLoop.end();

  equals(records.get('length'), 2, 'record length should be 2');

});

test("Using orderBy in SC.Query returned from findAll()", function() {

  var q = SC.Query.create({recordType: MyApp.Foo, orderBy:"firstName ASC"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 5, 'record length should be 5');

  same(records.getEach('firstName'), ["Bert", "Emily", "Jane", "John", "Johnny"], 'first name should be properly sorted');

});

test("Using orderBy in SC.Query returned from findAll() and loading more records to original store key array", function() {

  SC.RunLoop.begin();
  var q = SC.Query.create({recordType: MyApp.Foo, orderBy:"firstName ASC"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 5, 'record length should be 5');

  equals(records.objectAt(0).get('firstName'), 'Bert', 'name should be Bert');
  equals(records.objectAt(4).get('firstName'), 'Johnny', 'name should be Johnny');

  var newStoreKeys2 = MyApp.store.loadRecords(MyApp.Foo, [
    { guid: 11, firstName: "Anna", lastName: "Petterson" }
  ]);

  MyApp.DataSource.storeKeys.replace(0,0,newStoreKeys2);
  SC.RunLoop.end();

  equals(records.objectAt(0).get('firstName'), 'Anna', 'name should be Anna');
  equals(records.objectAt(1).get('firstName'), 'Bert', 'name should be Bert');
  equals(records.objectAt(5).get('firstName'), 'Johnny', 'name should be Johnny');

});

test("Using orderBy in SC.Query and loading more records to the store", function() {

  SC.RunLoop.begin();
  var q = SC.Query.create({recordType: MyApp.Foo, orderBy:"firstName ASC"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 5, 'record length should be 5');
  equals(records.objectAt(0).get('firstName'), 'Bert', 'name should be Bert');

  MyApp.store.loadRecords(MyApp.Foo, [
    { guid: 11, firstName: "Anna", lastName: "Petterson" }
  ]);
  SC.RunLoop.end();

  equals(records.get('length'), 6, 'record length should be 6');

  equals(records.objectAt(0).get('firstName'), 'Anna', 'name should be Anna');
  equals(records.objectAt(5).get('firstName'), 'Johnny', 'name should be Johnny');

});

test("Chaining findAll() queries", function() {

  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"lastName='Doe'"});

  var records = MyApp.store.findAll(q);
  equals(records.get('length'), 2, 'record length should be 2');

  var q2 = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName='John'"});

  var records2 = records.findAll(q2);

  equals(records2.get('length'), 1, 'record length should be 1');

  equals(records2.objectAt(0).get('firstName'), 'John', 'name should be John');

});

test("Chaining findAll() queries and loading more records", function() {

  SC.RunLoop.begin();
  var q = SC.Query.create({recordType: MyApp.Foo, conditions:"lastName='Doe'"});
  var q2 = SC.Query.create({recordType: MyApp.Foo, conditions:"firstName='John'"});

  var records = MyApp.store.findAll(q).findAll(q2);
  equals(records.get('length'), 1, 'record length should be 1');

  MyApp.store.loadRecords(MyApp.Foo, [
    { guid: 11, firstName: "John", lastName: "Doe" }
  ]);
  SC.RunLoop.end();

  equals(records.get('length'), 2, 'record length should be 2');

});
<|endoftext|>


<commit_before>"use strict";

var mod = function(
  _,
  Options
) {

  var ConsoleLogAppender = function() {
    this.initialize.apply(this, arguments);
  };

  _.extend(ConsoleLogAppender.prototype, {
    initialize: function(opts) {
      opts = Options.fromObject(opts);
      this._console = opts.getOrElse("console", console);
      this._timeDelegate = opts.getOrElse("timeDelegate", function(){
        return new Date();
      })
    },

    log: function(loggerName, descendants, logLevel, logLevelName, args) {
      // Use the furthest ancestor as the logged name (since it originated there)
      var furthestAncestor = descendants[descendants.length - 1];
      if (furthestAncestor) {
        loggerName = furthestAncestor;
      }
      this._log(["["+logLevelName+"]["+loggerName+"]["+this._getTime()+"]"].concat(args));
    },

    _getTime: function() {
      return this._timeDelegate();
    },

    _log: function(logItems) {
      // Why does he do this? Is he insane? Well, yes.
      //
      // But mostly, I do this because console.log isn't, in all cases,
      // something you can call .apply on. Last I checked, in IE calling
      // console.log.apply(console, []) will throw an error. So that's why the
      // big ugly switch.
      //
      // If you need more than 7 items, well, I can't help you (but you can - add another
      // switch case).
      switch(logItems.length) {
        case 0:
          this._console.log();
          break;
        case 1:
          this._console.log(logItems[0]);
          break;
        case 2:
          this._console.log(logItems[0], logItems[1]);
          break;
        case 3:
          this._console.log(logItems[0], logItems[1], logItems[2]);
          break;
        case 4:
          this._console.log(logItems[0], logItems[1], logItems[2], logItems[3]);
          break;
        case 5:
          this._console.log(logItems[0], logItems[1], logItems[2], logItems[3], logItems[4]);
          break;
        case 6:
          this._console.log(logItems[0], logItems[1], logItems[2], logItems[3], logItems[4], logItems[5]);
          break;
        case 7:
          this._console.log(logItems[0], logItems[1], logItems[2], logItems[3], logItems[4], logItems[5], logItems[6]);
          break;
        default:
          var label = logItems.shift();
          this._console.log(label, logItems);
      }
    }
  });

  return ConsoleLogAppender;
};

module.exports = mod(
  require("underscore"),
  require("../../core/options")
);
<commit_msg>Semicolon.<commit_after>"use strict";

var mod = function(
  _,
  Options
) {

  var ConsoleLogAppender = function() {
    this.initialize.apply(this, arguments);
  };

  _.extend(ConsoleLogAppender.prototype, {
    initialize: function(opts) {
      opts = Options.fromObject(opts);
      this._console = opts.getOrElse("console", console);
      this._timeDelegate = opts.getOrElse("timeDelegate", function(){
        return new Date();
      });
    },

    log: function(loggerName, descendants, logLevel, logLevelName, args) {
      // Use the furthest ancestor as the logged name (since it originated there)
      var furthestAncestor = descendants[descendants.length - 1];
      if (furthestAncestor) {
        loggerName = furthestAncestor;
      }
      this._log(["["+logLevelName+"]["+loggerName+"]["+this._getTime()+"]"].concat(args));
    },

    _getTime: function() {
      return this._timeDelegate();
    },

    _log: function(logItems) {
      // Why does he do this? Is he insane? Well, yes.
      //
      // But mostly, I do this because console.log isn't, in all cases,
      // something you can call .apply on. Last I checked, in IE calling
      // console.log.apply(console, []) will throw an error. So that's why the
      // big ugly switch.
      //
      // If you need more than 7 items, well, I can't help you (but you can - add another
      // switch case).
      switch(logItems.length) {
        case 0:
          this._console.log();
          break;
        case 1:
          this._console.log(logItems[0]);
          break;
        case 2:
          this._console.log(logItems[0], logItems[1]);
          break;
        case 3:
          this._console.log(logItems[0], logItems[1], logItems[2]);
          break;
        case 4:
          this._console.log(logItems[0], logItems[1], logItems[2], logItems[3]);
          break;
        case 5:
          this._console.log(logItems[0], logItems[1], logItems[2], logItems[3], logItems[4]);
          break;
        case 6:
          this._console.log(logItems[0], logItems[1], logItems[2], logItems[3], logItems[4], logItems[5]);
          break;
        case 7:
          this._console.log(logItems[0], logItems[1], logItems[2], logItems[3], logItems[4], logItems[5], logItems[6]);
          break;
        default:
          var label = logItems.shift();
          this._console.log(label, logItems);
      }
    }
  });

  return ConsoleLogAppender;
};

module.exports = mod(
  require("underscore"),
  require("../../core/options")
);
<|endoftext|>


<commit_before>/**
* A Node module for Electron ipc messaging.
* Talks with the AngularJS ngElectron module.
* Info: https://develephant.github.io/ngElectron
* See also: https://develephant.gitgub.io/amy
**/
var angularBridge = new Object();

angularBridge.send = function ( msg, bw ) {
  var msg = msg;
  bw = bw || require('browser-window').getFocusedWindow();

  if (bw) {
    bw.webContents
      .send('ELECTRON_BRIDGE_CLIENT', msg);
  }
}
angularBridge.listen = function ( _listener ) {
  var _listener = _listener;
  var i = require('ipc')
  i.on('ELECTRON_BRIDGE_HOST', function( evt, msg ) {
      _listener( msg );
  });
}

module.exports = angularBridge;
<commit_msg>Update ng-bridge.js<commit_after>/**
* A Node module for Electron ipc messaging.
* Talks with the AngularJS ngElectron module.
* Info: https://develephant.github.io/ngElectron
* See also: https://develephant.gitgub.io/amy
**/
var angularBridge = new Object();

angularBridge.send = function ( msg, bw ) {
  var msg = msg;
  bw = bw || require('browser-window').getFocusedWindow();

  if (bw) {
    bw.webContents
      .send('ELECTRON_BRIDGE_CLIENT', msg);
  }
}
angularBridge.listen = function ( _listener ) {
  var _listener = _listener;
  var i = require('electron').ipcMain;
  i.on('ELECTRON_BRIDGE_HOST', function( evt, msg ) {
      _listener( msg );
  });
}

module.exports = angularBridge;
<|endoftext|>


<commit_before>frappe.provide('frappe.views');

frappe.views.KanbanView = class KanbanView extends frappe.views.ListView {
	static load_last_view() {
		const route = frappe.get_route();
		if (route.length === 3) {
			const doctype = route[1];
			const user_settings = frappe.get_user_settings(doctype)['Kanban'] || {};
			if (!user_settings.last_kanban_board) {
				frappe.msgprint({
					title: __('Error'),
					indicator: 'red',
					message: __('Missing parameter Kanban Board Name')
				});
				frappe.set_route('List', doctype, 'List');
				return true;
			}
			route.push(user_settings.last_kanban_board);
			frappe.set_route(route);
			return true;
		}
		return false;
	}

	get view_name() {
		return 'Kanban';
	}

	setup_defaults() {
		super.setup_defaults();
		this.board_name = frappe.get_route()[3];
		this.page_title = this.board_name;
		this.card_meta = this.get_card_meta();

		this.menu_items.push({
			label: __('Save filters'),
			action: () => {
				this.save_kanban_board_filters();
			}
		});

		return this.get_board();
	}

	get_board() {
		return frappe.db.get_doc('Kanban Board', this.board_name)
			.then(board => {
				this.board = board;
				this.board.filters_array = JSON.parse(this.board.filters || '[]');
				this.filters = this.board.filters_array;
			});
	}

	before_refresh() {

	}

	setup_view() {

	}

	set_fields() {
		super.set_fields();
		this._add_field(this.card_meta.title_field);
	}

	before_render() {
		frappe.model.user_settings.save(this.doctype, 'last_view', this.view_name);
		this.save_view_user_settings({
			last_kanban_board: this.board_name
		});
	}

	on_filter_change() {
		if (JSON.stringify(this.board.filters_array) !== JSON.stringify(this.filter_area.get())) {
			this.page.set_indicator(__('Not Saved'), 'orange');
		} else {
			this.page.clear_indicator();
		}
	}

	save_kanban_board_filters() {
		const filters = this.filter_area.get();

		frappe.call({
			method: 'frappe.desk.doctype.kanban_board.kanban_board.save_filters',
			args: {
				board_name: this.board_name,
				filters: filters
			}
		}).then(r => {
			if (r.exc) {
				frappe.show_alert({
					indicator: 'red',
					message: __('There was an error saving filters')
				});
				return;
			}
			frappe.show_alert({
				indicator: 'green',
				message: __('Filters saved')
			});

			this.board.filters_array = filters;
			this.on_filter_change();
		});
	}

	render() {
		const board_name = this.board_name;
		if (this.kanban && board_name === this.kanban.board_name) {
			this.kanban.update(this.data);
			return;
		}

		this.kanban = new frappe.views.KanbanBoard({
			doctype: this.doctype,
			board: this.board,
			board_name: board_name,
			cards: this.data,
			card_meta: this.card_meta,
			wrapper: this.$result,
			cur_list: this,
			user_settings: this.view_user_settings
		});
	}

	get_card_meta() {
		var meta = frappe.get_meta(this.doctype);
		var doc = frappe.model.get_new_doc(this.doctype);
		var title_field = null;
		var quick_entry = false;

		if (this.meta.title_field) {
			title_field = frappe.meta.get_field(this.doctype, this.meta.title_field);
		}

		this.meta.fields.forEach((df) => {
			const is_valid_field =
				in_list(['Data', 'Text', 'Small Text', 'Text Editor'], df.fieldtype)
				&& !df.hidden;

			if (is_valid_field && !title_field) {
				// can be mapped to textarea
				title_field = df;
			}
		});

		// quick entry
		var mandatory = meta.fields.filter((df) => df.reqd && !doc[df.fieldname]);

		if (mandatory.some(df => df.fieldtype === 'Table') || mandatory.length > 1) {
			quick_entry = true;
		}

		if (!title_field) {
			title_field = frappe.meta.get_field(this.doctype, 'name');
		}

		return {
			quick_entry: quick_entry,
			title_field: title_field
		};
	}

	get required_libs() {
		return [
			'assets/frappe/js/lib/fluxify.min.js',
			'assets/frappe/js/frappe/views/kanban/kanban_board.js'
		];
	}
};

frappe.views.KanbanView.setup_dropdown_in_sidebar = function(doctype, $dropdown) {
	// get kanban boards and append to dropdown
	get_kanban_boards()
		.then((kanban_boards) => {
			if (!kanban_boards) return;

			$('

').appendTo($dropdown);

			kanban_boards.forEach(board => {
				const route = ['List', board.reference_doctype, 'Kanban', board.name].join('/');

				$(`

						${__(board.name)}
					${board.private ? '' : ''}

				`).appendTo($dropdown);
			});
		});

	$dropdown.on('click', '.new-kanban-board', () => {
		const dialog = new_kanban_dialog();
		dialog.show();
	});

	function make_kanban_board(board_name, field_name, project) {
		return frappe.call({
			method: 'frappe.desk.doctype.kanban_board.kanban_board.quick_kanban_board',
			args: {
				doctype,
				board_name,
				field_name,
				project
			},
			callback: function(r) {
				var kb = r.message;
				if (kb.filters) {
					frappe.provide('frappe.kanban_filters');
					frappe.kanban_filters[kb.kanban_board_name] = kb.filters;
				}
				frappe.set_route('List', doctype, 'Kanban', kb.kanban_board_name);
			}
		});
	}

	let dialog = null;

	function new_kanban_dialog() {
		if (dialog) return dialog;

		const fields = get_fields_for_dialog();

		let primary_action_label = fields.length > 1 ? __('Save') : '';
		let primary_action = fields.length > 1 ?
			({ board_name, field_name, project }) => {
				make_kanban_board(board_name, field_name, project)
					.then(() => dialog.hide(), (err) => frappe.msgprint(err));
			} : null;

		dialog = new frappe.ui.Dialog({
			title: __('New Kanban Board'),
			fields,
			primary_action_label,
			primary_action
		});
		return dialog;
	}

	function get_fields_for_dialog() {

		let fields = [{
			fieldtype: 'Data',
			fieldname: 'board_name',
			label: __('Kanban Board Name'),
			reqd: 1,
			description: ['Note', 'ToDo'].includes(doctype) ?
				__('This Kanban Board will be private') : ''
		}];

		if (doctype === 'Task') {
			fields.push({
				fieldtype: 'Link',
				fieldname: 'project',
				label: __('Project'),
				options: 'Project'
			});
		}

		const select_fields =
			frappe.get_meta(doctype).fields
				.filter(df => {
					return df.fieldtype === 'Select' &&
						df.fieldname !== 'kanban_column';
				});

		if (select_fields.length > 0) {
			fields.push({
				fieldtype: 'Select',
				fieldname: 'field_name',
				label: __('Columns based on'),
				options: select_fields.map(df => ({label: df.label, value: df.fieldname})),
				default: select_fields[0],
				reqd: 1,
			});
		} else {
			fields = [{
				fieldtype: 'HTML',
				options: `

						${__('No fields found that can be used as a Kanban Column. Use the Customize Form to add a Custom Field of type "Select".')}

							${__('Customize Form')}

				`
			}];
		}

		return fields;
	}

	function get_kanban_boards() {
		return frappe.call('frappe.desk.doctype.kanban_board.kanban_board.get_kanban_boards', { doctype })
			.then(r => r.message);
	}
};
<commit_msg>Added code to setup events<commit_after>frappe.provide('frappe.views');

frappe.views.KanbanView = class KanbanView extends frappe.views.ListView {
	static load_last_view() {
		const route = frappe.get_route();
		if (route.length === 3) {
			const doctype = route[1];
			const user_settings = frappe.get_user_settings(doctype)['Kanban'] || {};
			if (!user_settings.last_kanban_board) {
				frappe.msgprint({
					title: __('Error'),
					indicator: 'red',
					message: __('Missing parameter Kanban Board Name')
				});
				frappe.set_route('List', doctype, 'List');
				return true;
			}
			route.push(user_settings.last_kanban_board);
			frappe.set_route(route);
			return true;
		}
		return false;
	}

	get view_name() {
		return 'Kanban';
	}

	setup_defaults() {
		super.setup_defaults();
		this.board_name = frappe.get_route()[3];
		this.page_title = this.board_name;
		this.card_meta = this.get_card_meta();

		this.menu_items.push({
			label: __('Save filters'),
			action: () => {
				this.save_kanban_board_filters();
			}
		});

		return this.get_board();
	}

	get_board() {
		return frappe.db.get_doc('Kanban Board', this.board_name)
			.then(board => {
				this.board = board;
				this.board.filters_array = JSON.parse(this.board.filters || '[]');
				this.filters = this.board.filters_array;
			});
	}

	before_refresh() {

	}

	setup_view() {
		this.setup_events();

	}

	set_fields() {
		super.set_fields();
		this._add_field(this.card_meta.title_field);
	}

	before_render() {
		frappe.model.user_settings.save(this.doctype, 'last_view', this.view_name);
		this.save_view_user_settings({
			last_kanban_board: this.board_name
		});
	}

	on_filter_change() {
		if (JSON.stringify(this.board.filters_array) !== JSON.stringify(this.filter_area.get())) {
			this.page.set_indicator(__('Not Saved'), 'orange');
		} else {
			this.page.clear_indicator();
		}
	}

	save_kanban_board_filters() {
		const filters = this.filter_area.get();

		frappe.call({
			method: 'frappe.desk.doctype.kanban_board.kanban_board.save_filters',
			args: {
				board_name: this.board_name,
				filters: filters
			}
		}).then(r => {
			if (r.exc) {
				frappe.show_alert({
					indicator: 'red',
					message: __('There was an error saving filters')
				});
				return;
			}
			frappe.show_alert({
				indicator: 'green',
				message: __('Filters saved')
			});

			this.board.filters_array = filters;
			this.on_filter_change();
		});
	}

	render() {
		const board_name = this.board_name;
		if (this.kanban && board_name === this.kanban.board_name) {
			this.kanban.update(this.data);
			return;
		}

		this.kanban = new frappe.views.KanbanBoard({
			doctype: this.doctype,
			board: this.board,
			board_name: board_name,
			cards: this.data,
			card_meta: this.card_meta,
			wrapper: this.$result,
			cur_list: this,
			user_settings: this.view_user_settings
		});
	}

	get_card_meta() {
		var meta = frappe.get_meta(this.doctype);
		var doc = frappe.model.get_new_doc(this.doctype);
		var title_field = null;
		var quick_entry = false;

		if (this.meta.title_field) {
			title_field = frappe.meta.get_field(this.doctype, this.meta.title_field);
		}

		this.meta.fields.forEach((df) => {
			const is_valid_field =
				in_list(['Data', 'Text', 'Small Text', 'Text Editor'], df.fieldtype)
				&& !df.hidden;

			if (is_valid_field && !title_field) {
				// can be mapped to textarea
				title_field = df;
			}
		});

		// quick entry
		var mandatory = meta.fields.filter((df) => df.reqd && !doc[df.fieldname]);

		if (mandatory.some(df => df.fieldtype === 'Table') || mandatory.length > 1) {
			quick_entry = true;
		}

		if (!title_field) {
			title_field = frappe.meta.get_field(this.doctype, 'name');
		}

		return {
			quick_entry: quick_entry,
			title_field: title_field
		};
	}

	get required_libs() {
		return [
			'assets/frappe/js/lib/fluxify.min.js',
			'assets/frappe/js/frappe/views/kanban/kanban_board.js'
		];
	}
};

frappe.views.KanbanView.setup_dropdown_in_sidebar = function(doctype, $dropdown) {
	// get kanban boards and append to dropdown
	get_kanban_boards()
		.then((kanban_boards) => {
			if (!kanban_boards) return;

			$('

').appendTo($dropdown);

			kanban_boards.forEach(board => {
				const route = ['List', board.reference_doctype, 'Kanban', board.name].join('/');

				$(`

						${__(board.name)}
					${board.private ? '' : ''}

				`).appendTo($dropdown);
			});
		});

	$dropdown.on('click', '.new-kanban-board', () => {
		const dialog = new_kanban_dialog();
		dialog.show();
	});

	function make_kanban_board(board_name, field_name, project) {
		return frappe.call({
			method: 'frappe.desk.doctype.kanban_board.kanban_board.quick_kanban_board',
			args: {
				doctype,
				board_name,
				field_name,
				project
			},
			callback: function(r) {
				var kb = r.message;
				if (kb.filters) {
					frappe.provide('frappe.kanban_filters');
					frappe.kanban_filters[kb.kanban_board_name] = kb.filters;
				}
				frappe.set_route('List', doctype, 'Kanban', kb.kanban_board_name);
			}
		});
	}

	let dialog = null;

	function new_kanban_dialog() {
		if (dialog) return dialog;

		const fields = get_fields_for_dialog();

		let primary_action_label = fields.length > 1 ? __('Save') : '';
		let primary_action = fields.length > 1 ?
			({ board_name, field_name, project }) => {
				make_kanban_board(board_name, field_name, project)
					.then(() => dialog.hide(), (err) => frappe.msgprint(err));
			} : null;

		dialog = new frappe.ui.Dialog({
			title: __('New Kanban Board'),
			fields,
			primary_action_label,
			primary_action
		});
		return dialog;
	}

	function get_fields_for_dialog() {

		let fields = [{
			fieldtype: 'Data',
			fieldname: 'board_name',
			label: __('Kanban Board Name'),
			reqd: 1,
			description: ['Note', 'ToDo'].includes(doctype) ?
				__('This Kanban Board will be private') : ''
		}];

		if (doctype === 'Task') {
			fields.push({
				fieldtype: 'Link',
				fieldname: 'project',
				label: __('Project'),
				options: 'Project'
			});
		}

		const select_fields =
			frappe.get_meta(doctype).fields
				.filter(df => {
					return df.fieldtype === 'Select' &&
						df.fieldname !== 'kanban_column';
				});

		if (select_fields.length > 0) {
			fields.push({
				fieldtype: 'Select',
				fieldname: 'field_name',
				label: __('Columns based on'),
				options: select_fields.map(df => ({label: df.label, value: df.fieldname})),
				default: select_fields[0],
				reqd: 1,
			});
		} else {
			fields = [{
				fieldtype: 'HTML',
				options: `

						${__('No fields found that can be used as a Kanban Column. Use the Customize Form to add a Custom Field of type "Select".')}

							${__('Customize Form')}

				`
			}];
		}

		return fields;
	}

	function get_kanban_boards() {
		return frappe.call('frappe.desk.doctype.kanban_board.kanban_board.get_kanban_boards', { doctype })
			.then(r => r.message);
	}
};
<|endoftext|>


<commit_before>javascript:!function() {
  var L = document.location.href,
    m = document.createElement('div'),
    d = 'v20140112',
    ver = '' + d + '';
  switch (true) {
//いつもの放送ページの処理
  case /live\.nicovideo\.jp\/watch/.test(L): {
  //ここ仕様変更に弱そう
    var h0 = document.getElementsByTagName('meta')[13].outerHTML,
  //放送IDを取得
      h = h0.replace(/.+?watch\/(lv\d+).*/, '$1'),
      Aries = '',
      del = 'var f = "flvplayer_container",flv = document.getElementById(f);flv.parentNode.removeChild(flv);';
//放送主かどうか
    var u0 = document.getElementById('siteHeaderNotification').outerHTML,
  //ログインしてるユーザーIDを取得
      u = u0.replace(/.+?nico-userid="(\d+)"[\s\S]+/, '$1'),
      n0 = document.getElementsByClassName('nicopedia_nushi');
  //放送主のユーザーIDを取得(表示がない放送は0)
      if (n0.length != '0') {
        var n1 = n0[0].innerHTML,
        n = n1.replace(/[\s\S]+nicovideo.jp\/user\/(\d+)"[\s\S]+/, '$1');
      } else {
        n = 0;
      }
  //ログインしてるユーザーIDと放送主のユーザーIDを比較
      if (u != n) {
        nushi = 'N';
      } else {
        nushi = 'Y';
      }
    break;
//新しい放送ページ(？)の処理
  } case /live2\.nicovideo\.jp\/watch/.test(L): {
    var h = L.replace(/.+?watch\/(lv\d+).*/, '$1'),
      s = document.getElementsByTagName('script')[17].outerHTML,
      p = s.replace(/[\s\u2028\u2029]/g,''),
    //URL のパラメータ
      we = 'webSocketUrl=ws://a.live2.nicovideo.jp/wsapi/v1/watch/',
      au = p.replace(/.*?"(audienceToken)".+?"(\w+)".*/,'&$1=$2'),
      re = p.replace(/.*?"(relatedNicoliveProgramId)".+?"(\w+)".*/,'&$1=$2'),
      br = p.replace(/.*?"(broadcastId)".+?"(\d+)".*/,'&$1=$2'),
      be = p.replace(/.*?"(beginTime)".+?"(\d+)".*/,'&$1=$2');
      Aries = '<input type="button" value="Aries" onClick="window.open(\'http://nl.nimg.jp/public/relive/1.4.36/assets/web/r1/swfs/v1/AriesPlayer.swf?' + we + au + re + br + be + '\',\'_blank\',\'width=960,height=512\');var f = "playerswf",flv = document.getElementById(f);flv.parentNode.removeChild(flv);">
',
      del = 'var f = "playerswf",flv = document.getElementById(f);flv.parentNode.removeChild(flv);',
      nushi = 'N';
    break;
//それ以外のページの処理
  } default: {
    var h = prompt('放送IDかURL', '');
    if (h.match(/lv[0-9]+/)) {
      h = h.replace(/.+?(lv\d+).*/, '$1'),
      Aries = '',
      del = '',
      nushi = 'Y';
    } else {
      alert('放送IDが入ってないよ！\n「' + h + '」\n連絡先とか　http://nico.ms/ar303976');
      return false;
    }
    break;
  }}
//放送主だったら追加
  if (nushi == 'Y') {
    nama1 = '放送主用
<input type="button" value="配信ツール" onClick="window.open(\'http://live.nicovideo.jp/nicolivebroadcaster.swf?dicfilename=NicoliveBroadcasterDictionaryJAJP.swf&v=' + h + '\',\'_blank\',\'width=900,height=250\')"><input type="button" value="放送情報変更" onClick="window.open(\'http://live.nicovideo.jp/editstream/' + h + '\',\'_blank\',\'width=960,height=600,scrollbars=1\')">
<input type="button" value="配信ツール(原宿)" onClick="window.open(\'http://live.nicovideo.jp/utility_v1.swf?v=' + h + '\',\'_blank\',\'width=950,height=200\')"> ',
    nama2 = '
※配信ツールはセッションが使えません
※かんたん配信タブは1番最初に操作したウィンドウの
配信ツールでなるべくいじってください
※放送情報変更の反映は少し時間がかかります
';
  } else {
    nama1 = '',
    nama2 = '';
  }
//ページに追加
    m.innerHTML = '
×プレイヤー変更
' + Aries + '<input type="button" value="GINZA" onClick="window.open(\'http://live.nicovideo.jp/nicoliveplayer.swf?v=' + h + '&languagecode=ja-jp\',\'_blank\',\'width=960,height=490\');' + del + '"><input type="button" value="ニコファーレ" onClick="window.open(\'http://live.nicovideo.jp/liveplayer_farre.swf?v=' + h + '\',\'_blank\',\'width=960,height=520\');' + del + '">
<input type="button" value="原宿" onClick="window.open(\'http://live.nicovideo.jp/liveplayer.swf?v=' + h + '\',\'_blank\',\'width=950,height=520\');' + del + '"><input type="button" value="ページ更新" onClick="window.location.reload(true)">
' + nama1 + nama2 + ver;
    m.style.color = 'rgb(250,250,250)';
    m.style.textAlign = 'center';
    m.style.padding = '10px';
    m.style.position = 'fixed';
    m.style.zIndex = '9999';
    m.style.fontSize = '12px';
    m.style.border = '2px solid black';
    m.style.right = '20px';
    m.style.bottom = '20px';
    m.style.background = 'rgba(0,128,255,0.5)';
    m.setAttribute("id", "nicoLivew");
    document.body.appendChild(m);
}();
<commit_msg>Update<commit_after>javascript:!function() {
  var L = document.location.href,
    m = document.createElement('div'),
    ua = window.navigator.userAgent.toLowerCase(),
    d = 'v20141231',
    ver = '' + d + '';
  switch (true) {
//いつもの放送ページの処理
  case /live\.nicovideo\.jp\/watch/.test(L): {
  //ここ仕様変更に弱そう
    var h0 = document.getElementsByTagName('meta')[13].outerHTML,
  //放送IDを取得
      h = h0.replace(/.+?watch\/(lv\d+).*/, '$1'),
      Aries = '',
      del = 'var f = "flvplayer_container",flv = document.getElementById(f);flv.parentNode.removeChild(flv);';
//放送主かどうか
    var u0 = document.getElementById('siteHeaderNotification').outerHTML,
  //ログインしてるユーザーIDを取得
      u = u0.replace(/.+?nico-userid="(\d+)"[\s\S]+/, '$1'),
      n0 = document.getElementsByClassName('nicopedia_nushi');
  //放送主のユーザーIDを取得(表示がない放送は0)
      if (n0.length != '0') {
        var n1 = n0[0].innerHTML,
        n = n1.replace(/[\s\S]+nicovideo.jp\/user\/(\d+)"[\s\S]+/, '$1');
      } else {
        n = 0;
      }
  //ログインしてるユーザーIDと放送主のユーザーIDを比較
      if (u != n) {
        nushi = 'N';
      } else {
        nushi = 'Y';
      }
    break;
//新しい放送ページ(？)の処理
  } case /live2\.nicovideo\.jp\/watch/.test(L): {
    var h = L.replace(/.+?watch\/(lv\d+).*/, '$1');
  //firefox だけちょっと違う
    if (ua.indexOf('firefox') != -1) {
      s = document.getElementsByTagName('script')[17].outerHTML;
    } else {
      s = document.getElementsByTagName('script')[16].outerHTML;
    }
    var p = s.replace(/[\s\u2028\u2029]/g,''),
    //URL のパラメータ
      we = 'webSocketUrl=ws://a.live2.nicovideo.jp/wsapi/v1/watch/',
      au = p.replace(/.*?"(audienceToken)".+?"(\w+)".*/,'&$1=$2'),
      re = p.replace(/.*?"(relatedNicoliveProgramId)".+?"(\w+)".*/,'&$1=$2'),
      br = p.replace(/.*?"(broadcastId)".+?"(\d+)".*/,'&$1=$2'),
      be = p.replace(/.*?"(beginTime)".+?"(\d+)".*/,'&$1=$2');
      Aries = '<input type="button" value="Aries" onClick="window.open(\'http://nl.nimg.jp/public/relive/1.4.36/assets/web/r1/swfs/v1/AriesPlayer.swf?' + we + au + re + br + be + '\',\'_blank\',\'width=960,height=512\');var f = "playerswf",flv = document.getElementById(f);flv.parentNode.removeChild(flv);">
',
      del = 'var f = "playerswf",flv = document.getElementById(f);flv.parentNode.removeChild(flv);',
      nushi = 'N';
    break;
//それ以外のページの処理
  } default: {
    var h = prompt('放送IDかURL', '');
    if (h.match(/lv[0-9]+/)) {
      h = h.replace(/.+?(lv\d+).*/, '$1'),
      Aries = '',
      del = '',
      nushi = 'Y';
    } else {
      alert('放送IDが入ってないよ！\n「' + h + '」\n連絡先とか　http://nico.ms/ar303976');
      return false;
    }
    break;
  }}
//放送主だったら追加
  if (nushi == 'Y') {
    nama1 = '放送主用
<input type="button" value="配信ツール" onClick="window.open(\'http://live.nicovideo.jp/nicolivebroadcaster.swf?dicfilename=NicoliveBroadcasterDictionaryJAJP.swf&v=' + h + '\',\'_blank\',\'width=900,height=250\')"><input type="button" value="放送情報変更" onClick="window.open(\'http://live.nicovideo.jp/editstream/' + h + '\',\'_blank\',\'width=960,height=600,scrollbars=1\')">
<input type="button" value="配信ツール(原宿)" onClick="window.open(\'http://live.nicovideo.jp/utility_v1.swf?v=' + h + '\',\'_blank\',\'width=950,height=200\')"> ',
    nama2 = '
※配信ツールはセッションが使えません
※かんたん配信タブは1番最初に操作したウィンドウの
配信ツールでなるべくいじってください
※放送情報変更の反映は少し時間がかかります
';
  } else {
    nama1 = '',
    nama2 = '';
  }
//ページに追加
    m.innerHTML = '
×プレイヤー変更
' + Aries + '<input type="button" value="GINZA" onClick="window.open(\'http://live.nicovideo.jp/nicoliveplayer.swf?v=' + h + '&languagecode=ja-jp\',\'_blank\',\'width=960,height=490\');' + del + '"><input type="button" value="ニコファーレ" onClick="window.open(\'http://live.nicovideo.jp/liveplayer_farre.swf?v=' + h + '\',\'_blank\',\'width=960,height=520\');' + del + '">
<input type="button" value="原宿" onClick="window.open(\'http://live.nicovideo.jp/liveplayer.swf?v=' + h + '\',\'_blank\',\'width=950,height=520\');' + del + '"><input type="button" value="ページ更新" onClick="window.location.reload(true)">
' + nama1 + nama2 + ver;
    m.style.color = 'rgb(250,250,250)';
    m.style.textAlign = 'center';
    m.style.padding = '10px';
    m.style.position = 'fixed';
    m.style.zIndex = '9999';
    m.style.fontSize = '12px';
    m.style.border = '2px solid black';
    m.style.right = '20px';
    m.style.bottom = '20px';
    m.style.background = 'rgba(0,128,255,0.5)';
    m.setAttribute("id", "nicoLivew");
    document.body.appendChild(m);
}();
<|endoftext|>


<commit_before>(function () {
	var menu = document.querySelector(".navbar-room-header .navbar-right"),
		playerContainer = document.getElementsByClassName("col-xs-8")[0],
		chatContainer = playerContainer.nextElementSibling,
		userlistContainer = document.getElementsByClassName("col-xs-4")[1],
		topRow = document.getElementsByClassName("row")[1],
		bottomRow = topRow.nextElementSibling;

	addToolbarItem("Big Player", "arrows-alt", toggleBigPlayer);
	addToolbarItem("Toggle Nightmode", "lightbulb-o", toggleNightMode);

	chrome.storage.sync.get([ "nightmode", "bigplayer" ], function (items) {
		console.log(items);
		if (items.nightmode === "1") {
			enableNightMode();
		}

		if (items.bigplayer === "1") {
			enableBigPlayer();
		}
	});

	function addToolbarItem(label, icon, onClick) {
		var li = document.createElement("li"),
			a = document.createElement("a"),
			i = document.createElement("i");

		menu.appendChild(li);

		li.appendChild(a);

		a.href = "#";
		a.addEventListener("click", onClick);
		a.appendChild(i);
		a.appendChild(document.createTextNode(" " + label));

		i.classList.add("fa", "fa-" + icon);
	}

	function enableNightMode() {
		document.body.classList.add("nightmode");
		chrome.storage.sync.set({ "nightmode": "1" });
	}

	function disableNightMode() {
		document.body.classList.remove("nightmode");
		chrome.storage.sync.set({ "nightmode": "0" });
	}

	function toggleNightMode() {
		if (document.body.classList.contains("nightmode")) {
			disableNightMode();
		} else {
			enableNightMode();
		}
	}

	function enableBigPlayer() {
		playerContainer.style.width = "100%";
		bottomRow.appendChild(chatContainer);
		bottomRow.appendChild(userlistContainer);
		chrome.storage.sync.set({ "bigplayer": "1" });
	}

	function disableBigPlayer() {
		playerContainer.style.width = "";
		topRow.appendChild(chatContainer);
		chrome.storage.sync.set({ "bigplayer": "0" });
	}

	function toggleBigPlayer() {
		if (playerContainer.style.width === "") {
			enableBigPlayer();
		} else {
			disableBigPlayer();
		}
	}
}());
<commit_msg>Removed left-over debug line<commit_after>(function () {
	var menu = document.querySelector(".navbar-room-header .navbar-right"),
		playerContainer = document.getElementsByClassName("col-xs-8")[0],
		chatContainer = playerContainer.nextElementSibling,
		userlistContainer = document.getElementsByClassName("col-xs-4")[1],
		topRow = document.getElementsByClassName("row")[1],
		bottomRow = topRow.nextElementSibling;

	addToolbarItem("Big Player", "arrows-alt", toggleBigPlayer);
	addToolbarItem("Toggle Nightmode", "lightbulb-o", toggleNightMode);

	chrome.storage.sync.get([ "nightmode", "bigplayer" ], function (items) {
		if (items.nightmode === "1") {
			enableNightMode();
		}

		if (items.bigplayer === "1") {
			enableBigPlayer();
		}
	});

	function addToolbarItem(label, icon, onClick) {
		var li = document.createElement("li"),
			a = document.createElement("a"),
			i = document.createElement("i");

		menu.appendChild(li);

		li.appendChild(a);

		a.href = "#";
		a.addEventListener("click", onClick);
		a.appendChild(i);
		a.appendChild(document.createTextNode(" " + label));

		i.classList.add("fa", "fa-" + icon);
	}

	function enableNightMode() {
		document.body.classList.add("nightmode");
		chrome.storage.sync.set({ "nightmode": "1" });
	}

	function disableNightMode() {
		document.body.classList.remove("nightmode");
		chrome.storage.sync.set({ "nightmode": "0" });
	}

	function toggleNightMode() {
		if (document.body.classList.contains("nightmode")) {
			disableNightMode();
		} else {
			enableNightMode();
		}
	}

	function enableBigPlayer() {
		playerContainer.style.width = "100%";
		bottomRow.appendChild(chatContainer);
		bottomRow.appendChild(userlistContainer);
		chrome.storage.sync.set({ "bigplayer": "1" });
	}

	function disableBigPlayer() {
		playerContainer.style.width = "";
		topRow.appendChild(chatContainer);
		chrome.storage.sync.set({ "bigplayer": "0" });
	}

	function toggleBigPlayer() {
		if (playerContainer.style.width === "") {
			enableBigPlayer();
		} else {
			disableBigPlayer();
		}
	}
}());
<|endoftext|>


<commit_before>// ==UserScript==
// @name        Y-marker
// @namespace   trespassersW
// @description Sets up keyboard shortcuts for placing bookmarks and navigation inside webpage.
// @include        http://*
// @include        https://*
// @include        file://*
// ** about:config -> greasemonkey.fileIsGreaseable <- true
// @version 15.04.15
// @license  MIT
// @updated  2015.04.15
// @released 2013-12-11
// @run-at document-end
// @grant unsafeWindow
// ==/UserScript==
/* 15.04.15 localStorage + unsafeWindow + ff37 + GM3.1 problems
 * 13-12-12 click on msg removes all marks
 * 1.1 don't run in editable fields
*/

(function(){ "use strict";
if(top!=self || !document || !document.body ) return;
var W = unsafeWindow || window; // localStorage doesn't live in sandbox?
/* key kombinations to invoke the skript */
var kShift = 1,  kCtrl = 2, kAlt = 4, kWin = 8;
var kJump = kAlt;
var kMark = kAlt+kShift;

/* sec; 0 to disable; -1 status bar only */
var tipShowtime = 2.2;

var kNobs = "-0123456789";
var kKeys = {
 173: 0, 48: 1, 49: 2, 50: 3, 51: 4, 52: 5, 53: 6, 54: 7, 55: 8, 56: 9, 57: 10,
 189: 0, /* chrome, opera caps lock */
 109: 0  /* opera */
};
var minus1="-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1";

function kNob(k){ return kNobs.charAt(k); }

var U=undefined, D=window.document;
function _L(s) { 0 && console.log(s) };

var statMsg;
function msg(t,k, y){
 statMsg = "";
 if(U!==k)
  statMsg += "["+kNob(k)+"] ";
 if(U!==y)
  statMsg += ""+pt(y)+"% ";
 statMsg += t+ (noCoo ? "\u2262 ": "");
}

var locStor;
var noCoo;
// see SQlite manager -> %FFpath%\webappstore.sqlite -> find -> key -> contains Ym#

if(!locStor) try {
  locStor = W.localStorage;
  locStor.getItem("Ym#");
} catch(e){ locStor =null;  };

if(!locStor) try {
  noCoo="no cookies!!1";
  locStor = W.sessionStorage;
  locStor.getItem("Ym#");
} catch(e){ locStor =null };

if(!locStor && U===W.YmStorage){
  noCoo= "cookies are disabled!!!11";
  W.YmStorage= {
  setItem: function(k,v) {this.s[k]=v},
  getItem: function(k) {return this.s[k]? this.s[k]: null},
  removeItem: function(k) {this.s[k]=null},
  s: {}
 };
 locStor=W.YmStorage;
}

function pt(y) {
 try{
  y =Math.round(y*1000/(document.body.scrollHeight+1))/10;
 }catch(e){console.log("math\n"+e); return -1}
 return y;
}

var Ym;
var pz;

function ldYm(){
  var s= locStor.getItem(Ym);
  if(!s) s=minus1;
  pz=s.split(",")
}

function svYm(){
 var s=pz.join(",");
 locStor.setItem(Ym,s)
}

function jumpY(k){
 var y=pz[k];
 if(y > -1) {
   if( y!= scrollY ){
    pz[0] = scrollY;
    scroll(0,y);
    msg("jump",k,y);
   }else
    msg("here",k,y);
   return 1;
 }
 msg("none",k);
 return 0;
}

function markY(k){
 pz[k]=scrollY;
 if(k>=1)
  svYm();
 msg("mark",k,pz[k]);
 return 1;
}

var kMap= {16: kShift, 17:kCtrl, 18: kAlt, 91: kWin};
var keyMod=0;
var kkWin= (kMark | kJump) & kWin;

function klear(e) {
 var k= e.keyCode;
 if(!k) return;
 var km=kMap[k];
 if(km) {
  keyMod &= -1 ^ km;
 }
}

function onKeydown(e) {
 try{
 var rc=0, k= e.keyCode;
 if(!k) return;
 // Don't run in input, select, textarea etc.
 var E = D.activeElement.tagName.toLowerCase();
 if (E == "input" || E == "select" || E == "textarea" ||
    (E=D.activeElement.contentEditable) == "true" ||
     E == "")
   {  keyMod = 0; return; }

 var km =kMap[k]; // ff doesnt track metaKey. stsuko
 if(km) {
   keyMod |= km;
   if( kkWin && km === kWin ) //???
    e.preventDefault(), e.stopPropagation();
   return;
 }
 km=keyMod;
 if( U=== (k=kKeys[k]) ){ keyMod = 0; return; }
 if( km === kJump ) {
   rc = jumpY(k);
 }else if( km === kMark ) {
   rc = markY(k);
 }else {
  return;
 }
 statSay();
 if(rc) e.preventDefault(),e.stopPropagation();
 }catch(e){console.log('smth wromg\n'+e)};
}

function mk(p, t, id, s) {
  var e = D.createElement(t);
  e.id=id;
  e.style.cssText = s;
  return p.appendChild(e);
};

/* RIP status bar replacement */
var sb;
function _css(){
if(!sb) sb = mk(
//D.body,
D.documentElement, // 2014-06-30 ???!!1
'section', "Y-marker-userjs-inf",
"position: fixed!important;\
z-index: 214748!important;\
top: 0px; right: 1px; bottom: auto; left: auto;\
background: rgba(221,255,221,.75);\
padding: 2px 3px 2px 8px; margin:0;\
border: none;\
border-radius: 12px 3px 3px 12px; \
color: #131;\
opacity: 1; display:none;\
font: normal 12px/14px sans-serif !important;\
text-shadow: #373 2px 2px 4px, #7F7 -2px -2px 4px;\
cursor:no-drop;\
"
);
/* click removes all  */
if(tipShowtime>0){
 sb.addEventListener("click",function (e) {
  locStor.removeItem(Ym);
  ldYm(); noTout();
 },false);
};
}

var tO;
function onTout(){
 tO=0; sb.style.display="none";
}
function noTout(){
 if(tO) clearTimeout(tO), onTout();
}

function statSay(t) {
 if(statMsg){
 _css();
   if(tipShowtime)
     W.status=statMsg;
   if(tipShowtime>0){
     noTout();
     sb.innerHTML= statMsg;
     sb.style.display="block";
     tO=setTimeout(onTout, (t? t: tipShowtime)*1000);
   }
 }
 statMsg="";
}

Ym="Ym#"+location.pathname;
_L("load: "+location+"\n >> "+Ym);

ldYm();
for(var k=1; k<2; k++){ /* pz.length */
 if(pz[k]>-1){
  scroll(0,pz[k]);
  msg('jump',k,pz[k]);
  statSay(5);
  break;
 }
};

if(noCoo)  msg(noCoo),   statSay(5);

addEventListener("keydown",onKeydown,false);
addEventListener("keyup",klear,false);

})();
<commit_msg>Y-marker.user.js<commit_after>// ==UserScript==
// @name        Y-marker
// @namespace   trespassersW
// @description Sets up keyboard shortcuts for placing bookmarks and navigation inside webpage.
// @include        http://*
// @include        https://*
// @include        file://*
// ** about:config -> greasemonkey.fileIsGreaseable <- true
// @version 16.02.22
// @license  MIT
// @released 2013-12-11
// @run-at document-end
// @grant GM_getValue
// @grant GM_setValue
// @grant unsafeWindow
// ==/UserScript==
/*
 16.02.22 [+] press Alt-Shift-0 twice to set starting Y-position for whole domain; [*] markers moved to GM_storage.
 * 13-12-12 click on msg removes all marks
 * 1.1 don't run in editable fields
*/
(function(){ "use strict";
if(top!=self || !document || !document.body ) return;
var W = unsafeWindow || window; // localStorage doesn't live in sandbox?
/* key kombinations to invoke the skript */
var kShift = 1,  kCtrl = 2, kAlt = 4, kWin = 8;
var kJump = kAlt;
var kMark = kAlt+kShift;

/* sec; 0 to disable; -1 status bar only */
var tipShowtime = 2.2;

var kNobs = "-0123456789";
var kKeys = {
 173: 0, 48: 1, 49: 2, 50: 3, 51: 4, 52: 5, 53: 6, 54: 7, 55: 8, 56: 9, 57: 10,
 189: 0, /* chrome, opera caps lock */
 109: 0  /* opera */
};
var minus1="-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1";
var LH=location.hostname || "Ym", LHP=LH+location.pathname;

function kNob(k){ return kNobs.charAt(k); }

var U=undefined, D=window.document;
var _L=  function() {};
//_L=console.log.bind(console);

var statMsg;
function msg(t,k, y){
 statMsg = "";
 if(U!==k)
  statMsg += "["+kNob(k)+"] ";
 if(U!==y)
  statMsg += ""+pt(y)+"% ";
 statMsg += t+ (noCoo ? "\u2262 ": "");
}

var locStor,locStored;
var noCoo;
// see SQlite manager -> %FFpath%\webappstore.sqlite -> find -> key -> contains Ym#

try {
  locStor = W.localStorage;
  locStored=locStor.getItem("Ym#"+location.pathname);
} catch(e){ locStor = locStored =null;  };

function pt(y) {
 try{
  y =Math.round(y*1000/(document.body.scrollHeight+1))/10;
 }catch(e){console.log("math\n"+e); return -1}
 return y;
}

var Ym;
var pz;

function ldYm(){
  var s;
  if(locStor && locStored){
    pz=locStored.split(",");
    svYm();
    locStor.removeItem("Ym#"+location.pathname);
    console.log('Ym: locS -> GM_S '+LHP);
    locStor = locStored = null;
  }
  s=GM_getValue(Ym,null);
  if(!s){ s=minus1;
  }else try{
    var y=JSON.parse(s);
    s=y[LHP] || y[LH] || minus1;
  }catch(e){console.log('ldYm: buggy data\n'+e)};
  pz=s.split(",");
}

function svYm(d){
 var y={},s=pz.join(",");
 try{
   y=JSON.parse(GM_getValue(Ym,'{}'));
 }catch(e){console.log('svYm: buggy data\n'+e);}
 if(!d) y[LHP]= s;
 else{ //  marker for whole domain
     y[LH]= s;
 }
 //_L((d?LH:LHP)+": saved "+s);
 GM_setValue(Ym,JSON.stringify(y));
}

function rmYm(){
 var y={};
 try{
   y=JSON.parse(GM_getValue(Ym,'{}'));
 }catch(e){console.log('rmYm: buggy data\n'+e); y={}; }
  if(y[LH]) delete y[LH],  _L("rmH: " +LH);
  if(y[LHP]) delete y[LHP],  _L("rmHP: " +LHP);
 GM_setValue(Ym,JSON.stringify(y));
 pz=minus1.split(",");
}

function jumpY(k){
 var y=pz[k];
 if(y > -1) {
   if( y!= scrollY ){
    pz[0] = scrollY;
    scroll(0,y);
    msg("jump",k,y);
   }else
    msg("here",k,y);
   return 1;
 }
 msg("none",k);
 return 0;
}

function markY(k){
 var d="";
 if(k==1 && scrollY == pz[k] ) d="!";
 pz[k]=scrollY;
 if(k>=1)
  svYm(d);
 msg("mark"+d,k,pz[k]);
 return 1;
}

var kMap= {16: kShift, 17:kCtrl, 18: kAlt, 91: kWin};
var keyMod=0;
var kkWin= (kMark | kJump) & kWin;

function klear(e) {
 var k= e.keyCode;
 if(!k) return;
 var km=kMap[k];
 if(km) {
  keyMod &= -1 ^ km;
 }
}

function onKeydown(e) {
 try{
 var rc=0, k= e.keyCode;
 if(!k) return;
 // Don't run in input, select, textarea etc.
 var E = D.activeElement.tagName.toLowerCase();
 if (E == "input" || E == "select" || E == "textarea" ||
    (E=D.activeElement.contentEditable) == "true" ||
     E == "")
   {  keyMod = 0; return; }

 var km =kMap[k]; // ff doesnt track metaKey. stsuko
 if(km) {
   keyMod |= km;
   if( kkWin && km === kWin ) //???
    e.preventDefault(), e.stopPropagation();
   return;
 }
 km=keyMod;
 if( U=== (k=kKeys[k]) ){ keyMod = 0; return; }
 if( km === kJump ) {
   rc = jumpY(k);
 }else if( km === kMark ) {
   rc = markY(k);
 }else {
  return;
 }
 statSay();
 if(rc) e.preventDefault(),e.stopPropagation();
 }catch(e){console.log('smth wromg\n'+e)};
}

function mk(p, t, id, s) {
  var e = D.createElement(t);
  e.id=id;
  e.style.cssText = s;
  return p.appendChild(e);
};

/* RIP status bar replacement */
var sb;
function _css(){
if(!sb) sb = mk(
//D.body,
D.documentElement, // 2014-06-30 ???!!1
'section', "Y-marker-userjs-inf",
"position: fixed!important;\
z-index: 214748!important;\
top: 0px; right: 1px; bottom: auto; left: auto;\
background: rgba(221,255,221,.75);\
padding: 2px 3px 2px 8px; margin:0;\
border: none;\
border-radius: 12px 3px 3px 12px; \
color: #131;\
opacity: 1; display:none;\
font: normal 12px/14px sans-serif !important;\
text-shadow: #373 2px 2px 4px, #7F7 -2px -2px 4px;\
cursor:no-drop;\
"
);
/* click removes all  */
if(tipShowtime>0){
 sb.addEventListener("click",function (e) {
  rmYm(); //locStor.removeItem(Ym);
  ldYm(); noTout();
 },false);
};
}

var tO;
function onTout(){
 tO=0; sb.style.display="none";
}
function noTout(){
 if(tO) clearTimeout(tO), onTout();
}

function statSay(t) {
 if(statMsg){
 _css();
   if(tipShowtime)
     W.status=statMsg;
   if(tipShowtime>0){
     noTout();
     sb.innerHTML= statMsg;
     sb.style.display="block";
     tO=setTimeout(onTout, (t? t: tipShowtime)*1000);
   }
 }
 statMsg="";
}

Ym="Ym#";//+location.pathname;

ldYm();
for(var k=1; k<2; k++){ /* pz.length */
 if(pz[k]>-1){
  scroll(0,pz[k]);
  msg('jump',k,pz[k]);
  statSay(5);
  break;
 }
};

if(noCoo)  msg(noCoo),   statSay(5);

addEventListener("keydown",onKeydown,false);
addEventListener("keyup",klear,false);

})();
<|endoftext|>


<commit_before>'use strict'

var Transaction = require('./transaction')
var request = require('../request')

var MAX_QUEUE_SIZE = Infinity
var MAX_SEND_DELAY = 60000

var Instrumentation = module.exports = function (client) {
  if (!(this instanceof Instrumentation)) return new Instrumentation(client)
  this._client = client
  this._queue = []
}

Instrumentation.prototype.add = function (transaction) {
  if (this._client.active && this._ff_instrument) this._queue.push(transaction)
  if (this._queue.length >= MAX_QUEUE_SIZE) this._send()
  else if (this._queue.length && !this._timeout) this._queueSend()
}

Instrumentation.prototype.startTransaction = function (name, type, result) {
  return new Transaction(this._client, name, type, result)
}

Instrumentation.prototype._send = function () {
  clearTimeout(this._timeout)
  this._timeout = null
  request.transactions(this._client, this._flush()) // TODO: Maybe add callback and re-queue stuff incase of a transmission error?
}

Instrumentation.prototype._queueSend = function () {
  this._timeout = setTimeout(this._send.bind(this), MAX_SEND_DELAY) // TODO: Should we unref the _timeout?
}

Instrumentation.prototype._flush = function () {
  var transactions = groupTransactions(this._queue)
  var traces = groupTraces([].concat.apply([], this._queue.map(function (trans) {
    return trans.traces
  })))
  this._queue = []
  return { transactions: transactions, traces: traces }
}

function groupTransactions (transactions) {
  var groups = groupByMinute(transactions, transactionGroupingKey)

  return Object.keys(groups).map(function (key) {
    var trans = groups[key][0]
    var durations = groups[key].map(function (trans) {
      return trans.duration()
    })
    return {
      transaction: trans.name,
      result: trans.result,
      kind: trans.type,
      timestamp: groupingTs(trans._start).toISOString(),
      durations: durations
    }
  })
}

function groupTraces (traces) {
  var groups = groupByMinute(traces, traceGroupingKey)

  return Object.keys(groups).map(function (key) {
    var trace = groups[key][0]
    var startTimeSum = 0
    var durations = groups[key].map(function (trace) {
      startTimeSum += trace.startTime()
      return [trace.duration(), trace.transaction.duration()]
    })
    return {
      transaction: trace.transaction.name,
      signature: trace.signature,
      durations: durations,
      start_time: startTimeSum / groups[key].length,
      kind: trace.type,
      timestamp: groupingTs(trace._start).toISOString(),
      frames: [], // TODO
      parents: trace.ancestors(),
      extra: trace.extra || {}
    }
  })
}

function groupByMinute (arr, grouper) {
  var groups = {}

  arr.forEach(function (obj) {
    var key = grouper(obj)
    if (key in groups) groups[key].push(obj)
    else groups[key] = [obj]
  })

  return groups
}

function groupingTs (ts) {
  return new Date(ts.getFullYear(), ts.getMonth(), ts.getDate(), ts.getHours(), ts.getMinutes())
}

function transactionGroupingKey (trans) {
  return groupingTs(trans._start).getTime() + '|' + trans.name + '|' + trans.result + '|' + trans.type
}

function traceGroupingKey (trace) {
  var ancestors = trace.ancestors().map(function (trace) { return trace.signature }).join(',')
  return groupingTs(trace._start).getTime() + '|' + trace.transaction.name + '|' + ancestors + '|' + trace.signature + '|' + trace.type
}
<commit_msg>Fix check of instrument feature flag<commit_after>'use strict'

var Transaction = require('./transaction')
var request = require('../request')

var MAX_QUEUE_SIZE = Infinity
var MAX_SEND_DELAY = 60000

var Instrumentation = module.exports = function (client) {
  if (!(this instanceof Instrumentation)) return new Instrumentation(client)
  this._client = client
  this._queue = []
}

Instrumentation.prototype.add = function (transaction) {
  if (this._client.active && this._client._ff_instrument) this._queue.push(transaction)
  if (this._queue.length >= MAX_QUEUE_SIZE) this._send()
  else if (this._queue.length && !this._timeout) this._queueSend()
}

Instrumentation.prototype.startTransaction = function (name, type, result) {
  return new Transaction(this._client, name, type, result)
}

Instrumentation.prototype._send = function () {
  clearTimeout(this._timeout)
  this._timeout = null
  request.transactions(this._client, this._flush()) // TODO: Maybe add callback and re-queue stuff incase of a transmission error?
}

Instrumentation.prototype._queueSend = function () {
  this._timeout = setTimeout(this._send.bind(this), MAX_SEND_DELAY) // TODO: Should we unref the _timeout?
}

Instrumentation.prototype._flush = function () {
  var transactions = groupTransactions(this._queue)
  var traces = groupTraces([].concat.apply([], this._queue.map(function (trans) {
    return trans.traces
  })))
  this._queue = []
  return { transactions: transactions, traces: traces }
}

function groupTransactions (transactions) {
  var groups = groupByMinute(transactions, transactionGroupingKey)

  return Object.keys(groups).map(function (key) {
    var trans = groups[key][0]
    var durations = groups[key].map(function (trans) {
      return trans.duration()
    })
    return {
      transaction: trans.name,
      result: trans.result,
      kind: trans.type,
      timestamp: groupingTs(trans._start).toISOString(),
      durations: durations
    }
  })
}

function groupTraces (traces) {
  var groups = groupByMinute(traces, traceGroupingKey)

  return Object.keys(groups).map(function (key) {
    var trace = groups[key][0]
    var startTimeSum = 0
    var durations = groups[key].map(function (trace) {
      startTimeSum += trace.startTime()
      return [trace.duration(), trace.transaction.duration()]
    })
    return {
      transaction: trace.transaction.name,
      signature: trace.signature,
      durations: durations,
      start_time: startTimeSum / groups[key].length,
      kind: trace.type,
      timestamp: groupingTs(trace._start).toISOString(),
      frames: [], // TODO
      parents: trace.ancestors(),
      extra: trace.extra || {}
    }
  })
}

function groupByMinute (arr, grouper) {
  var groups = {}

  arr.forEach(function (obj) {
    var key = grouper(obj)
    if (key in groups) groups[key].push(obj)
    else groups[key] = [obj]
  })

  return groups
}

function groupingTs (ts) {
  return new Date(ts.getFullYear(), ts.getMonth(), ts.getDate(), ts.getHours(), ts.getMinutes())
}

function transactionGroupingKey (trans) {
  return groupingTs(trans._start).getTime() + '|' + trans.name + '|' + trans.result + '|' + trans.type
}

function traceGroupingKey (trace) {
  var ancestors = trace.ancestors().map(function (trace) { return trace.signature }).join(',')
  return groupingTs(trace._start).getTime() + '|' + trace.transaction.name + '|' + ancestors + '|' + trace.signature + '|' + trace.type
}
<|endoftext|>


<commit_before>/**
 * Commands
 * Cassius - https://github.com/sirDonovan/Cassius
 *
 * This file contains the base commands for Cassius.
 *
 * @license MIT license
 */

'use strict';

let commands = {
	// Developer commands
	js: 'eval',
	eval: function (target, room, user) {
		if (!user.isDeveloper()) return;
		try {
			target = eval(target);
			this.say(JSON.stringify(target));
		} catch (e) {
			this.say(e.name + ": " + e.message);
		}
	},

	// Informational commands
	about: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		room.say(Config.username + " code by sirDonovan: https://github.com/sirDonovan/Cassius with additions made by Spooktune~");
	},

	beep: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		room.say("boop");
	},

	argbeep: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		room.say("/me boops " + target);
	},

	intro: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("/addhtmlbox
Welcome to Scrabble!
 PS Scrabble Website

Play Scrabble!

");
	},

	roomdesc: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("/addhtmlbox
Play Scrabble with friends, join Scrabble tournaments, and compete in the exciting new Scrabblemons metagame!
");
	},

	pwogg: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("What will Snap break this time?");
	},

	nt: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("this is why I don't play with timer.");
	},

	play: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say('/addhtmlbox  Welcome to Scrabble! Click to play! <button style="background-color: #c90100; border-radius: 5px; border: solid, 1px, white; color: white; font-size: 12px; padding: 3px 5px; font-weight: bold; auto; box-shadow:2px 2px black; transform: skew(-15deg);display:inline-block;margin-top:10px">Play!</button>');
	},

	dab: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		room.say("/me dabs");
	},

	argdab: function (target, room, user) {
        if (room !== user && !user.hasRank(room, '+')) return;
        room.say("/me dabs on " + target);
    },

	argdunk: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		room.say("/me dunks on " + target);
	},

	git: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		room.say("https://github.com/DatSpookTho/Pwogg");
	},

	scrabmonstour: function (target, room, user) {
        if (room === user || !user.hasRank(room, '+')) return;
        room.say('/tour create gen 7 ou, elimination');
        room.say('/tour name Scrabblemons');
	},

    tourofficial: function (target, room, user) {
        if (room === user || !user.hasRank(room, '%')) return;
		room.say('/tour create gen 7 ou, elimination');
		room.say('/tour name Scrabblemons');
		room.say("/wall Hosting a scrabgame of Official Scrabblemons Tour! Click the join button to participate! Check http://scrabble-ps.weebly.com/scrabble-mons-guide.html if you don't know how to play!");
    },

    tourstart: function (target, room, user) {
		if (room === user || !user.hasRank(room, '%')) return;
		room.say('/tour start');
		room.say('/wall Good luck to everyone!');
	},

    scrabtour: function (target, room, user) {
        if (room === user || !user.hasRank(room, '+')) return;
        room.say('/wall Hosting a scrabgame of Official Scrabble Tour! It will be ran through challonge and the host will post a link after signups are closed! Do /me in to join!')
    },

	scrabword: 'scrabwords',
	scrabwords: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		let num = parseInt(target);
		if (!num || num < 1) num = 1;
		if (num === 1) {
			room.say(Tools.sample(Tools.words.sixletter));
		} else if (num === 2) {
			room.say(Tools.sample(Tools.words.sixletter, 2).join(", "));
		} else {
			let first = Tools.sample(Tools.words.sixletter, num - 1);
			room.say(first.join(", ") + " and " + Tools.sample(Tools.words.sixletter));
		}
	},

	scrabword1v1: 'scrabwords1v1',
	scrabwords1v1: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		let num = parseInt(target);
		if (!num || num < 1) num = 1;
		if (num === 1) {
			room.say(Tools.sample(Tools.words.threeletter));
		} else if (num === 2) {
			room.say(Tools.sample(Tools.words.threeletter, 2).join(", "));
		} else {
			let first = Tools.sample(Tools.words.threeletter, num - 1);
			room.say(first.join(", ") + " and " + Tools.sample(Tools.words.threeletter));
		}
	},

	answer: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		let aa = ["No", "Dont touch me", "Yes!", "Please try again later", "Probably", "/me does a barrel roll", "Pw-ogg has obliterated your question using a potato chip and a pair of dice. try again later", "can you not", "soon™", "Yes ma'am", "Tis i, the frenchist fry, Tis u, i have no clue.", "/me grinds question into a pulp", "i mean yeah i guess", "chances are that is a no", "can i get a number nine large with extra dip and a side of not going to happen", "no, try a healthy dose of Pw-ogg™ instead!"];
		room.say(Tools.sample(aa));
	},

	//client.send("scrabble|/mn
	// Game commands
	signups: 'creategame',
	creategame: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		if (!Config.games || !Config.games.includes(room.id)) return this.say("Games are not enabled for this room.");
		if (!Games.createGame(target, room)) return;
		room.game.signups();
	},
	start: 'startgame',
	startgame: function (target, room, user) {
		if (!room.game || !user.hasRank(room, '+')) return;
		room.game.start();
	},
	end: 'endgame',
	endgame: function (target, room, user) {
		if (!room.game || !user.hasRank(room, '+')) return;
		room.game.forceEnd();
	},
	join: 'joingame',
	joingame: function (target, room, user) {
		if (!room.game) return;
		room.game.join(user);
	},
	leave: 'leavegame',
	leavegame: function (target, room, user) {
		if (!room.game) return;
		room.game.leave(user);
	},

	//memes
	topaz: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Excadrill");
	},
	ard: 'arandom',
	arandom: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Ducklett");
	},

	spook: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Heatmor");
	},

	snap: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Misdreavus");
	},

	dsg: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Giratina-Origin");
	},

	order: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Zygarde-10%");
	},

	azu: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Celebi");
	},

	sty: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Drifblim");
	},

	qtie: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Glameow");
	},

	moo: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Miltank");
	},

	swag: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Black Glasses");
	},
};

module.exports = commands;<commit_msg>what are pwoggs<commit_after>/**
 * Commands
 * Cassius - https://github.com/sirDonovan/Cassius
 *
 * This file contains the base commands for Cassius.
 *
 * @license MIT license
 */

'use strict';

let commands = {
	// Developer commands
	js: 'eval',
	eval: function (target, room, user) {
		if (!user.isDeveloper()) return;
		try {
			target = eval(target);
			this.say(JSON.stringify(target));
		} catch (e) {
			this.say(e.name + ": " + e.message);
		}
	},

	// Informational commands
	about: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		room.say(Config.username + " code by sirDonovan: https://github.com/sirDonovan/Cassius with additions made by Spooktune~");
	},

	beep: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		room.say("boop");
	},

	argbeep: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		room.say("/me boops " + target);
	},

	intro: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("/addhtmlbox
Welcome to Scrabble!
 PS Scrabble Website

Play Scrabble!

");
	},

	roomdesc: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("/addhtmlbox
Play Scrabble with friends, join Scrabble tournaments, and compete in the exciting new Scrabblemons metagame!
");
	},

	pwogg: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("Pw-ogg is named Pw-ogg because of a fictional species called Woggs made by global voice __SUNFISHED__, and whilst coming up with different names for said species, came up Poggs, combining the two came Pwogg!");
	},

	nt: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("this is why I don't play with timer.");
	},

	play: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say('/addhtmlbox  Welcome to Scrabble! Click to play! <button style="background-color: #c90100; border-radius: 5px; border: solid, 1px, white; color: white; font-size: 12px; padding: 3px 5px; font-weight: bold; auto; box-shadow:2px 2px black; transform: skew(-15deg);display:inline-block;margin-top:10px">Play!</button>');
	},

	dab: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		room.say("/me dabs");
	},

	argdab: function (target, room, user) {
        if (room !== user && !user.hasRank(room, '+')) return;
        room.say("/me dabs on " + target);
    },

	argdunk: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		room.say("/me dunks on " + target);
	},

	git: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		room.say("https://github.com/DatSpookTho/Pwogg");
	},

	scrabmonstour: function (target, room, user) {
        if (room === user || !user.hasRank(room, '+')) return;
        room.say('/tour create gen 7 ou, elimination');
        room.say('/tour name Scrabblemons');
	},

    tourofficial: function (target, room, user) {
        if (room === user || !user.hasRank(room, '%')) return;
		room.say('/tour create gen 7 ou, elimination');
		room.say('/tour name Scrabblemons');
		room.say("/wall Hosting a scrabgame of Official Scrabblemons Tour! Click the join button to participate! Check http://scrabble-ps.weebly.com/scrabble-mons-guide.html if you don't know how to play!");
    },

    tourstart: function (target, room, user) {
		if (room === user || !user.hasRank(room, '%')) return;
		room.say('/tour start');
		room.say('/wall Good luck to everyone!');
	},

    scrabtour: function (target, room, user) {
        if (room === user || !user.hasRank(room, '+')) return;
        room.say('/wall Hosting a scrabgame of Official Scrabble Tour! It will be ran through challonge and the host will post a link after signups are closed! Do /me in to join!')
    },

	scrabword: 'scrabwords',
	scrabwords: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		let num = parseInt(target);
		if (!num || num < 1) num = 1;
		if (num === 1) {
			room.say(Tools.sample(Tools.words.sixletter));
		} else if (num === 2) {
			room.say(Tools.sample(Tools.words.sixletter, 2).join(", "));
		} else {
			let first = Tools.sample(Tools.words.sixletter, num - 1);
			room.say(first.join(", ") + " and " + Tools.sample(Tools.words.sixletter));
		}
	},

	scrabword1v1: 'scrabwords1v1',
	scrabwords1v1: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		let num = parseInt(target);
		if (!num || num < 1) num = 1;
		if (num === 1) {
			room.say(Tools.sample(Tools.words.threeletter));
		} else if (num === 2) {
			room.say(Tools.sample(Tools.words.threeletter, 2).join(", "));
		} else {
			let first = Tools.sample(Tools.words.threeletter, num - 1);
			room.say(first.join(", ") + " and " + Tools.sample(Tools.words.threeletter));
		}
	},

	answer: function (target, room, user) {
		if (room !== user && !user.hasRank(room, '+')) return;
		let aa = ["No", "Dont touch me", "Yes!", "Please try again later", "Probably", "/me does a barrel roll", "Pw-ogg has obliterated your question using a potato chip and a pair of dice. try again later", "can you not", "soon™", "Yes ma'am", "Tis i, the frenchist fry, Tis u, i have no clue.", "/me grinds question into a pulp", "i mean yeah i guess", "chances are that is a no", "can i get a number nine large with extra dip and a side of not going to happen", "no, try a healthy dose of Pw-ogg™ instead!"];
		room.say(Tools.sample(aa));
	},

	//client.send("scrabble|/mn
	// Game commands
	signups: 'creategame',
	creategame: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		if (!Config.games || !Config.games.includes(room.id)) return this.say("Games are not enabled for this room.");
		if (!Games.createGame(target, room)) return;
		room.game.signups();
	},
	start: 'startgame',
	startgame: function (target, room, user) {
		if (!room.game || !user.hasRank(room, '+')) return;
		room.game.start();
	},
	end: 'endgame',
	endgame: function (target, room, user) {
		if (!room.game || !user.hasRank(room, '+')) return;
		room.game.forceEnd();
	},
	join: 'joingame',
	joingame: function (target, room, user) {
		if (!room.game) return;
		room.game.join(user);
	},
	leave: 'leavegame',
	leavegame: function (target, room, user) {
		if (!room.game) return;
		room.game.leave(user);
	},

	//memes
	topaz: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Excadrill");
	},
	ard: 'arandom',
	arandom: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Ducklett");
	},

	spook: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Heatmor");
	},

	snap: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Misdreavus");
	},

	dsg: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Giratina-Origin");
	},

	order: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Zygarde-10%");
	},

	azu: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Celebi");
	},

	sty: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Drifblim");
	},

	qtie: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Glameow");
	},

	moo: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Miltank");
	},

	swag: function (target, room, user) {
		if (!user.hasRank(room, '+')) return;
		room.say("!dt Black Glasses");
	},
};

module.exports = commands;<|endoftext|>


<commit_before>'use strict'

const occupy = require('./occupy-window')

module.exports = WindowWrapper

function WindowWrapper (window, x, y) {
  this.id = window.id
  const bounds = window.constructor.name === 'BrowserWindow'
    ? window.getBounds()
    : {
      width: window.width,
      height: window.height,
      x: x || 0,
      y: y || 0
    }
  bounds.x = x || bounds.x || 0
  bounds.y = y || bounds.y || 0
  this.width = bounds.width
  this.height = bounds.height
  this.x = bounds.x
  this.y = bounds.y
  this.window = window
  if (this.window.constructor.name === 'BrowserWindow') {
    this.window.setBounds(bounds)
  }
}

WindowWrapper.prototype.changeSize = function (width, height) {
  this.grid.representation = occupy(
    this.grid.representation,
    Object.assign({}, this, { width, height }),
    Object.assign({}, this)
  )
  this.width = width
  this.height = height
  if (this.window.constructor.name === 'BrowserWindow') {
    const bounds = this.window.getBounds()
    this.window.setBounds(Object.assign({}, bounds, {width, height}))
  }
}

WindowWrapper.prototype.changeLocation = function (x, y) {
  this.grid.representation = occupy(
    this.grid.representation,
    Object.assign({}, this, { x, y }),
    this
  )
  this.x = x
  this.y = y
  if (this.window.constructor.name === 'BrowserWindow') {
    const bounds = this.window.getBounds()
    this.window.setBounds(Object.assign({}, bounds, {x, y}))
  }
}
<commit_msg>validate window params<commit_after>'use strict'

const occupy = require('./occupy-window')
const assert = require('assert')
const validate = require('validate.js')

module.exports = WindowWrapper

function WindowWrapper (window, xPos, yPos) {
  const x = xPos || 0
  const y = yPos || 0
  assert(validate.isInteger(x))
  assert(validate.isInteger(y))
  assert(validate.isObject(window))
  this.id = window.id
  const bounds = window.constructor.name === 'BrowserWindow'
    ? window.getBounds()
    : {
      width: window.width,
      height: window.height,
      x: x || 0,
      y: y || 0
    }
  bounds.x = x || bounds.x || 0
  bounds.y = y || bounds.y || 0
  this.width = bounds.width
  this.height = bounds.height
  this.x = bounds.x
  this.y = bounds.y
  this.window = window
  if (this.window.constructor.name === 'BrowserWindow') {
    this.window.setBounds(bounds)
  }
}

WindowWrapper.prototype.changeSize = function (width, height) {
  this.grid.representation = occupy(
    this.grid.representation,
    Object.assign({}, this, { width, height }),
    Object.assign({}, this)
  )
  this.width = width
  this.height = height
  if (this.window.constructor.name === 'BrowserWindow') {
    const bounds = this.window.getBounds()
    this.window.setBounds(Object.assign({}, bounds, {width, height}))
  }
}

WindowWrapper.prototype.changeLocation = function (x, y) {
  this.grid.representation = occupy(
    this.grid.representation,
    Object.assign({}, this, { x, y }),
    this
  )
  this.x = x
  this.y = y
  if (this.window.constructor.name === 'BrowserWindow') {
    const bounds = this.window.getBounds()
    this.window.setBounds(Object.assign({}, bounds, {x, y}))
  }
}
<|endoftext|>