<commit_before>/**
 * Copyright 2016 The AMP HTML Authors. 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.
 */

import {AmpEvents} from '../../src/amp-events';
import {createFixtureIframe} from '../../testing/iframe';

// Checks if an amp element gets upgraded.
function checkElementUpgrade(element) {
  expect(element).to.have.class('i-amphtml-element');
  expect(element).to.have.class('i-amphtml-layout-responsive');
  expect(element).to.have.class('i-amphtml-layout-size-defined');
  expect(element).to.not.have.class('amp-notbuilt');
  expect(element).to.not.have.class('i-amphtml-notbuilt');
  expect(element).to.not.have.class('amp-unresolved');
  expect(element).to.not.have.class('i-amphtml-unresolved');
}

/**
 * Check all elements in the fixture are upgraded correctly.
 * @param {string} fixtureName
 * @param {!Array} testElements
 */
function testLoadOrderFixture(fixtureName, testElements) {
  let fixture;
  return createFixtureIframe(fixtureName, 500)
    .then((f) => {
      fixture = f;
      for (let i = 0; i < testElements.length; i++) {
        expect(fixture.doc.querySelectorAll(testElements[i])).to.have.length(1);
      }
      return fixture.awaitEvent(AmpEvents.LOAD_START, testElements.length);
    })
    .then(() => {
      for (let i = 0; i < testElements.length; i++) {
        const testElement = fixture.doc.querySelectorAll(testElements[i])[0];
        checkElementUpgrade(testElement);
        if (testElement.tagName == 'AMP-FIT-TEXT') {
          expect(
            fixture.doc.getElementsByClassName('i-amphtml-fit-text-content')
          ).to.have.length(1);
        }
      }
    });
}

