<commit_before>describe("Game is created", function() {
    it("creates a stage", function() {
       var ExpectedStage = new Kinetic.Stage({
        container: 'container',
        width: 500,
        height: 600
    });
        var ActualStage = gameFactory.createGame();
        expect(ActualStage.attrs).toEqual(ExpectedStage.attrs);
    });

    it("creates a game board", function() {
        var Expected_game_board = new Kinetic.Group({
            x: 50,
            y: 80
        });
        var Actual_game_board = gameFactory.createGameboard();
        //Kinetic objects are a bit complex, if you just grab attrs, it contains the attributes we actually set, such as x and y here
        expect(Actual_game_board.attrs).toEqual(Expected_game_board.attrs);
    });

    it("creates 3 boxes and draws them on the game board", function() {
        expect(true).toEqual(true);
    });

    it("adds game board to game board layer", function() {
        expect(true).toEqual(true);
    });

    it("creates 9 red and 9 white game pieces and adds to game board layer", function() {
        expect(true).toEqual(true);
    });

    it("adds game board layer to the stage", function() {
        expect(true).toEqual(true);
    });
});
<commit_msg>Added unit tests for creating gameboard and gamepiece<commit_after>describe("Game is created", function() {

    beforeEach(function() {
	  this.gameFactory = new GameBoard(50, 80, {biggest_side: 400, middle_side: 270, smallest_side:140});
    });

    it("sets x", function(){
	expect(50).toEqual(this.gameFactory.x);
    });

    it("sets y", function(){
	expect(80).toEqual(this.gameFactory.y);
    });

    it("sets box lengths", function(){
	expect({biggest_side: 400, middle_side: 270, smallest_side:140}).toEqual(this.gameFactory.box_lengths);
    });

    it("sets side length", function(){
	expect(400).toEqual(this.gameFactory.sideLength);
    });

    it("starts in phase one at game start", function(){
	expect(true).toEqual(this.gameFactory.in_phase_1());
    });

    it("does not start in phase 2 at game start", function(){
	expect(false).toEqual(this.gameFactory.in_phase_2());
    });

    it("does not start in phase 3 at game start", function(){
	expect(false).toEqual(this.gameFactory.in_phase_3());
    });

    it("creates 18 game pieces", function(){
	expect(18).toEqual(this.gameFactory.gamePieceArray.length);
    });

    it("creates 24 game spaces", function(){
	expect(24).toEqual(this.gameFactory.gameSpaceArray.length);
    });

    it("creates a stage", function() {

       //this.gameFactory = new GameBoard(50, 80, {biggest_side: 400, middle_side: 270, smallest_side:140});

       var ExpectedStage = new Kinetic.Stage({
        container: 'container',
        width: 500,
        height: 600
    });

        var ActualStage = this.gameFactory.stageContainer;
        expect(ActualStage.attrs).toEqual(ExpectedStage.attrs);
    });

    it("creates a game board", function() {

	//var gameFactory = new GameBoard(50, 80, {biggest_side: 400, middle_side: 270, smallest_side:140});

        var Expected_game_board = new Kinetic.Group({
            x: 50,
            y: 80
        });
        var Actual_game_board = this.gameFactory.game_board;
        //Kinetic objects are a bit complex, if you just grab attrs, it contains the attributes we actually set, such as x and y here
        expect(Actual_game_board.attrs).toEqual(Expected_game_board.attrs);
    });

    it("sets only one piece to movable", function(){

	var countDraggable = 0;

	for(var i = 0; i < this.gameFactory.gamePieceArray.length; i++){
	    if(this.gameFactory.gamePieceArray[i].circle.draggable()){
	       countDraggable++;
	    }
	}

	expect(1).toEqual(countDraggable);
    });

    it("sets the first white piece to movable", function(){
	expect(true).toEqual(this.gameFactory.gamePieceArray[17].circle.draggable());
    });

    it("creates 3 boxes and draws them on the game board", function() {
        expect(true).toEqual(true);
    });

    it("adds game board to game board layer", function() {
        expect(true).toEqual(true);
    });

    it("creates 9 red and 9 white game pieces and adds to game board layer", function() {
        expect(true).toEqual(true);
    });

    it("adds game board layer to the stage", function() {
        expect(true).toEqual(true);
    });
});

describe("Game piece is created", function() {

    beforeEach(function() {

	this.gameFactory = new GameBoard(50, 80, {biggest_side: 400, middle_side: 270, smallest_side:140});

	this.gamePiece = new GamePiece(      450,
					      30,
					      'red',
					      false,
					      this.gameFactory.gameBoardLayer,
					      this.gameFactory.gameSpaceArray,
					      0, this.gameFactory
				      );
    });

    it("creates a circle", function(){
	var Expected_circle = new Kinetic.Circle({
				      x: 450,
                                      y: 30,
                                      radius: 20,
                                      fill: 'red',
                                      stroke: 'black',
                                      strokeWidth: 2,
                                      draggable: false});

	expect(this.gamePiece.circle.attrs).toEqual(Expected_circle.attrs);
    });

    it("test the setDraggable function", function() {

	this.gamePiece.setDraggable(true);

        expect(true).toEqual(this.gamePiece.circle.draggable());
    });

    it("test the set_next function", function() {

	this.gamePiece.set_next(true);

        expect(true).toEqual(this.gamePiece.circle.next);
    });

    it("test the setInMill function", function() {

	this.gamePiece.setInMill();

        expect(false).toEqual(this.gamePiece.removable);
    });

});
<|endoftext|>


<commit_before>
//
// Test Model
// Defines which parts of our tests are mutable, and how to execute the test.
//
function Test(test){
	this.section = test.section || false;
	this.aside = test.aside || false;

	this.result = ko.observable();
	this.response = ko.observable();
	this.request = ko.observable();
	this.path = ko.observable(test.path);
	this.noauth = test.auth === false;
	this.side = test.aside || null;
	this.note = test.note || '';
	this.execute = test.execute || function(service,callback){
		var authResponse = hello.getAuthResponse(service);
		var test = this;
		var action = function(r){
			test.result('working');
			var data = JSON.parse(ko.toJSON(test.data.itemsAsObject()));
			var cb = function(r){

				// update the test
				var b = test.validate(r);

				// update model
				test.response(r);

				// update model
				test.result(b?'success':'failed');

				if(callback&&typeof(callback)==='function'){
					callback();
				}
			}

			if(test.method === 'login'){
				test.request( hello.login('knarly',data,cb) );
				return;
			}

			// Call hello.api
			// Save the request information
			test.request( hello.api(test.path(), test.method, data, cb) );
		};

		action({authResponse:authResponse});
	};
	this.method = test.method || 'get';
	this.data = new Dictionary( test.data || {} );
	this.validate = test.validate || function(r){return r && !("error" in r);};
	this.name = test.name || false;
	return this;
}

//
// When everything is loaded, we map `tests` to applyBindings
// Map the items in the JSON array 'tests' to the Test model and bind to Knockout
//
$(function(){
	// Bind model
	ko.applyBindings(ko.mapping.fromJS({tests:tests}, {tests : {create: function(options){return new Test(options.data);}}}));
});

/////////////////////////////////
//
// EXTENSIONS OF KNOCKOUT
//
/////////////////////////////////

//
// make contenteditable controller
// e.g.
ko.bindingHandlers.contenteditable = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        ko.utils.registerEventHandler(element, "keyup", function() {
            var modelValue = valueAccessor();
            var elementValue = element.innerHTML;
            if (ko.isWriteableObservable(modelValue)) {
                modelValue(elementValue);

            }
            else { //handle non-observable one-way binding
                var allBindings = allBindingsAccessor();
                if (allBindings['_ko_property_writers'] && allBindings['_ko_property_writers'].htmlValue) allBindings['_ko_property_writers'].htmlValue(elementValue);
            }
        }
                                     )
    },
    update: function(element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor()) || "";
        if (element.innerHTML !== value) {
            element.innerHTML = value;
        }
    }
};

