<commit_before>wwt.app.factory('UILibrary', ['$rootScope', 'AppState', 'Util', 'Localization', '$modal', '$sce', function ($rootScope, appState, util, loc, $modal, $sce) {

  $rootScope.layerManagerHidden = appState.get('layerManagerHidden') ? true : false;

  $rootScope.toggleLayerManager = function () {
    $rootScope.layerManagerHidden = !$rootScope.layerManagerHidden;
    appState.set('layerManagerHidden', $rootScope.layerManagerHidden);
  };

  $rootScope.getCreditsText = function (place) {
    return util.getCreditsText(place);
  };
  $rootScope.getCreditsUrl = function (place) {
    return util.getCreditsUrl(place);
  }

  $rootScope.getClassificationText = function (clsid) {
    var txt = util.getClassificationText(clsid);
    return txt || loc.getFromEn('Unknown');
  };

  $rootScope.secondsToTime = function (secs) {
    return util.secondsToTime(secs);
  };

  $rootScope.isMobile = util.isMobile;

  $rootScope.resLocation = $('body').data('res-location');
  $rootScope.bottomControlsWidth = function () {
    return (angular.element('div.context-panel').width() - angular.element('body.desktop .fov-panel').width()) + 1;
  }
  $rootScope.layerManagerHeight = function () {
    return $(window).height() - (168 + $('body.desktop .context-panel').height());
  };

  $rootScope.copyLink = function (event, selector) {
    var src = $(event.currentTarget);
    var input = selector ? src.parent().find(selector) : src.prev();
    input[0].select();
    document.execCommand('copy');
    var flyout = $('
Copied successfully
');
    input.parent().css('position', 'relative').append(flyout);
    //flyout.fadeIn(200).show();
    setTimeout(function () {
      flyout.fadeOut(1111);
    }, 3333);
  };
  $rootScope.altUnits = [
    {type: 1, label: 'Meters'},
    {type: 2, label: 'Feet'},
    {type: 3, label: 'Inches'},
    {type: 4, label: 'Miles'},
    {type: 5, label: 'Kilometers'},
    {type: 6, label: 'Astronomical Units'},
    {type: 7, label: 'Light Years'},
    {type: 8, label: 'Parsecs'},
    {type: 9, label: 'MegaParsecs'},
    {type: 10, label: 'Custom'}
  ];

  $rootScope.observingLocation = {name:'My Location'};

  var setObservingLocation = function(props){
    $rootScope.$applyAsync(function(){
    props.localHorizonMode = props.localHorizonMode === undefined ?
      $rootScope.ctl.settings._localHorizonMode :
      props.localHorizonMode;
    $rootScope.observingLocation = Object.assign($rootScope.observingLocation,props);
    var earthMap = wwtlib.LayerManager.get_allMaps().Earth;

    var rf = new wwtlib.ReferenceFrame();
    rf.name = 'Observing Location';
    rf.lat = props.lat;
    rf.lng = props.lng;
    rf.altitude = props.altitude;
    wwtlib.LayerManager.referenceFrameWizardFinished(rf);
    $rootScope.hasSetupObservingLocation = true;
    var newSettings = {
      _locationAltitude:props.altitude,//.toFixed(1) +'m',//0.00000690228892768605
      _locationLat:props.lat,//47.70409186039239
      _locationLng:props.lng,//-122.30266851233682
      _localHorizonMode:props.localHorizonMode
    };
    Object.assign(wwt.wc.settings,newSettings);
    wwtlib.LayerManager.layerSelectionChanged(earthMap);
  });
};

  var initTypeList = function (typeKey, scopeKey) {
    if (typeof scopeKey != 'string') {
      scopeKey = util.firstCharLower(typeKey)
    }
    $rootScope[scopeKey] = Object.keys(wwtlib[typeKey]).map(function (label, type) {
      return {
        type: type,
        label: util.firstCharUpper(label)
      }
    });
  };
  initTypeList('CoordinatesTypes', 'coordTypes');
  var enums = ['AltTypes', 'PointScaleTypes', 'MarkerScales', 'MarkerMixes', 'PlotTypes', 'ColorMaps'];
  enums.forEach(initTypeList);

  var annotationOpts = function (s) {
    var obj = {};
    var pairs = s.split(',');
    pairs.forEach(function (kv) {
      kv = kv.split(':');
      var k = kv[0].toLowerCase();
      var v = kv[1];
      if (k === 'embed' || k === 'youtube') {
        v += ':' + kv[2];
        var expression = /^(https?:\/\/)?((www\.)?(youtube(-nocookie)?|youtube.googleapis)\.com.*(v\/|v=|vi=|vi\/|e\/|embed\/|user\/.*\/u\/\d+\/)|youtu\.be\/)([_0-9a-z-]+)/i;
        v = v.match(expression)[7];
        k = 'youtube'
      }
      obj[k] = v;
    });
    return obj;
  };
  $rootScope.loadVOTableModal = wwt.loadVOTableModal = function (votable) {

    var modalScope = $rootScope.$new();
    modalScope.customClass = 'vo-tbl-modal';
    modalScope.voTableLayer = votable.get_table ? votable : wwtlib.VoTableLayer.create(votable);
    modalScope.votable = modalScope.voTableLayer.get_table();

    $modal({
      scope: modalScope,
      templateUrl: 'views/modals/centered-modal-template.html?v=' + util.resVersion,
      contentTemplate: 'views/modals/vo-table-viewer.html?v=' + util.resVersion,
      show: true,
      placement: 'center',
      backdrop: false
    });
  };

  var showColorpicker = function (colorpicker, e) {
    var modalScope = $rootScope.$new();
    modalScope.colorpicker = colorpicker;
    modalScope.mouse = e;
    modalScope.customClass = 'colorpicker-modal';
    $modal({
      scope: modalScope,
      templateUrl: 'views/modals/centered-modal-template.html?v=' + util.resVersion,
      contentTemplate: 'views/modals/colorpicker.html?v=' + util.resVersion,
      show: true,
      placement: 'center',
      backdrop: false,
      controller: 'colorpickerController'
    });
  };

  var loadingModal;
  $rootScope.loading = function (flag, content) {
    if (loadingModal) {
      loadingModal.hide();
      loadingModal = null;
    }
    if (flag) {
      loadingModal = $modal({
        templateUrl: 'views/modals/loading-content.html?v=' + util.resVersion,
        show: true,
        content: content || 'Content Loading. Please Wait...',
        placement: 'center'
      });
    }
  }
  if (util.getQSParam('debug') === 'disable') {
    setTimeout(function () {
      wwtlib.WWTControl.singleton.render = function () {
        //console.log('fixed render loop :)');
      };
      //testing only:
      $('#WorldWideTelescopeControlHost').html('');
    }, 888)

  }
  var frameWizardDialog = wwtlib.LayerManager.get_frameWizardDialog();
  var showFrameWizardDialog = function (refFrame, propertyMode) {
    //console.log({refFrame: refFrame});
    var modalScope = $rootScope.$new();
    refFrame.name = refFrame.name || '';
    modalScope.refFrame = refFrame;
    modalScope.dialog = frameWizardDialog;
    modalScope.propertyMode = propertyMode;
    //modalScope.mouse = e;
    modalScope.customClass = 'wizard';
    $modal({
      scope: modalScope,
      templateUrl: 'views/modals/centered-modal-template.html?v=' + util.resVersion,
      contentTemplate: 'views/modals/ref-frame-wiz.html?v=' + util.resVersion,
      show: true,
      placement: 'center',
      backdrop: false,
      controller: 'refFrameController'

    });
  };
//scope,callback,cssClass,controller,template,backdrop - template=required
  var showModal = function (props) {
    //console.log({refFrame: refFrame});
    var modalScope = props.scope ? props.scope.$new() : $rootScope.$new();

    var modalConfig = {
      scope: modalScope,
      templateUrl: 'views/modals/centered-modal-template.html?v=' + util.resVersion,
      contentTemplate: 'views/modals/' + props.template + '.html?v=' + util.resVersion,
      show: true,
      //placement: 'center',
      backdrop: props.backdrop !== undefined ? props.backdrop : false,
      controller: props.controller
    };
    if (props.cssClass) {
      modalScope.customClass = props.cssClass;
    }
    if (props.fixedPosition) {
      modalScope.customClass += ' noreposition';
      modalConfig.animation = false;
      modalConfig.backdropAnimation = false;
      setTimeout(function(){
        $('.noreposition').removeClass('noreposition').find('.modal-dialog').css({left:300});
      },2222);
    } else {
      modalConfig.placement = 'centered';
    }
    var modal = $modal(modalConfig);

    if (props.callback) {
      props.callback({modal: modal, scope: modalScope, modalConfig: modalConfig});
    }
  };

  var dataVizWiz = wwtlib.LayerManager.get_dataVizWizardDialog();
  var showDataVizWiz = function (layerMap) {
    //console.log(layerMap);
    var modalScope = $rootScope.$new();
    var propertyMode = typeof layerMap !== 'string';
    modalScope.propertyMode = propertyMode;
    if (!propertyMode) {
      modalScope.layerMap = layerMap;
    } else {
      modalScope.layer = layerMap;
    }
    modalScope.customClass = 'wizard';
    modalScope.dialog = dataVizWiz;
    $modal({
      scope: modalScope,
      templateUrl: 'views/modals/centered-modal-template.html?v=' + util.resVersion,
      contentTemplate: 'views/modals/data-viz-wiz.html?v=' + util.resVersion,
      show: true,
      placement: 'center',
      backdrop: false,
      controller: 'DataVizController'
    });
  };

  var refFrameDialog = wwtlib.LayerManager.get_referenceFramePropsDialog();
  //console.log(refFrameDialog);
  var showRefFrameProps = function (refFrame) {
    showFrameWizardDialog(refFrame, true);
  };

  var greatCircleDlg = wwtlib.LayerManager.get_greatCircleDlg();
  //console.log(greatCircleDlg);
  var showGreatCircleDlg = function (layer) {
    //console.log(layer);
    var modalScope = $rootScope.$new();
    modalScope.layer = layer;
    modalScope.customClass = 'great-circle';
    $modal({
      scope: modalScope,
      templateUrl: 'views/modals/centered-modal-template.html?v=' + util.resVersion,
      contentTemplate: 'views/modals/great-circle.html?v=' + util.resVersion,
      show: true,
      placement: 'center',
      backdrop: false,
      controller: 'greatCircleController'
    });
  };

  var embedVideo = function (videoid) {
    var modalScope = $rootScope.$new();
    modalScope.url = $sce.trustAsResourceUrl('//www.youtube.com/embed/' + videoid + '?autoplay=1');
    modalScope.customClass = 'wizard embed-modal';
    $modal({
      scope: modalScope,
      animation: false,
      backdropAnimation: false,
      templateUrl: 'views/modals/centered-modal-template.html?v=' + util.resVersion,
      contentTemplate: 'views/modals/embed-video.html?v=' + util.resVersion,
      show: true,
      //placement: 'center',
      backdrop: false,
      controller: 'EmbedController'
    });
  };
  wwt.root = $rootScope;

  return {
    addDialogHooks: function () {
      wwt.wc.add_annotationClicked(function (interface, event) {
        var opts = annotationOpts(event.get_id());
        if (opts.youtube) {
          embedVideo(opts.youtube);
        } else if (opts.link) {
          window.open(opts.link);
        }
      });
      wwt.wc.add_voTableDisplay(wwt.loadVOTableModal);
      wwt.wc.add_colorPickerDisplay(showColorpicker);
      frameWizardDialog.add_showDialogHook(function (frame) {
        showFrameWizardDialog(frame, false);
      });
      refFrameDialog.add_showDialogHook(showRefFrameProps);
      greatCircleDlg.add_showDialogHook(showGreatCircleDlg);
      dataVizWiz.add_showDialogHook(showDataVizWiz);
    },
    embedVideo: embedVideo,
    annotationOpts: annotationOpts,
    showModal: showModal,
    showErrorMessage:function(msg){
      var scope = $rootScope.$new();
      scope.message = msg;
      scope.title = 'Error';
      var props = {
        scope:scope,
        template:'message'
      };

      showModal(props);
    },
    setObservingLocation:setObservingLocation
  };
}]);

<commit_msg>adding compiled js and layermanager fix on init<commit_after>wwt.app.factory('UILibrary', ['$rootScope', 'AppState', 'Util', 'Localization', '$modal', '$sce', function ($rootScope, appState, util, loc, $modal, $sce) {

  $rootScope.layerManagerHidden = appState.get('layerManagerHidden') ? true : false;

  $rootScope.toggleLayerManager = function () {
    $rootScope.layerManagerHidden = !$rootScope.layerManagerHidden;
    appState.set('layerManagerHidden', $rootScope.layerManagerHidden);
  };

  $rootScope.getCreditsText = function (place) {
    return util.getCreditsText(place);
  };
  $rootScope.getCreditsUrl = function (place) {
    return util.getCreditsUrl(place);
  }

  $rootScope.getClassificationText = function (clsid) {
    var txt = util.getClassificationText(clsid);
    return txt || loc.getFromEn('Unknown');
  };

  $rootScope.secondsToTime = function (secs) {
    return util.secondsToTime(secs);
  };

  $rootScope.isMobile = util.isMobile;

  $rootScope.resLocation = $('body').data('res-location');
  $rootScope.bottomControlsWidth = function () {
    return (angular.element('div.context-panel').width() - angular.element('body.desktop .fov-panel').width()) + 1;
  }
  $rootScope.layerManagerHeight = function () {
    return $(window).height() - (168 + $('body.desktop .context-panel').height());
  };

  $rootScope.copyLink = function (event, selector) {
    var src = $(event.currentTarget);
    var input = selector ? src.parent().find(selector) : src.prev();
    input[0].select();
    document.execCommand('copy');
    var flyout = $('
Copied successfully
');
    input.parent().css('position', 'relative').append(flyout);
    //flyout.fadeIn(200).show();
    setTimeout(function () {
      flyout.fadeOut(1111);
    }, 3333);
  };
  $rootScope.altUnits = [
    {type: 1, label: 'Meters'},
    {type: 2, label: 'Feet'},
    {type: 3, label: 'Inches'},
    {type: 4, label: 'Miles'},
    {type: 5, label: 'Kilometers'},
    {type: 6, label: 'Astronomical Units'},
    {type: 7, label: 'Light Years'},
    {type: 8, label: 'Parsecs'},
    {type: 9, label: 'MegaParsecs'},
    {type: 10, label: 'Custom'}
  ];

  $rootScope.observingLocation = {name:'My Location'};

  var setObservingLocation = function(props){
    $rootScope.$applyAsync(function(){
    props.localHorizonMode = props.localHorizonMode === undefined ?
      $rootScope.ctl.settings._localHorizonMode :
      props.localHorizonMode;
    $rootScope.observingLocation = Object.assign($rootScope.observingLocation,props);
    var earthMap = wwtlib.LayerManager.get_allMaps().Earth;
    wwtlib.LayerManager.layerSelectionChanged(earthMap);
    var rf = new wwtlib.ReferenceFrame();
    rf.name = 'Observing Location';
    rf.lat = props.lat;
    rf.lng = props.lng;
    rf.altitude = props.altitude;

    wwtlib.LayerManager.referenceFrameWizardFinished(rf);
    $rootScope.hasSetupObservingLocation = true;
    var newSettings = {
      _locationAltitude:props.altitude,//.toFixed(1) +'m',//0.00000690228892768605
      _locationLat:props.lat,//47.70409186039239
      _locationLng:props.lng,//-122.30266851233682
      _localHorizonMode:props.localHorizonMode
    };
    Object.assign(wwt.wc.settings,newSettings);
    wwtlib.LayerManager.layerSelectionChanged(earthMap);
  });
};

  var initTypeList = function (typeKey, scopeKey) {
    if (typeof scopeKey != 'string') {
      scopeKey = util.firstCharLower(typeKey)
    }
    $rootScope[scopeKey] = Object.keys(wwtlib[typeKey]).map(function (label, type) {
      return {
        type: type,
        label: util.firstCharUpper(label)
      }
    });
  };
  initTypeList('CoordinatesTypes', 'coordTypes');
  var enums = ['AltTypes', 'PointScaleTypes', 'MarkerScales', 'MarkerMixes', 'PlotTypes', 'ColorMaps'];
  enums.forEach(initTypeList);

  var annotationOpts = function (s) {
    var obj = {};
    var pairs = s.split(',');
    pairs.forEach(function (kv) {
      kv = kv.split(':');
      var k = kv[0].toLowerCase();
      var v = kv[1];
      if (k === 'embed' || k === 'youtube') {
        v += ':' + kv[2];
        var expression = /^(https?:\/\/)?((www\.)?(youtube(-nocookie)?|youtube.googleapis)\.com.*(v\/|v=|vi=|vi\/|e\/|embed\/|user\/.*\/u\/\d+\/)|youtu\.be\/)([_0-9a-z-]+)/i;
        v = v.match(expression)[7];
        k = 'youtube'
      }
      obj[k] = v;
    });
    return obj;
  };
  $rootScope.loadVOTableModal = wwt.loadVOTableModal = function (votable) {

    var modalScope = $rootScope.$new();
    modalScope.customClass = 'vo-tbl-modal';
    modalScope.voTableLayer = votable.get_table ? votable : wwtlib.VoTableLayer.create(votable);
    modalScope.votable = modalScope.voTableLayer.get_table();

    $modal({
      scope: modalScope,
      templateUrl: 'views/modals/centered-modal-template.html?v=' + util.resVersion,
      contentTemplate: 'views/modals/vo-table-viewer.html?v=' + util.resVersion,
      show: true,
      placement: 'center',
      backdrop: false
    });
  };

  var showColorpicker = function (colorpicker, e) {
    var modalScope = $rootScope.$new();
    modalScope.colorpicker = colorpicker;
    modalScope.mouse = e;
    modalScope.customClass = 'colorpicker-modal';
    $modal({
      scope: modalScope,
      templateUrl: 'views/modals/centered-modal-template.html?v=' + util.resVersion,
      contentTemplate: 'views/modals/colorpicker.html?v=' + util.resVersion,
      show: true,
      placement: 'center',
      backdrop: false,
      controller: 'colorpickerController'
    });
  };

  var loadingModal;
  $rootScope.loading = function (flag, content) {
    if (loadingModal) {
      loadingModal.hide();
      loadingModal = null;
    }
    if (flag) {
      loadingModal = $modal({
        templateUrl: 'views/modals/loading-content.html?v=' + util.resVersion,
        show: true,
        content: content || 'Content Loading. Please Wait...',
        placement: 'center'
      });
    }
  }
  if (util.getQSParam('debug') === 'disable') {
    setTimeout(function () {
      wwtlib.WWTControl.singleton.render = function () {
        //console.log('fixed render loop :)');
      };
      //testing only:
      $('#WorldWideTelescopeControlHost').html('');
    }, 888)

  }
  var frameWizardDialog = wwtlib.LayerManager.get_frameWizardDialog();
  var showFrameWizardDialog = function (refFrame, propertyMode) {
    //console.log({refFrame: refFrame});
    var modalScope = $rootScope.$new();
    refFrame.name = refFrame.name || '';
    modalScope.refFrame = refFrame;
    modalScope.dialog = frameWizardDialog;
    modalScope.propertyMode = propertyMode;
    //modalScope.mouse = e;
    modalScope.customClass = 'wizard';
    $modal({
      scope: modalScope,
      templateUrl: 'views/modals/centered-modal-template.html?v=' + util.resVersion,
      contentTemplate: 'views/modals/ref-frame-wiz.html?v=' + util.resVersion,
      show: true,
      placement: 'center',
      backdrop: false,
      controller: 'refFrameController'

    });
  };
//scope,callback,cssClass,controller,template,backdrop - template=required
  var showModal = function (props) {
    //console.log({refFrame: refFrame});
    var modalScope = props.scope ? props.scope.$new() : $rootScope.$new();

    var modalConfig = {
      scope: modalScope,
      templateUrl: 'views/modals/centered-modal-template.html?v=' + util.resVersion,
      contentTemplate: 'views/modals/' + props.template + '.html?v=' + util.resVersion,
      show: true,
      //placement: 'center',
      backdrop: props.backdrop !== undefined ? props.backdrop : false,
      controller: props.controller
    };
    if (props.cssClass) {
      modalScope.customClass = props.cssClass;
    }
    if (props.fixedPosition) {
      modalScope.customClass += ' noreposition';
      modalConfig.animation = false;
      modalConfig.backdropAnimation = false;
      setTimeout(function(){
        $('.noreposition').removeClass('noreposition').find('.modal-dialog').css({left:300});
      },2222);
    } else {
      modalConfig.placement = 'centered';
    }
    var modal = $modal(modalConfig);

    if (props.callback) {
      props.callback({modal: modal, scope: modalScope, modalConfig: modalConfig});
    }
  };

  var dataVizWiz = wwtlib.LayerManager.get_dataVizWizardDialog();
  var showDataVizWiz = function (layerMap) {
    //console.log(layerMap);
    var modalScope = $rootScope.$new();
    var propertyMode = typeof layerMap !== 'string';
    modalScope.propertyMode = propertyMode;
    if (!propertyMode) {
      modalScope.layerMap = layerMap;
    } else {
      modalScope.layer = layerMap;
    }
    modalScope.customClass = 'wizard';
    modalScope.dialog = dataVizWiz;
    $modal({
      scope: modalScope,
      templateUrl: 'views/modals/centered-modal-template.html?v=' + util.resVersion,
      contentTemplate: 'views/modals/data-viz-wiz.html?v=' + util.resVersion,
      show: true,
      placement: 'center',
      backdrop: false,
      controller: 'DataVizController'
    });
  };

  var refFrameDialog = wwtlib.LayerManager.get_referenceFramePropsDialog();
  //console.log(refFrameDialog);
  var showRefFrameProps = function (refFrame) {
    showFrameWizardDialog(refFrame, true);
  };

  var greatCircleDlg = wwtlib.LayerManager.get_greatCircleDlg();
  //console.log(greatCircleDlg);
  var showGreatCircleDlg = function (layer) {
    //console.log(layer);
    var modalScope = $rootScope.$new();
    modalScope.layer = layer;
    modalScope.customClass = 'great-circle';
    $modal({
      scope: modalScope,
      templateUrl: 'views/modals/centered-modal-template.html?v=' + util.resVersion,
      contentTemplate: 'views/modals/great-circle.html?v=' + util.resVersion,
      show: true,
      placement: 'center',
      backdrop: false,
      controller: 'greatCircleController'
    });
  };

  var embedVideo = function (videoid) {
    var modalScope = $rootScope.$new();
    modalScope.url = $sce.trustAsResourceUrl('//www.youtube.com/embed/' + videoid + '?autoplay=1');
    modalScope.customClass = 'wizard embed-modal';
    $modal({
      scope: modalScope,
      animation: false,
      backdropAnimation: false,
      templateUrl: 'views/modals/centered-modal-template.html?v=' + util.resVersion,
      contentTemplate: 'views/modals/embed-video.html?v=' + util.resVersion,
      show: true,
      //placement: 'center',
      backdrop: false,
      controller: 'EmbedController'
    });
  };
  wwt.root = $rootScope;

  return {
    addDialogHooks: function () {
      wwt.wc.add_annotationClicked(function (interface, event) {
        var opts = annotationOpts(event.get_id());
        if (opts.youtube) {
          embedVideo(opts.youtube);
        } else if (opts.link) {
          window.open(opts.link);
        }
      });
      wwt.wc.add_voTableDisplay(wwt.loadVOTableModal);
      wwt.wc.add_colorPickerDisplay(showColorpicker);
      frameWizardDialog.add_showDialogHook(function (frame) {
        showFrameWizardDialog(frame, false);
      });
      refFrameDialog.add_showDialogHook(showRefFrameProps);
      greatCircleDlg.add_showDialogHook(showGreatCircleDlg);
      dataVizWiz.add_showDialogHook(showDataVizWiz);
    },
    embedVideo: embedVideo,
    annotationOpts: annotationOpts,
    showModal: showModal,
    showErrorMessage:function(msg){
      var scope = $rootScope.$new();
      scope.message = msg;
      scope.title = 'Error';
      var props = {
        scope:scope,
        template:'message'
      };

      showModal(props);
    },
    setObservingLocation:setObservingLocation
  };
}]);

<|endoftext|>


<commit_before>describe("Courses", function () {
    beforeEach(() => {
        cy.app("clean");
        cy.appScenario("setup");
    });
    describe("admin user", () => {
        beforeEach(() => {
            cy.appScenario("admin");
            cy.visit("/users/sign_in");
            cy.get('input[type="email"]').type("administrator@mampf.edu");
            cy.get('input[type="password"]').type("test123456");
            cy.get('input[type="submit"]').click();
        });
        it("can create module", () => {
            cy.visit('/administration');
            cy.get('i[title="Modul anlegen"]').click();
            cy.get('input[name="course[title]"]').type("Lineare Algebra I");
            cy.get('input[name="course[short_title]"]').type("LA I");
            cy.get('input[type="submit"]').click();
            cy.visit('/administration');
            cy.contains("Lineare Algebra I").should("exist");
        });
        it("can create lecture", () => {
            cy.appFactories([
                ['create', 'course'],
                ['create', 'term']
            ]).then((records) => {
                cy.server();
                cy.route('**/new').as('new');
                cy.route('POST', '/lectures').as('courses');
                cy.visit('/administration');
                cy.get('a[title="Veranstaltung anlegen"]').click();
                //cy.wait('@new');
                cy.get("div#new-lecture-area").contains("Speichern").click();
                cy.wait('@courses');
                cy.contains(records[0].title).should("exist");
                cy.contains(`${records[1].season} ${records[1].year}`).should("exist");
            });
        });

    });
    describe("teacher",()=>{
        beforeEach(() => {
            cy.appScenario("teacher");
            cy.visit("/users/sign_in");
            cy.get('input[type="email"]').type("teacher@mampf.edu");
            cy.get('input[type="password"]').type("test123456");
            cy.get('input[type="submit"]').click();
        });
        it("can subscribe to unpublished on page", () => {
            cy.appFactories([
                ["create", "lecture",{"teacher_id":1} ]
            ], (courses) => {
                cy.visit(`/lectures/${courses[0].id}`);
                cy.contains("Fehler").should("exist");
                cy.contains("Veranstaltung abonnieren").click();
                cy.contains("Vorlesungsinhalt").should("exist");
            });
        });
    });
    describe("simple user", () => {
        beforeEach(() => {
            cy.appScenario("non_admin");
            cy.visit("/users/sign_in");
            cy.get('input[type="email"]').type("max@mampf.edu");
            cy.get('input[type="password"]').type("test123456");
            cy.get('input[type="submit"]').click();
        });
        it("can subscribe", () => {
            //call a scenario in app_commands/scenarios

            cy.appFactories([
                ['create_list', 'lecture', 6, 'released_for_all']
            ]).then((records) => {
                cy.visit("/main/start");
                cy.contains("Veranstaltungssuche").click();
                //cy.get('input[name="search[fulltext]"]').type(records[0][0].title)
                cy.contains("Suche").click();
                cy.get('[title="abonnieren"]').first().click();
                cy.get('[title="abbestellen"]').should("exist");
            });
        });
        it("can subscribe on page", () => {
            cy.appFactories([
                ["create", "lecture", "released_for_all"]
            ], (courses) => {
                cy.visit(`/lectures/${courses[0].id}`);
                cy.contains("Fehler").should("exist");
                cy.contains("Veranstaltung abonnieren").click();
                cy.contains("Vorlesungsinhalt").should("exist");
            })
        });
        it("is blocked to subscribe on page", () => {
            cy.appFactories([
                ["create", "lecture"]
            ], (courses) => {
                cy.visit(`/lectures/${courses[0].id}`);
                cy.contains("Fehler").should("exist");
                cy.contains("Veranstaltung abonnieren").click();
                cy.contains("Vorlesungsinhalt").should("not.exist");
                cy.contains("Fehler").should("exist");
            });
        });
        it("can not subscribe on page to unpublished", () => {
            cy.appFactories([
                ["create", "lecture" ]
            ], (courses) => {
                cy.visit(`/lectures/${courses[0].id}`);
                cy.contains("unveröffentlicht").should("exist");
            });
        });
    });
});<commit_msg>Use .then()<commit_after>describe("Courses", function () {
    beforeEach(() => {
        cy.app("clean");
        cy.appScenario("setup");
    });
    describe("admin user", () => {
        beforeEach(() => {
            cy.appScenario("admin");
            cy.visit("/users/sign_in");
            cy.get('input[type="email"]').type("administrator@mampf.edu");
            cy.get('input[type="password"]').type("test123456");
            cy.get('input[type="submit"]').click();
        });
        it("can create module", () => {
            cy.visit('/administration');
            cy.get('i[title="Modul anlegen"]').click();
            cy.get('input[name="course[title]"]').type("Lineare Algebra I");
            cy.get('input[name="course[short_title]"]').type("LA I");
            cy.get('input[type="submit"]').click();
            cy.visit('/administration');
            cy.contains("Lineare Algebra I").should("exist");
        });
        it("can create lecture", () => {
            cy.appFactories([
                ['create', 'course'],
                ['create', 'term']
            ]).then((records) => {
                cy.server();
                cy.route('**/new').as('new');
                cy.route('POST', '/lectures').as('courses');
                cy.visit('/administration');
                cy.get('a[title="Veranstaltung anlegen"]').click();
                //cy.wait('@new');
                cy.get("div#new-lecture-area").contains("Speichern").click();
                cy.wait('@courses');
                cy.contains(records[0].title).should("exist");
                cy.contains(`${records[1].season} ${records[1].year}`).should("exist");
            });
        });

    });
    describe("teacher", () => {
        beforeEach(() => {
            cy.appScenario("teacher");
            cy.visit("/users/sign_in");
            cy.get('input[type="email"]').type("teacher@mampf.edu");
            cy.get('input[type="password"]').type("test123456");
            cy.get('input[type="submit"]').click();
        });
        it("can subscribe to unpublished on page", () => {
            cy.appFactories([
                ["create", "lecture", {
                    "teacher_id": 1
                }]
            ]).then((courses) => {
                cy.visit(`/lectures/${courses[0].id}`);
                cy.contains("Fehler").should("exist");
                cy.contains("Veranstaltung abonnieren").click();
                cy.contains("Vorlesungsinhalt").should("exist");
            });
        });
    });
    describe("simple user", () => {
        beforeEach(() => {
            cy.appScenario("non_admin");
            cy.visit("/users/sign_in");
            cy.get('input[type="email"]').type("max@mampf.edu");
            cy.get('input[type="password"]').type("test123456");
            cy.get('input[type="submit"]').click();
        });
        it("can subscribe", () => {
            //call a scenario in app_commands/scenarios

            cy.appFactories([
                ['create_list', 'lecture', 6, 'released_for_all']
            ]).then((records) => {
                cy.visit("/main/start");
                cy.contains("Veranstaltungssuche").click();
                //cy.get('input[name="search[fulltext]"]').type(records[0][0].title)
                cy.contains("Suche").click();
                cy.get('[title="abonnieren"]').first().click();
                cy.get('[title="abbestellen"]').should("exist");
            });
        });
        it("can subscribe on page", () => {
            cy.appFactories([
                ["create", "lecture", "released_for_all"]
            ].then((courses) => {
                cy.visit(`/lectures/${courses[0].id}`);
                cy.contains("Fehler").should("exist");
                cy.contains("Veranstaltung abonnieren").click();
                cy.contains("Vorlesungsinhalt").should("exist");
            }));
        });
        it("is blocked to subscribe on page", () => {
            cy.appFactories([
                ["create", "lecture"]
            ]).then((courses) => {
                cy.visit(`/lectures/${courses[0].id}`);
                cy.contains("Fehler").should("exist");
                cy.contains("Veranstaltung abonnieren").click();
                cy.contains("Vorlesungsinhalt").should("not.exist");
                cy.contains("Fehler").should("exist");
            });
        });
        it("can not subscribe on page to unpublished", () => {
            cy.appFactories([
                ["create", "lecture"]
            ]).then((courses) => {
                cy.visit(`/lectures/${courses[0].id}`);
                cy.contains("unveröffentlicht").should("exist");
            });
        });
    });
});<|endoftext|>


<commit_before>(function() {

    var redblack = {};
    var root = this;
    var orig = root.redblack;

    if (typeof module !== 'undefined' && module.exports) {
        module.exports = redblack;
    } else {
        root.redblack = redblack;
    }

    redblack.VERSION = '0.1.1';

    redblack.noConflict = function() {
        root.redblack = orig;
        return redblack;
    };

    redblack.tree = function() {
        return new Tree();
    };

    var BLACK = redblack.BLACK = 'black';
    var RED = redblack.RED = 'red';

    // Node
    // ---------------

    function Node(key, value) {
        this.key = key;
        this.value = value;
        this.color = RED;
        this.left = null;
        this.right = null;
        this.parent = null;
    };

    Node.prototype.grandparent = function() {
        if (this.parent === null) return null;
        return this.parent.parent;
    };

    Node.prototype.sibling = function() {
        if (this.parent === null) return null;
        return this === this.parent.left ? this.parent.right : this.parent.left;
    };

    Node.prototype.uncle = function() {
        if (this.parent === null) return null;
        return this.parent.sibling();
    };

    // Cursor
    // ---------------

    function Cursor(tree, start, end) {
        this.tree = tree;
        this.start = start;
        this.end = end;

        var self = this;
        this.walk = function walk(node, iterator) {
            if (node === null) return;

            if (start !== undefined && node.key < start) {
                walk(node.right, iterator);
            } else if (end !== undefined && node.key > end) {
                walk(node.left, iterator);
            } else {
                walk(node.left, iterator);
                iterator(node.value, node.key, self.tree);
                walk(node.right, iterator);
            }
        };
    };

    Cursor.prototype.forEach = function(iterator) {
        this.walk(this.tree.root, iterator);
    };

    Cursor.prototype.map = function(iterator) {
        var results = [];

        this.forEach(function(value, key, tree) {
            results.push(iterator(value, key, tree));
        });

        return results;
    };

    // Tree
    // ---------------

    function Tree() {
        this.root = null;
        this.balancer = new Balancer(this);
    };

    Tree.prototype.get = function(key) {
        var node = find(this.root, key);
        return node === null ? null : node.value;
    };

    Tree.prototype.insert = function(key, value) {
        var newNode = new Node(key, value);

        if (this.root === null) {
            this.root = newNode;
        } else {
            var node = this.root;

            while (true) {
                if (key < node.key) {
                    if (node.left === null) {
                        node.left = newNode;
                        break;
                    } else {
                        node = node.left;
                    }
                } else if (key > node.key) {
                    if (node.right === null) {
                        node.right = newNode;
                        break;
                    } else {
                        node = node.right;
                    }
                } else {
                    node.value = value;
                    return;
                }
            }

            newNode.parent = node;
        }

        this.balancer.inserted(newNode);
    };

    Tree.prototype.delete = function(key) {
        var node = find(this.root, key);
        if (node === null) return;

        if (node.left !== null && node.right !== null) {
            var pred = node.left;
            while (pred.right !== null) pred = pred.right;

            node.key = pred.key;
            node.value = pred.value;
            node = pred;
        }

        var child = (node.right === null) ? node.left : node.right;
        if (nodeColor(node) === BLACK) {
            node.color = nodeColor(child);
            this.balancer.deleted(node);
        }

        this.balancer.replaceNode(node, child);

        if (nodeColor(this.root) === RED) {
            this.root.color = BLACK;
        }
    };

    Tree.prototype.range = function(start, end) {
        return new Cursor(this, start, end);
    };

    // Proxy cursor methods
    for (var method in Cursor.prototype) {
        if (Cursor.prototype.hasOwnProperty(method)) {
            var func = Cursor.prototype[method];
            Tree.prototype[method] = function() {
                var cursor = new Cursor(this);
                return func.apply(cursor, arguments);
            };
        }
    }

    // Balancer
    // ---------------

    function Balancer(tree) {
        this.tree = tree;
    };

    Balancer.prototype.inserted = function(node) {
        this.insertCase1(node);
    };

    Balancer.prototype.deleted = function(node) {
        this.deleteCase1(node);
    };

    Balancer.prototype.replaceNode = function(original, replacement) {
        if (original.parent === null) {
            this.tree.root = replacement;
        } else {
            if (original === original.parent.left) {
                original.parent.left = replacement;
            } else {
                original.parent.right = replacement;
            }
        }

        if (replacement !== null) {
            replacement.parent = original.parent;
        }
    };

    Balancer.prototype.rotateLeft = function(node) {
        var right = node.right;
        this.replaceNode(node, right);

        // Update pointers
        node.right = right.left;
        if (right.left !== null) right.left.parent = node;
        right.left = node;
        node.parent = right;
    };

    Balancer.prototype.rotateRight = function(node) {
        var left = node.left;
        this.replaceNode(node, left);

        // Update pointers
        node.left = left.right;
        if (left.right !== null) left.right.parent = node;
        left.right = node;
        node.parent = left;
    };

    Balancer.prototype.insertCase1 = function(node) {
        if (node.parent === null) {
            node.color = BLACK;
        } else {
            this.insertCase2(node);
        }
    };

    Balancer.prototype.insertCase2 = function(node) {
        if (nodeColor(node.parent) === BLACK) {
            return;
        } else {
            this.insertCase3(node);
        }
    };

    Balancer.prototype.insertCase3 = function(node) {
        var uncle = node.uncle();
        var grandparent = node.grandparent();

        if (uncle !== null && nodeColor(uncle) === RED) {
            node.parent.color = BLACK;
            uncle.color = BLACK;
            grandparent.color = RED;
            this.insertCase1(grandparent);
        } else {
            this.insertCase4(node);
        }
    };

    Balancer.prototype.insertCase4 = function(node) {
        var grandparent = node.grandparent();

        if (node === node.parent.right && node.parent === grandparent.left) {
            this.rotateLeft(node.parent);
            node = node.left;
        } else if (node === node.parent.left && node.parent === grandparent.right) {
            this.rotateRight(node.parent);
            node = node.right;
        }

        this.insertCase5(node);
    };

    Balancer.prototype.insertCase5 = function(node) {
        var grandparent = node.grandparent();

        node.parent.color = BLACK;
        grandparent.color = RED;

        if (node === node.parent.left && node.parent === grandparent.right) {
            this.rotateRight(grandparent);
        } else {
            this.rotateLeft(grandparent);
        }
    };

    Balancer.prototype.deleteCase1 = function(node) {
        if (node.parent !== null) this.deleteCase2(node);
    };

    Balancer.prototype.deleteCase2 = function(node) {
        var sibling = node.sibling();

        if (nodeColor(sibling) === RED) {
            node.parent.color = RED;
            sibling.color = BLACK;
            if (node === node.parent.left) {
                this.rotateLeft(node.parent);
            } else {
                this.rotateRight(node.parent);
            }
        }

        this.deleteCase3(node);
    };

    Balancer.prototype.deleteCase3 = function(node) {
        var sibling = node.sibling();

        if (nodeColor(node.parent) === BLACK &&
            nodeColor(sibling) === BLACK &&
            nodeColor(sibling.left) === BLACK &&
            nodeColor(sibling.right) === BLACK) {

            sibling.color = RED;
            this.deleteCase1(node.parent);
        } else {
            this.deleteCase4(node);
        }
    };

    Balancer.prototype.deleteCase4 = function(node) {
        var sibling = node.sibling();

        if (nodeColor(node.parent) === RED &&
            nodeColor(sibling) === BLACK &&
            nodeColor(sibling.left) === BLACK &&
            nodeColor(sibling.right) === BLACK) {

            sibling.color = RED;
            node.parent.color = BLACK;
        } else {
            this.deleteCase5(node);
        }
    };

    Balancer.prototype.deleteCase5 = function(node) {
        var sibling = node.sibling();

        if (node === node.parent.left &&
            nodeColor(sibling) === BLACK &&
            nodeColor(sibling.left) === RED &&
            nodeColor(sibling.right) === BLACK) {

            sibling.color = RED;
            sibling.left.color = BLACK;
            this.rotateRight(sibling);
        } else if (node === node.parent.right &&
            nodeColor(sibling) === BLACK &&
            nodeColor(sibling.right) === RED &&
            nodeColor(sibling.left) === BLACK) {

            sibling.color = RED;
            sibling.right.color = BLACK;
            this.rotateLeft(sibling);
        }

        this.deleteCase6(node);
    };

    Balancer.prototype.deleteCase6 = function(node) {
        var sibling = node.sibling();

        sibling.color = nodeColor(node.parent);
        node.parent.color = BLACK;

        if (node === node.parent.left) {
            sibling.right.color = BLACK;
            this.rotateLeft(node.parent);
        } else {
            sibling.left.color = BLACK;
            this.rotateRight(node.parent);
        }
    };

    // Helpers
    // ---------------

    function nodeColor(node) {
        return node === null ? BLACK : node.color;
    };

    function find(node, key) {
        while (node !== null) {
            if (key === node.key) {
                return node;
            } else if (key < node.key) {
                node = node.left;
            } else if (key > node.key) {
                node = node.right;
            }
        }

        return node;
    };

})();<commit_msg>Fixed insert case 5<commit_after>(function() {

    var redblack = {};
    var root = this;
    var orig = root.redblack;

    if (typeof module !== 'undefined' && module.exports) {
        module.exports = redblack;
    } else {
        root.redblack = redblack;
    }

    redblack.VERSION = '0.1.1';

    redblack.noConflict = function() {
        root.redblack = orig;
        return redblack;
    };

    redblack.tree = function() {
        return new Tree();
    };

    var BLACK = redblack.BLACK = 'black';
    var RED = redblack.RED = 'red';

    // Node
    // ---------------

    function Node(key, value) {
        this.key = key;
        this.value = value;
        this.color = RED;
        this.left = null;
        this.right = null;
        this.parent = null;
    };

    Node.prototype.grandparent = function() {
        if (this.parent === null) return null;
        return this.parent.parent;
    };

    Node.prototype.sibling = function() {
        if (this.parent === null) return null;
        return this === this.parent.left ? this.parent.right : this.parent.left;
    };

    Node.prototype.uncle = function() {
        if (this.parent === null) return null;
        return this.parent.sibling();
    };

    // Cursor
    // ---------------

    function Cursor(tree, start, end) {
        this.tree = tree;
        this.start = start;
        this.end = end;

        var self = this;
        this.walk = function walk(node, iterator) {
            if (node === null) return;

            if (start !== undefined && node.key < start) {
                walk(node.right, iterator);
            } else if (end !== undefined && node.key > end) {
                walk(node.left, iterator);
            } else {
                walk(node.left, iterator);
                iterator(node.value, node.key, self.tree);
                walk(node.right, iterator);
            }
        };
    };

    Cursor.prototype.forEach = function(iterator) {
        this.walk(this.tree.root, iterator);
    };

    Cursor.prototype.map = function(iterator) {
        var results = [];

        this.forEach(function(value, key, tree) {
            results.push(iterator(value, key, tree));
        });

        return results;
    };

    // Tree
    // ---------------

    function Tree() {
        this.root = null;
        this.balancer = new Balancer(this);
    };

    Tree.prototype.get = function(key) {
        var node = find(this.root, key);
        return node === null ? null : node.value;
    };

    Tree.prototype.insert = function(key, value) {
        var newNode = new Node(key, value);

        if (this.root === null) {
            this.root = newNode;
        } else {
            var node = this.root;

            while (true) {
                if (key < node.key) {
                    if (node.left === null) {
                        node.left = newNode;
                        break;
                    } else {
                        node = node.left;
                    }
                } else if (key > node.key) {
                    if (node.right === null) {
                        node.right = newNode;
                        break;
                    } else {
                        node = node.right;
                    }
                } else {
                    node.value = value;
                    return;
                }
            }

            newNode.parent = node;
        }

        this.balancer.inserted(newNode);
    };

    Tree.prototype.delete = function(key) {
        var node = find(this.root, key);
        if (node === null) return;

        if (node.left !== null && node.right !== null) {
            var pred = node.left;
            while (pred.right !== null) pred = pred.right;

            node.key = pred.key;
            node.value = pred.value;
            node = pred;
        }

        var child = (node.right === null) ? node.left : node.right;
        if (nodeColor(node) === BLACK) {
            node.color = nodeColor(child);
            this.balancer.deleted(node);
        }

        this.balancer.replaceNode(node, child);

        if (nodeColor(this.root) === RED) {
            this.root.color = BLACK;
        }
    };

    Tree.prototype.range = function(start, end) {
        return new Cursor(this, start, end);
    };

    // Proxy cursor methods
    for (var method in Cursor.prototype) {
        if (Cursor.prototype.hasOwnProperty(method)) {
            var func = Cursor.prototype[method];
            Tree.prototype[method] = function() {
                var cursor = new Cursor(this);
                return func.apply(cursor, arguments);
            };
        }
    }

    // Balancer
    // ---------------

    function Balancer(tree) {
        this.tree = tree;
    };

    Balancer.prototype.inserted = function(node) {
        this.insertCase1(node);
    };

    Balancer.prototype.deleted = function(node) {
        this.deleteCase1(node);
    };

    Balancer.prototype.replaceNode = function(original, replacement) {
        if (original.parent === null) {
            this.tree.root = replacement;
        } else {
            if (original === original.parent.left) {
                original.parent.left = replacement;
            } else {
                original.parent.right = replacement;
            }
        }

        if (replacement !== null) {
            replacement.parent = original.parent;
        }
    };

    Balancer.prototype.rotateLeft = function(node) {
        var right = node.right;
        this.replaceNode(node, right);

        // Update pointers
        node.right = right.left;
        if (right.left !== null) right.left.parent = node;
        right.left = node;
        node.parent = right;
    };

    Balancer.prototype.rotateRight = function(node) {
        var left = node.left;
        this.replaceNode(node, left);

        // Update pointers
        node.left = left.right;
        if (left.right !== null) left.right.parent = node;
        left.right = node;
        node.parent = left;
    };

    Balancer.prototype.insertCase1 = function(node) {
        if (node.parent === null) {
            node.color = BLACK;
        } else {
            this.insertCase2(node);
        }
    };

    Balancer.prototype.insertCase2 = function(node) {
        if (nodeColor(node.parent) === BLACK) {
            return;
        } else {
            this.insertCase3(node);
        }
    };

    Balancer.prototype.insertCase3 = function(node) {
        var uncle = node.uncle();
        var grandparent = node.grandparent();

        if (uncle !== null && nodeColor(uncle) === RED) {
            node.parent.color = BLACK;
            uncle.color = BLACK;
            grandparent.color = RED;
            this.insertCase1(grandparent);
        } else {
            this.insertCase4(node);
        }
    };

    Balancer.prototype.insertCase4 = function(node) {
        var grandparent = node.grandparent();

        if (node === node.parent.right && node.parent === grandparent.left) {
            this.rotateLeft(node.parent);
            node = node.left;
        } else if (node === node.parent.left && node.parent === grandparent.right) {
            this.rotateRight(node.parent);
            node = node.right;
        }

        this.insertCase5(node);
    };

    Balancer.prototype.insertCase5 = function(node) {
        var grandparent = node.grandparent();

        node.parent.color = BLACK;
        grandparent.color = RED;

        if (node === node.parent.left && node.parent === grandparent.left) {
            this.rotateRight(grandparent);
        } else if (node === node.parent.right && node.parent === grandparent.right) {
            this.rotateLeft(grandparent);
        }
    };

    Balancer.prototype.deleteCase1 = function(node) {
        if (node.parent !== null) this.deleteCase2(node);
    };

    Balancer.prototype.deleteCase2 = function(node) {
        var sibling = node.sibling();

        if (nodeColor(sibling) === RED) {
            node.parent.color = RED;
            sibling.color = BLACK;
            if (node === node.parent.left) {
                this.rotateLeft(node.parent);
            } else {
                this.rotateRight(node.parent);
            }
        }

        this.deleteCase3(node);
    };

    Balancer.prototype.deleteCase3 = function(node) {
        var sibling = node.sibling();

        if (nodeColor(node.parent) === BLACK &&
            nodeColor(sibling) === BLACK &&
            nodeColor(sibling.left) === BLACK &&
            nodeColor(sibling.right) === BLACK) {

            sibling.color = RED;
            this.deleteCase1(node.parent);
        } else {
            this.deleteCase4(node);
        }
    };

    Balancer.prototype.deleteCase4 = function(node) {
        var sibling = node.sibling();

        if (nodeColor(node.parent) === RED &&
            nodeColor(sibling) === BLACK &&
            nodeColor(sibling.left) === BLACK &&
            nodeColor(sibling.right) === BLACK) {

            sibling.color = RED;
            node.parent.color = BLACK;
        } else {
            this.deleteCase5(node);
        }
    };

    Balancer.prototype.deleteCase5 = function(node) {
        var sibling = node.sibling();

        if (node === node.parent.left &&
            nodeColor(sibling) === BLACK &&
            nodeColor(sibling.left) === RED &&
            nodeColor(sibling.right) === BLACK) {

            sibling.color = RED;
            sibling.left.color = BLACK;
            this.rotateRight(sibling);
        } else if (node === node.parent.right &&
            nodeColor(sibling) === BLACK &&
            nodeColor(sibling.right) === RED &&
            nodeColor(sibling.left) === BLACK) {

            sibling.color = RED;
            sibling.right.color = BLACK;
            this.rotateLeft(sibling);
        }

        this.deleteCase6(node);
    };

    Balancer.prototype.deleteCase6 = function(node) {
        var sibling = node.sibling();

        sibling.color = nodeColor(node.parent);
        node.parent.color = BLACK;

        if (node === node.parent.left) {
            sibling.right.color = BLACK;
            this.rotateLeft(node.parent);
        } else {
            sibling.left.color = BLACK;
            this.rotateRight(node.parent);
        }
    };

    // Helpers
    // ---------------

    function nodeColor(node) {
        return node === null ? BLACK : node.color;
    };

    function find(node, key) {
        while (node !== null) {
            if (key === node.key) {
                return node;
            } else if (key < node.key) {
                node = node.left;
            } else if (key > node.key) {
                node = node.right;
            }
        }

        return node;
    };

})();<|endoftext|>


<commit_before>(function () {
  "use strict";
  window.app.views.RootView = Backbone.View.extend({
    template: "root-view",

    events: {
      'click [data-action="tac-modal"]': 'onShowTacModal',
      'click [data-action="embed-modal"]': 'onShowEmbedModal'
    },

    initialize: function() {
      _.bindAll(this, 'render', 'updateSidebar');

      this.listenTo(this.model.comments, 'add', this.updateSidebar);
      this.listenTo(this.model.comments, 'remove', this.updateSidebar);
      this.listenTo(this.model.comments, 'change:persisted', this.updateSidebar);
    },

    render: function() {
      var template = this.compileTemplate(this.template);
      this.$el.html(template(this.model.toJSON()));

      // Map view
      this.mapView = new app.views.MapView({
        model: this.model
      });
      this.$('[data-view="map-view"]').html(this.mapView.render().el);

      // Comments list
      var commentsList = new app.views.CommentsList({
        collection: this.model.comments
      });
      this.$('[data-view="comments-list"]').html(commentsList.render().el);

      // Submit view
      var submitView = new app.views.SubmitView({
        model: this.model
      });
      this.$('[data-view="submit-view"]').html(submitView.render().el);

      return this;
    },

    updateSidebar: function(comment) {
      var newComment = this.model.comments.findNew();
      this.$('.sidebar').toggleClass('sidebar--minimized', newComment);
      // Hackish...
      $('#map').toggleClass('map--full', newComment);
      this.mapView.map.invalidateSize();
    },

    onShowTacModal: function(evt) {
      this.$('#tac-modal').modal('show');
    },

    onShowEmbedModal: function(evt) {
      var template = this.compileTemplate("embed");
      this.$('[data-bind="embed"]').html(template({
        src: window.location.href,
        height: "700px",
        width: "1000px"
      }));
      this.$('#embed-modal').modal('show');
    }
  });
}());
<commit_msg>Fixed unwanted route changes on opening modals<commit_after>(function () {
  "use strict";
  window.app.views.RootView = Backbone.View.extend({
    template: "root-view",

    events: {
      'click [data-action="tac-modal"]': 'onShowTacModal',
      'click [data-action="embed-modal"]': 'onShowEmbedModal'
    },

    initialize: function() {
      _.bindAll(this, 'render', 'updateSidebar');

      this.listenTo(this.model.comments, 'add', this.updateSidebar);
      this.listenTo(this.model.comments, 'remove', this.updateSidebar);
      this.listenTo(this.model.comments, 'change:persisted', this.updateSidebar);
    },

    render: function() {
      var template = this.compileTemplate(this.template);
      this.$el.html(template(this.model.toJSON()));

      // Map view
      this.mapView = new app.views.MapView({
        model: this.model
      });
      this.$('[data-view="map-view"]').html(this.mapView.render().el);

      // Comments list
      var commentsList = new app.views.CommentsList({
        collection: this.model.comments
      });
      this.$('[data-view="comments-list"]').html(commentsList.render().el);

      // Submit view
      var submitView = new app.views.SubmitView({
        model: this.model
      });
      this.$('[data-view="submit-view"]').html(submitView.render().el);

      return this;
    },

    updateSidebar: function(comment) {
      var newComment = this.model.comments.findNew();
      this.$('.sidebar').toggleClass('sidebar--minimized', newComment);
      // Hackish...
      $('#map').toggleClass('map--full', newComment);
      this.mapView.map.invalidateSize();
    },

    onShowTacModal: function(evt) {
      evt.preventDefault();
      this.$('#tac-modal').modal('show');
    },

    onShowEmbedModal: function(evt) {
      evt.preventDefault();
      var template = this.compileTemplate("embed");
      this.$('[data-bind="embed"]').html(template({
        src: window.location.href,
        height: "700px",
        width: "1000px"
      }));
      this.$('#embed-modal').modal('show');
    }
  });
}());
<|endoftext|>


<commit_before>var post = function(action, data){
  return new Promise(function(resolve, reject){

    console.log("About to make a post call - ");
    console.log(action);
    console.log(data);

    var request = $.post(action, data);

    request.done(function(serverData){
      resolve(serverData)
    });

    request.fail(function(serverData){
      reject(serverData)
    });
  });
}

var get = function(action, data){
  return new Promise(function(resolve, reject){

    console.log("About to make a get call - ");
    console.log(action);
    console.log(data);

    var request = $.get(action, data);

    request.done(function(serverData){
      resolve(serverData)
    });

    request.fail(function(serverData){
      reject(serverData)
    });
  });
}

var view = {
  goTo: function(contentId){
    $(":mobile-pagecontainer").pagecontainer("change", contentId);
  },
  errorMessage: function(errorTarget, message){
    $(errorTarget).text("There was an error signing in. " + message);
  },
  loginUser: function(){
    this.updatePersonalInfo();
    this.goTo('#cardsPage');
  },
  logoutUser: function(){
    this.goTo('#loginPage');
  },
  updatePersonalInfo: function(){
    var name = localStorage.getItem("u_first_name");
    name += " " + localStorage.getItem("u_last_name");
    $(".uName").text(name);
    $(".uSchoolName").text(localStorage.getItem('u_school_name'));
  },
  showObservation: function(observations){
    observation = observations[0];
    $('#emptyNotice').hide();
    this.updateNickname(observation);
    this.updateObservationForm(observation);
    $('.time').datebox({
        mode: "durationflipbox",
        overrideDurationOrder:["h","i","s"],
        overrideDurationFormat: "%DM:%DS"
    });
  },
  updateNickname: function(observation){
    var student = observation[2];
    var nickname = student['nickname'];
    $("#sAlias").text(nickname);
  },
  updateObservationForm: function(observation){
    var record_inputs = this.makeRecordInputs(observation[1]);
    $('#observationRecordsForm').prepend($(record_inputs));
    $('#observationRecordsForm').trigger('create');
  },
  makeRecordInputs: function(records){
    var inputs = '';
    $.each(records, function(index, record){
      console.log(record)
      input = '' + record["prompt"]  + ''
      if(record["meme"] == "Time"){
        input += '<input name="' + record["id"] + '" type="text" placeholder="10" class="time" />';
      } else if(record["meme"] == "Percentage"){
        input += '<input type="range" name="' + record["id"] + '" value="50" min="0" max="100" />';
      } else if(record["meme"] == "Qualitative"){
        input += '<input type="range" name="' + record["id"] + '" value="5" min="0" max="5" />';
      } else if(record["meme"] == "Incidence"){
        input += '<input type="text" name="' + record["id"] + '"/>';
      } else if(record["meme"] == "Boolean"){
        input += '<select name="' + record["id"] + '" data-role="slider"><option value="true">Yes</option><option value="false">No</option></select>';
      } else {
        input += '<input type="text" name="' + record["id"] + '" />';
      }
      inputs += input;
    });
    return inputs;
  }
}

var app = {
  initialize: function() {
    this.bindEvents();
  },
  bindEvents: function() {
    $("#loginForm").submit(this.submitLoginForm);
    $("#logoutLink").click(this.handleLogOut);
  },
  handleLogOut: function(){
    localStorage.removeItem("uid");
    localStorage.removeItem("utoken");
    view.logoutUser();
  },
  getObservations: function(user_id, authenticity_token){
    var data = "user_id=" + user_id + "&authenticity_token=" + authenticity_token;

    get('http://localhost:3000/api/v1/observations?' + data)
      .then(function(serverData){
        localStorage.setItem("observations", serverData);
        view.showObservation(serverData);
      })
      .catch(function(serverData){
        console.log('error');
        console.log(serverData.responseText)
      });
  },
  submitLoginForm: function(){
    var data = $("#loginForm").serialize();
    post('http://localhost:3000/api/v1/login', data)
      .then(function(serverData){
        localStorage.setItem("uid", serverData.id);
        localStorage.setItem("utoken", serverData.token);
        localStorage.setItem("u_first_name", serverData.first_name);
        localStorage.setItem("u_last_name", serverData.last_name);
        localStorage.setItem("u_school_name", serverData.school_name);

        app.getObservations(serverData.id, serverData.token);
        view.loginUser();
      })
      .catch(function(serverData){
        view.errorMessage('#loginError', serverData.responseText);
      });

    return false;
  }
};<commit_msg>Add event bindings to observation form submit<commit_after>var post = function(action, data){
  return new Promise(function(resolve, reject){

    console.log("About to make a post call - ");
    console.log(action);
    console.log(data);

    var request = $.post(action, data);

    request.done(function(serverData){
      resolve(serverData)
    });

    request.fail(function(serverData){
      reject(serverData)
    });
  });
}

var get = function(action, data){
  return new Promise(function(resolve, reject){

    console.log("About to make a get call - ");
    console.log(action);
    console.log(data);

    var request = $.get(action, data);

    request.done(function(serverData){
      resolve(serverData)
    });

    request.fail(function(serverData){
      reject(serverData)
    });
  });
}

var view = {
  goTo: function(contentId){
    $(":mobile-pagecontainer").pagecontainer("change", contentId);
  },
  errorMessage: function(errorTarget, message){
    $(errorTarget).text("There was an error signing in. " + message);
  },
  loginUser: function(){
    this.updatePersonalInfo();
    this.goTo('#cardsPage');
  },
  logoutUser: function(){
    this.goTo('#loginPage');
  },
  updatePersonalInfo: function(){
    var name = localStorage.getItem("u_first_name");
    name += " " + localStorage.getItem("u_last_name");
    $(".uName").text(name);
    $(".uSchoolName").text(localStorage.getItem('u_school_name'));
  },
  showObservation: function(observations){
    observation = observations[0];
    $('#emptyNotice').hide();
    this.updateNickname(observation);
    this.updateObservationForm(observation);
    $('.time').datebox({
        mode: "durationflipbox",
        overrideDurationOrder:["h","i","s"],
        overrideDurationFormat: "%DM:%DS"
    });
  },
  updateNickname: function(observation){
    var student = observation[2];
    var nickname = student['nickname'];
    $("#sAlias").text(nickname);
  },
  updateObservationForm: function(observation){
    var record_inputs = this.makeRecordInputs(observation[1]);
    $('#observationRecordsForm').prepend($(record_inputs));
    $('#observationRecordsForm').trigger('create');
  },
  makeRecordInputs: function(records){
    var inputs = '';
    $.each(records, function(index, record){
      console.log(record)
      input = '' + record["prompt"]  + ''
      if(record["meme"] == "Time"){
        input += '<input name="' + record["id"] + '" type="text" placeholder="10" class="time" />';
      } else if(record["meme"] == "Percentage"){
        input += '<input type="range" name="' + record["id"] + '" value="50" min="0" max="100" />';
      } else if(record["meme"] == "Qualitative"){
        input += '<input type="range" name="' + record["id"] + '" value="5" min="0" max="5" />';
      } else if(record["meme"] == "Incidence"){
        input += '<input type="text" name="' + record["id"] + '"/>';
      } else if(record["meme"] == "Boolean"){
        input += '<select name="' + record["id"] + '" data-role="slider"><option value="true">Yes</option><option value="false">No</option></select>';
      } else {
        input += '<input type="text" name="' + record["id"] + '" />';
      }
      inputs += input;
    });
    return inputs;
  }
}

var app = {
  initialize: function() {
    this.bindEvents();
  },
  bindEvents: function() {
    $("#loginForm").submit(this.submitLoginForm);
    $("#observationRecordsForm").submit(this.submitObservationForm);
    $("#logoutLink").click(this.handleLogOut);
  },
  handleLogOut: function(){
    localStorage.removeItem("uid");
    localStorage.removeItem("utoken");
    view.logoutUser();
  },
  getObservations: function(user_id, authenticity_token){
    var data = "user_id=" + user_id + "&authenticity_token=" + authenticity_token;

    get('http://localhost:3000/api/v1/observations?' + data)
      .then(function(serverData){
        localStorage.setItem("observations", serverData);
        view.showObservation(serverData);
      })
      .catch(function(serverData){
        console.log('error');
        console.log(serverData.responseText)
      });
  },
  submitLoginForm: function(){
    var data = $("#loginForm").serialize();
    post('http://localhost:3000/api/v1/login', data)
      .then(function(serverData){
        localStorage.setItem("uid", serverData.id);
        localStorage.setItem("utoken", serverData.token);
        localStorage.setItem("u_first_name", serverData.first_name);
        localStorage.setItem("u_last_name", serverData.last_name);
        localStorage.setItem("u_school_name", serverData.school_name);

        app.getObservations(serverData.id, serverData.token);
        view.loginUser();
      })
      .catch(function(serverData){
        view.errorMessage('#loginError', serverData.responseText);
      });

    return false;
  },
  submitObservationForm: function(){
    console.log('got to submitObservationForm');
    return false;
  }
};<|endoftext|>


<commit_before>export default function() {
  return typeof global !== 'undefined'
    && ({}).toString.call(global) === '[object global]';
}
<commit_msg>Fixed issue with node 7<commit_after>export default function() {
  return typeof global === 'object' && typeof process === 'object'
    && Object.prototype.toString.call(process) === '[object process]';
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
 var app = {
    // Application Constructor
    initialize: function() {
      this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
      document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicitly call 'app.receivedEvent(...);'
    onDeviceReady: function() {
      app.receivedEvent('deviceready');
      var watchID = navigator.geolocation.watchPosition(geo.onSuccess, geo.onError, { timeout: 30000 });
      window.addEventListener("batterystatus", app.onBatteryStatus, false);
      document.addEventListener("online", app.onOnline, false);
      document.addEventListener("offline", app.onOffline, false);
      app.changeStatusBar();

    },

    onOnline: function() {
      $("#connectionStatus").html("ConnectionStatus: " + navigator.connection.type);
    },

    onOffline: function() {
      $("#connectionStatus").html("ConnectionStatus: " + navigator.connection.type);
    },

    onBatteryStatus: function (status) {
      var batteryStatus = "Battery Level: " + status.level + " isPlugged: " + status.isPlugged;
      $("#batteryStatus").html(batteryStatus);
      console.log(batteryStatus)

    },

    playMedia: function() {
      var myMedia = new Media("/res/success.mp3");
      //var myMediaUrl = new Media("https://www.freesound.org/data/previews/162/162473_311243-lq.mp3")
      myMedia.play();
      //myMediaUrl.play();
    },

    changeStatusBar: function() {
      StatusBar.backgroundColorByHexString("#4B946A");
    },

    vibrate: function() {
      navigator.notification.vibrate( 1000 );
    },

    // Update DOM on a Received Event
    receivedEvent: function(id) {
      var parentElement = document.getElementById(id);
      var listeningElement = parentElement.querySelector('.listening');
      var receivedElement = parentElement.querySelector('.received');

      listeningElement.setAttribute('style', 'display:none;');
      receivedElement.setAttribute('style', 'display:block;');

      console.log('Received Event: ' + id);
    }
  };

  var geo = {
      // onSuccess Callback
    //   This method accepts a `Position` object, which contains
    //   the current GPS coordinates
    //
    onSuccess: function (position) {
      var element = document.getElementById('geolocation');
      element.innerHTML = 'Latitude: '  + position.coords.latitude
      + '\t Longitude: ' + position.coords.longitude;

      console.log(element.innerHTML)
    },

    // onError Callback receives a PositionError object
    //
    onError: function (error) {
      var element = document.getElementById('geolocation');
      element.innerHTML = 'GPS error code: '    + error.code    + '\n' + 'message: ' + error.message + '\n';
    }

    // Options: throw an error if no update is received every 30 seconds.
    //
    //var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 });
  }

  /* Main Game Handling class */
  var TicTacToe = {
    playerOWins: 0,
    playerXWins: 0,
    turn: "O",  // Keeps a record of who's turn it is
    board: ["", "", "", "", "", "", "", "", "", ""],  // Keeps a record of the TicTacToe Board
    win: false, // records who won if the game is over

    // Clears and start*s a new game with a new board /
    restartGame: function() {
      // Draw the board
      var board_table = '

';
      $("#board_div").html(board_table);
      $("#menu").hide();

      // clear the board
      this.board = ["", "", "", "", "", "", "", "", "", ""];

      // Add on-click events to each of the boxes of the board
      $("#board_div td").click(function(e) {
        TicTacToe.move( e.target.id );
      });

    },

    // Handles clicks spaces on the board /
    move: function(id) {
      var space = $("#" + id);  // Board space table element
      var num = id.replace("ttt", ""); // # representing the space on the board

      // If no one's gone there, and the game isn't over, go there!
      if (!this.board[num] && !this.win) {
        space.html( this.turn );
        this.board[num] = this.turn;
        this.nextTurn();  // End turn
      }
    },

    // Iterate turn and check if anyone one yet /
    nextTurn: function() {
      this.turn = (this.turn == "O") ? "X" : "O";
      this.win = this.check4Win();
      if (this.win) {
        this.endGame();
      }
    },

    // Display who won and options for new games /
    endGame: function() {
      var resultMessage = '';
      if (this.win == "Cat") {
        app.vibrate(2000);
        resultMessage = "Result: Tie.";
      } else {
        app.playMedia();
        this.win == 'X' ? this.playerXWins++ : this.playerOWins++;
        $("#deviceready .event.received").html("[X vs 0] = " + this.playerXWins + " : " + this.playerOWins);
        resultMessage = "Player " + this.win + " wins!";
      }

      if(navigator.platform != "Win32") {
        navigator.notification.confirm(
            resultMessage,  // message
            onConfirm,         // callback
            'Game Over',            // title
            ['Play Again?', 'Exit']           // buttonName
            );
      } else {
        $("#menu").html(resultMessage);
        $("#menu").append("
Play Again
");
        $("#menu").show();
        // Button for playing again.
        $("#play_again").click(function () { onConfirm(1)  });
      }
      function onConfirm(confirmButtonIndex) {
        if(confirmButtonIndex == 1){
         TicTacToe.restartGame();
       } else {
        if (navigator.app) {
          navigator.app.exitApp();
        }
        else if (navigator.device) {
          navigator.device.exitApp();
        } else {
          window.close();
        }
      }

    }

    this.win = false;

  },

    // If any of these patters of board spaces have all X's or all O's somebody won!
    wins: [[0,1,2], [3,4,5], [6,7,8], [0,3,6], [1,4,7], [2,5,8], [0,4,8], [6,4,2]],

    // Check for whether someone won the game of it was a Cat's game. /
    check4Win: function() {

      // Loop through all possible winning combinations
      for (k in this.wins){
        var pattern = this.wins[k];
        var p = this.board[pattern[0]] + this.board[pattern[1]] + this.board[pattern[2]];
        if (p == "XXX") {
              return "X";  // X Won!
            } else if (p == "OOO") {
              return "O";  // O Won!
            }
          }

          // Check if all spaces in the board are filled, then its a Cat's game
          var cnt = 0;
          for (s in this.board) {
            if (this.board[s]) { cnt+=1; }
          }
          if (cnt == 9) {
            return "Cat";  // Cat's game!
          }
        }
      };

      $(document).ready(function() {
        // Start a game!
        TicTacToe.restartGame();
        $("h1").click(function(){
          var status_toggle = $("#status_div").css('display') == 'none' ? 'block' : 'none';
          $("#status_div").css('display', status_toggle);
        })

        $("#deviceready").click(function(){
          StatusBar.isVisible ? StatusBar.hide() : StatusBar.show();
        })

      });<commit_msg>media update<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
 var app = {
    // Application Constructor
    initialize: function() {
      this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
      document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicitly call 'app.receivedEvent(...);'
    onDeviceReady: function() {
      app.receivedEvent('deviceready');
      var watchID = navigator.geolocation.watchPosition(geo.onSuccess, geo.onError, { timeout: 30000 });
      window.addEventListener("batterystatus", app.onBatteryStatus, false);
      document.addEventListener("online", app.onOnline, false);
      document.addEventListener("offline", app.onOffline, false);
      app.changeStatusBar();

    },

    onOnline: function() {
      $("#connectionStatus").html("ConnectionStatus: " + navigator.connection.type);
    },

    onOffline: function() {
      $("#connectionStatus").html("ConnectionStatus: " + navigator.connection.type);
    },

    onBatteryStatus: function (status) {
      var batteryStatus = "Battery Level: " + status.level + " isPlugged: " + status.isPlugged;
      $("#batteryStatus").html(batteryStatus);
      console.log(batteryStatus)

    },

    playMedia: function() {
      var resourceUrl = ''
      if(navigator.platform != "Win32") {
        resourceUrl = "https://www.freesound.org/data/previews/162/162473_311243-lq.mp3"
      } else {
        resourceUrl = "/res/success.mp3"
      }
      var myMediaUrl = new Media(resourceUrl)
      myMediaUrl.play();
    },

    changeStatusBar: function() {
      StatusBar.backgroundColorByHexString("#4B946A");
    },

    vibrate: function() {
      navigator.notification.vibrate( 1000 );
    },

    // Update DOM on a Received Event
    receivedEvent: function(id) {
      var parentElement = document.getElementById(id);
      var listeningElement = parentElement.querySelector('.listening');
      var receivedElement = parentElement.querySelector('.received');

      listeningElement.setAttribute('style', 'display:none;');
      receivedElement.setAttribute('style', 'display:block;');

      console.log('Received Event: ' + id);
    }
  };

  var geo = {
      // onSuccess Callback
    //   This method accepts a `Position` object, which contains
    //   the current GPS coordinates
    //
    onSuccess: function (position) {
      var element = document.getElementById('geolocation');
      element.innerHTML = 'Latitude: '  + position.coords.latitude
      + '\t Longitude: ' + position.coords.longitude;

      console.log(element.innerHTML)
    },

    // onError Callback receives a PositionError object
    //
    onError: function (error) {
      var element = document.getElementById('geolocation');
      element.innerHTML = 'GPS error code: '    + error.code    + '\n' + 'message: ' + error.message + '\n';
    }

    // Options: throw an error if no update is received every 30 seconds.
    //
    //var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 });
  }

  /* Main Game Handling class */
  var TicTacToe = {
    playerOWins: 0,
    playerXWins: 0,
    turn: "O",  // Keeps a record of who's turn it is
    board: ["", "", "", "", "", "", "", "", "", ""],  // Keeps a record of the TicTacToe Board
    win: false, // records who won if the game is over

    // Clears and start*s a new game with a new board /
    restartGame: function() {
      // Draw the board
      var board_table = '

';
      $("#board_div").html(board_table);
      $("#menu").hide();

      // clear the board
      this.board = ["", "", "", "", "", "", "", "", "", ""];

      // Add on-click events to each of the boxes of the board
      $("#board_div td").click(function(e) {
        TicTacToe.move( e.target.id );
      });

    },

    // Handles clicks spaces on the board /
    move: function(id) {
      var space = $("#" + id);  // Board space table element
      var num = id.replace("ttt", ""); // # representing the space on the board

      // If no one's gone there, and the game isn't over, go there!
      if (!this.board[num] && !this.win) {
        space.html( this.turn );
        this.board[num] = this.turn;
        this.nextTurn();  // End turn
      }
    },

    // Iterate turn and check if anyone one yet /
    nextTurn: function() {
      this.turn = (this.turn == "O") ? "X" : "O";
      this.win = this.check4Win();
      if (this.win) {
        this.endGame();
      }
    },

    // Display who won and options for new games /
    endGame: function() {
      var resultMessage = '';
      if (this.win == "Cat") {
        app.vibrate(2000);
        resultMessage = "Result: Tie.";
      } else {
        app.playMedia();
        this.win == 'X' ? this.playerXWins++ : this.playerOWins++;
        $("#deviceready .event.received").html("[X vs 0] = " + this.playerXWins + " : " + this.playerOWins);
        resultMessage = "Player " + this.win + " wins!";
      }

      if(navigator.platform != "Win32") {
        navigator.notification.confirm(
            resultMessage,  // message
            onConfirm,         // callback
            'Game Over',            // title
            ['Play Again?', 'Exit']           // buttonName
            );
      } else {
        $("#menu").html(resultMessage);
        $("#menu").append("
Play Again
");
        $("#menu").show();
        // Button for playing again.
        $("#play_again").click(function () { onConfirm(1)  });
      }
      function onConfirm(confirmButtonIndex) {
        if(confirmButtonIndex == 1){
         TicTacToe.restartGame();
       } else {
        if (navigator.app) {
          navigator.app.exitApp();
        }
        else if (navigator.device) {
          navigator.device.exitApp();
        } else {
          window.close();
        }
      }

    }

    this.win = false;

  },

    // If any of these patters of board spaces have all X's or all O's somebody won!
    wins: [[0,1,2], [3,4,5], [6,7,8], [0,3,6], [1,4,7], [2,5,8], [0,4,8], [6,4,2]],

    // Check for whether someone won the game of it was a Cat's game. /
    check4Win: function() {

      // Loop through all possible winning combinations
      for (k in this.wins){
        var pattern = this.wins[k];
        var p = this.board[pattern[0]] + this.board[pattern[1]] + this.board[pattern[2]];
        if (p == "XXX") {
              return "X";  // X Won!
            } else if (p == "OOO") {
              return "O";  // O Won!
            }
          }

          // Check if all spaces in the board are filled, then its a Cat's game
          var cnt = 0;
          for (s in this.board) {
            if (this.board[s]) { cnt+=1; }
          }
          if (cnt == 9) {
            return "Cat";  // Cat's game!
          }
        }
      };

      $(document).ready(function() {
        // Start a game!
        TicTacToe.restartGame();
        $("h1").click(function(){
          var status_toggle = $("#status_div").css('display') == 'none' ? 'block' : 'none';
          $("#status_div").css('display', status_toggle);
        })

        $("#deviceready").click(function(){
          StatusBar.isVisible ? StatusBar.hide() : StatusBar.show();
        })

      });<|endoftext|>