describe('test extensions loading in multiple orders', function () {
  this.timeout(15000);

  before(function () {
    // TODO(#32523) Remove this when Bento experiment is done.
    if (BENTO_AUTO_UPGRADE) {
      this.skipTest();
    }
  });

  it('one extension, extension loads first, all scripts in header', () => {
    return testLoadOrderFixture(
      'test/fixtures/script-load-extension-head-v0-head.html',
      ['amp-fit-text']
    );
  });

  it('one extension, v0 loads first, all scripts in header', () => {
    return testLoadOrderFixture(
      'test/fixtures/script-load-v0-head-extension-head.html',
      ['amp-fit-text']
    );
  });

  // TODO(#30528): skip this test as it doesn't make sense. The script
  // tags are in the footer and our posthtml transforms break on the
  // transformation of these invalid html files.
  it.skip('one extension, extension loads first, all scripts in footer', () => {
    return testLoadOrderFixture(
      'test/fixtures/script-load-extension-footer-v0-footer.html',
      ['amp-fit-text']
    );
  });

  // TODO(#30528): skip this test as it doesn't make sense. The script
  // tags are in the footer and our posthtml transforms break on the
  // transformation of these invalid html files.
  it.skip('one extension, v0 loads first, all scripts in footer', () => {
    return testLoadOrderFixture(
      'test/fixtures/script-load-v0-footer-extension-footer.html',
      ['amp-fit-text']
    );
  });

  it('one extension, v0 in header, extension script in footer', () => {
    return testLoadOrderFixture(
      'test/fixtures/script-load-v0-head-extension-footer.html',
      ['amp-fit-text']
    );
  });

  // TODO(choumx); This test times out when run with the prod AMP config.
  // See #11588.
  it.skip('two extensions, one of extension scripts and v0 in header', () => {
    return testLoadOrderFixture('test/fixtures/script-load-extensions.html', [
      'amp-fit-text',
      'amp-iframe',
    ]);
  });
});
<commit_msg>Do not expect `i-amphtml-` element for Bento version (#32582)<commit_after>/**
 * Copyright 2016 The AMP HTML Authors. 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.
 */

import {AmpEvents} from '../../src/amp-events';
import {createFixtureIframe} from '../../testing/iframe';

// Checks if an amp element gets upgraded.
function checkElementUpgrade(element) {
  expect(element).to.have.class('i-amphtml-element');
  expect(element).to.have.class('i-amphtml-layout-responsive');
  expect(element).to.have.class('i-amphtml-layout-size-defined');
  expect(element).to.not.have.class('amp-notbuilt');
  expect(element).to.not.have.class('i-amphtml-notbuilt');
  expect(element).to.not.have.class('amp-unresolved');
  expect(element).to.not.have.class('i-amphtml-unresolved');
}

/**
 * Check all elements in the fixture are upgraded correctly.
 * @param {string} fixtureName
 * @param {!Array} testElements
 */
function testLoadOrderFixture(fixtureName, testElements) {
  let fixture;
  return createFixtureIframe(fixtureName, 500)
    .then((f) => {
      fixture = f;
      for (let i = 0; i < testElements.length; i++) {
        expect(fixture.doc.querySelectorAll(testElements[i])).to.have.length(1);
      }
      return fixture.awaitEvent(AmpEvents.LOAD_START, testElements.length);
    })
    .then(() => {
      for (let i = 0; i < testElements.length; i++) {
        const testElement = fixture.doc.querySelectorAll(testElements[i])[0];
        checkElementUpgrade(testElement);
        if (testElement.tagName == 'AMP-FIT-TEXT') {
          // TODO(#32523) Remove this when Bento experiment is done.
          if (BENTO_AUTO_UPGRADE) {
            expect(testElement.shadowRoot).to.be.defined;
          } else {
            expect(
              fixture.doc.getElementsByClassName('i-amphtml-fit-text-content')
            ).to.have.length(1);
          }
        }
      }
    });
}

describe('test extensions loading in multiple orders', function () {
  this.timeout(15000);

  before(function () {
    // TODO(#32523) Remove this when Bento experiment is done.
    if (BENTO_AUTO_UPGRADE) {
      this.skipTest();
    }
  });

  it('one extension, extension loads first, all scripts in header', () => {
    return testLoadOrderFixture(
      'test/fixtures/script-load-extension-head-v0-head.html',
      ['amp-fit-text']
    );
  });

  it('one extension, v0 loads first, all scripts in header', () => {
    return testLoadOrderFixture(
      'test/fixtures/script-load-v0-head-extension-head.html',
      ['amp-fit-text']
    );
  });

  // TODO(#30528): skip this test as it doesn't make sense. The script
  // tags are in the footer and our posthtml transforms break on the
  // transformation of these invalid html files.
  it.skip('one extension, extension loads first, all scripts in footer', () => {
    return testLoadOrderFixture(
      'test/fixtures/script-load-extension-footer-v0-footer.html',
      ['amp-fit-text']
    );
  });

  // TODO(#30528): skip this test as it doesn't make sense. The script
  // tags are in the footer and our posthtml transforms break on the
  // transformation of these invalid html files.
  it.skip('one extension, v0 loads first, all scripts in footer', () => {
    return testLoadOrderFixture(
      'test/fixtures/script-load-v0-footer-extension-footer.html',
      ['amp-fit-text']
    );
  });

  it('one extension, v0 in header, extension script in footer', () => {
    return testLoadOrderFixture(
      'test/fixtures/script-load-v0-head-extension-footer.html',
      ['amp-fit-text']
    );
  });

  // TODO(choumx); This test times out when run with the prod AMP config.
  // See #11588.
  it.skip('two extensions, one of extension scripts and v0 in header', () => {
    return testLoadOrderFixture('test/fixtures/script-load-extensions.html', [
      'amp-fit-text',
      'amp-iframe',
    ]);
  });
});
<|endoftext|>


<commit_before>// Given an element and selector, returns true of the selector matches.
// This uses the native Element.matches API when possible.
//
// For example:
//
//     matches(document.body, 'body') // => true

var proto  = Element.prototype;
var vendor = proto.matchesSelector || proto.webkitMatchesSelector || proto.mozMatchesSelector || proto.msMatchesSelector || proto.oMatchesSelector;
var isDOM  = require('is-dom');

module.exports = function match(el, selector) {

  // Always return false if the element provided is not a DOM Element
  // or is the document. This catches an illegal invocation error.
  if (isDOM(el) === false || el === document) {
    return false
  }

  // Element.matches is still a newer feature, so it must be identified
  // that it is supported
  if (vendor) {
    return vendor.call(el, selector);
  }

  // Otherwise we traverse the tree
  var nodes = el.parentNode.querySelectorAll(selector);

  for (var i = 0; i < nodes.length; ++i) {
    if (nodes[i] == el) return true;
  }

  return false;
};
<commit_msg>[update] Matches with breakout function<commit_after>// Given an element and selector, returns true of the selector matches.
// This uses the native Element.matches API when possible.
//
// For example:
//
//     matches(document.body, 'body') // => true

var proto  = Element.prototype;
var vendor = proto.matchesSelector || proto.webkitMatchesSelector || proto.mozMatchesSelector || proto.msMatchesSelector || proto.oMatchesSelector;
var isDOM  = require('is-dom');

function isNotMatchable(value) {
  return isDOM(value) === false || value === document;
}

module.exports = function match(el, selector) {

  // Always return false if the element provided is not a DOM Element
  // or is the document. This catches an illegal invocation error.
  if (isNotMatchable(el)) return false

  // Element.matches is still a newer feature, so it must be identified
  // that it is supported
  if (vendor) return vendor.call(el, selector);

  // Otherwise we traverse the tree
  var nodes = el.parentNode.querySelectorAll(selector);

  for (var i = 0; i < nodes.length; ++i) {
    if (nodes[i] == el) return true;
  }

  return false;
};
<|endoftext|>


<commit_before>/**
 * @fileOverview Popup classes.
 */
'use strict';

/**
 * Controller for notifications
 * @param {Object} $scope Angular scope.
 * @constructor
 */
define(['frontend/controllers/module', 'darkwallet', 'frontend/port', 'require'], function (controllers, DarkWallet, Port, require) {
  controllers.controller('NotificationsCtrl', ['$scope', '$window', 'modals', 'notify', '$brc', function($scope, $window, modals, notify, $brc) {

  $scope.tasks = [];
  $scope.modals = modals;

  var linkTasks = function() {
      var identity = DarkWallet.getIdentity();
      var sections = Object.keys(identity.tasks.tasks);
      var tasks = [];
      sections.forEach(function(section) {
          identity.tasks.tasks[section].forEach(function(task) {
              if (!task.seen) {
                  // TODO: to be removed:
                  if (task.progress === undefined) {
                      task.progress = 33;
                  }
                  var outPocket, inPocket;
                  if (!(task.outPocket === undefined)) {
                      var outType = (typeof task.outPocket === 'number') ? 'hd' : (task.outPocket.slice(0, 9) === 'readonly:') : 'readonly' : 'multisig';
                      outPocket = identity.wallet.pockets.getPocket(task.outPocket, outType);
                  }
                  if (!(task.inPocket === undefined)) {
                      var inType = (typeof task.inPocket === 'number') ? 'hd' : (task.inPocket.slice(0, 9) === 'readonly:') : 'readonly' : 'multisig';
                      inPocket = identity.wallet.pockets.getPocket(task.inPocket, inType);
                  }
                  var guiTask = {section: section, store: task, outPocket: outPocket, inPocket: inPocket};
                  if (section == 'multisig') {
                      // Get this here so we don't need Object in angular :-P
                      guiTask.nSigs = Object.keys(task.pending[0].signatures).length;
                      guiTask.fund = identity.wallet.multisig.search({address: task.address||task.inPocket});
                      var canSign = identity.wallet.multisig.canSign(guiTask.fund);
                      // TODO: move setting the finished state to a better place
                      if (guiTask.nSigs >= guiTask.fund.m) {
                          task.state = 'finished';
                      }
                      canSign.some(function(myIdx) {
                          guiTask.canSign = true;
                          if (task.pending[0].signatures.hasOwnProperty(myIdx)) {
                              guiTask.signed = true;
                              return true;
                          }
                      });
                  }
                  tasks.push(guiTask);
              }
          });
      });
      $scope.tasks = tasks;
  }

  $scope.acceptFund = function(guiTask) {
      DarkWallet.service.multisigTrack.accept(guiTask.store);

      var fundIndex = DarkWallet.getIdentity().wallet.multisig.funds.indexOf(guiTask.store.fund);

      // Go to the fund page
      $window.open('index.html#wallet/fund/multisig/'+fundIndex);
  }

  /**
   * Continue signing after getting the password
   */
  function finishSignFundTx(password, guiTask) {
      require(['dwutil/multisig'], function(MultisigFund) {
          var identity = DarkWallet.getIdentity();

          var fund = new MultisigFund(guiTask.fund);

          var fundTask = fund.getFundTask(guiTask.store);

          var inputs = fund.getValidInputs(fundTask.tx);

          var signed;
          try {
              signed = fund.signTransaction(password, fundTask, inputs);
          } catch (e) {
              notify.warning("Invalid Password");
              return;
          }

          if (!signed) {
              notify.warning("Transaction was already signed by us");
              return;
          }
          var tx = fund.finishTransaction(fundTask);
          if (tx) {
              $brc.broadcast(tx, fundTask);
              notify.success('Signed transaction and broadcasted transaction!');
          } else {
              notify.success('Signed transaction');
          }
          if (!$scope.$$phase) {
              $scope.$apply();
          }
      });
  };

  $scope.signTask = function(guiTask) {
      // import transaction here
      modals.password('Unlock password', function(password) {
          finishSignFundTx(password, guiTask);
      });
  }

  // Wallet service, connect to get notified about identity getting loaded.
  Port.connect('wallet', function(data) {
    if (data.type == 'ready') {
        // identity is ready here
        linkTasks();
        if(!$scope.$$phase) {
            $scope.$apply();
        }
    }
  });

}]);
});
<commit_msg>fix syntax error.<commit_after>/**
 * @fileOverview Popup classes.
 */
'use strict';

/**
 * Controller for notifications
 * @param {Object} $scope Angular scope.
 * @constructor
 */
define(['frontend/controllers/module', 'darkwallet', 'frontend/port', 'require'], function (controllers, DarkWallet, Port, require) {
  controllers.controller('NotificationsCtrl', ['$scope', '$window', 'modals', 'notify', '$brc', function($scope, $window, modals, notify, $brc) {

  $scope.tasks = [];
  $scope.modals = modals;

  var linkTasks = function() {
      var identity = DarkWallet.getIdentity();
      var sections = Object.keys(identity.tasks.tasks);
      var tasks = [];
      sections.forEach(function(section) {
          identity.tasks.tasks[section].forEach(function(task) {
              if (!task.seen) {
                  // TODO: to be removed:
                  if (task.progress === undefined) {
                      task.progress = 33;
                  }
                  var outPocket, inPocket;
                  if (!(task.outPocket === undefined)) {
                      var outType = (typeof task.outPocket === 'number') ? 'hd' : (task.outPocket.slice(0, 9) === 'readonly:') ? 'readonly' : 'multisig';
                      outPocket = identity.wallet.pockets.getPocket(task.outPocket, outType);
                  }
                  if (!(task.inPocket === undefined)) {
                      var inType = (typeof task.inPocket === 'number') ? 'hd' : (task.inPocket.slice(0, 9) === 'readonly:') ? 'readonly' : 'multisig';
                      inPocket = identity.wallet.pockets.getPocket(task.inPocket, inType);
                  }
                  var guiTask = {section: section, store: task, outPocket: outPocket, inPocket: inPocket};
                  if (section == 'multisig') {
                      // Get this here so we don't need Object in angular :-P
                      guiTask.nSigs = Object.keys(task.pending[0].signatures).length;
                      guiTask.fund = identity.wallet.multisig.search({address: task.address||task.inPocket});
                      var canSign = identity.wallet.multisig.canSign(guiTask.fund);
                      // TODO: move setting the finished state to a better place
                      if (guiTask.nSigs >= guiTask.fund.m) {
                          task.state = 'finished';
                      }
                      canSign.some(function(myIdx) {
                          guiTask.canSign = true;
                          if (task.pending[0].signatures.hasOwnProperty(myIdx)) {
                              guiTask.signed = true;
                              return true;
                          }
                      });
                  }
                  tasks.push(guiTask);
              }
          });
      });
      $scope.tasks = tasks;
  }

  $scope.acceptFund = function(guiTask) {
      DarkWallet.service.multisigTrack.accept(guiTask.store);

      var fundIndex = DarkWallet.getIdentity().wallet.multisig.funds.indexOf(guiTask.store.fund);

      // Go to the fund page
      $window.open('index.html#wallet/fund/multisig/'+fundIndex);
  }

  /**
   * Continue signing after getting the password
   */
  function finishSignFundTx(password, guiTask) {
      require(['dwutil/multisig'], function(MultisigFund) {
          var identity = DarkWallet.getIdentity();

          var fund = new MultisigFund(guiTask.fund);

          var fundTask = fund.getFundTask(guiTask.store);

          var inputs = fund.getValidInputs(fundTask.tx);

          var signed;
          try {
              signed = fund.signTransaction(password, fundTask, inputs);
          } catch (e) {
              notify.warning("Invalid Password");
              return;
          }

          if (!signed) {
              notify.warning("Transaction was already signed by us");
              return;
          }
          var tx = fund.finishTransaction(fundTask);
          if (tx) {
              $brc.broadcast(tx, fundTask);
              notify.success('Signed transaction and broadcasted transaction!');
          } else {
              notify.success('Signed transaction');
          }
          if (!$scope.$$phase) {
              $scope.$apply();
          }
      });
  };

  $scope.signTask = function(guiTask) {
      // import transaction here
      modals.password('Unlock password', function(password) {
          finishSignFundTx(password, guiTask);
      });
  }

  // Wallet service, connect to get notified about identity getting loaded.
  Port.connect('wallet', function(data) {
    if (data.type == 'ready') {
        // identity is ready here
        linkTasks();
        if(!$scope.$$phase) {
            $scope.$apply();
        }
    }
  });

}]);
});
<|endoftext|>


<commit_before>(function () {
    'use strict';

    function WordCtrl(Term, Game, $location, $route, $scope) {
        var time;

        $scope.word = 'tralala';
        $scope.started = false;
        $scope.term = Term.get({
            discipline: $route.current.params.discipline
        });

        $scope.start = function() {
            $scope.started = true;
            time = new Date().getTime();
        };

        $scope.redirect = function() {
            // post results back here
            time = new Date().getTime() - time;
            Game.save({
                    session: {
                        time: time,
                        termId: $scope.term.id,
                        discipline: $route.current.params.discipline
                    }
                },
                function(response){
                    console.log(response);
                    $location.path('/summary');
            });

        };
    }

    angular.module('controllers') // [] instantiates controller module
           .controller('WordCtrl', ['Term', 'Game', '$location', '$route', '$scope', WordCtrl]);
})();<commit_msg>Remove session wrapper.<commit_after>(function () {
    'use strict';

    function WordCtrl(Term, Game, $location, $route, $scope) {
        var time;

        $scope.word = 'tralala';
        $scope.started = false;
        $scope.term = Term.get({
            discipline: $route.current.params.discipline
        });

        $scope.start = function() {
            $scope.started = true;
            time = new Date().getTime();
        };

        $scope.redirect = function() {
            // post results back here
            time = new Date().getTime() - time;
            Game.save({
                    time: time,
                    termId: $scope.term.id,
                    discipline: $route.current.params.discipline
                },
                function(response){
                    console.log(response);
                    $location.path('/summary');
            });

        };
    }

    angular.module('controllers') // [] instantiates controller module
           .controller('WordCtrl', ['Term', 'Game', '$location', '$route', '$scope', WordCtrl]);
})();<|endoftext|>


<commit_before>/**
 * @namespace nitch.device
 * @description Stuff for devices
**/
nitch.device = {

	mediaQueries: {
		ipad3: "only screen and (min-width: 768px) and (max-width: 1024px) and (-webkit-device-pixel-ratio: 2)",
		ipad2: "only screen and (min-width: 768px) and (max-width: 1024px)",
		iphone4s: "only screen and (min-device-width : 640px) and (max-device-width : 960px) and (-webkit-device-pixel-ratio: 2)",
		iphone4: "only screen and (min-device-width : 640px) and (max-device-width : 960px)",
		iphone3: "only screen and (min-device-width : 320px) and (max-device-width : 480px)"
	},

/**
 * @namespace nitch.device.type
 * @method
 * @description Tries it's best to guess the device type based on the user-agent string sent. All based off Categorizr.js: Device Detection Scripts
 * @returns {string} tv | tablet | mobile | desktop
 * @example nitch.device.type()
**/
	type: function() {
		var ua = window.navigator.userAgent;
         return  ua.match(/GoogleTV|SmartTV|Internet.TV|NetCast|NETTV|AppleTV|boxee|Kylo|Roku|DLNADOC|CE\-HTML/i) ? 'tv'
                // tv-based gaming console
              : ua.match(/Xbox|PLAYSTATION.3|Wii/i) ? 'tv'
                // tablet
              : ua.match(/iPad/i) || ua.match(/tablet/i) && !ua.match(/RX-34/i) || ua.match(/FOLIO/i) ? 'tablet'
                // android tablet
              : ua.match(/Linux/i) && ua.match(/Android/i) && !ua.match(/Fennec|mobi|HTC.Magic|HTCX06HT|Nexus.One|SC-02B|fone.945/i) ? 'tablet'
                // Kindle or Kindle Fire
              : ua.match(/Kindle/i) || ua.match(/Mac.OS/i) && ua.match(/Silk/i) ? 'tablet'
                // pre Android 3.0 Tablet
              : ua.match(/GT-P10|SC-01C|SHW-M180S|SGH-T849|SCH-I800|SHW-M180L|SPH-P100|SGH-I987|zt180|HTC(.Flyer|\_Flyer)|Sprint.ATP51|ViewPad7|pandigital(sprnova|nova)|Ideos.S7|Dell.Streak.7|Advent.Vega|A101IT|A70BHT|MID7015|Next2|nook/i) || ua.match(/MB511/i) && ua.match(/RUTEM/i) ? 'tablet'
                // unique Mobile User Agent
              : ua.match(/BOLT|Fennec|Iris|Maemo|Minimo|Mobi|mowser|NetFront|Novarra|Prism|RX-34|Skyfire|Tear|XV6875|XV6975|Google.Wireless.Transcoder/i) ? 'mobile'
                // odd Opera User Agent - http://goo.gl/nK90K
              : ua.match(/Opera/i) && ua.match(/Windows.NT.5/i) && ua.match(/HTC|Xda|Mini|Vario|SAMSUNG\-GT\-i8000|SAMSUNG\-SGH\-i9/i) ? 'mobile'
                // Windows Desktop
              : ua.match(/Windows.(NT|XP|ME|9)/) && !ua.match(/Phone/i) || ua.match(/Win(9|.9|NT)/i) ? 'desktop'
                // Mac Desktop
              : ua.match(/Macintosh|PowerPC/i) && !ua.match(/Silk/i) ? 'desktop'
                // Linux Desktop
              : ua.match(/Linux/i) && ua.match(/X11/i) ? 'desktop'
                // Solaris, SunOS, BSD Desktop
              : ua.match(/Solaris|SunOS|BSD/i) ? 'desktop'
                // Desktop BOT/Crawler/Spider
              : ua.match(/Bot|Crawler|Spider|Yahoo|ia_archiver|Covario-IDS|findlinks|DataparkSearch|larbin|Mediapartners-Google|NG-Search|Snappy|Teoma|Jeeves|TinEye/i) && !ua.match(/Mobile/i) ? 'desktop'
                // assume it is a Mobile Device (mobile-first)
              : 'mobile';
	},

/**
 * @name nitch.device.features
 * @description Think of this as a shody version of Modernzr. Basically it's an object that will return the availability of some core features
 * @example // What Chrome on the desktop returns
nitch.device.features = {
	DeviceOrientationEvent: true
	OrientationEvent: false
	appCache: true
	audioAcc: "probably"
	audioElement: true
	audioMp3: "maybe"
	audioOgg: "probably"
	audioWav: "probably"
	geoLocation: true
	isFullScreen: false
	localStorage: true
	mouse: true
	onLine: true
	orientation: false
	pixelRatio: 1
	screenHeight: 900
	screenWidth: 1440
	sessionStorage: true
	touch: false
	videoElement: false
	webGL: true
	windowHeight: 802
	windowWidth: 1432
}
 **/

 /**
 * @name nitch.device.ft
 * @method
 * @private
 * @returns {object} nitch.device.features
 * @example nitch.device.ft()
**/
	ft: function(debug) {
		var audio = new Audio();
		this.features = {
			onLine: (typeof navigator.onLine === "undefined" ? false : navigator.onLine),
			localStorage: (typeof window.localStorage === "undefined" ? false : true),
			appCache: (typeof window.applicationCache === "undefined" ? false : true),
			sessionStorage: (typeof window.sessionStorage === "undefined" ? false: true),
			geoLocation: (typeof navigator.geolocation === "undefined" ? false : true),
			audioOgg: audio.canPlayType('audio/ogg; codecs="vorbis"'),
			audioMp3: audio.canPlayType('audio/mpeg; codecs="mp3"'),
			audioAcc: audio.canPlayType('audio/mp4; codecs="mp4a.40.2"'),
			audioWav: audio.canPlayType('audio/wav; codecs="1"'),
			pixelRatio: (window.devicePixelRatio ? window.devicePixelRatio : 1),
			mouse: (typeof window.onmousedown === "undefined" ? false : true),
			touch: (typeof window.ontouchstart === "undefined" ? false : true),
			screenHeight: screen.height,
			screenWidth: screen.width,
			windowWidth: window.innerWidth || document.body.offsetWidth || 0,
			windowHeight: window.innerHeight || document.body.offsetHeight || 0,
			orientation: (typeof window.orientation === "undefined" ? false : window.orientation), // typically going to be 0, -90, 90
			isFullScreen: (typeof navigator.standalone === "undefined" ? false : true), // iOS in webapp mode
			DeviceOrientationEvent: (typeof window.DeviceOrientationEvent === "undefined" ? false : true),
			OrientationEvent: (typeof window.OrientationEvent === "undefined" ? false : true), // The Moz version of DeviceOrientationEvent
			audioElement: (typeof window.Audio === "undefined" ? false : true),
			videoElement: (typeof window.Video === "undefined" ? false : true),
			webGL: (typeof window.WebGLRenderingContext === "undefined" ? false : true)
		}

		if(debug === true) {
			var html = '
';
			for (var capability in this.features){
				html += '
'+capability+': '+this.device[capability]+'
';
				}
			html += '
';
			nitch.dom('#container').after(html);
		}
	},

/**
 * @namespace nitch.device.watchOrientation
 * @method
 * @description Adds a class to the body and an event to update when orientation changes for the iPhone 3 (iOS 4.2.1), as it doesn't support media queries in CSS.
This is called by default when the document is ready

**/
	watchOrientation: function() {
		watchit = function() {
			var orientation = window.orientation;
			if(orientation == 90 || orientation == -90) {
				nitch.dom("body").removeClass("portrait");
				nitch.dom("body").addClass("landscape");
			} else {
				nitch.dom("body").removeClass("landscape");
				nitch.dom("body").addClass("portrait");
			}
		},
		watchit();
		window.addEventListener( "orientationchange", watchit, false );
	},

/**
 * @namespace nitch.device.stylesheet
 * @method
 * @description Injects a stylesheet based on UserAgent and if it's a mobile, with a media query
 * @param {Object} stylesheet
 * @param {string} stylesheet.device Device name with the url of the stylesheet.
For desktop and tv support just use the device name 'desktop' or 'tv'.

 * @param {String} stylesheet.url url of the stylesheet
 * @requires MediaMatch.js
 * @example nitch.device.stylesheet({
	desktop: "style/desktop/style.css"
	tv: "style/tv/style.css"
	ipad3: "style/ipad3/style.css",
	ipad2: "style/ipad/style.css",
	iphone4s: "style/iphone4s/style.css",
	iphone4: "style/iphone4/style.css",
	iphone3: "style/iphone/style.css"
});
**/
	stylesheet: function(opts) {
		if(!opts) { return; }

		nitch.device.stylesheet.prototype.add = function(uri, mediaQuery) {
			nitch.dom("head").append('<link type="text/css" rel="stylesheet" media="'+mediaQuery+'" href="'+uri+'" />');
		}

		var device = nitch.device.type();

		for (var css in opts){
			if (css == "tv" && device == "tv") {
				this.add(opts[css], "");
			} else if (css == "desktop" && device == "desktop") {
				this.add(opts[css], "");
				return;
			} else {
				// Else it must be a mobile device, let the media queries begin!
				if(window.matchMedia(nitch.device.mediaQueries[css]).matches)  {
					this.add(opts[css], nitch.device.mediaQueries[css]);
					return;
				}
			}
		}
	},

/**
 * @name nitch.device.setAppcache
 * @method
 * @description Injects an appcache manifest based on UserAgent and if it's a mobile, with a media query
 * @param {Object} appcache
 * @param {String} appcache.device Device name with the url of the manifest
 * @param {String} appcache.url Url of the manifest.
For desktop and tv support just use the device name 'desktop' or 'tv'.

 * @requires MediaMatch.js
 * @example nitch.device.appcache({
	desktop: "style/desktop/appcache.manifest",
	ipad3: "style/ipad3/appcache.manifest",
	ipad2: "style/ipad/appcache.manifest",
	iphone4s: "style/iphone4s/appcache.manifest",
	iphone4: "style/iphone4/appcache.manifest",
	iphone3: "style/iphone/appcache.manifest"
});
**/
	appcache: function(opts) {
		if (window.applicationCache && opts) {

			var device = nitch.device.type();

			for (var appcache in opts){
				if (appcache == "tv" && device == "tv") {
					nitch.dom("html").attr("manifest",  opts[appcache]);
				} else if (appcache == "desktop" && device == "desktop") {
					nitch.dom("html").attr("manifest",  opts[appcache]);
					return;
				} else {
					// Else it must be a mobile device, let the media query matching begin!
					if(window.matchMedia(nitch.device.mediaQueries[css]).matches)  {
						nitch.dom("html").attr("manifest",  opts[appcache]);
						return;
					}
				}
			}
		}
	}

};
<commit_msg>cleaning up the dom<commit_after>/**
 * @namespace nitch.device
 * @description Stuff for devices
**/
nitch.device = {

	mediaQueries: {
		ipad3: "only screen and (min-width: 768px) and (max-width: 1024px) and (-webkit-device-pixel-ratio: 2)",
		ipad2: "only screen and (min-width: 768px) and (max-width: 1024px)",
		iphone4s: "only screen and (min-device-width : 640px) and (max-device-width : 960px) and (-webkit-device-pixel-ratio: 2)",
		iphone4: "only screen and (min-device-width : 640px) and (max-device-width : 960px)",
		iphone3: "only screen and (min-device-width : 320px) and (max-device-width : 480px)"
	},

/**
 * @namespace nitch.device.type
 * @method
 * @description Tries it's best to guess the device type based on the user-agent string sent. All based off Categorizr.js: Device Detection Scripts
 * @returns {string} tv | tablet | mobile | desktop
 * @example nitch.device.type()
**/
	type: function() {
		var ua = window.navigator.userAgent;
         return  ua.match(/GoogleTV|SmartTV|Internet.TV|NetCast|NETTV|AppleTV|boxee|Kylo|Roku|DLNADOC|CE\-HTML/i) ? 'tv'
                // tv-based gaming console
              : ua.match(/Xbox|PLAYSTATION.3|Wii/i) ? 'tv'
                // tablet
              : ua.match(/iPad/i) || ua.match(/tablet/i) && !ua.match(/RX-34/i) || ua.match(/FOLIO/i) ? 'tablet'
                // android tablet
              : ua.match(/Linux/i) && ua.match(/Android/i) && !ua.match(/Fennec|mobi|HTC.Magic|HTCX06HT|Nexus.One|SC-02B|fone.945/i) ? 'tablet'
                // Kindle or Kindle Fire
              : ua.match(/Kindle/i) || ua.match(/Mac.OS/i) && ua.match(/Silk/i) ? 'tablet'
                // pre Android 3.0 Tablet
              : ua.match(/GT-P10|SC-01C|SHW-M180S|SGH-T849|SCH-I800|SHW-M180L|SPH-P100|SGH-I987|zt180|HTC(.Flyer|\_Flyer)|Sprint.ATP51|ViewPad7|pandigital(sprnova|nova)|Ideos.S7|Dell.Streak.7|Advent.Vega|A101IT|A70BHT|MID7015|Next2|nook/i) || ua.match(/MB511/i) && ua.match(/RUTEM/i) ? 'tablet'
                // unique Mobile User Agent
              : ua.match(/BOLT|Fennec|Iris|Maemo|Minimo|Mobi|mowser|NetFront|Novarra|Prism|RX-34|Skyfire|Tear|XV6875|XV6975|Google.Wireless.Transcoder/i) ? 'mobile'
                // odd Opera User Agent - http://goo.gl/nK90K
              : ua.match(/Opera/i) && ua.match(/Windows.NT.5/i) && ua.match(/HTC|Xda|Mini|Vario|SAMSUNG\-GT\-i8000|SAMSUNG\-SGH\-i9/i) ? 'mobile'
                // Windows Desktop
              : ua.match(/Windows.(NT|XP|ME|9)/) && !ua.match(/Phone/i) || ua.match(/Win(9|.9|NT)/i) ? 'desktop'
                // Mac Desktop
              : ua.match(/Macintosh|PowerPC/i) && !ua.match(/Silk/i) ? 'desktop'
                // Linux Desktop
              : ua.match(/Linux/i) && ua.match(/X11/i) ? 'desktop'
                // Solaris, SunOS, BSD Desktop
              : ua.match(/Solaris|SunOS|BSD/i) ? 'desktop'
                // Desktop BOT/Crawler/Spider
              : ua.match(/Bot|Crawler|Spider|Yahoo|ia_archiver|Covario-IDS|findlinks|DataparkSearch|larbin|Mediapartners-Google|NG-Search|Snappy|Teoma|Jeeves|TinEye/i) && !ua.match(/Mobile/i) ? 'desktop'
                // assume it is a Mobile Device (mobile-first)
              : 'mobile';
	},

/**
 * @name nitch.device.features
 * @description Think of this as a shody version of Modernzr. Basically it's an object that will return the availability of some core features
 * @example // What Chrome on the desktop returns
nitch.device.features = {
	DeviceOrientationEvent: true
	OrientationEvent: false
	appCache: true
	audioAcc: "probably"
	audioElement: true
	audioMp3: "maybe"
	audioOgg: "probably"
	audioWav: "probably"
	geoLocation: true
	isFullScreen: false
	localStorage: true
	mouse: true
	onLine: true
	orientation: false
	pixelRatio: 1
	screenHeight: 900
	screenWidth: 1440
	sessionStorage: true
	touch: false
	videoElement: false
	webGL: true
	windowHeight: 802
	windowWidth: 1432
}
 **/

 /**
 * @name nitch.device.ft
 * @method
 * @private
 * @returns {object} nitch.device.features
 * @example nitch.device.ft()
**/
	ft: function(debug) {
		var audio = new Audio();
		this.features = {
			onLine: (typeof navigator.onLine === "undefined" ? false : navigator.onLine),
			localStorage: (typeof window.localStorage === "undefined" ? false : true),
			appCache: (typeof window.applicationCache === "undefined" ? false : true),
			sessionStorage: (typeof window.sessionStorage === "undefined" ? false: true),
			geoLocation: (typeof navigator.geolocation === "undefined" ? false : true),
			audioOgg: audio.canPlayType('audio/ogg; codecs="vorbis"'),
			audioMp3: audio.canPlayType('audio/mpeg; codecs="mp3"'),
			audioAcc: audio.canPlayType('audio/mp4; codecs="mp4a.40.2"'),
			audioWav: audio.canPlayType('audio/wav; codecs="1"'),
			pixelRatio: (window.devicePixelRatio ? window.devicePixelRatio : 1),
			mouse: (typeof window.onmousedown === "undefined" ? false : true),
			touch: (typeof window.ontouchstart === "undefined" ? false : true),
			screenHeight: screen.height,
			screenWidth: screen.width,
			windowWidth: window.innerWidth || document.body.offsetWidth || 0,
			windowHeight: window.innerHeight || document.body.offsetHeight || 0,
			orientation: (typeof window.orientation === "undefined" ? false : window.orientation), // typically going to be 0, -90, 90
			isFullScreen: (typeof navigator.standalone === "undefined" ? false : true), // iOS in webapp mode
			DeviceOrientationEvent: (typeof window.DeviceOrientationEvent === "undefined" ? false : true),
			OrientationEvent: (typeof window.OrientationEvent === "undefined" ? false : true), // The Moz version of DeviceOrientationEvent
			audioElement: (typeof window.Audio === "undefined" ? false : true),
			videoElement: (typeof window.Video === "undefined" ? false : true),
			webGL: (typeof window.WebGLRenderingContext === "undefined" ? false : true)
		}

		if(debug === true) {
			var html = '
';
			for (var capability in this.features){
				html += '
'+capability+': '+this.device[capability]+'
';
				}
			html += '
';
			nitch.dom('#container').after(html);
		}
	},

/**
 * @namespace nitch.device.watchOrientation
 * @method
 * @description Adds a class to the body and an event to update when orientation changes for the iPhone 3 (iOS 4.2.1), as it doesn't support media queries in CSS.
This is called by default when the document is ready

**/
	watchOrientation: function() {
		nitch.watchit = function() {
			var orientation = window.orientation;
			if(orientation == 90 || orientation == -90) {
				nitch.dom("body").removeClass("portrait");
				nitch.dom("body").addClass("landscape");
			} else {
				nitch.dom("body").removeClass("landscape");
				nitch.dom("body").addClass("portrait");
			}
		},
		nitch.watchit();
		window.addEventListener( "orientationchange", nitch.watchit, false );
	},

/**
 * @namespace nitch.device.stylesheet
 * @method
 * @description Injects a stylesheet based on UserAgent and if it's a mobile, with a media query
 * @param {Object} stylesheet
 * @param {string} stylesheet.device Device name with the url of the stylesheet.
For desktop and tv support just use the device name 'desktop' or 'tv'.

 * @param {String} stylesheet.url url of the stylesheet
 * @requires MediaMatch.js
 * @example nitch.device.stylesheet({
	desktop: "style/desktop/style.css"
	tv: "style/tv/style.css"
	ipad3: "style/ipad3/style.css",
	ipad2: "style/ipad/style.css",
	iphone4s: "style/iphone4s/style.css",
	iphone4: "style/iphone4/style.css",
	iphone3: "style/iphone/style.css"
});
**/
	stylesheet: function(opts) {
		if(!opts) { return; }

		nitch.device.stylesheet.prototype.add = function(uri, mediaQuery) {
			nitch.dom("head").append('<link type="text/css" rel="stylesheet" media="'+mediaQuery+'" href="'+uri+'" />');
		}

		var device = nitch.device.type();

		for (var css in opts){
			if (css == "tv" && device == "tv") {
				this.add(opts[css], "");
			} else if (css == "desktop" && device == "desktop") {
				this.add(opts[css], "");
				return;
			} else {
				// Else it must be a mobile device, let the media queries begin!
				if(window.matchMedia(nitch.device.mediaQueries[css]).matches)  {
					this.add(opts[css], nitch.device.mediaQueries[css]);
					return;
				}
			}
		}
	},

/**
 * @name nitch.device.setAppcache
 * @method
 * @description Injects an appcache manifest based on UserAgent and if it's a mobile, with a media query
 * @param {Object} appcache
 * @param {String} appcache.device Device name with the url of the manifest
 * @param {String} appcache.url Url of the manifest.
For desktop and tv support just use the device name 'desktop' or 'tv'.

 * @requires MediaMatch.js
 * @example nitch.device.appcache({
	desktop: "style/desktop/appcache.manifest",
	ipad3: "style/ipad3/appcache.manifest",
	ipad2: "style/ipad/appcache.manifest",
	iphone4s: "style/iphone4s/appcache.manifest",
	iphone4: "style/iphone4/appcache.manifest",
	iphone3: "style/iphone/appcache.manifest"
});
**/
	appcache: function(opts) {
		if (window.applicationCache && opts) {

			var device = nitch.device.type();

			for (var appcache in opts){
				if (appcache == "tv" && device == "tv") {
					nitch.dom("html").attr("manifest",  opts[appcache]);
				} else if (appcache == "desktop" && device == "desktop") {
					nitch.dom("html").attr("manifest",  opts[appcache]);
					return;
				} else {
					// Else it must be a mobile device, let the media query matching begin!
					if(window.matchMedia(nitch.device.mediaQueries[css]).matches)  {
						nitch.dom("html").attr("manifest",  opts[appcache]);
						return;
					}
				}
			}
		}
	}

};
<|endoftext|>


<commit_before>var d3 = require('d3');

var Plotly = require('@lib/index');
var Plots = require('@src/plots/plots');
var Lib = require('@src/lib');

var createGraphDiv = require('../assets/create_graph_div');
var destroyGraphDiv = require('../assets/destroy_graph_div');
var selectButton = require('../assets/modebar_button');

/*
 * WebGL interaction test cases fail on the CircleCI
 * most likely due to a WebGL/driver issue
 *
 */

describe('Test plot structure', function() {
    'use strict';

    afterEach(destroyGraphDiv);

    describe('gl3d plots', function() {
        var mock = require('@mocks/gl3d_marker-arrays.json');

        beforeEach(function(done) {
            Plotly.plot(createGraphDiv(), mock.data, mock.layout).then(done);
        });

        it('has one *canvas* node', function() {
            var nodes = d3.selectAll('canvas');
            expect(nodes[0].length).toEqual(1);
        });
    });

    describe('gl2d plots', function() {
        var mock = require('@mocks/gl2d_10.json');

        beforeEach(function(done) {
            Plotly.plot(createGraphDiv(), mock.data, mock.layout).then(done);
        });

        it('has one *canvas* node', function() {
            var nodes = d3.selectAll('canvas');
            expect(nodes[0].length).toEqual(1);
        });
    });

    describe('gl3d modebar click handlers', function() {
        var gd, modeBar;

        beforeEach(function(done) {
            var mockData = [{
                type: 'scatter3d'
            }, {
                type: 'surface', scene: 'scene2'
            }];

            var mockLayout = {
                scene: { camera: { eye: { x: 0.1, y: 0.1, z: 1 }}},
                scene2: { camera: { eye: { x: 2.5, y: 2.5, z: 2.5 }}}
            };

            gd = createGraphDiv();
            Plotly.plot(gd, mockData, mockLayout).then(function() {
                modeBar = gd._fullLayout._modeBar;
                done();
            });
        });

        function assertScenes(cont, attr, val) {
            var sceneIds = Plots.getSubplotIds(cont, 'gl3d');

            sceneIds.forEach(function(sceneId) {
                var thisVal = Lib.nestedProperty(cont[sceneId], attr).get();
                expect(thisVal).toEqual(val);
            });
        }

        describe('button zoom3d', function() {
            it('should updates the scene dragmode and dragmode button', function() {
                var buttonTurntable = selectButton(modeBar, 'tableRotation'),
                    buttonZoom3d = selectButton(modeBar, 'zoom3d');

                assertScenes(gd._fullLayout, 'dragmode', 'turntable');
                expect(buttonTurntable.isActive()).toBe(true);
                expect(buttonZoom3d.isActive()).toBe(false);

                buttonZoom3d.click();
                assertScenes(gd.layout, 'dragmode', 'zoom');
                expect(gd.layout.dragmode).toBe(undefined);
                expect(gd._fullLayout.dragmode).toBe('zoom');
                expect(buttonTurntable.isActive()).toBe(false);
                expect(buttonZoom3d.isActive()).toBe(true);

                buttonTurntable.click();
                assertScenes(gd._fullLayout, 'dragmode', 'turntable');
                expect(buttonTurntable.isActive()).toBe(true);
                expect(buttonZoom3d.isActive()).toBe(false);
            });
        });

        describe('button pan3d', function() {
            it('should updates the scene dragmode and dragmode button', function() {
                var buttonTurntable = selectButton(modeBar, 'tableRotation'),
                    buttonPan3d = selectButton(modeBar, 'pan3d');

                assertScenes(gd._fullLayout, 'dragmode', 'turntable');
                expect(buttonTurntable.isActive()).toBe(true);
                expect(buttonPan3d.isActive()).toBe(false);

                buttonPan3d.click();
                assertScenes(gd.layout, 'dragmode', 'pan');
                expect(gd.layout.dragmode).toBe(undefined);
                expect(gd._fullLayout.dragmode).toBe('zoom');
                expect(buttonTurntable.isActive()).toBe(false);
                expect(buttonPan3d.isActive()).toBe(true);

                buttonTurntable.click();
                assertScenes(gd._fullLayout, 'dragmode', 'turntable');
                expect(buttonTurntable.isActive()).toBe(true);
                expect(buttonPan3d.isActive()).toBe(false);
            });
        });

        describe('button orbitRotation', function() {
            it('should updates the scene dragmode and dragmode button', function() {
                var buttonTurntable = selectButton(modeBar, 'tableRotation'),
                    buttonOrbit = selectButton(modeBar, 'orbitRotation');

                assertScenes(gd._fullLayout, 'dragmode', 'turntable');
                expect(buttonTurntable.isActive()).toBe(true);
                expect(buttonOrbit.isActive()).toBe(false);

                buttonOrbit.click();
                assertScenes(gd.layout, 'dragmode', 'orbit');
                expect(gd.layout.dragmode).toBe(undefined);
                expect(gd._fullLayout.dragmode).toBe('zoom');
                expect(buttonTurntable.isActive()).toBe(false);
                expect(buttonOrbit.isActive()).toBe(true);

                buttonTurntable.click();
                assertScenes(gd._fullLayout, 'dragmode', 'turntable');
                expect(buttonTurntable.isActive()).toBe(true);
                expect(buttonOrbit.isActive()).toBe(false);
            });
        });

        describe('buttons resetCameraDefault3d and resetCameraLastSave3d', function() {
            // changes in scene objects are not instantaneous
            var DELAY = 1000;

            it('should update the scene camera', function(done) {
                var sceneLayout = gd._fullLayout.scene,
                    sceneLayout2 = gd._fullLayout.scene2,
                    scene = sceneLayout._scene,
                    scene2 = sceneLayout2._scene;

                expect(sceneLayout.camera.eye)
                    .toEqual({x: 0.1, y: 0.1, z: 1});
                expect(sceneLayout2.camera.eye)
                    .toEqual({x: 2.5, y: 2.5, z: 2.5});

                selectButton(modeBar, 'resetCameraDefault3d').click();
                setTimeout(function() {
                    expect(sceneLayout.camera.eye)
                        .toEqual({x: 0.1, y: 0.1, z: 1}, 'does not change the layout objects');
                    expect(scene.camera.eye)
                        .toEqual([1.2500000000000002, 1.25, 1.25]);
                    expect(sceneLayout2.camera.eye)
                        .toEqual({x: 2.5, y: 2.5, z: 2.5}, 'does not change the layout objects');
                    expect(scene2.camera.eye)
                        .toEqual([1.2500000000000002, 1.25, 1.25]);

                    selectButton(modeBar, 'resetCameraLastSave3d').click();
                    setTimeout(function() {
                        expect(sceneLayout.camera.eye)
                            .toEqual({x: 0.1, y: 0.1, z: 1}, 'does not change the layout objects');
                        expect(scene.camera.eye)
                            .toEqual([ 0.10000000000000016, 0.10000000000000016, 1]);
                        expect(sceneLayout2.camera.eye)
                            .toEqual({x: 2.5, y: 2.5, z: 2.5}, 'does not change the layout objects');
                        expect(scene2.camera.eye)
                            .toEqual([2.500000000000001, 2.5000000000000004, 2.5000000000000004]);

                        done();
                    }, DELAY);
                }, DELAY);
            });
        });

        describe('button hoverClosest3d', function() {
            it('should update the scene hovermode and spikes', function() {
                var buttonHover = selectButton(modeBar, 'hoverClosest3d');

                assertScenes(gd._fullLayout, 'hovermode', 'closest');
                expect(buttonHover.isActive()).toBe(true);

                buttonHover.click();
                assertScenes(gd._fullLayout, 'hovermode', false);
                assertScenes(gd._fullLayout, 'xaxis.showspikes', false);
                assertScenes(gd._fullLayout, 'yaxis.showspikes', false);
                assertScenes(gd._fullLayout, 'zaxis.showspikes', false);
                expect(buttonHover.isActive()).toBe(false);

                buttonHover.click();
                assertScenes(gd._fullLayout, 'hovermode', 'closest');
                assertScenes(gd._fullLayout, 'xaxis.showspikes', true);
                assertScenes(gd._fullLayout, 'yaxis.showspikes', true);
                assertScenes(gd._fullLayout, 'zaxis.showspikes', true);
                expect(buttonHover.isActive()).toBe(true);
            });
        });

    });
});
<commit_msg>Change precision and delay time for gl_plot_interact test<commit_after>var d3 = require('d3');

var Plotly = require('@lib/index');
var Plots = require('@src/plots/plots');
var Lib = require('@src/lib');

var createGraphDiv = require('../assets/create_graph_div');
var destroyGraphDiv = require('../assets/destroy_graph_div');
var selectButton = require('../assets/modebar_button');
var customMatchers = require('../assets/custom_matchers');

/*
 * WebGL interaction test cases fail on the CircleCI
 * most likely due to a WebGL/driver issue
 *
 */

describe('Test plot structure', function() {
    'use strict';

    beforeEach(function() {
        jasmine.addMatchers(customMatchers);
    });

    afterEach(destroyGraphDiv);

    describe('gl3d plots', function() {
        var mock = require('@mocks/gl3d_marker-arrays.json');

        beforeEach(function(done) {
            Plotly.plot(createGraphDiv(), mock.data, mock.layout).then(done);
        });

        it('has one *canvas* node', function() {
            var nodes = d3.selectAll('canvas');
            expect(nodes[0].length).toEqual(1);
        });
    });

    describe('gl2d plots', function() {
        var mock = require('@mocks/gl2d_10.json');

        beforeEach(function(done) {
            Plotly.plot(createGraphDiv(), mock.data, mock.layout).then(done);
        });

        it('has one *canvas* node', function() {
            var nodes = d3.selectAll('canvas');
            expect(nodes[0].length).toEqual(1);
        });
    });

    describe('gl3d modebar click handlers', function() {
        var gd, modeBar;

        beforeEach(function(done) {
            var mockData = [{
                type: 'scatter3d'
            }, {
                type: 'surface', scene: 'scene2'
            }];

            var mockLayout = {
                scene: { camera: { eye: { x: 0.1, y: 0.1, z: 1 }}},
                scene2: { camera: { eye: { x: 2.5, y: 2.5, z: 2.5 }}}
            };

            gd = createGraphDiv();
            Plotly.plot(gd, mockData, mockLayout).then(function() {
                modeBar = gd._fullLayout._modeBar;
                done();
            });
        });

        function assertScenes(cont, attr, val) {
            var sceneIds = Plots.getSubplotIds(cont, 'gl3d');

            sceneIds.forEach(function(sceneId) {
                var thisVal = Lib.nestedProperty(cont[sceneId], attr).get();
                expect(thisVal).toEqual(val);
            });
        }

        describe('button zoom3d', function() {
            it('should updates the scene dragmode and dragmode button', function() {
                var buttonTurntable = selectButton(modeBar, 'tableRotation'),
                    buttonZoom3d = selectButton(modeBar, 'zoom3d');

                assertScenes(gd._fullLayout, 'dragmode', 'turntable');
                expect(buttonTurntable.isActive()).toBe(true);
                expect(buttonZoom3d.isActive()).toBe(false);

                buttonZoom3d.click();
                assertScenes(gd.layout, 'dragmode', 'zoom');
                expect(gd.layout.dragmode).toBe(undefined);
                expect(gd._fullLayout.dragmode).toBe('zoom');
                expect(buttonTurntable.isActive()).toBe(false);
                expect(buttonZoom3d.isActive()).toBe(true);

                buttonTurntable.click();
                assertScenes(gd._fullLayout, 'dragmode', 'turntable');
                expect(buttonTurntable.isActive()).toBe(true);
                expect(buttonZoom3d.isActive()).toBe(false);
            });
        });

        describe('button pan3d', function() {
            it('should updates the scene dragmode and dragmode button', function() {
                var buttonTurntable = selectButton(modeBar, 'tableRotation'),
                    buttonPan3d = selectButton(modeBar, 'pan3d');

                assertScenes(gd._fullLayout, 'dragmode', 'turntable');
                expect(buttonTurntable.isActive()).toBe(true);
                expect(buttonPan3d.isActive()).toBe(false);

                buttonPan3d.click();
                assertScenes(gd.layout, 'dragmode', 'pan');
                expect(gd.layout.dragmode).toBe(undefined);
                expect(gd._fullLayout.dragmode).toBe('zoom');
                expect(buttonTurntable.isActive()).toBe(false);
                expect(buttonPan3d.isActive()).toBe(true);

                buttonTurntable.click();
                assertScenes(gd._fullLayout, 'dragmode', 'turntable');
                expect(buttonTurntable.isActive()).toBe(true);
                expect(buttonPan3d.isActive()).toBe(false);
            });
        });

        describe('button orbitRotation', function() {
            it('should updates the scene dragmode and dragmode button', function() {
                var buttonTurntable = selectButton(modeBar, 'tableRotation'),
                    buttonOrbit = selectButton(modeBar, 'orbitRotation');

                assertScenes(gd._fullLayout, 'dragmode', 'turntable');
                expect(buttonTurntable.isActive()).toBe(true);
                expect(buttonOrbit.isActive()).toBe(false);

                buttonOrbit.click();
                assertScenes(gd.layout, 'dragmode', 'orbit');
                expect(gd.layout.dragmode).toBe(undefined);
                expect(gd._fullLayout.dragmode).toBe('zoom');
                expect(buttonTurntable.isActive()).toBe(false);
                expect(buttonOrbit.isActive()).toBe(true);

                buttonTurntable.click();
                assertScenes(gd._fullLayout, 'dragmode', 'turntable');
                expect(buttonTurntable.isActive()).toBe(true);
                expect(buttonOrbit.isActive()).toBe(false);
            });
        });

        describe('buttons resetCameraDefault3d and resetCameraLastSave3d', function() {
            // changes in scene objects are not instantaneous
            var DELAY = 200;

            it('should update the scene camera', function(done) {
                var sceneLayout = gd._fullLayout.scene,
                    sceneLayout2 = gd._fullLayout.scene2,
                    scene = sceneLayout._scene,
                    scene2 = sceneLayout2._scene;

                expect(sceneLayout.camera.eye)
                    .toEqual({x: 0.1, y: 0.1, z: 1});
                expect(sceneLayout2.camera.eye)
                    .toEqual({x: 2.5, y: 2.5, z: 2.5});

                selectButton(modeBar, 'resetCameraDefault3d').click();
                setTimeout(function() {
                    expect(sceneLayout.camera.eye)
                        .toEqual({x: 0.1, y: 0.1, z: 1}, 'does not change the layout objects');
                    expect(scene.camera.eye)
                        .toBeCloseToArray([1.25, 1.25, 1.25], 4);
                    expect(sceneLayout2.camera.eye)
                        .toEqual({x: 2.5, y: 2.5, z: 2.5}, 'does not change the layout objects');
                    expect(scene2.camera.eye)
                        .toBeCloseToArray([1.25, 1.25, 1.25], 4);

                    selectButton(modeBar, 'resetCameraLastSave3d').click();
                    setTimeout(function() {
                        expect(sceneLayout.camera.eye)
                            .toEqual({x: 0.1, y: 0.1, z: 1}, 'does not change the layout objects');
                        expect(scene.camera.eye)
                            .toBeCloseToArray([ 0.1, 0.1, 1], 4);
                        expect(sceneLayout2.camera.eye)
                            .toEqual({x: 2.5, y: 2.5, z: 2.5}, 'does not change the layout objects');
                        expect(scene2.camera.eye)
                            .toBeCloseToArray([2.5, 2.5, 2.5], 4);

                        done();
                    }, DELAY);
                }, DELAY);
            });
        });

        describe('button hoverClosest3d', function() {
            it('should update the scene hovermode and spikes', function() {
                var buttonHover = selectButton(modeBar, 'hoverClosest3d');

                assertScenes(gd._fullLayout, 'hovermode', 'closest');
                expect(buttonHover.isActive()).toBe(true);

                buttonHover.click();
                assertScenes(gd._fullLayout, 'hovermode', false);
                assertScenes(gd._fullLayout, 'xaxis.showspikes', false);
                assertScenes(gd._fullLayout, 'yaxis.showspikes', false);
                assertScenes(gd._fullLayout, 'zaxis.showspikes', false);
                expect(buttonHover.isActive()).toBe(false);

                buttonHover.click();
                assertScenes(gd._fullLayout, 'hovermode', 'closest');
                assertScenes(gd._fullLayout, 'xaxis.showspikes', true);
                assertScenes(gd._fullLayout, 'yaxis.showspikes', true);
                assertScenes(gd._fullLayout, 'zaxis.showspikes', true);
                expect(buttonHover.isActive()).toBe(true);
            });
        });

    });
});
<|endoftext|>


<commit_before>function getMonsterDom(monster) {
    var name = monster.getName();
    var hp = monster.getCurrentHP();
    var hpPercentage = hp * 100 / hp;
    var baseHP = monster.getBaseHP();
    var mana = monster.getCurrentMana();
    var baseMana = monster.getBaseMana();
    var manaPercentage = mana * 100 / baseMana;
    var time = monster.getTimeToNextMove();
    var speed = monster.getSpeed();
    var speedPercentage = time * 100 / speed;

    return `

${name}

            ${hp} / ${baseHP}

 0}">

            ${mana} / ${baseMana}

            ${time} / ${speed}

`;
}

export default {
    bindTooltips: function(dungeon, grid) {
        $(grid).attr('title', 'Hi').tooltip({
            content: function() {
                var $cell = $(this);
                var x = +$cell.attr('data-x');
                var y = +$cell.attr('data-y');
                var tile = dungeon.getTile(x, y);
                var creature = tile.getCreature();

                var pc = dungeon.getPlayableCharacter();

                if(!pc.canSee(dungeon, tile)) {
                    return null;
                } else {
                    return $(`

${tile.getName()}

                            ${
                                creature ? (
                                    (creature === pc) ? 'You are here' : getMonsterDom(creature)
                                ) : ''
                            }

                    `);
                }
            },

            items: '.cell',

            tooltipClass: 'grid-tooltip',

            position: {
                my: 'left+15 top+5',
                at: 'right top'
            },

            show: {
                delay: 800
            },

            close: function( event, ui ) {
                ui.tooltip.hover(function () {
                    $(this).stop(true).fadeTo(400, 1);
                    //.fadeIn("slow"); // doesn't work because of stop()
                }, function () {
                    $(this).fadeOut(400, function(){ $(this).remove(); });
                });
            }
        });
    }
};
<commit_msg>Fixes<commit_after>function getMonsterDom(monster) {
    var name = monster.getName();
    var hp = monster.getCurrentHP();
    var hpPercentage = hp * 100 / hp;
    var baseHP = monster.getBaseHP();
    var mana = monster.getCurrentMana();
    var baseMana = monster.getBaseMana();
    var manaPercentage = mana * 100 / baseMana;
    var time = monster.getTimeToNextMove();
    var speed = monster.getSpeed();
    var speedPercentage = time * 100 / speed;

    return `

${name}

            ${hp} / ${baseHP}

 0}">

            ${mana} / ${baseMana}

            ${time} / ${speed}

`;
}

export default {
    bindTooltips: function(dungeon, grid) {
        $(grid).attr('title', 'Hi').tooltip({
            content: function() {
                var $cell = $(this);
                var x = +$cell.attr('data-x');
                var y = +$cell.attr('data-y');
                var tile = dungeon.getTile(x, y);
                var creature = tile.getCreature();

                var pc = dungeon.getPlayableCharacter();
                var pcHasSeenTile = pc.hasSeen(tile);
                var pcCanSeeTile = pc.canSee(dungeon, tile);

                if(!pcHasSeenTile) {
                    return null;
                } else {
                    return $(`

${tile.getName()}

                            ${
                                (creature && pcCanSeeTile) ? (
                                    (creature === pc) ? 'You are here' : getMonsterDom(creature)
                                ) : ''
                            }

                    `);
                }
            },

            items: '.cell',

            tooltipClass: 'grid-tooltip',

            position: {
                my: 'left+15 top+5',
                at: 'right top'
            },

            show: {
                delay: 1200
            },

            close: function( event, ui ) {
                ui.tooltip.hover(function () {
                    $(this).stop(true).fadeTo(400, 1);
                    //.fadeIn("slow"); // doesn't work because of stop()
                }, function () {
                    $(this).fadeOut(400, function(){ $(this).remove(); });
                });
            }
        });
    }
};
<|endoftext|>


<commit_before>$(function(){
	$(document).on('click','.update_public_flag', function(){
		if (GL.execute_flg) return false;
		update_public_flag(this);
		return false;
	});
});

function delte_image(id) {
	var is_tmp = (arguments.length > 1) ? arguments[1] : false;

	var post_uri = is_tmp ? 'site/api/delte_tmp_image' : 'album/image/api/delete';
	var target_attribute_prefix = is_tmp ? '#note_image_tmp' : '#note_image_uploaded';
	delete_item_execute_ajax(post_uri, id, target_attribute_prefix, false);
	return false;
}

function get_uploaded_images(content_id)
{
	var get_data_added = (arguments.length > 1) ? arguments[1] : {};
console.log(get_data_added);
	get_upload_images('#uploaded_images', 'album/image/api/uploaded_images/note.html', content_id, '', get_data_added);
}

function get_tmp_images(tmp_hash)
{
	get_upload_images('#tmp_images', 'site/api/tmp_images/note.html', 0, tmp_hash);
}

function get_upload_images(target_atter, get_uri)
{
	var content_id = (arguments.length > 2) ? arguments[2] : 0;
	var tmp_hash   = (arguments.length > 3) ? arguments[3] : '';
	var get_data_added = (arguments.length > 4) ? arguments[4] : {};

	var targetDomElement = $(target_atter);

	var get_data = {};
	get_data['nochache'] = (new Date()).getTime();
	if (content_id > 0) get_data['content_id'] = content_id;
	if (tmp_hash.length > 0) get_data['tmp_hash'] = tmp_hash;
	if (get_data_added) {
		get_data = $.extend(get_data, get_data_added);
	}

	$.ajax({
		url : get_baseUrl() + get_uri,
		type : 'GET',
		dataType : 'text',
		data : get_data,
		timeout: 10000,
		beforeSend: function(xhr, settings) {
			GL.execute_flg = true;
			if (targetDomElement) {
				$(targetDomElement).html(get_loading_image_tag(true));
			}
		},
		complete: function(xhr, textStatus) {
			GL.execute_flg = false;
		},
		success: function(result){
			$('.loading_image').remove();
			$(targetDomElement).html(result);
		},
		error: function(result) {
			$('.loading_image').remove();
			$.jGrowl(get_error_message(result['status'], '読み込みに失敗しました。'));
		}
	});
}
<commit_msg>日記編集時にアップロード済み写真削除前に削除確認するようにした<commit_after>$(function(){
	$(document).on('click','.update_public_flag', function(){
		if (GL.execute_flg) return false;
		update_public_flag(this);
		return false;
	});
});

function delte_image(id) {
	var is_tmp = (arguments.length > 1) ? arguments[1] : false;
	var post_uri = is_tmp ? 'site/api/delte_tmp_image' : 'album/image/api/delete';
	var target_attribute_prefix = is_tmp ? '#note_image_tmp' : '#note_image_uploaded';

	if (is_tmp) {
		delete_item_execute_ajax(post_uri, id, target_attribute_prefix, false);
	} else {
		apprise('削除した写真は元に戻せません。削除しますか？', {'confirm':true}, function(r) {
			if (r == true) delete_item_execute_ajax(post_uri, id, target_attribute_prefix, false);
		});
	}

	return false;
}

function get_uploaded_images(content_id)
{
	var get_data_added = (arguments.length > 1) ? arguments[1] : {};
console.log(get_data_added);
	get_upload_images('#uploaded_images', 'album/image/api/uploaded_images/note.html', content_id, '', get_data_added);
}

function get_tmp_images(tmp_hash)
{
	get_upload_images('#tmp_images', 'site/api/tmp_images/note.html', 0, tmp_hash);
}

function get_upload_images(target_atter, get_uri)
{
	var content_id = (arguments.length > 2) ? arguments[2] : 0;
	var tmp_hash   = (arguments.length > 3) ? arguments[3] : '';
	var get_data_added = (arguments.length > 4) ? arguments[4] : {};

	var targetDomElement = $(target_atter);

	var get_data = {};
	get_data['nochache'] = (new Date()).getTime();
	if (content_id > 0) get_data['content_id'] = content_id;
	if (tmp_hash.length > 0) get_data['tmp_hash'] = tmp_hash;
	if (get_data_added) {
		get_data = $.extend(get_data, get_data_added);
	}

	$.ajax({
		url : get_baseUrl() + get_uri,
		type : 'GET',
		dataType : 'text',
		data : get_data,
		timeout: 10000,
		beforeSend: function(xhr, settings) {
			GL.execute_flg = true;
			if (targetDomElement) {
				$(targetDomElement).html(get_loading_image_tag(true));
			}
		},
		complete: function(xhr, textStatus) {
			GL.execute_flg = false;
		},
		success: function(result){
			$('.loading_image').remove();
			$(targetDomElement).html(result);
		},
		error: function(result) {
			$('.loading_image').remove();
			$.jGrowl(get_error_message(result['status'], '読み込みに失敗しました。'));
		}
	});
}
<|endoftext|>


<commit_before>var selectedcourseid;

//viewmodel for the assess page
function pageViewModel(gvm) {
    gvm.app  = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectRapportName")}, gvm);
    gvm.title = ko.computed(function(){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n. __("AssessTitle2");}, gvm);
    gvm.userId = -1;

    // Page specific i18n bindings
    gvm.pageHeader = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AssessTitle2");}, gvm);
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectRapportName");}, gvm);
    gvm.homeManual = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("HomeRapportManual");}, gvm);
    gvm.foundProjects = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("FoundProjects");}, gvm);
    gvm.selectCourse = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("SelectCourse");}, gvm);

    // Pagination i18n bindings
    gvm.addBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AddBtn")}, gvm);

    // Table i18n bindings
    gvm.werkficheID = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("werkficheID");}, gvm);
    gvm.werkficheName = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("werkficheName");}, gvm);
    gvm.werkficheDate = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("werkficheDate");}, gvm);
    gvm.werkficheAction = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("werkficheAction");}, gvm);

    gvm.availableCourses = ko.observableArray([]);
    gvm.availableStudentlists = ko.observableArray([]);
    gvm.availableStudents = ko.observableArray([]);

    gvm.currentCourseId = null;
    gvm.currentStudentlistId = null;
    gvm.currentStudentId = null;

    gvm.updateDropdowns = function() {
        $.getJSON('api/lastdropdownrapporten/' + gvm.userId, function(data) {
            if(!$.isEmptyObject(data)) {
                $.each(data, function(i, item) {
                    $(".btn-courseRapport span:first").text(item.course);
                    $(".btn-studentlist span:first").text(item.studentlist);
                    $('.btn-student span:first').text(item.student);
                    gvm.currentCourseId = item.courseid;
                    gvm.currentStudentlistId = item.studentlistid;
                    gvm.currentStudentId = item.studentid;
                    gvm.updateCourseRapport();
                    loadTablePage(item.courseid, 1);
                });
            } else {
                gvm.updateCourseRapport();
            }
        });
    }

    //Houdt bij wat geselecteerd wordt
    //Wordt opgeroepen bij iedere wijziging (niet ingevulde velden = NULL)
    gvm.saveLastSelectedDropdowns = function() {
        data = {};
        data["user"] = gvm.userId;
        data["course"] = $(".btn-courseRapport span:first").text();
        data["courseid"] = gvm.currentCourseId;
        data["studentlist"] = $('.btn-studentlist span:first').text();
        data["studentlistid"] = gvm.currentStudentlistId;
        data["student"] = $(".btn-student span:first").text();
        data["studentid"] = gvm.currentStudentId;
        console.log(data);
        $.ajax({
            type: "POST",
            url: "/api/savedropdownsRapport",
            data: data,
            success: function() {
                console.log("success");
            }
        })
    }

    gvm.updateCourseRapport = function() {
        $.getJSON('/api/coursefromteacher/' + gvm.userId, function(data) {
            console.log(gvm.userId);
            gvm.availableCourses.removeAll();
            $.each(data, function(i, item) {
                //  Put item in list
                gvm.availableCourses.push(item);

                // Add listener to listitem
                $("#coursebtn-" + item.id).click(function(){
                    gvm.currentCourseId = item.id;
                    selectedcourseid = item.id;
                    gvm.currentStudentlistId = null;
                    gvm.currentStudentId = null;
                    gvm.updateStudentlists(item.id, gvm.userId);
                    $(".btn-courseRapport span:first").text($(this).text());
                    $(".btn-studentlist span:first").text("Studentlist");
                    $('.btn-student span:first').text("Student");
                    gvm.saveLastSelectedDropdowns();
                });
            });
        });
    };

    /*
     * Update the student data
     */
    gvm.updateStudentlists = function(cid, uid) {
        //get all studentlists
        $.getJSON('api/studentlistdrop/' + cid + '/' + uid, function(data) {
            gvm.availableStudentlists.removeAll();
            $.each(data, function(i,item) {
                // Put item in list
                gvm.availableStudentlists.push(item);

                // Add listener to listitem
                $("#studentlistbtn-" + item.id).click(function(){
                    gvm.currentStudentlistId = item.id;
                    gvm.currentStudentId = null;
                    gvm.updateStudents(item.id);
                    $(".btn-studentlist span:first").text($(this).text());
                    $('.btn-student span:first').text("Student");
                    gvm.saveLastSelectedDropdowns();
                });
            })
        })
    }

    /*
     * Update the student data
     */
    gvm.updateStudents = function(id) {
        //get all students who follow that course
        $.getJSON('api/studentdrop/' + id, function(data) {
            gvm.availableStudents.removeAll();
            $.each(data, function(i,item) {
                // Put item in list
                gvm.availableStudents.push(item);

                // Add listener to listitem
                $("#studentbtn-" + item.id).click(function(){
                    gvm.currentStudentId = item.id;
                    $(".btn-student span:first").text($(this).text());
                    gvm.saveLastSelectedDropdowns();
                });
            })
        })
    }

    // The table data observable array
    gvm.tabledata = ko.observableArray([]);

    // Add data to the table
    gvm.addTableData = function(id, name, lastname, mail, score) {
        // Push data
        var tblOject = {tstudid: id, tname: name, tlname: lastname, tmail: mail, tscore: score};
        gvm.tabledata.push(tblOject);
    }

    gvm.clearTable = function() {
        gvm.tabledata.removeAll();
    }
}