//
// Bind beautifier handler
//
ko.bindingHandlers.beautify = {
    update: function(element, valueAccessor, allBindingsAccessor) {
		var value = ko.utils.unwrapObservable( valueAccessor() );

		value = (JSON.stringify(value,null,2)||'').replace(/https?:\/\/[^\'\"\s]+/ig, function(r){
			return r.link(r).replace('<a ', ' Value into mutable stores
//
function DictionaryItem(key, value) {
    this.key = ko.observable(key);
    this.value = ko.observable(value);
}

//
// Custom Dictionary observable in Knockout
// represent the dictionary object
//
function Dictionary(data) {
    this.items = ko.observableArray([]);
    for (field in data) {
        if (data.hasOwnProperty(field)) {
            this.items.push(new DictionaryItem(field, data[field]));
        }
    }

    this.addItem = function() {
        this.items.push(new DictionaryItem());
    }.bind(this);

    this.removeItem = function(item) {
        this.items.remove(item);
    }.bind(this);

    this.itemsAsObject = ko.dependentObservable(function() {
        var result = {};
        ko.utils.arrayForEach(this.items(), function(item) {
            result[item.key()] = item.value;
        });

        return result;
    }, this);
}<commit_msg>Update test<commit_after>
//
// Test Model
// Defines which parts of our tests are mutable, and how to execute the test.
//
function Test(test){
	this.section = test.section || false;
	this.aside = test.aside || false;

	this.result = ko.observable();
	this.response = ko.observable();
	this.request = ko.observable();
	this.path = ko.observable(test.path);
	this.noauth = test.auth === false;
	this.side = test.aside || null;
	this.note = test.note || '';
	this.execute = test.execute || function(service,callback){
		var authResponse = hello.getAuthResponse(service);
		var test = this;
		var action = function(r){
			test.result('working');
			var data = JSON.parse(ko.toJSON(test.data.itemsAsObject()));
			var cb = function(r){

				// update the test
				var b = test.validate(r);

				// passed?
				test.passed(b);

				// update model
				test.response(r);

				// update model
				test.result(b?'success':'failed');

				if(callback&&typeof(callback)==='function'){
					callback.call(test);
				}
			};

			if(test.method === 'login'){
				test.request( hello.login('knarly',data,cb) );
				return;
			}

			// Call hello.api
			// Save the request information
			test.request( hello.api(test.path(), test.method, data, cb) );
		};

		action({authResponse:authResponse});
	};
	this.method = test.method || 'get';
	this.data = new Dictionary( test.data || {} );
	this.validate = test.validate || function(r){return r && !("error" in r);};
	this.passed = ko.observable();
	this.name = test.name || false;
	return this;
}

//
// When everything is loaded, we map `tests` to applyBindings
// Map the items in the JSON array 'tests' to the Test model and bind to Knockout
//
$(function(){

	// Bind model
	var model = {
		tests:tests,
		executeTests: function(service){
			var self = this;
			// trigger test
			(function loop(i){
				var test = self.tests()[i];
				if(!test){
					return;
				}
				test.execute(service,function(){
					if(this.passed()){
						loop(++i);
					}
				});
			})(0);
		}
	};

	// Bind model
	// Map the data to TEST options.
	ko.applyBindings(ko.mapping.fromJS(model, {tests : {create: function(options){return new Test(options.data);}}}));
});

/////////////////////////////////
//
// EXTENSIONS OF KNOCKOUT
//
/////////////////////////////////

//
// make contenteditable controller
// e.g.
ko.bindingHandlers.contenteditable = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        ko.utils.registerEventHandler(element, "keyup", function() {
            var modelValue = valueAccessor();
            var elementValue = element.innerHTML;
            if (ko.isWriteableObservable(modelValue)) {
                modelValue(elementValue);

            }
            else { //handle non-observable one-way binding
                var allBindings = allBindingsAccessor();
                if (allBindings['_ko_property_writers'] && allBindings['_ko_property_writers'].htmlValue) allBindings['_ko_property_writers'].htmlValue(elementValue);
            }
        });
    },
    update: function(element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor()) || "";
        if (element.innerHTML !== value) {
            element.innerHTML = value;
        }
    }
};

//
// Bind beautifier handler
//
ko.bindingHandlers.beautify = {
    update: function(element, valueAccessor, allBindingsAccessor) {
		var value = ko.utils.unwrapObservable( valueAccessor() );

		value = (JSON.stringify(value,null,2)||'').replace(/https?:\/\/[^\'\"\s]+/ig, function(r){
			return r.link(r).replace('<a ', ' Value into mutable stores
//
function DictionaryItem(key, value) {
    this.key = ko.observable(key);
    this.value = ko.observable(value);
}

//
// Custom Dictionary observable in Knockout
// represent the dictionary object
//
function Dictionary(data) {
    this.items = ko.observableArray([]);
    for (var field in data) {
        if (data.hasOwnProperty(field)) {
            this.items.push(new DictionaryItem(field, data[field]));
        }
    }

    this.addItem = function() {
        this.items.push(new DictionaryItem());
    }.bind(this);

    this.removeItem = function(item) {
        this.items.remove(item);
    }.bind(this);

    this.itemsAsObject = ko.dependentObservable(function() {
        var result = {};
        ko.utils.arrayForEach(this.items(), function(item) {
            result[item.key()] = item.value;
        });

        return result;
    }, this);
}<|endoftext|>


<commit_before>// Copyright 2016 Joseph W. May. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * Returns an HTML-formatted string to display the imported gradebook
 * file selector.
 *
 * @returns An HTML-formatted string.
 */
function displayGradebooks() {
  var masteryTracker = new MasteryTracker();
  var gradebookSheets = masteryTracker.getUserCreatedSheets();
  var gradebookItems = constructSheetSelectItems_(gradebookSheets);

  // Construct the html form if there are imported gradebook sheets.
  var form = [];
  if (gradebookSheets.length > 0) {
    form.push('<form class="block" id="gradebooks">' +
        '
' +
          '
Scores will be imported from the following gradebooks. ' +
              'Uncheck a gradebook to skip it. Selected gradebooks ' +
              'must have identical assignments.
');

    // Construct the checkboxes for each assignment.
    form.push('
' +
        showCheckboxes('gradebooks', gradebookItems, true) +
      '

');

    // Construct the form control buttons.
    form.push('
' +
        '<input type="button" value="Select gradebooks" class="action" ' +
            'onclick="selectGradebooks_onclick();">' +
        showCloseButton() +
      '
</form>');
  } else {
    form.push('
' +
        '
' +
          'No gradebooks have been loaded into the tracker. ' +
          'You must complete step 1 first.' +
        '
' +
      '
' +
      showCloseButton());
  }

  return form.join('');
}

/**
 * Returns an HTML-formatted string to display the assignment selector.
 *
 * @returns An HTML-formatted string.
 */
function displayAssignments(sheetIds) {
  // Use the first selected assignment to get assignment names. This assumes
  // that all assignment names will be found in the other sheets...perhaps a
  // faulty assumption.
  // TODO: *** Add error catching for this ***
  var sheetId = sheetIds[0];

  // Save the current and remaining sheetIds for later use.
  var storage = new PropertyStore();
  storage.setProperty('sheetIds', sheetIds, true);

  var gradebook = new Gradebook(sheetId);
  var assignments = gradebook.getAssignmentNames();
  var assignmentItems = constructColumnSelectItems_(assignments, 2);

  // Construct the html form.
  var form = [];
  form.push('<form class="block" id="assignments">' +
    '
' +
      '
Select learning goal mastery data to import by checking the ' +
      'appropriate gradebook assignments below.
');

  // Construct the checkboxes for each assignment.
  form.push('
' +
      showCheckboxes('assignments', assignmentItems) +
    '

');

  // Construct the form control buttons.
  form.push('
' +
      '<input type="button" value="Select assignments" class="action" ' +
          'onclick="selectAssignments_onclick();">' +
      showCloseButton() +
    '
</form>');

  return form.join('');
}

/**
 * Returns an HTML-formatted string to display the mastery data importer form.
 *
 * @returns An HTML-formatted string.
 */
function displayMasteryData(assignments) {
  // Use the first selected assignment to get assignment names. This assumes
  // that all assignment names will be found in the other sheets...perhaps a
  // faulty assumption.
  // TODO: *** Add error catching for this ***
  var storage = new PropertyStore();
  var sheetIds = storage.getProperty('sheetIds', true);
  var sheetId = sheetIds[0];

  // Get the current gradebook.
  var gradebook = new Gradebook(sheetId);
  var masteryData = new MasteryData();

  // Construct the html form.
  var form = [];
  form.push('<form class="block" id="masteryData">' +
      '
' +
        '
Set the learning goal number and title for each imported ' +
           'assignment:
');

  // Construct assignments.
  form.push('
');
  for (var i = 0; i < assignments.length; i++) {
    form.push(
      '
' +
        '
' +
          '' +
            gradebook.getAssignmentName(assignments[i]) +
          '' +
        '
' +
        '
' +
          'Select learning goal:' +
            masteryData.getLearningGoalSelector() +
        '
' +
        '
' +
          'Learning goal title:' +
          '<input type="text" name="lgName" id="lgName">' +
        '
' +
        '
' +
          '' +
            '<input type="checkbox" name="retake"> Re-take ' +
            'This will add re-take data to a ' +
                'learning goal rather than replace existing data.' +
          '' +
        '
' +
        '<input type="hidden" name="assignment" value="' +
          assignments[i] +
        '">' +
      '
'
    );
  }
  form.push('
');

  // Construct the form control buttons.
  form.push('
' +
      '<input type="button" value="Import mastery data" class="action" ' +
          'onclick="importMasteryData_onclick();">' +
      showCloseButton() +
    '
</form>');

  return form.join('');
}

/**
 * Imports the given assignments into the respective learning goal columns of
 * the mastery data sheet. Takes into account whether an assignment is a retake.
 *
 * @param {array} assignments Array of assignment numbers to import.
 * @param {array} lgNums Array of learning goal numbers as targets for
 *     the import.
 * @param {array} lgNames Array of learning goal names for the import.
 * @param {array} retakes Array of booleans indicating which learning goals
 *     are to be imported as retakes.
 * @returns An HTML-formatted string dislaying the completion message and
 *     close button.
 */
function importMasteryData(assignments, lgNums, lgNames, retakes) {
  var storage = new PropertyStore();
  var sheetIds = storage.getProperty('sheetIds', true);
  var masteryData = new MasteryData();

  // Loop over the selected spreadsheets containing the imported gradebook data.
  for (var i = 0; i < sheetIds.length; i++) {
    var sheetId = sheetIds[i];
    var gradebook = new Gradebook(sheetId);

    // Get the class period.
    var period = gradebook.getClassPeriod();

    // Get the CC flag.
    var isCC = gradebook.isCC();

    // Verify that the imported data arrays are equal in length.
    if ((assignments.length !== lgNums.length) &&
            (lgNums.length !== lgNames.length) &&
            (lgNames.length !== retakes.length)) {
      throw new Error('There was a problem importing the data. ' +
              'Please try again later.');
    }

    // Loop over the selected learning goal numbers.
    for (var j = 0; j < lgNums.length; j++) {
      var assignment = assignments[j];
      var lgNum = lgNums[j];
      var lgName = lgNames[j];
      var retake = retakes[j];

      // Set the learning goal name if given.
      if (lgName !== undefined && lgName !== null && lgName !== '') {
        masteryData.setLearningGoalName(lgNum, lgName);
      }

      // Set the mastery scores after clearing the old data.
      // Append data for CC classes.
      var scores = gradebook.getAssignmentScores(assignment);
      if (isCC === false) {
        masteryData.clearLearningGoalScores(period, lgNum, retake);
        masteryData.setLearningGoalScores(period, lgNum, scores, retake);
      } else {
        masteryData.appendLearningGoalScores(period, lgNum, scores, retake);
      }
    }
  }

  // Construct display message and close button for return.
  var complete = 'Import complete. You may close this window and ' +
      'complete step 3.' +
      '
' +
        showCloseButton() +
      '
';

  return complete;
}<commit_msg>improved error messages and message display<commit_after>// Copyright 2016 Joseph W. May. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * Returns an HTML-formatted string to display the imported gradebook
 * file selector.
 *
 * @returns An HTML-formatted string.
 */
function displayGradebooks() {
  var masteryTracker = new MasteryTracker();
  var gradebookSheets = masteryTracker.getUserCreatedSheets();
  var gradebookItems = constructSheetSelectItems_(gradebookSheets);

  // Construct the html form if there are imported gradebook sheets.
  var form = [];
  if (gradebookSheets.length > 0) {
    form.push('<form class="block" id="gradebooks">' +
        '
' +
          '
Scores will be imported from the following gradebooks. ' +
              'Uncheck a gradebook to skip it. Selected gradebooks ' +
              'must have identical assignments.
');

    // Construct the checkboxes for each assignment.
    form.push('
' +
        showCheckboxes('gradebooks', gradebookItems, true) +
      '

');

    // Construct the form control buttons.
    form.push('
' +
        '<input type="button" value="Select gradebooks" class="action" ' +
            'onclick="selectGradebooks_onclick();">' +
        showCloseButton() +
      '
</form>');
  } else {
    form.push('
' +
        '
' +
          'No gradebooks have been loaded into the tracker. ' +
          'You must complete step 1 first.' +
        '
' +
      '
' +
      showCloseButton());
  }

  return form.join('');
}

/**
 * Returns an HTML-formatted string to display the assignment selector.
 *
 * @returns An HTML-formatted string.
 */
function displayAssignments(sheetIds) {
  // Use the first selected assignment to get assignment names. This assumes
  // that all assignment names will be found in the other sheets...perhaps a
  // faulty assumption.
  // TODO: *** Add error catching for this ***
  var sheetId = sheetIds[0];
  var form = [];

  if (sheetIds.length > 0) {
    // Save the current and remaining sheetIds for later use.
    var storage = new PropertyStore();
    storage.setProperty('sheetIds', sheetIds, true);

    var gradebook = new Gradebook(sheetId);
    var assignments = gradebook.getAssignmentNames();
    var assignmentItems = constructColumnSelectItems_(assignments, 2);

    // Construct the html form.
    form.push('<form class="block" id="assignments">' +
      '
' +
        '
Select learning goal mastery data to import by checking the ' +
        'appropriate gradebook assignments below.
');

    // Construct the checkboxes for each assignment.
    form.push('
' +
        showCheckboxes('assignments', assignmentItems) +
      '

');

    // Construct the form control buttons.
    form.push('
' +
        '<input type="button" value="Select assignments" class="action" ' +
            'onclick="selectAssignments_onclick();">' +
        showCloseButton() +
      '
</form>');
  } else {
    form.push('
' +
        'No gradebooks were selected. You may close this window.' +
      '
' +
      showCloseButton());
  }

  return form.join('');
}

/**
 * Returns an HTML-formatted string to display the mastery data importer form.
 *
 * @returns An HTML-formatted string.
 */
function displayMasteryData(assignments) {
  // Use the first selected assignment to get assignment names. This assumes
  // that all assignment names will be found in the other sheets...perhaps a
  // faulty assumption.
  // TODO: *** Add error catching for this ***
  var storage = new PropertyStore();
  var sheetIds = storage.getProperty('sheetIds', true);
  var sheetId = sheetIds[0];

  // Get the current gradebook.
  var gradebook = new Gradebook(sheetId);
  var masteryData = new MasteryData();

  // Construct the html form.
  var form = [];
  form.push('<form class="block" id="masteryData">' +
      '
' +
        '
Set the learning goal number and title for each imported ' +
           'assignment:
');

  // Construct assignments.
  form.push('
');
  for (var i = 0; i < assignments.length; i++) {
    form.push(
      '
' +
        '
' +
          '' +
            gradebook.getAssignmentName(assignments[i]) +
          '' +
        '
' +
        '
' +
          'Select learning goal:' +
            masteryData.getLearningGoalSelector() +
        '
' +
        '
' +
          'Learning goal title:' +
          '<input type="text" name="lgName" id="lgName">' +
        '
' +
        '
' +
          '' +
            '<input type="checkbox" name="retake"> Re-take ' +
            'This will add re-take data to a ' +
                'learning goal rather than replace existing data.' +
          '' +
        '
' +
        '<input type="hidden" name="assignment" value="' +
          assignments[i] +
        '">' +
      '
'
    );
  }
  form.push('
');

  // Construct the form control buttons.
  form.push('
' +
      '<input type="button" value="Import mastery data" class="action" ' +
          'onclick="importMasteryData_onclick();">' +
      showCloseButton() +
    '
</form>');

  return form.join('');
}

/**
 * Imports the given assignments into the respective learning goal columns of
 * the mastery data sheet. Takes into account whether an assignment is a retake.
 *
 * @param {array} assignments Array of assignment numbers to import.
 * @param {array} lgNums Array of learning goal numbers as targets for
 *     the import.
 * @param {array} lgNames Array of learning goal names for the import.
 * @param {array} retakes Array of booleans indicating which learning goals
 *     are to be imported as retakes.
 * @returns An HTML-formatted string dislaying the completion message and
 *     close button.
 */
function importMasteryData(assignments, lgNums, lgNames, retakes) {
  var storage = new PropertyStore();
  var sheetIds = storage.getProperty('sheetIds', true);
  var masteryData = new MasteryData();

  // Loop over the selected spreadsheets containing the imported gradebook data.
  for (var i = 0; i < sheetIds.length; i++) {
    var sheetId = sheetIds[i];
    var gradebook = new Gradebook(sheetId);

    // Get the class period.
    var period = gradebook.getClassPeriod();

    // Get the CC flag.
    var isCC = gradebook.isCC();

    // Verify that the imported data arrays are equal in length.
    if ((assignments.length !== lgNums.length) &&
            (lgNums.length !== lgNames.length) &&
            (lgNames.length !== retakes.length)) {
      throw new Error('There was a problem importing the data. ' +
              'Please try again later.');
    }

    // Loop over the selected learning goal numbers.
    for (var j = 0; j < lgNums.length; j++) {
      var assignment = assignments[j];
      var lgNum = lgNums[j];
      var lgName = lgNames[j];
      var retake = retakes[j];

      // Set the learning goal name if given.
      if (lgName !== undefined && lgName !== null && lgName !== '') {
        masteryData.setLearningGoalName(lgNum, lgName);
      }

      // Set the mastery scores after clearing the old data.
      // Append data for CC classes.
      var scores = gradebook.getAssignmentScores(assignment);
      if (isCC === false) {
        masteryData.clearLearningGoalScores(period, lgNum, retake);
        masteryData.setLearningGoalScores(period, lgNum, scores, retake);
      } else {
        masteryData.appendLearningGoalScores(period, lgNum, scores, retake);
      }
    }
  }

  // Construct display message and close button for return.
  var complete = '
' +
        'Import complete. You may close this window and ' +
        'complete step 3.' +
      '
' +
      showCloseButton();

  return complete;
}<|endoftext|>


<commit_before>// https://egghead.io/lessons/javascript-redux-persisting-the-state-to-the-local-storage

export const loadState = () => {
  try {
    const serializedState = localStorage.getItem('weather');
    if (serializedState === null) {
      return undefined;
    }
    return JSON.parse(serializedState);
  } catch (err) {
    return undefined;
  }
};

export const saveState = weather => {
  try {
    const serializedState = JSON.stringify(weather);
    localStorage.setItem('weather', serializedState);
  } catch (err) {
    // Ignore write errors.
  }
};

export const clearStorage = () => {
  try {
    localStorage.setItem('weather', '');
    window.location.reload(true);
  } catch (err) {
    console.log(err);
  }
};
<commit_msg>update storage to load and save settings<commit_after>// https://egghead.io/lessons/javascript-redux-persisting-the-state-to-the-local-storage

export const loadState = (which = 'weather') => {
  try {
    let stateToReturn;
    // By default, return weather.
    if (which === 'weather') {
      stateToReturn = localStorage.getItem('weather');
      if (stateToReturn === null) {
        return undefined;
      }
    } else if (which === 'settings') {
      stateToReturn = localStorage.getItem('weather_settings');
    }

    return JSON.parse(stateToReturn);
  } catch (err) {
    return undefined;
  }
};

export const saveState = (weather, settings) => {
  try {
    if (weather) {
      const serializedState = JSON.stringify(weather);
      localStorage.setItem('weather', serializedState);
    }

    if (settings) {
      const serializedSettings = JSON.stringify(settings);
      localStorage.setItem('weather_settings', serializedSettings);
    }
  } catch (err) {
    // Ignore write errors.
  }
};

export const clearStorage = () => {
  try {
    localStorage.setItem('weather', '');
    window.location.reload(true);
  } catch (err) {
    console.log(err);
  }
};
<|endoftext|>


<commit_before>/*global zeit,Backbone,window,document*/
(function() {
    "use strict";

    var $ = window.jQuery;
    var _ = window.Underscore;

    zeit.cms.declare_namespace('zeit.content.image');
    zeit.cms.declare_namespace('zeit.content.image.browser');

    /* MODELS */

    zeit.content.image.Variant = Backbone.Model.extend({
        urlRoot: window.context_url + '/variants',

        make_url: function() {
            var self = this,
                url = self.get('url');
            return url + '?nocache=' + new Date().getTime();
        }
    });

    zeit.content.image.VariantList = Backbone.Collection.extend({

        model: zeit.content.image.Variant,
        url: window.context_url + '/variants'

    });

    zeit.content.image.VARIANTS = new zeit.content.image.VariantList();

    /* VIEWS */

    var AbstractVariant = Backbone.View.extend({

        render: function() {
            var self = this;
            self.image = self.create_image();

            // Replace default DIV element with img as rewire events.
            self.$el.replaceWith(self.image);
            self.setElement(self.image);

            return self;
        },

        create_image: function() {
            var self = this,
                image = $('');

            // Event handler so Jasmine tests can wait for the image to load.
            image.on('load', function() {
                self.trigger('render');
            });

            // Set src attribute after event registration
            image.attr('src', self.model.make_url());

            return image;
        }
    });

    zeit.content.image.browser.PreviewVariant = AbstractVariant.extend({

        create_image: function() {
            var self = this,
                image = AbstractVariant.prototype.create_image.apply(this);

            image.addClass('preview');

            // Set max-width defined in config as width to display smaller
            // sizes of a variant as big as allowed.
            if (self.model.has('max-size')) {
                var size = self.model.get('max-size').split('x');
                image.width(size[0]);
            }

            // Notify world that image was clicked to make the model active.
            image.on('click', function() {
                self.model.trigger('switch-focus', self.model, self);
            });

            return image;
        },

        update_image: function() {
            this.$el.attr('src', this.model.make_url());
        }
    });

    zeit.content.image.browser.EditableVariant = AbstractVariant.extend({

        create_image: function() {
            var self = this,
                image = AbstractVariant.prototype.create_image.apply(this);

            image.addClass('editor');

            return image;
        }
    });

    zeit.content.image.browser.VariantList = Backbone.View.extend({

        el: '#variant-preview',

        initialize: function() {
            this.listenTo(zeit.content.image.VARIANTS, 'reset', this.reset);
            this.listenTo(zeit.content.image.VARIANTS, 'reload', this.reload);
            this.model_views = [];
        },

        reset: function() {
            // Render all models. Used for initial load.
            var self = this;
            self.$el.empty();
            zeit.content.image.VARIANTS.each(function(variant) {
                var view = new zeit.content.image.browser.PreviewVariant(
                    {model: variant}
                );
                self.model_views.push(view);
                self.$el.append(view.render().el);
            });
        },

        reload: function() {
            // Only update src attribute of images.
            var self = this;
            $(self.model_views).each(function(index, view) {
                view.update_image();
            });
        }

    });

    zeit.content.image.browser.VariantEditor = Backbone.View.extend({

        el: '#variant-inner',

        events: {
            "dragstop .focuspoint": "save"
        },

        initialize: function() {
            var self = this;
            self.default_model = new zeit.content.image.Variant(
                {id: 'default'}
            );
            self.current_model = self.default_model;
            self.model_view = new zeit.content.image.browser.EditableVariant(
                {model: self.current_model}
            );
            self.model_view.img_css_class = 'editor';

            self.model_view.on('render', function() {
                self.trigger('render');
            });

            self.listenTo(zeit.content.image.VARIANTS, 'switch-focus', self.switch_focus);

            $('#reset').on('click', function() {
                self.switch_focus(
                    self.default_model,
                    new zeit.content.image.browser.EditableVariant(self.default_model)
                );
            });
        },

        prepare: function () {
            var self = this;
            self.default_model.fetch().done(function() {
                self.render();
            });
        },

        render: function() {
            var self = this;

            var update_border = function() {
                var w = self.image.width(),
                    h = self.image.height(),
                    zoom = $('#slider').slider("value") / 100,
                    focus_x = ((self.circle.position().left) / self.image.width()),
                    focus_y = ((self.circle.position().top) / self.image.height()),
                    square_size = Math.min(w, h);

                self.square.css('width', square_size * zoom);
                self.square.css('height', square_size * zoom);
                self.square.css('left', (w - square_size * zoom) * focus_x);
                self.square.css('top', (h - square_size * zoom) * focus_y);

                var ratio = w / h,
                    target_w, target_h;
                if (ratio > 16/9) {
                    target_w = w;
                    target_h = w * 9 / 16;
                } else {
                    target_w = h * 16 / 9;
                    target_h = h;
                }
                self.cinema.css('width', target_w * zoom);
                self.cinema.css('height', target_h * zoom);
                self.cinema.css('left', (w - target_w * zoom) * focus_x);
                self.cinema.css('top', (h - target_h * zoom) * focus_y);
            };

            self.$el.append(self.model_view.render().el);
            self.image = self.$('img');

            self.circle = $('

');
            self.circle.css('z-index', 100);
            self.$el.append(self.circle);
            self.circle.draggable();
            self.circle.on("drag", update_border);

            $('#slider').slider({
                min: 1,
                max: 100,
                value: self.current_model.get('zoom') * 100
            });

            $('#slider').on('slidestop', function() {
                self.save();
            });
            $("#slider").on("slide", update_border);

            self.square = $('

');
            self.cinema = $('

');
            self.$el.append(self.square);
            self.$el.append(self.cinema);

            self.update();
            update_border();
        },

        save: function() {
            var self = this;
            var focus_x = ((self.circle.position().left) / self.image.width());
            var focus_y = ((self.circle.position().top) / self.image.height());
            var zoom = $('#slider').slider("value") / 100;
            self.current_model.save(
                {"focus_x": focus_x, "focus_y": focus_y, "zoom": zoom}
            ).done(function() {
                zeit.content.image.VARIANTS.trigger('reload');
                self.notify_status("saved");
            });
        },

        update: function() {
            var self = this;
            self.circle.css('top', self.current_model.get('focus_y') * 100 + '%');
            self.circle.css('left', self.current_model.get('focus_x') * 100 + '%');
            $('#slider').slider("value", self.current_model.get('zoom') * 100);
        },

        switch_focus: function(model, view) {
            var self = this;
            self.model_view.$el.removeClass('active');
            self.model_view = view;
            self.model_view.$el.addClass('active');
            self.current_model = model;
            self.current_model.fetch().done(function() {
                self.update();
                self.notify_status("switched");
            });
        },

        notify_status: function(status) {
            // Used for Selenium tests
            var self = this;
            self.$el.addClass(status);
            window.setTimeout(function () {
                self.$el.removeClass(status);
            }, 2000);
        }
    });

    $(document).ready(function() {
        if (!$('#variant-content').length) {
            return;
        }

        new zeit.content.image.browser.VariantList();
        zeit.content.image.VARIANTS.fetch({reset: true}).done(function() {
            var view = new zeit.content.image.browser.VariantEditor();
            view.prepare();
        });

    });

})();
<commit_msg>Revert display of variant sizes, since it was only a dirty proof of concept.<commit_after>/*global zeit,Backbone,window,document*/
(function() {
    "use strict";

    var $ = window.jQuery;
    var _ = window.Underscore;

    zeit.cms.declare_namespace('zeit.content.image');
    zeit.cms.declare_namespace('zeit.content.image.browser');

    /* MODELS */

    zeit.content.image.Variant = Backbone.Model.extend({
        urlRoot: window.context_url + '/variants',

        make_url: function() {
            var self = this,
                url = self.get('url');
            return url + '?nocache=' + new Date().getTime();
        }
    });

    zeit.content.image.VariantList = Backbone.Collection.extend({

        model: zeit.content.image.Variant,
        url: window.context_url + '/variants'

    });

    zeit.content.image.VARIANTS = new zeit.content.image.VariantList();

    /* VIEWS */

    var AbstractVariant = Backbone.View.extend({

        render: function() {
            var self = this;
            self.image = self.create_image();

            // Replace default DIV element with img as rewire events.
            self.$el.replaceWith(self.image);
            self.setElement(self.image);

            return self;
        },

        create_image: function() {
            var self = this,
                image = $('');

            // Event handler so Jasmine tests can wait for the image to load.
            image.on('load', function() {
                self.trigger('render');
            });

            // Set src attribute after event registration
            image.attr('src', self.model.make_url());

            return image;
        }
    });

    zeit.content.image.browser.PreviewVariant = AbstractVariant.extend({

        create_image: function() {
            var self = this,
                image = AbstractVariant.prototype.create_image.apply(this);

            image.addClass('preview');

            // Set max-width defined in config as width to display smaller
            // sizes of a variant as big as allowed.
            if (self.model.has('max-size')) {
                var size = self.model.get('max-size').split('x');
                image.width(size[0]);
            }

            // Notify world that image was clicked to make the model active.
            image.on('click', function() {
                self.model.trigger('switch-focus', self.model, self);
            });

            return image;
        },

        update_image: function() {
            this.$el.attr('src', this.model.make_url());
        }
    });

    zeit.content.image.browser.EditableVariant = AbstractVariant.extend({

        create_image: function() {
            var self = this,
                image = AbstractVariant.prototype.create_image.apply(this);

            image.addClass('editor');

            return image;
        }
    });

    zeit.content.image.browser.VariantList = Backbone.View.extend({

        el: '#variant-preview',

        initialize: function() {
            this.listenTo(zeit.content.image.VARIANTS, 'reset', this.reset);
            this.listenTo(zeit.content.image.VARIANTS, 'reload', this.reload);
            this.model_views = [];
        },

        reset: function() {
            // Render all models. Used for initial load.
            var self = this;
            self.$el.empty();
            zeit.content.image.VARIANTS.each(function(variant) {
                var view = new zeit.content.image.browser.PreviewVariant(
                    {model: variant}
                );
                self.model_views.push(view);
                self.$el.append(view.render().el);
            });
        },

        reload: function() {
            // Only update src attribute of images.
            var self = this;
            $(self.model_views).each(function(index, view) {
                view.update_image();
            });
        }

    });

    zeit.content.image.browser.VariantEditor = Backbone.View.extend({

        el: '#variant-inner',

        events: {
            "dragstop .focuspoint": "save"
        },

        initialize: function() {
            var self = this;
            self.default_model = new zeit.content.image.Variant(
                {id: 'default'}
            );
            self.current_model = self.default_model;
            self.model_view = new zeit.content.image.browser.EditableVariant(
                {model: self.current_model}
            );
            self.model_view.img_css_class = 'editor';

            self.model_view.on('render', function() {
                self.trigger('render');
            });

            self.listenTo(zeit.content.image.VARIANTS, 'switch-focus', self.switch_focus);

            $('#reset').on('click', function() {
                self.switch_focus(
                    self.default_model,
                    new zeit.content.image.browser.EditableVariant(self.default_model)
                );
            });
        },

        prepare: function () {
            var self = this;
            self.default_model.fetch().done(function() {
                self.render();
            });
        },

        render: function() {
            var self = this;

            self.$el.append(self.model_view.render().el);
            self.image = self.$('img');

            self.circle = $('

');
            self.$el.append(self.circle);
            self.circle.draggable();

            $('#slider').slider({
                min: 1,
                max: 100,
                value: self.current_model.get('zoom') * 100
            });

            $('#slider').on('slidestop', function() {
                self.save();
            });

            self.update();
        },

        save: function() {
            var self = this;
            var focus_x = ((self.circle.position().left) / self.image.width());
            var focus_y = ((self.circle.position().top) / self.image.height());
            var zoom = $('#slider').slider("value") / 100;
            self.current_model.save(
                {"focus_x": focus_x, "focus_y": focus_y, "zoom": zoom}
            ).done(function() {
                zeit.content.image.VARIANTS.trigger('reload');
                self.notify_status("saved");
            });
        },

        update: function() {
            var self = this;
            self.circle.css('top', self.current_model.get('focus_y') * 100 + '%');
            self.circle.css('left', self.current_model.get('focus_x') * 100 + '%');
            $('#slider').slider("value", self.current_model.get('zoom') * 100);
        },

        switch_focus: function(model, view) {
            var self = this;
            self.model_view.$el.removeClass('active');
            self.model_view = view;
            self.model_view.$el.addClass('active');
            self.current_model = model;
            self.current_model.fetch().done(function() {
                self.update();
                self.notify_status("switched");
            });
        },

        notify_status: function(status) {
            // Used for Selenium tests
            var self = this;
            self.$el.addClass(status);
            window.setTimeout(function () {
                self.$el.removeClass(status);
            }, 2000);
        }
    });

    $(document).ready(function() {
        if (!$('#variant-content').length) {
            return;
        }

        new zeit.content.image.browser.VariantList();
        zeit.content.image.VARIANTS.fetch({reset: true}).done(function() {
            var view = new zeit.content.image.browser.VariantEditor();
            view.prepare();
        });

    });

})();
<|endoftext|>


<commit_before>app.controller('SearchFormController', ['$scope','Search',
    function($scope,Search) {
     if (annyang) {
        console.log('Okkkkkkkkkkkkkkkkk');
        // Let's define our first command. First the text we expect, and then the function it should call
        var commands = {
          'search :account contacts': function(account) {
            $scope.searchQuery = account + ' and type:Contact';

            console.log('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@');
            $scope.$apply();
            $scope.executeSearch($scope.searchQuery);
          },
          'search *term': function(term) {
            $scope.searchQuery = term;

            console.log('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@');
            $scope.$apply();
            $scope.executeSearch($scope.searchQuery);
          }

        };

        // Add our commands to annyang
        annyang.addCommands(commands);

        // Start listening. You can call this here, or attach this call to an event, button, etc.
        annyang.start();
      }
     var params ={};
     $scope.result = undefined;
     $scope.q = undefined;
     $scope.$watch('searchQuery', function() {
         params['q'] = $scope.searchQuery;
         gapi.client.crmengine.search(params).execute(function(resp) {
            if (resp.items){
              $scope.results = resp.items;
              $scope.$apply();
            };

          });
     });
     $scope.selectResult = function(){
      console.log('You are welcome On the morning day');
        var url = Search.getUrl($scope.searchQuery.type,$scope.searchQuery.id);
        $scope.searchQuery=' ';
        window.location.replace(url);
     };
     $scope.executeSearch = function(searchQuery){
      if (typeof(searchQuery)=='string'){
         window.location.replace('#/search/'+searchQuery);
      }else{
        var url = Search.getUrl($scope.searchQuery.type,$scope.searchQuery.id);
        $scope.searchQuery=' ';
        window.location.replace(url);
      }

     };
}]);

app.controller('SearchShowController', ['$scope','$route', 'Auth','Search',
    function($scope,$route,Auth,Search) {
     $scope.isSignedIn = false;
     $scope.immediateFailed = false;
     $scope.nextPageToken = undefined;
     $scope.prevPageToken = undefined;
     $scope.isLoading = false;
     $scope.pagination = {};
     $scope.currentPage = 01;
     $scope.pages = [];

     // What to do after authentication
     $scope.runTheProcess = function(){
          var params = {'limit':7,'q':$route.current.params.q};
          Search.list($scope,params);
     };
     // We need to call this to refresh token when user credentials are invalid
     $scope.refreshToken = function() {
          Auth.refreshToken();
     };

     $scope.listNextPageItems = function(){
        var nextPage = $scope.currentPage + 1;
        var params = {};
          if ($scope.pages[nextPage]){
            params = {'q':$route.current.params.q,
                      'limit':7,

                      'pageToken':$scope.pages[nextPage]
                     }
          }else{
            params = {'q':$route.current.params.q,
                      'limit':7}
          }

          $scope.currentPage = $scope.currentPage + 1 ;
          Search.list($scope,params);
     };
     $scope.listPrevPageItems = function(){
       var prevPage = $scope.currentPage - 1;
       var params = {};
          if ($scope.pages[prevPage]){
            params = { 'q':$route.current.params.q,
                      'limit':7,

                      'pageToken':$scope.pages[prevPage]
                     }
        }else{
            params = {'q':$route.current.params.q,
                      'limit':7}
          }
          $scope.currentPage = $scope.currentPage - 1 ;
          Search.list($scope,params);
     };

     // Google+ Authentication
     Auth.init($scope);

}]);
<commit_msg>adding some commandsds to iogrow now<commit_after>app.controller('SearchFormController', ['$scope','Search',
    function($scope,Search) {
     if (annyang) {
        console.log('Okkkkkkkkkkkkkkkkk');
        // Let's define our first command. First the text we expect, and then the function it should call
        var commands = {
          'ok google go to contacts': function(account) {
            window.location.replace('/#/contacts');
          },
          'ok google go to accounts': function(account) {
            window.location.replace('/#/accounts');
          },
          'ok google go to leads': function(account) {
            window.location.replace('/#/leads');
          },
          'ok google go to opportunities': function(account) {
            window.location.replace('/#/opportunities');
          },
          'ok google go to cases': function(account) {
            window.location.replace('/#/cases');
          },
          'ok google go to tasks': function(account) {
            window.location.replace('/#/tasks');
          },
          'search :account contacts': function(account) {
            $scope.searchQuery = account + ' and type:Contact';

            console.log('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@');
            $scope.$apply();
            $scope.executeSearch($scope.searchQuery);
          },
          'search *term': function(term) {
            $scope.searchQuery = term;

            console.log('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@');
            $scope.$apply();
            $scope.executeSearch($scope.searchQuery);
          }

        };

        // Add our commands to annyang
        annyang.addCommands(commands);

        // Start listening. You can call this here, or attach this call to an event, button, etc.
        annyang.start();
      }
     var params ={};
     $scope.result = undefined;
     $scope.q = undefined;
     $scope.$watch('searchQuery', function() {
         params['q'] = $scope.searchQuery;
         gapi.client.crmengine.search(params).execute(function(resp) {
            if (resp.items){
              $scope.results = resp.items;
              $scope.$apply();
            };

          });
     });
     $scope.selectResult = function(){
      console.log('You are welcome On the morning day');
        var url = Search.getUrl($scope.searchQuery.type,$scope.searchQuery.id);
        $scope.searchQuery=' ';
        window.location.replace(url);
     };
     $scope.executeSearch = function(searchQuery){
      if (typeof(searchQuery)=='string'){
         window.location.replace('#/search/'+searchQuery);
      }else{
        var url = Search.getUrl($scope.searchQuery.type,$scope.searchQuery.id);
        $scope.searchQuery=' ';
        window.location.replace(url);
      }

     };
}]);

app.controller('SearchShowController', ['$scope','$route', 'Auth','Search',
    function($scope,$route,Auth,Search) {
     $scope.isSignedIn = false;
     $scope.immediateFailed = false;
     $scope.nextPageToken = undefined;
     $scope.prevPageToken = undefined;
     $scope.isLoading = false;
     $scope.pagination = {};
     $scope.currentPage = 01;
     $scope.pages = [];

     // What to do after authentication
     $scope.runTheProcess = function(){
          var params = {'limit':7,'q':$route.current.params.q};
          Search.list($scope,params);
     };
     // We need to call this to refresh token when user credentials are invalid
     $scope.refreshToken = function() {
          Auth.refreshToken();
     };

     $scope.listNextPageItems = function(){
        var nextPage = $scope.currentPage + 1;
        var params = {};
          if ($scope.pages[nextPage]){
            params = {'q':$route.current.params.q,
                      'limit':7,

                      'pageToken':$scope.pages[nextPage]
                     }
          }else{
            params = {'q':$route.current.params.q,
                      'limit':7}
          }

          $scope.currentPage = $scope.currentPage + 1 ;
          Search.list($scope,params);
     };
     $scope.listPrevPageItems = function(){
       var prevPage = $scope.currentPage - 1;
       var params = {};
          if ($scope.pages[prevPage]){
            params = { 'q':$route.current.params.q,
                      'limit':7,

                      'pageToken':$scope.pages[prevPage]
                     }
        }else{
            params = {'q':$route.current.params.q,
                      'limit':7}
          }
          $scope.currentPage = $scope.currentPage - 1 ;
          Search.list($scope,params);
     };

     // Google+ Authentication
     Auth.init($scope);

}]);
<|endoftext|>


<commit_before>/* eslint max-len: ["error", { "code": 120 }] */
'use strict';

describe('test that audio and video are on or off on start according to urlVars and cookies', function () {
  let chrome$;
  context('audio on, video off via cookies', function () {
    before(function (done) {
      this.timeout(60000);
      helper.newPad({
        padPrefs: {
          rtcEnabled: true,
          fakeWebrtcFirefox: true,
          audioEnabledOnStart: true,
          videoEnabledOnStart: false,
        },
        cb() {
          chrome$ = helper.padChrome$;
          helper.waitFor(() => {
            chrome$ = helper.padChrome$;
            return chrome$ && chrome$('#rtcbox video').length === 1;
          }, 1000).done(done);
        },
      });
    });

    it('has the expected checkbox values with and without urlVars', function (done) {
      chrome$ = helper.padChrome$;
      expect(chrome$('#options-audioenabledonstart').prop('checked')).to.equal(true);
      expect(chrome$('#options-videoenabledonstart').prop('checked')).to.equal(false);

      // overriding with url params
      chrome$.window.ep_webrtc.setUrlParamString('?webrtcaudioenabled=false&webrtcvideoenabled=true');
      chrome$.window.ep_webrtc.setupCheckboxes();
      expect(chrome$('#options-audioenabledonstart').prop('checked')).to.equal(false);
      expect(chrome$('#options-videoenabledonstart').prop('checked')).to.equal(true);

      done();
    });
  });

  context('audio off, video on via cookies, no url params', function () {
    before(function (done) {
      this.timeout(60000);
      helper.newPad({
        padPrefs: {
          rtcEnabled: true,
          fakeWebrtcFirefox: true,
          audioEnabledOnStart: false,
          videoEnabledOnStart: true,
        },
        cb() {
          let chrome$;
          chrome$ = helper.padChrome$;
          helper.waitFor(() => {
            chrome$ = helper.padChrome$;
            return chrome$ && chrome$('#rtcbox video').length === 1;
          }, 1000).done(done);
        },
      });
    });

    it('has the expected checkbox values with and without urlVars', function (done) {
      chrome$ = helper.padChrome$;
      expect(chrome$('#options-audioenabledonstart').prop('checked')).to.equal(false);
      expect(chrome$('#options-videoenabledonstart').prop('checked')).to.equal(true);

      // overriding with url params
      chrome$.window.ep_webrtc.setUrlParamString('?webrtcaudioenabled=true&webrtcvideoenabled=false');
      chrome$.window.ep_webrtc.setupCheckboxes();
      expect(chrome$('#options-audioenabledonstart').prop('checked')).to.equal(true);
      expect(chrome$('#options-videoenabledonstart').prop('checked')).to.equal(false);

      done();
    });
  });
});
<commit_msg>tests: Redo `audio_video_on_start.js` tests<commit_after>'use strict';

describe('audio/video on/off according to query parameters/cookies', function () {
  const cartesian = function* (head, ...tail) {
    const remainder = tail.length > 0 ? cartesian(...tail) : [[]];
    for (const r of remainder) for (const h of head) yield [h, ...r];
  };

  const testCases = cartesian(['audio', 'video'], [null, false, true], [null, false, true]);

  for (const [avType, cookieVal, queryVal] of testCases) {
    it(`${avType} cookie=${cookieVal} query=${queryVal}`, async function () {
      this.timeout(60000);
      await helper.aNewPad({
        padPrefs: Object.assign({
          rtcEnabled: true,
          fakeWebrtcFirefox: true,
        }, cookieVal == null ? {} : {[`${avType}EnabledOnStart`]: cookieVal}),
        params: queryVal == null ? {} : {[`webrtc${avType}enabled`]: queryVal},
      });
      const chrome$ = helper.padChrome$;
      await helper.waitForPromise(() => chrome$('#rtcbox').data('initialized'));
      const {disabled} = chrome$.window.clientVars.webrtc[avType];
      const checkbox = chrome$(`#options-${avType}enabledonstart`);
      if (disabled === 'hard') {
        expect(checkbox.length).to.equal(0); // There shouldn't even be a checkbox.
      } else {
        const wantChecked = (queryVal || (queryVal == null && cookieVal) ||
                             (queryVal == null && cookieVal == null && disabled === 'none'));
        expect(checkbox.prop('checked')).to.equal(wantChecked);
      }
    });
  }
});
<|endoftext|>


<commit_before>// AppleTV media player: http://www.appletv.com/developer

var airplay     = require('airplay')
  , util        = require('util')
  , devices     = require('./../../core/device')
  , steward     = require('./../../core/steward')
  , media       = require('./../device-media')
  , mdns        = require('mdns')
  , utility     = require('./../../core/utility')
  , url         = require('url')
  ;

var logger = media.logger;

var AppleTV = exports.Device = function(deviceID, deviceUID, info) {

  this.whatami = '/device/media/appletv/video';
  this.deviceID = deviceID.toString();
  this.deviceUID = deviceUID;
  this.name = info.device.name;
  this.getName();

  this.info = {
    track : { position: 0, duration: 0 }
  };
  this.url = info.url;

  var parts = url.parse(info.url);
  var self = this;

  this.appletv = new airplay.Device(deviceID, {
    host : parts.hostname
  , port: parts.port
  }, function() {
    self.status = 'idle';
    self.changed();
    self.refresh();
    logger.info('device/' + self.deviceID, self.appletv.serverInfo_);
  });

  utility.broker.subscribe('actors', function(request, taskID, actor, perform, parameter) {
    if (actor !== ('device/' + self.deviceID)) return;

    if (request === 'perform') return self.perform(self, taskID, perform, parameter);
  });

};
util.inherits(AppleTV, media.Device);

AppleTV.operations = {
  stop : function(device, params) {/* jshint unused: false */
    device.stop();
  }
, play : function(device, params) {/* jshint unused: false */
    if (params && params.url) {
      device.play(params.url, 0);
    } else {
      device.rate(1.0);
    }
  }
, pause : function(device, params) {/* jshint unused: false */
    device.rate(0.0);
  }
, 'set' : function(device, params) {/* jshint unused: false */
    if (params) {
      if (typeof params.position !== 'undefined') {
        var position = parseFloat(params.position);
        if (isNaN(position)) {
          position = 0;
        }

        device.scrub(position/1000);
      }
    }
  }
};

AppleTV.prototype.perform = function(self, taskID, perform, parameter) {
  var params;
  try { params = JSON.parse(parameter); } catch(e) {}

  if (!!AppleTV.operations[perform]) {
    AppleTV.operations[perform](this.appletv, params);
    return steward.performed(taskID);
  }

  return devices.perform(self, taskID, perform, parameter);
};

var validate_perform = function(perform, parameter) {
  if (!!AppleTV.operations[perform]) return { invalid: [], requires: [] };

  return devices.validate_perform(perform, parameter);
};

AppleTV.prototype.refresh = function() {
  var timeout = (this.status === 'idle') ? (5 * 1000) : 350;
  var self = this;

  this.appletv.status(function(status) {
    if (status.duration === undefined) {
      self.status = 'idle';
    } else {
      status.position *= 1000;
      status.duration *= 1000;

      if (status.position === self.info.track.position) {
        self.status = "paused";
      } else {
        self.status = "playing"
      }

      self.info.track = status;
    }

    self.changed();

    // set the timeout here so we don't get a runaway
    // timer condition.
    setTimeout(self.refresh.bind(self), timeout);
  });
};

exports.start = function() {
  var discovery = utility.logger('discovery');

  mdns.createBrowser(mdns.tcp('airplay')).on('serviceUp', function(service) {

    var model = service.txtRecord.model.match(/([\d]*),([\d]*)/).slice(1).join('.');
    var info =  { source  : 'mdns'
                , device  : { url          : 'http://' + service.host + ':' + service.port + '/'
                            , name         : service.name
                            , manufacturer : 'APPLE'
                            , model        : { name        : service.name
                                             , description : service.name
                                             , number      : model
                                             }
                            , unit         : { serial      : service.txtRecord.macaddress
                                             , udn         : 'uuid:' + service.txtRecord.macaddress
                                             }
                              }
                };

    info.url = info.device.url;

    info.deviceType = '/device/media/appletv/video';
    info.id = info.device.unit.udn;
    if (devices.devices[info.id]) return;

    logger.info('mDNS ' + info.device.name, { url: info.url });
    devices.discover(info);

  }).on('serviceDown', function(service) {
    discovery.debug('_airplay._tcp', { event: 'down', name: service.name, host: service.host });
  }).on('serviceChanged', function(service) {
    discovery.debug('_airplay._tcp', { event: 'changed', name: service.name, host: service.host });
  }).on('error', function(err) {
    discovery.error('_airplay._tcp', { event: 'mdns', diagnostic: err.message });
  }).start();

    steward.actors.device.media.appletv = steward.actors.device.media.appletv ||
        { $info     : { type: '/device/media/appletv' } };

    steward.actors.device.media.appletv.video =
        { $info     : { type       : '/device/media/appletv/video'
                      , observe    : []
                      , perform    : [
                                       'play'
                                     , 'stop'
                                     , 'pause'
                                     , 'set'
                                     ]
                      , properties : { name    : true
                                     , status  : [ 'idle', 'playing', 'paused' ]
                                     , track   : {
                                         uri         : true
                                       , position    : 'milliseconds'
                                       , duration    : 'milliseconds'}
                                     }
                      }
        , $validate : { perform    : validate_perform }
        };
    devices.makers['/device/media/appletv/video'] = AppleTV;
};
<commit_msg>hinted<commit_after>// AppleTV media player: http://www.appletv.com/developer

var airplay     = require('airplay')
  , util        = require('util')
  , devices     = require('./../../core/device')
  , steward     = require('./../../core/steward')
  , media       = require('./../device-media')
  , mdns        = require('mdns')
  , utility     = require('./../../core/utility')
  , url         = require('url')
  ;

var logger = media.logger;

var AppleTV = exports.Device = function(deviceID, deviceUID, info) {

  this.whatami = '/device/media/appletv/video';
  this.deviceID = deviceID.toString();
  this.deviceUID = deviceUID;
  this.name = info.device.name;
  this.getName();

  this.info = {
    track : { position: 0, duration: 0 }
  };
  this.url = info.url;

  var parts = url.parse(info.url);
  var self = this;

  this.appletv = new airplay.Device(deviceID, {
    host : parts.hostname
  , port: parts.port
  }, function() {
    self.status = 'idle';
    self.changed();
    self.refresh();
    logger.info('device/' + self.deviceID, self.appletv.serverInfo_);
  });

  utility.broker.subscribe('actors', function(request, taskID, actor, perform, parameter) {
    if (actor !== ('device/' + self.deviceID)) return;

    if (request === 'perform') return self.perform(self, taskID, perform, parameter);
  });

};
util.inherits(AppleTV, media.Device);

AppleTV.operations = {
  stop : function(device, params) {/* jshint unused: false */
    device.stop();
  }
, play : function(device, params) {/* jshint unused: false */
    if (params && params.url) {
      device.play(params.url, 0);
    } else {
      device.rate(1.0);
    }
  }
, pause : function(device, params) {/* jshint unused: false */
    device.rate(0.0);
  }
, 'set' : function(device, params) {/* jshint unused: false */
    if (params) {
      if (typeof params.position !== 'undefined') {
        var position = parseFloat(params.position);
        if (isNaN(position)) {
          position = 0;
        }

        device.scrub(position/1000);
      }
    }
  }
};

AppleTV.prototype.perform = function(self, taskID, perform, parameter) {
  var params;
  try { params = JSON.parse(parameter); } catch(e) {}

  if (!!AppleTV.operations[perform]) {
    AppleTV.operations[perform](this.appletv, params);
    return steward.performed(taskID);
  }

  return devices.perform(self, taskID, perform, parameter);
};

var validate_perform = function(perform, parameter) {
  if (!!AppleTV.operations[perform]) return { invalid: [], requires: [] };

  return devices.validate_perform(perform, parameter);
};

AppleTV.prototype.refresh = function() {
  var timeout = (this.status === 'idle') ? (5 * 1000) : 350;
  var self = this;

  this.appletv.status(function(status) {
    if (status.duration === undefined) {
      self.status = 'idle';
    } else {
      status.position *= 1000;
      status.duration *= 1000;

      if (status.position === self.info.track.position) {
        self.status = "paused";
      } else {
        self.status = "playing";
      }

      self.info.track = status;
    }

    self.changed();

    // set the timeout here so we don't get a runaway
    // timer condition.
    setTimeout(self.refresh.bind(self), timeout);
  });
};

exports.start = function() {
  var discovery = utility.logger('discovery');

  mdns.createBrowser(mdns.tcp('airplay')).on('serviceUp', function(service) {

    var model = service.txtRecord.model.match(/([\d]*),([\d]*)/).slice(1).join('.');
    var info =  { source  : 'mdns'
                , device  : { url          : 'http://' + service.host + ':' + service.port + '/'
                            , name         : service.name
                            , manufacturer : 'APPLE'
                            , model        : { name        : service.name
                                             , description : service.name
                                             , number      : model
                                             }
                            , unit         : { serial      : service.txtRecord.macaddress
                                             , udn         : 'uuid:' + service.txtRecord.macaddress
                                             }
                              }
                };

    info.url = info.device.url;

    info.deviceType = '/device/media/appletv/video';
    info.id = info.device.unit.udn;
    if (devices.devices[info.id]) return;

    logger.info('mDNS ' + info.device.name, { url: info.url });
    devices.discover(info);

  }).on('serviceDown', function(service) {
    discovery.debug('_airplay._tcp', { event: 'down', name: service.name, host: service.host });
  }).on('serviceChanged', function(service) {
    discovery.debug('_airplay._tcp', { event: 'changed', name: service.name, host: service.host });
  }).on('error', function(err) {
    discovery.error('_airplay._tcp', { event: 'mdns', diagnostic: err.message });
  }).start();

    steward.actors.device.media.appletv = steward.actors.device.media.appletv ||
        { $info     : { type: '/device/media/appletv' } };

    steward.actors.device.media.appletv.video =
        { $info     : { type       : '/device/media/appletv/video'
                      , observe    : []
                      , perform    : [
                                       'play'
                                     , 'stop'
                                     , 'pause'
                                     , 'set'
                                     ]
                      , properties : { name    : true
                                     , status  : [ 'idle', 'playing', 'paused' ]
                                     , track   : {
                                         uri         : true
                                       , position    : 'milliseconds'
                                       , duration    : 'milliseconds'}
                                     }
                      }
        , $validate : { perform    : validate_perform }
        };
    devices.makers['/device/media/appletv/video'] = AppleTV;
};
<|endoftext|>


<commit_before>/*
Flot plugin for showing a crosshair, thin lines, when the mouse hovers
over the plot.

  crosshair: {
    mode: null or "x" or "y" or "xy"
    color: color
    lineWidth: number
  }

Set the mode to one of "x", "y" or "xy". The "x" mode enables a
vertical crosshair that lets you trace the values on the x axis, "y"
enables a horizontal crosshair and "xy" enables them both. "color" is
the color of the crosshair (default is "rgba(170, 0, 0, 0.80)"),
"lineWidth" is the width of the drawn lines (default is 1).

The plugin also adds two public methods:

  - setCrosshair(pos)

    Set the position of the crosshair. Note that this is cleared if
    the user moves the mouse. "pos" should be on the form { x: xpos,
    y: ypos } (or x2 and y2 if you're using the secondary axes), which
    is coincidentally the same format as what you get from a "plothover"
    event. If "pos" is null, the crosshair is cleared.

  - clearCrosshair()

    Clear the crosshair.

*/

(function ($) {
    var options = {
        crosshair: {
            mode: null, // one of null, "x", "y" or "xy",
            color: "rgba(170, 0, 0, 0.80)",
            lineWidth: 1
        }
    };

    function init(plot) {
        // position of crosshair in pixels
        var crosshair = { x: -1, y: -1 };

        plot.setCrosshair = function setCrosshair(pos) {
            if (!pos)
                crosshair.x = -1;
            else {
                var axes = plot.getAxes();

                crosshair.x = Math.max(0, Math.min(pos.x != null ? axes.xaxis.p2c(pos.x) : axes.x2axis.p2c(pos.x2), plot.width()));
                crosshair.y = Math.max(0, Math.min(pos.y != null ? axes.yaxis.p2c(pos.y) : axes.y2axis.p2c(pos.y2), plot.height()));
            }

            plot.triggerRedrawOverlay();
        };

        plot.clearCrosshair = plot.setCrosshair; // passes null for pos

        plot.hooks.bindEvents.push(function (plot, eventHolder) {
            if (!plot.getOptions().crosshair.mode)
                return;

            eventHolder.mouseout(function () {
                if (crosshair.x != -1) {
                    crosshair.x = -1;
                    plot.triggerRedrawOverlay();
                }
            });

            eventHolder.mousemove(function (e) {
                if (!plot.getSelection()) {
                    var offset = plot.offset();
                    crosshair.x = Math.max(0, Math.min(e.pageX - offset.left, plot.width()));
                    crosshair.y = Math.max(0, Math.min(e.pageY - offset.top, plot.height()));
                    plot.triggerRedrawOverlay();
                }
                else
                    crosshair.x = -1; // hide the crosshair while selecting
            });
        });

        plot.hooks.drawOverlay.push(function (plot, ctx) {
            var c = plot.getOptions().crosshair;
            if (!c.mode)
                return;

            var plotOffset = plot.getPlotOffset();

            ctx.save();
            ctx.translate(plotOffset.left, plotOffset.top);

            if (crosshair.x != -1) {
                ctx.strokeStyle = c.color;
                ctx.lineWidth = c.lineWidth;
                ctx.lineJoin = "round";

                ctx.beginPath();
                if (c.mode.indexOf("x") != -1) {
                    ctx.moveTo(crosshair.x, 0);
                    ctx.lineTo(crosshair.x, plot.height());
                }
                if (c.mode.indexOf("y") != -1) {
                    ctx.moveTo(0, crosshair.y);
                    ctx.lineTo(plot.width(), crosshair.y);
                }
                ctx.stroke();
            }
            ctx.restore();
        });
    }

    $.plot.plugins.push({
        init: init,
        options: options,
        name: 'crosshair',
        version: '1.0'
    });
})(jQuery);
<commit_msg>Integrated patch for adding locking feature to the crosshair plugin from Phrogz<commit_after>/*
Flot plugin for showing a crosshair, thin lines, when the mouse hovers
over the plot.

  crosshair: {
    mode: null or "x" or "y" or "xy"
    color: color
    lineWidth: number
  }

Set the mode to one of "x", "y" or "xy". The "x" mode enables a
vertical crosshair that lets you trace the values on the x axis, "y"
enables a horizontal crosshair and "xy" enables them both. "color" is
the color of the crosshair (default is "rgba(170, 0, 0, 0.80)"),
"lineWidth" is the width of the drawn lines (default is 1).

The plugin also adds four public methods:

  - setCrosshair(pos)

    Set the position of the crosshair. Note that this is cleared if
    the user moves the mouse. "pos" should be on the form { x: xpos,
    y: ypos } (or x2 and y2 if you're using the secondary axes), which
    is coincidentally the same format as what you get from a "plothover"
    event. If "pos" is null, the crosshair is cleared.

  - clearCrosshair()

    Clear the crosshair.

  - lockCrosshair(pos)

    Cause the crosshair to lock to the current location, no longer
    updating if the user moves the mouse. Optionally supply a position
    (passed on to setCrosshair()) to move it to.

    Example usage:
      var myFlot = $.plot( $("#graph"), ..., { crosshair: { mode: "x" } } };
      $("#graph").bind("plothover", function (evt, position, item) {
        if (item) {
          // Lock the crosshair to the data point being hovered
          myFlot.lockCrosshair({ x: item.datapoint[0], y: item.datapoint[1] });
        }
        else {
          // Return normal crosshair operation
          myFlot.unlockCrosshair();
        }
      });

  - unlockCrosshair()

    Free the crosshair to move again after locking it.
*/

(function ($) {
    var options = {
        crosshair: {
            mode: null, // one of null, "x", "y" or "xy",
            color: "rgba(170, 0, 0, 0.80)",
            lineWidth: 1
        }
    };

    function init(plot) {
        // position of crosshair in pixels
        var crosshair = { x: -1, y: -1, locked: false };

        plot.setCrosshair = function setCrosshair(pos) {
            if (!pos)
                crosshair.x = -1;
            else {
                var axes = plot.getAxes();

                crosshair.x = Math.max(0, Math.min(pos.x != null ? axes.xaxis.p2c(pos.x) : axes.x2axis.p2c(pos.x2), plot.width()));
                crosshair.y = Math.max(0, Math.min(pos.y != null ? axes.yaxis.p2c(pos.y) : axes.y2axis.p2c(pos.y2), plot.height()));
            }

            plot.triggerRedrawOverlay();
        };

        plot.clearCrosshair = plot.setCrosshair; // passes null for pos

        plot.lockCrosshair = function lockCrosshair(pos) {
            if (pos)
                plot.setCrosshair(pos);
            crosshair.locked = true;
        }

        plot.unlockCrosshair = function unlockCrosshair() {
            crosshair.locked = false;
        }

        plot.hooks.bindEvents.push(function (plot, eventHolder) {
            if (!plot.getOptions().crosshair.mode)
                return;

            eventHolder.mouseout(function () {
                if (crosshair.x != -1) {
                    crosshair.x = -1;
                    plot.triggerRedrawOverlay();
                }
            });

            eventHolder.mousemove(function (e) {
                if (!plot.getSelection()) {
                    if (!crosshair.locked) {
                        var offset = plot.offset();
                        crosshair.x = Math.max(0, Math.min(e.pageX - offset.left, plot.width()));
                        crosshair.y = Math.max(0, Math.min(e.pageY - offset.top, plot.height()));
                        plot.triggerRedrawOverlay();
                    }
                }
                else
                    crosshair.x = -1; // hide the crosshair while selecting
            });
        });

        plot.hooks.drawOverlay.push(function (plot, ctx) {
            var c = plot.getOptions().crosshair;
            if (!c.mode)
                return;

            var plotOffset = plot.getPlotOffset();

            ctx.save();
            ctx.translate(plotOffset.left, plotOffset.top);

            if (crosshair.x != -1) {
                ctx.strokeStyle = c.color;
                ctx.lineWidth = c.lineWidth;
                ctx.lineJoin = "round";

                ctx.beginPath();
                if (c.mode.indexOf("x") != -1) {
                    ctx.moveTo(crosshair.x, 0);
                    ctx.lineTo(crosshair.x, plot.height());
                }
                if (c.mode.indexOf("y") != -1) {
                    ctx.moveTo(0, crosshair.y);
                    ctx.lineTo(plot.width(), crosshair.y);
                }
                ctx.stroke();
            }
            ctx.restore();
        });
    }

    $.plot.plugins.push({
        init: init,
        options: options,
        name: 'crosshair',
        version: '1.0'
    });
})(jQuery);
<|endoftext|>


<commit_before>//
// Flot Watermark Plugin, Version 1.0.
//
// Copyright (c) 2014 Benjamin Weiss.
//
// Licensed under the MIT license.
//

(function ($) {
	// default values
	var options = {
		watermark: {
			// common settings
			mode: "text",
			order: "foreground",
			position: 'c',
			opacity: 0.3,
			margin: 10,
			// text mode settings
			text: "COPYRIGHT",
			color: "rgb(0, 0, 0)",
			font: "30px Arial",
			// image mode settings
			src: 'watermark.png',
			scaling: 1.0,
		}
	};

	var watermarkImage = new Image();
	var loadedImage = undefined;

	function init(plot) {
		var usedHook;
		plot.hooks.processOptions.push(function(plot, options) {
			var options = options.watermark;
			if (options.order == "background") {
				usedHook = plot.hooks.drawBackground;
			}
			else if (options.order == "foreground") {
				usedHook = plot.hooks.draw;
			}
			else {
				console.log("No valid order specified. Using foreground.")
				usedHook = plot.hooks.draw;
			}
			usedHook.push(function (plot, ctx) {
				if (options.mode == "text") {
					// Textmode
					drawText(plot, ctx, options);
				}
				else if (options.mode == "image") {
					// Imagemode
					if (watermarkImage.src == loadedImage) {
						drawImage(plot, ctx, options);
					}
					else {
						watermarkImage.onload = function() {
							loadedImage = watermarkImage.src;
							drawImage(plot, ctx, options);
						}
						watermarkImage.src = options.src;
					}
				}
				else {
					return;
				}
			});
		});
	}

	function drawText(plot, ctx, options) {
		ctx.save();
		var xPos;
		var yPos;
		var offset;

		var margin = options.margin;
		if (margin[0] == null)
			margin = [margin, margin];

		var axes = plot.getAxes();
		switch(options.position) {
			case 'nw':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.max});
				xPos = offset.left + margin[0];
				yPos = offset.top + margin[1];
				ctx.textAlign = 'left';
				ctx.textBaseline = 'top';
				break;
			case 'n':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.max});
				xPos = offset.left + plot.width()/2;
				yPos = offset.top + margin[1];
				ctx.textAlign = 'center';
				ctx.textBaseline = 'top';
				break;
			case 'ne':
				offset = plot.pointOffset({x: axes.xaxis.max, y: axes.yaxis.max});
				xPos = offset.left - margin[0];
				yPos = offset.top + margin[1];
				ctx.textAlign = 'right';
				ctx.textBaseline = 'top';
				break;
			case 'e':
				offset = plot.pointOffset({x: axes.xaxis.max, y: axes.yaxis.max});
				xPos = offset.left - margin[0];
				yPos = offset.top + plot.height()/2;
				ctx.textAlign = 'right';
				ctx.textBaseline = 'middle';
				break;
			case 'se':
				offset = plot.pointOffset({x: axes.xaxis.max, y: axes.yaxis.min});
				xPos = offset.left - margin[0];
				yPos = offset.top - margin[1];
				ctx.textAlign = 'right';
				ctx.textBaseline = 'bottom';
				break;
			case 's':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.min});
				xPos = offset.left + plot.width()/2;
				yPos = offset.top - margin[1];
				ctx.textAlign = 'center';
				ctx.textBaseline = 'bottom';
				break;
			case 'sw':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.min});
				xPos = offset.left + margin[0];
				yPos = offset.top - margin[1];
				ctx.textAlign = 'left';
				ctx.textBaseline = 'bottom';
				break;
			case 'w':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.max});
				xPos = offset.left + margin[0];
				yPos = offset.top + plot.height()/2;
				ctx.textAlign = 'left';
				ctx.textBaseline = 'middle';
				break;
			case 'c':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.max});
				xPos = offset.left + plot.width()/2;
				yPos = offset.top + plot.height()/2;
				ctx.textAlign = 'center';
				ctx.textBaseline = 'middle';
				break;
			default:
				console.log("No valid position specified.");
		}

		// read font options
		ctx.globalAlpha = options.opacity;
		ctx.font = options.font;
		ctx.fillStyle = options.color;
		ctx.fillText(options.text, xPos, yPos);
		ctx.restore();
	}

	function drawImage(plot, ctx, options) {
		ctx.save();
		var width = watermarkImage.width;
		var height = watermarkImage.height;
		var xPos;
		var yPos;

		var margin = options.margin;
		if (margin[0] == null)
			margin = [margin, margin];

		var axes = plot.getAxes();
		switch(options.position) {
			case 'nw':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.max});
				xPos = offset.left + margin[0];
				yPos = offset.top + margin[1];
				break;
			case 'n':
				offset = plot.pointOffset({x: axes.xaxis.max, y: axes.yaxis.max});
				xPos = offset.left - plot.width()/2 - options.scaling * width/2;
				yPos = offset.top + margin[1];
				break;
			case 'ne':
				offset = plot.pointOffset({x: axes.xaxis.max, y: axes.yaxis.max});
				xPos = offset.left - options.scaling * width - margin[0];
				yPos = offset.top + margin[1];
				break;
			case 'e':
				offset = plot.pointOffset({x: axes.xaxis.max, y: axes.yaxis.max});
				xPos = offset.left - options.scaling * width - margin[0];
				yPos = offset.top + plot.height()/2 - options.scaling * height/2;
				break;
			case 'se':
				offset = plot.pointOffset({x: axes.xaxis.max, y: axes.yaxis.min});
				xPos = offset.left - options.scaling * width - margin[0];
				yPos = offset.top - options.scaling * height - margin[1];
				break;
			case 's':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.min});
				xPos = offset.left + plot.width()/2 - options.scaling * width/2;
				yPos = offset.top - options.scaling * height - margin[1];
				break;
			case 'sw':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.min});
				xPos = offset.left + margin[0];
				yPos = offset.top - options.scaling * height - margin[1];
				break;
			case 'w':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.max});
				xPos = offset.left + margin[0];
				yPos = offset.top + plot.height()/2 - options.scaling * height/2;
				break;
			case 'c':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.max});
				xPos = offset.left + plot.width()/2 - options.scaling * width/2;
				yPos = offset.top + plot.height()/2 - options.scaling * height/2;
				break;
			default:
				console.log("No valid position.");
		}
		ctx.globalAlpha = options.opacity;
		ctx.drawImage(watermarkImage, xPos, yPos, options.scaling * width, options.scaling * height);
		ctx.restore();
	}
	$.plot.plugins.push({
		init: init,
			options: options,
			name: "Watermark",
			version: "1.0"
	});
})(jQuery);<commit_msg>Making watermark image work in more than one chart<commit_after>//
// Flot Watermark Plugin, Version 1.0.
//
// Copyright (c) 2014 Benjamin Weiss.
//
// Licensed under the MIT license.
//

(function ($) {
	// default values
	var options = {
		watermark: {
			// common settings
			mode: "text",
			order: "foreground",
			position: 'c',
			opacity: 0.3,
			margin: 10,
			// text mode settings
			text: "COPYRIGHT",
			color: "rgb(0, 0, 0)",
			font: "30px Arial",
			// image mode settings
			src: 'watermark.png',
			scaling: 1.0,
		}
	};

	var loadedImage = undefined;

	function init(plot) {
		var usedHook;
		plot.hooks.processOptions.push(function(plot, options) {
			var options = options.watermark;
			if (options.order == "background") {
				usedHook = plot.hooks.drawBackground;
			}
			else if (options.order == "foreground") {
				usedHook = plot.hooks.draw;
			}
			else {
				console.log("No valid order specified. Using foreground.")
				usedHook = plot.hooks.draw;
			}
			usedHook.push(function (plot, ctx) {
				if (options.mode == "text") {
					// Textmode
					drawText(plot, ctx, options);
				}
				else if (options.mode == "image") {
					var watermarkImage = new Image();
					// Imagemode
					if (watermarkImage.src == loadedImage) {
						drawImage(plot, ctx, options, watermarkImage);
					}
					else {
						watermarkImage.onload = function() {
							loadedImage = watermarkImage.src;
							drawImage(plot, ctx, options, watermarkImage);
						}
						watermarkImage.src = options.src;
					}
				}
				else {
					return;
				}
			});
		});
	}

	function drawText(plot, ctx, options) {
		ctx.save();
		var xPos;
		var yPos;
		var offset;

		var margin = options.margin;
		if (margin[0] == null)
			margin = [margin, margin];

		var axes = plot.getAxes();
		switch(options.position) {
			case 'nw':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.max});
				xPos = offset.left + margin[0];
				yPos = offset.top + margin[1];
				ctx.textAlign = 'left';
				ctx.textBaseline = 'top';
				break;
			case 'n':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.max});
				xPos = offset.left + plot.width()/2;
				yPos = offset.top + margin[1];
				ctx.textAlign = 'center';
				ctx.textBaseline = 'top';
				break;
			case 'ne':
				offset = plot.pointOffset({x: axes.xaxis.max, y: axes.yaxis.max});
				xPos = offset.left - margin[0];
				yPos = offset.top + margin[1];
				ctx.textAlign = 'right';
				ctx.textBaseline = 'top';
				break;
			case 'e':
				offset = plot.pointOffset({x: axes.xaxis.max, y: axes.yaxis.max});
				xPos = offset.left - margin[0];
				yPos = offset.top + plot.height()/2;
				ctx.textAlign = 'right';
				ctx.textBaseline = 'middle';
				break;
			case 'se':
				offset = plot.pointOffset({x: axes.xaxis.max, y: axes.yaxis.min});
				xPos = offset.left - margin[0];
				yPos = offset.top - margin[1];
				ctx.textAlign = 'right';
				ctx.textBaseline = 'bottom';
				break;
			case 's':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.min});
				xPos = offset.left + plot.width()/2;
				yPos = offset.top - margin[1];
				ctx.textAlign = 'center';
				ctx.textBaseline = 'bottom';
				break;
			case 'sw':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.min});
				xPos = offset.left + margin[0];
				yPos = offset.top - margin[1];
				ctx.textAlign = 'left';
				ctx.textBaseline = 'bottom';
				break;
			case 'w':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.max});
				xPos = offset.left + margin[0];
				yPos = offset.top + plot.height()/2;
				ctx.textAlign = 'left';
				ctx.textBaseline = 'middle';
				break;
			case 'c':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.max});
				xPos = offset.left + plot.width()/2;
				yPos = offset.top + plot.height()/2;
				ctx.textAlign = 'center';
				ctx.textBaseline = 'middle';
				break;
			default:
				console.log("No valid position specified.");
		}

		// read font options
		ctx.globalAlpha = options.opacity;
		ctx.font = options.font;
		ctx.fillStyle = options.color;
		ctx.fillText(options.text, xPos, yPos);
		ctx.restore();
	}

	function drawImage(plot, ctx, options, watermarkImage) {
		ctx.save();
		var width = watermarkImage.width;
		var height = watermarkImage.height;
		var xPos;
		var yPos;

		var margin = options.margin;
		if (margin[0] == null)
			margin = [margin, margin];

		var axes = plot.getAxes();
		switch(options.position) {
			case 'nw':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.max});
				xPos = offset.left + margin[0];
				yPos = offset.top + margin[1];
				break;
			case 'n':
				offset = plot.pointOffset({x: axes.xaxis.max, y: axes.yaxis.max});
				xPos = offset.left - plot.width()/2 - options.scaling * width/2;
				yPos = offset.top + margin[1];
				break;
			case 'ne':
				offset = plot.pointOffset({x: axes.xaxis.max, y: axes.yaxis.max});
				xPos = offset.left - options.scaling * width - margin[0];
				yPos = offset.top + margin[1];
				break;
			case 'e':
				offset = plot.pointOffset({x: axes.xaxis.max, y: axes.yaxis.max});
				xPos = offset.left - options.scaling * width - margin[0];
				yPos = offset.top + plot.height()/2 - options.scaling * height/2;
				break;
			case 'se':
				offset = plot.pointOffset({x: axes.xaxis.max, y: axes.yaxis.min});
				xPos = offset.left - options.scaling * width - margin[0];
				yPos = offset.top - options.scaling * height - margin[1];
				break;
			case 's':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.min});
				xPos = offset.left + plot.width()/2 - options.scaling * width/2;
				yPos = offset.top - options.scaling * height - margin[1];
				break;
			case 'sw':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.min});
				xPos = offset.left + margin[0];
				yPos = offset.top - options.scaling * height - margin[1];
				break;
			case 'w':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.max});
				xPos = offset.left + margin[0];
				yPos = offset.top + plot.height()/2 - options.scaling * height/2;
				break;
			case 'c':
				offset = plot.pointOffset({x: axes.xaxis.min, y: axes.yaxis.max});
				xPos = offset.left + plot.width()/2 - options.scaling * width/2;
				yPos = offset.top + plot.height()/2 - options.scaling * height/2;
				break;
			default:
				console.log("No valid position.");
		}
		ctx.globalAlpha = options.opacity;
		ctx.drawImage(watermarkImage, xPos, yPos, options.scaling * width, options.scaling * height);
		ctx.restore();
	}
	$.plot.plugins.push({
		init: init,
		options: options,
		name: "Watermark",
		version: "1.0"
	});
})(jQuery);<|endoftext|>