function getAllTeachers() {
    teachers = [];
    teachersid = [];
    $.getJSON('/api/getteacherrapport', function(data) {
        $.each(data, function(i, item) {
            teachers.push(item.firstname + " " + item.lastname);
            teachersid.push(item.id);
        });
    });
    return teachers;
}

function getAllWorksheets() {
    worksheets = [];
    worksheetsid = [];
    console.log("geselecteerd courseid " + selectedcourseid)
    $.getJSON('/api/worksheets/' + selectedcourseid, function(data) {
        $.each(data, function(i, item) {
            worksheets.push(item.Name);
            worksheets.push(item.id);
            console.log(data)
        });
    });
    return worksheets;
}

function loadTablePage(pagenr)
{
    $.getJSON('/api/worksheets/page/' + pagenr, function(data){

        /* Clear current table page */
        viewModel.clearTable();

        // Load table data
        $.each(data.data, function(i, item) {
            viewModel.addTableData(item.id,  item.firstname, item.lastname, item.mail);
        });

        /* Let previous en next buttons work */
        if(data.prev == "none"){
            $('#pager-prev-btn').addClass('disabled');
        } else {
            $('#pager-prev-btn').removeClass('disabled');
            $('#pager-prev-btn a').click(function(){
                loadTablePage(data.prev);
            });
        }

        if(data.next == "none"){
            $('#pager-next-btn').addClass('disabled');
        } else {
            $('#pager-next-btn').removeClass('disabled');
            $('#pager-next-btn a').click(function(){
                loadTablePage(data.next);
            });
        }

        // Number of pager buttons
        var numItems = $('.pager-nr-btn').length;

        /* Calculate for the pager buttons */
        var lowPage = Math.floor(pagenr/numItems) + 1;

        $('.pager-nr-btn').each(function() {
            /* calculate current page number */
            var thispagenr = lowPage++;

            /* Add the page number */
            $(this).html('' + thispagenr + '');

            /* Add active class to current page */
            if(thispagenr == pagenr) {
                $(this).addClass('active');
            } else {
                $(this).removeClass('active');
            }

            /* Disable inactive classes and bind handlers to active classes */
            if(thispagenr > data.pagecount) {
                $(this).addClass('disabled');
            } else {
                /* Add click listener for button */
                $(this).click(function() {
                    loadTablePage(thispagenr);
                });
            }
        });
    });
}

function initPage() {
    $.getJSON('/api/currentuser', function(data) {
        viewModel.userId = data.id;
        viewModel.updateDropdowns();
    });

    $('#addGroupForm').hide();

    $('#addWorksheetBtn').click(function() {
        $("#addGroupForm").show();
        $('#worksheetComplete').autocomplete({ source: getAllWorksheets() });
    });

    $('#addNewWorksheetBtn').click(function() {

        console.log("toevoegen")
        //effectief toevoegen
        //table herladen

        //Indien gewenst toevoegformulier weer verbergen.
        $('#addGroupForm').hide();
    });
}<commit_msg>Make it possible to add worksheets for a specific course.<commit_after>var selectedcourseid;

//viewmodel for the assess page
function pageViewModel(gvm) {
    gvm.app  = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectRapportName")}, gvm);
    gvm.title = ko.computed(function(){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n. __("AssessTitle2");}, gvm);
    gvm.userId = -1;

    // Page specific i18n bindings
    gvm.pageHeader = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AssessTitle2");}, gvm);
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectRapportName");}, gvm);
    gvm.homeManual = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("HomeRapportManual");}, gvm);
    gvm.foundProjects = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("FoundProjects");}, gvm);
    gvm.selectCourse = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("SelectCourse");}, gvm);

    // Pagination i18n bindings
    gvm.addBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AddBtn")}, gvm);

    // Table i18n bindings
    gvm.werkficheID = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("werkficheID");}, gvm);
    gvm.werkficheName = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("werkficheName");}, gvm);
    gvm.werkficheDate = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("werkficheDate");}, gvm);
    gvm.werkficheAction = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("werkficheAction");}, gvm);

    gvm.availableCourses = ko.observableArray([]);
    gvm.availableStudentlists = ko.observableArray([]);
    gvm.availableStudents = ko.observableArray([]);

    gvm.currentCourseId = null;
    gvm.currentStudentlistId = null;
    gvm.currentStudentId = null;

    gvm.updateDropdowns = function() {
        $.getJSON('api/lastdropdownrapporten/' + gvm.userId, function(data) {
            if(!$.isEmptyObject(data)) {
                $.each(data, function(i, item) {
                    $(".btn-courseRapport span:first").text(item.course);
                    $(".btn-studentlist span:first").text(item.studentlist);
                    $('.btn-student span:first').text(item.student);
                    gvm.currentCourseId = item.courseid;
                    selectedcourseid = item.courseid;
                    gvm.currentStudentlistId = item.studentlistid;
                    gvm.currentStudentId = item.studentid;
                    gvm.updateCourseRapport();
                    loadTablePage(item.courseid, 1);
                });
            } else {
                gvm.updateCourseRapport();
            }
        });
    }

    //Houdt bij wat geselecteerd wordt
    //Wordt opgeroepen bij iedere wijziging (niet ingevulde velden = NULL)
    gvm.saveLastSelectedDropdowns = function() {
        data = {};
        data["user"] = gvm.userId;
        data["course"] = $(".btn-courseRapport span:first").text();
        data["courseid"] = gvm.currentCourseId;
        data["studentlist"] = $('.btn-studentlist span:first').text();
        data["studentlistid"] = gvm.currentStudentlistId;
        data["student"] = $(".btn-student span:first").text();
        data["studentid"] = gvm.currentStudentId;
        console.log(data);
        $.ajax({
            type: "POST",
            url: "/api/savedropdownsRapport",
            data: data,
            success: function() {
                console.log("success");
            }
        })
    }

    gvm.updateCourseRapport = function() {
        $.getJSON('/api/coursefromteacher/' + gvm.userId, function(data) {
            console.log(gvm.userId);
            gvm.availableCourses.removeAll();
            $.each(data, function(i, item) {
                //  Put item in list
                gvm.availableCourses.push(item);

                // Add listener to listitem
                $("#coursebtn-" + item.id).click(function(){
                    gvm.currentCourseId = item.id;
                    selectedcourseid = item.id;
                    gvm.currentStudentlistId = null;
                    gvm.currentStudentId = null;
                    gvm.updateStudentlists(item.id, gvm.userId);
                    $(".btn-courseRapport span:first").text($(this).text());
                    $(".btn-studentlist span:first").text("Studentlist");
                    $('.btn-student span:first').text("Student");
                    gvm.saveLastSelectedDropdowns();
                });
            });
        });
    };

    /*
     * Update the student data
     */
    gvm.updateStudentlists = function(cid, uid) {
        //get all studentlists
        $.getJSON('api/studentlistdrop/' + cid + '/' + uid, function(data) {
            gvm.availableStudentlists.removeAll();
            $.each(data, function(i,item) {
                // Put item in list
                gvm.availableStudentlists.push(item);

                // Add listener to listitem
                $("#studentlistbtn-" + item.id).click(function(){
                    gvm.currentStudentlistId = item.id;
                    gvm.currentStudentId = null;
                    gvm.updateStudents(item.id);
                    $(".btn-studentlist span:first").text($(this).text());
                    $('.btn-student span:first').text("Student");
                    gvm.saveLastSelectedDropdowns();
                });
            })
        })
    }

    /*
     * Update the student data
     */
    gvm.updateStudents = function(id) {
        //get all students who follow that course
        $.getJSON('api/studentdrop/' + id, function(data) {
            gvm.availableStudents.removeAll();
            $.each(data, function(i,item) {
                // Put item in list
                gvm.availableStudents.push(item);

                // Add listener to listitem
                $("#studentbtn-" + item.id).click(function(){
                    gvm.currentStudentId = item.id;
                    $(".btn-student span:first").text($(this).text());
                    gvm.saveLastSelectedDropdowns();
                });
            })
        })
    }

    // The table data observable array
    gvm.tabledata = ko.observableArray([]);

    // Add data to the table
    gvm.addTableData = function(id, name, lastname, mail, score) {
        // Push data
        var tblOject = {tstudid: id, tname: name, tlname: lastname, tmail: mail, tscore: score};
        gvm.tabledata.push(tblOject);
    }

    gvm.clearTable = function() {
        gvm.tabledata.removeAll();
    }
}