<commit_before>(function(Factlink, $, _, easyXDM, undefined) {
  // Initiate the easyXDM object
  Factlink.remote = new easyXDM.Rpc({
    // The URL to load
    remote: FactlinkConfig.api + "/factlink/intermediate",
    // The iFrame where the intermediate should be loaded in
    container: "factlink-modal-frame"
  }, {
    // See modal.js #Factlink.modal
    local: Factlink.modal,
    remote: {
      createEvidence: {},
      createNewEvidence: {},
      showFactlink: {},
      position: {},
      opinionateFactlink: {},
      ajax: {}
    }
  });

  Factlink.post = function(path, options) {
    Factlink.ajax(path, $.extend({
      type: "POST"
    }, options));
  };

  Factlink.get = function(path, options) {
    Factlink.ajax(path, $.extend({
      type: "GET"
    }, options));
  };

  Factlink.ajax = function(path, options) {
    var success = ( $.isFunction(options.success) ? options.success : function(){} );
    var error = ( $.isFunction(options.error) ? options.error : function(){} );
    delete options.success;
    delete options.error;

    Factlink.remote.ajax(path, options, success, error);
  };

  $(window).trigger("factlink.loaded");
})(window.Factlink, Factlink.$, Factlink._, Factlink.easyXDM);
<commit_msg>don't send an empty function when we don't receive a function (this allows the xdm-backend to set a default error handler when we did not define one)<commit_after>(function(Factlink, $, _, easyXDM, undefined) {
  // Initiate the easyXDM object
  Factlink.remote = new easyXDM.Rpc({
    // The URL to load
    remote: FactlinkConfig.api + "/factlink/intermediate",
    // The iFrame where the intermediate should be loaded in
    container: "factlink-modal-frame"
  }, {
    // See modal.js #Factlink.modal
    local: Factlink.modal,
    remote: {
      createEvidence: {},
      createNewEvidence: {},
      showFactlink: {},
      position: {},
      opinionateFactlink: {},
      ajax: {}
    }
  });

  Factlink.post = function(path, options) {
    Factlink.ajax(path, $.extend({
      type: "POST"
    }, options));
  };

  Factlink.get = function(path, options) {
    Factlink.ajax(path, $.extend({
      type: "GET"
    }, options));
  };

  Factlink.ajax = function(path, options) {
    var success = ( $.isFunction(options.success) ? options.success : undefined );
    var error = ( $.isFunction(options.error) ? options.error : undefined );
    delete options.success;
    delete options.error;

    Factlink.remote.ajax(path, options, success, error);
  };

  $(window).trigger("factlink.loaded");
})(window.Factlink, Factlink.$, Factlink._, Factlink.easyXDM);
<|endoftext|>