function getAllTeachers() {
    teachers = [];
    teachersid = [];
    $.getJSON('/api/getteacherrapport', function(data) {
        $.each(data, function(i, item) {
            teachers.push(item.firstname + " " + item.lastname);
            teachersid.push(item.id);
        });
    });
    return teachers;
}

function getAllWorksheets() {
    worksheets = [];
    worksheetsid = [];
    $.getJSON('/api/worksheets/' + selectedcourseid, function(data) {
        $.each(data, function(i, item) {
            worksheets.push(item.Name);
            worksheets.push(item.id);
        });
    });
    return worksheets;
}

function loadTablePage(pagenr)
{
    $.getJSON('/api/worksheets/page/' + pagenr, function(data){

        /* Clear current table page */
        viewModel.clearTable();

        // Load table data
        $.each(data.data, function(i, item) {
            viewModel.addTableData(item.id,  item.firstname, item.lastname, item.mail);
        });

        /* Let previous en next buttons work */
        if(data.prev == "none"){
            $('#pager-prev-btn').addClass('disabled');
        } else {
            $('#pager-prev-btn').removeClass('disabled');
            $('#pager-prev-btn a').click(function(){
                loadTablePage(data.prev);
            });
        }

        if(data.next == "none"){
            $('#pager-next-btn').addClass('disabled');
        } else {
            $('#pager-next-btn').removeClass('disabled');
            $('#pager-next-btn a').click(function(){
                loadTablePage(data.next);
            });
        }

        // Number of pager buttons
        var numItems = $('.pager-nr-btn').length;

        /* Calculate for the pager buttons */
        var lowPage = Math.floor(pagenr/numItems) + 1;

        $('.pager-nr-btn').each(function() {
            /* calculate current page number */
            var thispagenr = lowPage++;

            /* Add the page number */
            $(this).html('' + thispagenr + '');

            /* Add active class to current page */
            if(thispagenr == pagenr) {
                $(this).addClass('active');
            } else {
                $(this).removeClass('active');
            }

            /* Disable inactive classes and bind handlers to active classes */
            if(thispagenr > data.pagecount) {
                $(this).addClass('disabled');
            } else {
                /* Add click listener for button */
                $(this).click(function() {
                    loadTablePage(thispagenr);
                });
            }
        });
    });
}

function initPage() {
    $.getJSON('/api/currentuser', function(data) {
        viewModel.userId = data.id;
        viewModel.updateDropdowns();
    });

    $('#addGroupForm').hide();

    $('#addWorksheetBtn').click(function() {
        $("#addGroupForm").show();
        $('#worksheetComplete').autocomplete({ source: getAllWorksheets() });
    });

    $('#addNewWorksheetBtn').click(function() {

        console.log("toevoegen")
        //effectief toevoegen
        //table herladen

        //Indien gewenst toevoegformulier weer verbergen.
        $('#addGroupForm').hide();
    });
}<|endoftext|>