<commit_before>describe('locators', function() {
  beforeEach(function() {
    browser.get('index.html#/form');
  });

  describe('by binding', function() {
    it('should find an element by binding', function() {
      var greeting = element(by.binding('greeting'));

      expect(greeting.getText()).toEqual('Hiya');
    });

    it('should allow custom expectations to expect an element', function() {
      jasmine.addMatchers({
        toHaveText: function() {
          return {
            compare: function(actual, expected) {
              return {
                pass: actual.getText().then(function(actual) {
                  return actual === expected;
                })
              };
            }
          };
        }
      });

      expect(element(by.binding('greeting'))).toHaveText('Hiya');
    });

    it('should find a binding by partial match', function() {
      var greeting = element(by.binding('greet'));

      expect(greeting.getText()).toEqual('Hiya');
    });

    it('should find exact match by exactBinding', function() {
      var greeting = element(by.exactBinding('greeting'));

      expect(greeting.getText()).toEqual('Hiya');
    });

    it('should not find partial match by exactBinding', function() {
      var greeting = element(by.exactBinding('greet'));

      expect(greeting.isPresent()).toBe(false);
    });

    it('should find an element by binding with ng-bind attribute',
        function() {
      var name = element(by.binding('username'));

      expect(name.getText()).toEqual('Anon');
    });

    it('should find an element by binding with ng-bind-template attribute',
        function() {
      var name = element(by.binding('nickname|uppercase'));

      expect(name.getText()).toEqual('(ANNIE)');
    });
  });

  describe('by model', function() {
    it('should find an element by text input model', function() {
      var username = element(by.model('username'));
      var name = element(by.binding('username'));

      username.clear();
      expect(name.getText()).toEqual('');

      username.sendKeys('Jane Doe');
      expect(name.getText()).toEqual('Jane Doe');
    });

    it('should find an element by checkbox input model', function() {
      expect(element(by.id('shower')).isDisplayed()).
          toBe(true);

      var colors = element(by.model('show')).click();

      expect(element(by.id('shower')).isDisplayed()).
          toBe(false);
    });

    it('should find a textarea by model', function() {
      var about = element(by.model('aboutbox'));
      expect(about.getAttribute('value')).toEqual('This is a text box');

      about.clear();
      about.sendKeys('Something else to write about');

      expect(about.getAttribute('value')).
          toEqual('Something else to write about');
    });

    it('should find multiple selects by model', function() {
      var selects = element.all(by.model('dayColor.color'));
      expect(selects.count()).toEqual(3);
    });

    it('should find the selected option', function() {
      var select = element(by.model('fruit'));
      var selectedOption = select.element(by.css('option:checked'));
      expect(selectedOption.getText()).toEqual('apple');
    });

    it('should find inputs with alternate attribute forms', function() {
      var letterList = element(by.id('letterlist'));
      expect(letterList.getText()).toBe('');

      element(by.model('check.w')).click();
      expect(letterList.getText()).toBe('w');

      element(by.model('check.x')).click();
      expect(letterList.getText()).toBe('wx');
    });

    it('should find multiple inputs', function() {
      element.all(by.model('color')).then(function(arr) {
        expect(arr.length).toEqual(3);
      });
    });

    it('should clear text from an input model', function() {
      var username = element(by.model('username'));
      var name = element(by.binding('username'));

      username.clear();
      expect(name.getText()).toEqual('');

      username.sendKeys('Jane Doe');
      expect(name.getText()).toEqual('Jane Doe');

      username.clear();
      expect(name.getText()).toEqual('');
    });
  });

  describe('by partial button text', function() {
    it('should find multiple buttons containing "text"', function() {
      element.all(by.partialButtonText('text')).then(function(arr) {
        expect(arr.length).toEqual(4);
        expect(arr[0].getAttribute('id')).toBe('exacttext');
        expect(arr[1].getAttribute('id')).toBe('otherbutton');
        expect(arr[2].getAttribute('id')).toBe('submitbutton');
        expect(arr[3].getAttribute('id')).toBe('inputbutton');
      });
    });
  });

  describe('by button text', function() {
    it('should find two button containing "Exact text"', function() {
      element.all(by.buttonText('Exact text')).then(function(arr) {
        expect(arr.length).toEqual(2);
        expect(arr[0].getAttribute('id')).toBe('exacttext');
        expect(arr[1].getAttribute('id')).toBe('submitbutton');
      });
    });

    it('should not find any buttons containing "text"', function() {
      element.all(by.buttonText('text')).then(function(arr) {
        expect(arr.length).toEqual(0);
      });
    });

  });

  describe('by repeater', function() {
    beforeEach(function() {
      browser.get('index.html#/repeater');
    });

    it('should find by partial match', function() {
      var fullMatch = element(
          by.repeater('baz in days | filter:\'T\'').
              row(0).column('baz.initial'));
      expect(fullMatch.getText()).toEqual('T');

      var partialMatch = element(
          by.repeater('baz in days').row(0).column('b'));
      expect(partialMatch.getText()).toEqual('T');

      var partialRowMatch = element(
          by.repeater('baz in days').row(0));
      expect(partialRowMatch.getText()).toEqual('T');

      var partialRowMatch = element(
          by.repeater('baz in tDays').row(0));
      expect(partialRowMatch.getText()).toEqual('T');
    });

    it('should return all rows when unmodified', function() {
      var all =
          element.all(by.repeater('allinfo in days'));
      all.then(function(arr) {
        expect(arr.length).toEqual(5);
        expect(arr[0].getText()).toEqual('M Monday');
        expect(arr[1].getText()).toEqual('T Tuesday');
        expect(arr[2].getText()).toEqual('W Wednesday');
      });
    });

    it('should return a single column', function() {
      var initials = element.all(
          by.repeater('allinfo in days').column('initial'));
      initials.then(function(arr) {
        expect(arr.length).toEqual(5);
        expect(arr[0].getText()).toEqual('M');
        expect(arr[1].getText()).toEqual('T');
        expect(arr[2].getText()).toEqual('W');
      });

      var names = element.all(
          by.repeater('allinfo in days').column('name'));
      names.then(function(arr) {
        expect(arr.length).toEqual(5);
        expect(arr[0].getText()).toEqual('Monday');
        expect(arr[1].getText()).toEqual('Tuesday');
        expect(arr[2].getText()).toEqual('Wednesday');
      });
    });

    it('should allow chaining while returning a single column', function() {
      var secondName = element(by.css('.allinfo')).element(
        by.repeater('allinfo in days').column('name').row(2));
      expect(secondName.getText()).toEqual('Wednesday');
    });

    it('should return a single row', function() {
      var secondRow = element(
          by.repeater('allinfo in days').row(1));
      expect(secondRow.getText()).toEqual('T Tuesday');
    });

    it('should return an individual cell', function() {
      var secondNameByRowFirst = element(
          by.repeater('allinfo in days').
          row(1).
          column('name'));

      var secondNameByColumnFirst = element(
          by.repeater('allinfo in days').
          column('name').
          row(1));

      expect(secondNameByRowFirst.getText()).toEqual('Tuesday');
      expect(secondNameByColumnFirst.getText()).toEqual('Tuesday');
    });

    it('should find a using data-ng-repeat', function() {
      var byRow =
        element(by.repeater('day in days').row(2));
      expect(byRow.getText()).toEqual('W');

      var byCol =
          element(by.repeater('day in days').row(2).
          column('day'));
      expect(byCol.getText()).toEqual('W');
    });

    it('should find using ng:repeat', function() {
      var byRow =
        element(by.repeater('bar in days').row(2));
      expect(byRow.getText()).toEqual('W');

      var byCol =
          element(by.repeater('bar in days').row(2).
          column('bar'));
      expect(byCol.getText()).toEqual('W');
    });

    it('should determine if repeater elements are present', function() {
      expect(element(by.repeater('allinfo in days').row(3)).isPresent()).
          toBe(true);
      // There are only 5 rows, so the 6th row is not present.
      expect(element(by.repeater('allinfo in days').row(5)).isPresent()).
          toBe(false);
    });

    it('should have by.exactRepeater working', function() {
      expect(element(by.exactRepeater('day in d')).isPresent()).toBe(false);
      expect(element(by.exactRepeater('day in days')).isPresent()).toBe(true);
    });

    describe('repeaters using ng-repeat-start and ng-repeat-end', function() {
      it('should return all elements when unmodified', function() {
        var all =
            element.all(by.repeater('bloop in days'));

        all.then(function(arr) {
          expect(arr.length).toEqual(3 * 5);
          expect(arr[0].getText()).toEqual('M');
          expect(arr[1].getText()).toEqual('-');
          expect(arr[2].getText()).toEqual('Monday');
          expect(arr[3].getText()).toEqual('T');
          expect(arr[4].getText()).toEqual('-');
          expect(arr[5].getText()).toEqual('Tuesday');
        });
      });

      it('should return a group of elements for a row', function() {
        var firstRow = element.all(by.repeater('bloop in days').row(0));

        firstRow.then(function(arr) {
          expect(arr.length).toEqual(3);
          expect(arr[0].getText()).toEqual('M');
          expect(arr[1].getText()).toEqual('-');
          expect(arr[2].getText()).toEqual('Monday');
        });
      });

      it('should return a group of elements for a column', function() {
        var nameColumn = element.all(
          by.repeater('bloop in days').column('name'));

        nameColumn.then(function(arr) {
          expect(arr.length).toEqual(5);
          expect(arr[0].getText()).toEqual('Monday');
          expect(arr[1].getText()).toEqual('Tuesday');
        });
      });

      it('should find an individual element', function() {
        var firstInitial = element(
          by.repeater('bloop in days').row(0).column('bloop.initial'));

        expect(firstInitial.getText()).toEqual('M');
      });
    });
  });

  describe('by css containing text', function() {
    it('should find elements by css and partial text', function() {
      element.all(by.cssContainingText('#animals ul .pet', 'dog')).then(function(arr) {
        expect(arr.length).toEqual(2);
        expect(arr[0].getAttribute('id')).toBe('bigdog');
        expect(arr[1].getAttribute('id')).toBe('smalldog');
      });
    });

    it('should find elements with text-transform style', function() {
      expect(element(by.cssContainingText('#transformedtext div', 'Uppercase'))
          .getAttribute('id')).toBe('textuppercase');
      expect(element(by.cssContainingText('#transformedtext div', 'Lowercase'))
          .getAttribute('id')).toBe('textlowercase');
      expect(element(by.cssContainingText('#transformedtext div', 'capitalize'))
          .getAttribute('id')).toBe('textcapitalize');
    });
  });

  describe('by options', function() {
    it('should find elements by options', function() {
      var allOptions = element.all(by.options('fruit for fruit in fruits'));
      expect(allOptions.count()).toEqual(4);

      var firstOption = allOptions.first();
      expect(firstOption.getText()).toEqual('apple');
    });
  });

  describe('by deep css', function() {
    beforeEach(function() {
      browser.get('index.html#/shadow');
    });

    // Shadow DOM is not currently supported outside of Chrome.
    browser.getCapabilities().then(function(capabilities) {
      if (capabilities.get('browserName') == 'chrome') {

        it('should find items inside the shadow DOM', function() {
          var parentHeading = element(by.deepCss('.parentshadowheading'));
          var olderChildHeading = element(by.deepCss('.oldershadowheading'));
          var youngerChildHeading = element(by.deepCss('.youngershadowheading'));

          expect(parentHeading.isPresent()).toBe(true);
          expect(olderChildHeading.isPresent()).toBe(true);
          expect(youngerChildHeading.isPresent()).toBe(true);

          expect(parentHeading.getText()).toEqual('Parent');
          expect(olderChildHeading.getText()).toEqual('Older Child');
          expect(youngerChildHeading.getText()).toEqual('Younger Child');

          expect(element(by.deepCss('.originalcontent')).getText())
              .toEqual('original content');
        });
      }
    });
  });

  it('should determine if an element is present', function() {
    expect(browser.isElementPresent(by.binding('greet'))).toBe(true);
    expect(browser.isElementPresent(by.binding('nopenopenope'))).toBe(false);
  });

  it('should determine if an ElementFinder is present', function() {
    expect(browser.isElementPresent(element(by.binding('greet')))).toBe(true);
    expect(browser.isElementPresent(element(by.binding('nopenopenope'))))
        .toBe(false);
  });
});
<commit_msg>chore(test): fix by.exactRepeater test<commit_after>describe('locators', function() {
  beforeEach(function() {
    browser.get('index.html#/form');
  });

  describe('by binding', function() {
    it('should find an element by binding', function() {
      var greeting = element(by.binding('greeting'));

      expect(greeting.getText()).toEqual('Hiya');
    });

    it('should allow custom expectations to expect an element', function() {
      jasmine.addMatchers({
        toHaveText: function() {
          return {
            compare: function(actual, expected) {
              return {
                pass: actual.getText().then(function(actual) {
                  return actual === expected;
                })
              };
            }
          };
        }
      });

      expect(element(by.binding('greeting'))).toHaveText('Hiya');
    });

    it('should find a binding by partial match', function() {
      var greeting = element(by.binding('greet'));

      expect(greeting.getText()).toEqual('Hiya');
    });

    it('should find exact match by exactBinding', function() {
      var greeting = element(by.exactBinding('greeting'));

      expect(greeting.getText()).toEqual('Hiya');
    });

    it('should not find partial match by exactBinding', function() {
      var greeting = element(by.exactBinding('greet'));

      expect(greeting.isPresent()).toBe(false);
    });

    it('should find an element by binding with ng-bind attribute',
        function() {
      var name = element(by.binding('username'));

      expect(name.getText()).toEqual('Anon');
    });

    it('should find an element by binding with ng-bind-template attribute',
        function() {
      var name = element(by.binding('nickname|uppercase'));

      expect(name.getText()).toEqual('(ANNIE)');
    });
  });

  describe('by model', function() {
    it('should find an element by text input model', function() {
      var username = element(by.model('username'));
      var name = element(by.binding('username'));

      username.clear();
      expect(name.getText()).toEqual('');

      username.sendKeys('Jane Doe');
      expect(name.getText()).toEqual('Jane Doe');
    });

    it('should find an element by checkbox input model', function() {
      expect(element(by.id('shower')).isDisplayed()).
          toBe(true);

      var colors = element(by.model('show')).click();

      expect(element(by.id('shower')).isDisplayed()).
          toBe(false);
    });

    it('should find a textarea by model', function() {
      var about = element(by.model('aboutbox'));
      expect(about.getAttribute('value')).toEqual('This is a text box');

      about.clear();
      about.sendKeys('Something else to write about');

      expect(about.getAttribute('value')).
          toEqual('Something else to write about');
    });

    it('should find multiple selects by model', function() {
      var selects = element.all(by.model('dayColor.color'));
      expect(selects.count()).toEqual(3);
    });

    it('should find the selected option', function() {
      var select = element(by.model('fruit'));
      var selectedOption = select.element(by.css('option:checked'));
      expect(selectedOption.getText()).toEqual('apple');
    });

    it('should find inputs with alternate attribute forms', function() {
      var letterList = element(by.id('letterlist'));
      expect(letterList.getText()).toBe('');

      element(by.model('check.w')).click();
      expect(letterList.getText()).toBe('w');

      element(by.model('check.x')).click();
      expect(letterList.getText()).toBe('wx');
    });

    it('should find multiple inputs', function() {
      element.all(by.model('color')).then(function(arr) {
        expect(arr.length).toEqual(3);
      });
    });

    it('should clear text from an input model', function() {
      var username = element(by.model('username'));
      var name = element(by.binding('username'));

      username.clear();
      expect(name.getText()).toEqual('');

      username.sendKeys('Jane Doe');
      expect(name.getText()).toEqual('Jane Doe');

      username.clear();
      expect(name.getText()).toEqual('');
    });
  });

  describe('by partial button text', function() {
    it('should find multiple buttons containing "text"', function() {
      element.all(by.partialButtonText('text')).then(function(arr) {
        expect(arr.length).toEqual(4);
        expect(arr[0].getAttribute('id')).toBe('exacttext');
        expect(arr[1].getAttribute('id')).toBe('otherbutton');
        expect(arr[2].getAttribute('id')).toBe('submitbutton');
        expect(arr[3].getAttribute('id')).toBe('inputbutton');
      });
    });
  });

  describe('by button text', function() {
    it('should find two button containing "Exact text"', function() {
      element.all(by.buttonText('Exact text')).then(function(arr) {
        expect(arr.length).toEqual(2);
        expect(arr[0].getAttribute('id')).toBe('exacttext');
        expect(arr[1].getAttribute('id')).toBe('submitbutton');
      });
    });

    it('should not find any buttons containing "text"', function() {
      element.all(by.buttonText('text')).then(function(arr) {
        expect(arr.length).toEqual(0);
      });
    });

  });

  describe('by repeater', function() {
    beforeEach(function() {
      browser.get('index.html#/repeater');
    });

    it('should find by partial match', function() {
      var fullMatch = element(
          by.repeater('baz in days | filter:\'T\'').
              row(0).column('baz.initial'));
      expect(fullMatch.getText()).toEqual('T');

      var partialMatch = element(
          by.repeater('baz in days').row(0).column('b'));
      expect(partialMatch.getText()).toEqual('T');

      var partialRowMatch = element(
          by.repeater('baz in days').row(0));
      expect(partialRowMatch.getText()).toEqual('T');
    });

    it('should return all rows when unmodified', function() {
      var all =
          element.all(by.repeater('allinfo in days'));
      all.then(function(arr) {
        expect(arr.length).toEqual(5);
        expect(arr[0].getText()).toEqual('M Monday');
        expect(arr[1].getText()).toEqual('T Tuesday');
        expect(arr[2].getText()).toEqual('W Wednesday');
      });
    });

    it('should return a single column', function() {
      var initials = element.all(
          by.repeater('allinfo in days').column('initial'));
      initials.then(function(arr) {
        expect(arr.length).toEqual(5);
        expect(arr[0].getText()).toEqual('M');
        expect(arr[1].getText()).toEqual('T');
        expect(arr[2].getText()).toEqual('W');
      });

      var names = element.all(
          by.repeater('allinfo in days').column('name'));
      names.then(function(arr) {
        expect(arr.length).toEqual(5);
        expect(arr[0].getText()).toEqual('Monday');
        expect(arr[1].getText()).toEqual('Tuesday');
        expect(arr[2].getText()).toEqual('Wednesday');
      });
    });

    it('should allow chaining while returning a single column', function() {
      var secondName = element(by.css('.allinfo')).element(
        by.repeater('allinfo in days').column('name').row(2));
      expect(secondName.getText()).toEqual('Wednesday');
    });

    it('should return a single row', function() {
      var secondRow = element(
          by.repeater('allinfo in days').row(1));
      expect(secondRow.getText()).toEqual('T Tuesday');
    });

    it('should return an individual cell', function() {
      var secondNameByRowFirst = element(
          by.repeater('allinfo in days').
          row(1).
          column('name'));

      var secondNameByColumnFirst = element(
          by.repeater('allinfo in days').
          column('name').
          row(1));

      expect(secondNameByRowFirst.getText()).toEqual('Tuesday');
      expect(secondNameByColumnFirst.getText()).toEqual('Tuesday');
    });

    it('should find a using data-ng-repeat', function() {
      var byRow =
        element(by.repeater('day in days').row(2));
      expect(byRow.getText()).toEqual('W');

      var byCol =
          element(by.repeater('day in days').row(2).
          column('day'));
      expect(byCol.getText()).toEqual('W');
    });

    it('should find using ng:repeat', function() {
      var byRow =
        element(by.repeater('bar in days').row(2));
      expect(byRow.getText()).toEqual('W');

      var byCol =
          element(by.repeater('bar in days').row(2).
          column('bar'));
      expect(byCol.getText()).toEqual('W');
    });

    it('should determine if repeater elements are present', function() {
      expect(element(by.repeater('allinfo in days').row(3)).isPresent()).
          toBe(true);
      // There are only 5 rows, so the 6th row is not present.
      expect(element(by.repeater('allinfo in days').row(5)).isPresent()).
          toBe(false);
    });

    it('should have by.exactRepeater working', function() {
      expect(element(by.exactRepeater('day in d')).isPresent()).toBe(false);
      expect(element(by.exactRepeater('day in days')).isPresent()).toBe(true);

      // Full ng-repeat: baz in tDays = (days | filter:'T')
      var repeaterWithEqualSign = element(
          by.exactRepeater('baz in tDays').row(0));
      expect(repeaterWithEqualSign.getText()).toEqual('T');

      // Full ng-repeat: baz in days | filter:'T'
      var repeaterWithPipe = element(
          by.exactRepeater('baz in days').row(0));
      expect(repeaterWithPipe.getText()).toEqual('T');
    });

    describe('repeaters using ng-repeat-start and ng-repeat-end', function() {
      it('should return all elements when unmodified', function() {
        var all =
            element.all(by.repeater('bloop in days'));

        all.then(function(arr) {
          expect(arr.length).toEqual(3 * 5);
          expect(arr[0].getText()).toEqual('M');
          expect(arr[1].getText()).toEqual('-');
          expect(arr[2].getText()).toEqual('Monday');
          expect(arr[3].getText()).toEqual('T');
          expect(arr[4].getText()).toEqual('-');
          expect(arr[5].getText()).toEqual('Tuesday');
        });
      });

      it('should return a group of elements for a row', function() {
        var firstRow = element.all(by.repeater('bloop in days').row(0));

        firstRow.then(function(arr) {
          expect(arr.length).toEqual(3);
          expect(arr[0].getText()).toEqual('M');
          expect(arr[1].getText()).toEqual('-');
          expect(arr[2].getText()).toEqual('Monday');
        });
      });

      it('should return a group of elements for a column', function() {
        var nameColumn = element.all(
          by.repeater('bloop in days').column('name'));

        nameColumn.then(function(arr) {
          expect(arr.length).toEqual(5);
          expect(arr[0].getText()).toEqual('Monday');
          expect(arr[1].getText()).toEqual('Tuesday');
        });
      });

      it('should find an individual element', function() {
        var firstInitial = element(
          by.repeater('bloop in days').row(0).column('bloop.initial'));

        expect(firstInitial.getText()).toEqual('M');
      });
    });
  });

  describe('by css containing text', function() {
    it('should find elements by css and partial text', function() {
      element.all(by.cssContainingText('#animals ul .pet', 'dog')).then(function(arr) {
        expect(arr.length).toEqual(2);
        expect(arr[0].getAttribute('id')).toBe('bigdog');
        expect(arr[1].getAttribute('id')).toBe('smalldog');
      });
    });

    it('should find elements with text-transform style', function() {
      expect(element(by.cssContainingText('#transformedtext div', 'Uppercase'))
          .getAttribute('id')).toBe('textuppercase');
      expect(element(by.cssContainingText('#transformedtext div', 'Lowercase'))
          .getAttribute('id')).toBe('textlowercase');
      expect(element(by.cssContainingText('#transformedtext div', 'capitalize'))
          .getAttribute('id')).toBe('textcapitalize');
    });
  });

  describe('by options', function() {
    it('should find elements by options', function() {
      var allOptions = element.all(by.options('fruit for fruit in fruits'));
      expect(allOptions.count()).toEqual(4);

      var firstOption = allOptions.first();
      expect(firstOption.getText()).toEqual('apple');
    });
  });

  describe('by deep css', function() {
    beforeEach(function() {
      browser.get('index.html#/shadow');
    });

    // Shadow DOM is not currently supported outside of Chrome.
    browser.getCapabilities().then(function(capabilities) {
      if (capabilities.get('browserName') == 'chrome') {

        it('should find items inside the shadow DOM', function() {
          var parentHeading = element(by.deepCss('.parentshadowheading'));
          var olderChildHeading = element(by.deepCss('.oldershadowheading'));
          var youngerChildHeading = element(by.deepCss('.youngershadowheading'));

          expect(parentHeading.isPresent()).toBe(true);
          expect(olderChildHeading.isPresent()).toBe(true);
          expect(youngerChildHeading.isPresent()).toBe(true);

          expect(parentHeading.getText()).toEqual('Parent');
          expect(olderChildHeading.getText()).toEqual('Older Child');
          expect(youngerChildHeading.getText()).toEqual('Younger Child');

          expect(element(by.deepCss('.originalcontent')).getText())
              .toEqual('original content');
        });
      }
    });
  });

  it('should determine if an element is present', function() {
    expect(browser.isElementPresent(by.binding('greet'))).toBe(true);
    expect(browser.isElementPresent(by.binding('nopenopenope'))).toBe(false);
  });

  it('should determine if an ElementFinder is present', function() {
    expect(browser.isElementPresent(element(by.binding('greet')))).toBe(true);
    expect(browser.isElementPresent(element(by.binding('nopenopenope'))))
        .toBe(false);
  });
});
<|endoftext|>


<commit_before>/*global FormplayerFrontend, Util */

FormplayerFrontend.module("Menus", function (Menus, FormplayerFrontend, Backbone, Marionette, $) {
    Menus.Controller = {
        selectMenu: function (options) {

            options.preview = FormplayerFrontend.currentUser.displayOptions.singleAppMode;

            var fetchingNextMenu = FormplayerFrontend.request("app:select:menus", options);

            /*
             Determine the next screen to display.  Could be
             a list of commands (modules and/or forms)
             a list of entities (cases) and their details
             */
            $.when(fetchingNextMenu).done(function (menuResponse) {
                // show any notifications from Formplayer
                if (menuResponse.notification && !_.isNull(menuResponse.notification.message)) {
                    FormplayerFrontend.request("handleNotification", menuResponse.notification);
                }

                if (menuResponse.shouldRequestLocation) {
                    Menus.Util.handleLocationRequest(options);
                }
                Menus.Util.startOrStopLocationWatching(menuResponse.shouldWatchLocation);

                // If redirect was set, clear and go home.
                if (menuResponse.clearSession) {
                    FormplayerFrontend.trigger("apps:currentApp");
                    return;
                }

                var urlObject = Util.currentUrlToObject();
                // If we don't have an appId in the URL (usually due to form preview)
                // then parse the appId from the response.
                if (urlObject.appId === undefined || urlObject.appId === null) {
                    if (menuResponse.appId === null || menuResponse.appId === undefined) {
                        FormplayerFrontend.request('showError', "Response did not contain appId even though it was" +
                            "required. If this persists, please report an issue to CommCareHQ");
                        FormplayerFrontend.trigger("apps:list");
                        return;
                    }
                    urlObject.appId = menuResponse.appId;
                    Util.setUrlToObject(urlObject);
                }

                Menus.Controller.showMenu(menuResponse);
            }).fail(function() {
                // if it didn't go through, then it displayed an error message.
                // the right thing to do is then to just stay in the same place.
            });
        },

        selectDetail: function(caseId, detailIndex, isPersistent) {
            var urlObject = Util.currentUrlToObject();
            if (!isPersistent) {
                urlObject.addStep(caseId);
            }
            var fetchingDetails = FormplayerFrontend.request("entity:get:details", urlObject, isPersistent);
            $.when(fetchingDetails).done(function (detailResponse) {
                Menus.Controller.showDetail(detailResponse, detailIndex, caseId);
            }).fail(function() {
                FormplayerFrontend.trigger('navigateHome');
            });
        },

        showMenu: function (menuResponse) {
            var menuListView = Menus.Util.getMenuView(menuResponse);

            if (menuListView) {
                FormplayerFrontend.regions.main.show(menuListView.render());
            }
            if (menuResponse.persistentCaseTile && !FormplayerFrontend.currentUser.displayOptions.singleAppMode) {
                Menus.Controller.showPersistentCaseTile(menuResponse.persistentCaseTile);
            } else {
                FormplayerFrontend.regions.persistentCaseTile.empty();
            }

            if (menuResponse.breadcrumbs) {
                Menus.Util.showBreadcrumbs(menuResponse.breadcrumbs);
            } else {
                FormplayerFrontend.regions.breadcrumb.empty();
            }
            if (menuResponse.appVersion) {
                FormplayerFrontend.trigger('setVersionInfo', menuResponse.appVersion);
            }
        },

        showPersistentCaseTile: function (persistentCaseTile) {
            var detailView = Menus.Controller.getCaseTile(persistentCaseTile);
            FormplayerFrontend.regions.persistentCaseTile.show(detailView.render());
        },

        showDetail: function (model, detailTabIndex, caseId) {
            var self = this;
            var detailObjects = model.models;
            // If we have no details, just select the entity
            if (detailObjects === null || detailObjects === undefined || detailObjects.length === 0) {
                FormplayerFrontend.trigger("menu:select", caseId);
                return;
            }
            var detailObject = detailObjects[detailTabIndex];
            var menuListView = Menus.Controller.getDetailList(detailObject);

            var tabModels = _.map(detailObjects, function (detail, index) {
                return {title: detail.get('title'), id: index};
            });
            var tabCollection = new Backbone.Collection();
            tabCollection.reset(tabModels);

            var tabListView = new Menus.Views.DetailTabListView({
                collection: tabCollection,
                showDetail: function (detailTabIndex) {
                    self.showDetail(model, detailTabIndex, caseId);
                },
            });

            $('#select-case').off('click').click(function () {
                FormplayerFrontend.trigger("menu:select", caseId);
            });
            $('#case-detail-modal').find('.js-detail-tabs').html(tabListView.render().el);
            $('#case-detail-modal').find('.js-detail-content').html(menuListView.render().el);
            $('#case-detail-modal').modal('show');

            if (model.isPersistentDetail) {
                $('#case-detail-modal').find('#select-case').hide();
            } else {
                $('#case-detail-modal').find('#select-case').show();
            }
        },

        getDetailList: function (detailObject) {

            if (detailObject.get('entities')) {
                var entities = detailObject.get('entities');
                var listModel = [];
                // we need to map the details and headers JSON to a list for a Backbone Collection
                for (var i = 0; i < entities.length; i++) {
                    var listObj = {};
                    listObj.data = entities[i].data;
                    listObj.id = i;
                    listModel.push(listObj);
                }
                var listCollection = new Backbone.Collection();
                listCollection.reset(listModel);
                var menuData = {
                    collection: listCollection,
                    headers: detailObject.get('headers'),
                    styles: detailObject.get('styles'),
                    title: detailObject.get('title'),
                };
                return new Menus.Views.CaseListDetailView(menuData);
            }

            var headers = detailObject.get('headers');
            var details = detailObject.get('details');
            var styles = detailObject.get('styles');
            var detailModel = [];
            // we need to map the details and headers JSON to a list for a Backbone Collection
            for (var i = 0; i < headers.length; i++) {
                var obj = {};
                obj.data = details[i];
                obj.header = headers[i];
                obj.style = styles[i];
                obj.id = i;
                detailModel.push(obj);
            }
            var detailCollection = new Backbone.Collection();
            detailCollection.reset(detailModel);
            return new Menus.Views.DetailListView({
                collection: detailCollection,
            });
        },

        // return a case tile from a detail object (for persistent case tile)
        getCaseTile: function (detailObject) {
            var detailModel = new Backbone.Model({
                data: detailObject.details,
                id: 0,
            });
            var numEntitiesPerRow = detailObject.numEntitiesPerRow || 1;
            var numRows = detailObject.maxHeight;
            var numColumns = detailObject.maxWidth;
            var useUniformUnits = detailObject.useUniformUnits || false;
            var caseTileStyles = Menus.Views.buildCaseTileStyles(detailObject.tiles, numRows, numColumns,
                numEntitiesPerRow, useUniformUnits, 'persistent');
            // Style the positioning of the elements within a tile (IE element 1 at grid position 1 / 2 / 4 / 3
            $("#persistent-cell-layout-style").html(caseTileStyles[0]).data("css-polyfilled", false);
            // Style the grid (IE each tile has 6 rows, 12 columns)
            $("#persistent-cell-grid-style").html(caseTileStyles[1]).data("css-polyfilled", false);
            return new Menus.Views.PersistentCaseTileView({
                model: detailModel,
                styles: detailObject.styles,
                tiles: detailObject.tiles,
                maxWidth: detailObject.maxWidth,
                maxHeight: detailObject.maxHeight,
                prefix: 'persistent',
                hasInlineTile: detailObject.hasInlineTile,
            });
        },
    };

    Menus.Util = {
        handleLocationRequest: function(optionsFromLastRequest) {
            var success = function(position) {
                Menus.Util.recordPosition(position);
                Menus.Controller.selectMenu(optionsFromLastRequest);
            };

            var error = function(err) {
                var msg;
                switch(err.code) {
                    case err.PERMISSION_DENIED:
                        msg = "You denied CommCare HQ permission to read your browser's current location. ";
                        break;
                    case err.TIMEOUT:
                        msg = "Your connection was not strong enough to acquire your location. Please try again later. ";
                        break;
                    case err.POSITION_UNAVAILABLE:
                    default:
                        msg = "Your browser location could not be determined. ";
                        break;
                }
                FormplayerFrontend.trigger('showError',
                    msg + "Without access to your location, computations that rely on the here() function will show up blank.");
            };

            if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(success, error, {timeout: 10000});
            }
        },

        startOrStopLocationWatching: function(shouldWatchLocation) {
            if (navigator.geolocation) {
                var notWatching = typeof sessionStorage.lastLocationWatchId === "undefined" || sessionStorage.lastLocationWatchId === '';
                if (notWatching && shouldWatchLocation) {
                    sessionStorage.lastLocationWatchId = navigator.geolocation.watchPosition(Menus.Util.recordPosition);
                } else if (!notWatching && !shouldWatchLocation) {
                    navigator.geolocation.clearWatch(sessionStorage.lastLocationWatchId);
                    sessionStorage.lastLocationWatchId = '';
                }
            }
        },

        recordPosition: function(position) {
            sessionStorage.locationLat = position.coords.latitude;
            sessionStorage.locationLon = position.coords.longitude;
            sessionStorage.locationAltitude = position.coords.altitude;
            sessionStorage.locationAccuracy = position.coords.accuracy;
        },

        showBreadcrumbs: function (breadcrumbs) {
            var detailCollection,
                breadcrumbModels;

            breadcrumbModels = _.map(breadcrumbs, function(breadcrumb, idx) {
                return {
                    data: breadcrumb,
                    id: idx,
                };
            });

            detailCollection = new Backbone.Collection(breadcrumbModels);
            var breadcrumbView = new Menus.Views.BreadcrumbListView({
                collection: detailCollection,
            });
            FormplayerFrontend.regions.breadcrumb.show(breadcrumbView.render());
        },

        getMenuView: function (menuResponse) {
            var menuData = {
                collection: menuResponse,
                title: menuResponse.title,
                headers: menuResponse.headers,
                widthHints: menuResponse.widthHints,
                actions: menuResponse.actions,
                pageCount: menuResponse.pageCount,
                currentPage: menuResponse.currentPage,
                styles: menuResponse.styles,
                type: menuResponse.type,
                sessionId: menuResponse.sessionId,
                tiles: menuResponse.tiles,
                numEntitiesPerRow: menuResponse.numEntitiesPerRow,
                maxHeight: menuResponse.maxHeight,
                maxWidth: menuResponse.maxWidth,
                useUniformUnits: menuResponse.useUniformUnits,
                isPersistentDetail: menuResponse.isPersistentDetail,
                sortIndices: menuResponse.sortIndices,
            };
            if (menuResponse.type === "commands") {
                return new Menus.Views.MenuListView(menuData);
            } else if (menuResponse.type === "query") {
                return new Menus.Views.QueryListView(menuData);
            }
            else if (menuResponse.type === "entities") {
                if (menuResponse.tiles === null || menuResponse.tiles === undefined) {
                    return new Menus.Views.CaseListView(menuData);
                } else {
                    if (menuResponse.numEntitiesPerRow > 1) {
                        return new Menus.Views.GridCaseTileListView(menuData);
                    } else {
                        return new Menus.Views.CaseTileListView(menuData);
                    }
                }
            }
        },
    };
});
<commit_msg>try indenting how stickler wants even though I think it's wrong..<commit_after>/*global FormplayerFrontend, Util */

FormplayerFrontend.module("Menus", function (Menus, FormplayerFrontend, Backbone, Marionette, $) {
    Menus.Controller = {
        selectMenu: function (options) {

            options.preview = FormplayerFrontend.currentUser.displayOptions.singleAppMode;

            var fetchingNextMenu = FormplayerFrontend.request("app:select:menus", options);

            /*
             Determine the next screen to display.  Could be
             a list of commands (modules and/or forms)
             a list of entities (cases) and their details
             */
            $.when(fetchingNextMenu).done(function (menuResponse) {
                // show any notifications from Formplayer
                if (menuResponse.notification && !_.isNull(menuResponse.notification.message)) {
                    FormplayerFrontend.request("handleNotification", menuResponse.notification);
                }

                if (menuResponse.shouldRequestLocation) {
                    Menus.Util.handleLocationRequest(options);
                }
                Menus.Util.startOrStopLocationWatching(menuResponse.shouldWatchLocation);

                // If redirect was set, clear and go home.
                if (menuResponse.clearSession) {
                    FormplayerFrontend.trigger("apps:currentApp");
                    return;
                }

                var urlObject = Util.currentUrlToObject();
                // If we don't have an appId in the URL (usually due to form preview)
                // then parse the appId from the response.
                if (urlObject.appId === undefined || urlObject.appId === null) {
                    if (menuResponse.appId === null || menuResponse.appId === undefined) {
                        FormplayerFrontend.request('showError', "Response did not contain appId even though it was" +
                            "required. If this persists, please report an issue to CommCareHQ");
                        FormplayerFrontend.trigger("apps:list");
                        return;
                    }
                    urlObject.appId = menuResponse.appId;
                    Util.setUrlToObject(urlObject);
                }

                Menus.Controller.showMenu(menuResponse);
            }).fail(function() {
                // if it didn't go through, then it displayed an error message.
                // the right thing to do is then to just stay in the same place.
            });
        },

        selectDetail: function(caseId, detailIndex, isPersistent) {
            var urlObject = Util.currentUrlToObject();
            if (!isPersistent) {
                urlObject.addStep(caseId);
            }
            var fetchingDetails = FormplayerFrontend.request("entity:get:details", urlObject, isPersistent);
            $.when(fetchingDetails).done(function (detailResponse) {
                Menus.Controller.showDetail(detailResponse, detailIndex, caseId);
            }).fail(function() {
                FormplayerFrontend.trigger('navigateHome');
            });
        },

        showMenu: function (menuResponse) {
            var menuListView = Menus.Util.getMenuView(menuResponse);

            if (menuListView) {
                FormplayerFrontend.regions.main.show(menuListView.render());
            }
            if (menuResponse.persistentCaseTile && !FormplayerFrontend.currentUser.displayOptions.singleAppMode) {
                Menus.Controller.showPersistentCaseTile(menuResponse.persistentCaseTile);
            } else {
                FormplayerFrontend.regions.persistentCaseTile.empty();
            }

            if (menuResponse.breadcrumbs) {
                Menus.Util.showBreadcrumbs(menuResponse.breadcrumbs);
            } else {
                FormplayerFrontend.regions.breadcrumb.empty();
            }
            if (menuResponse.appVersion) {
                FormplayerFrontend.trigger('setVersionInfo', menuResponse.appVersion);
            }
        },

        showPersistentCaseTile: function (persistentCaseTile) {
            var detailView = Menus.Controller.getCaseTile(persistentCaseTile);
            FormplayerFrontend.regions.persistentCaseTile.show(detailView.render());
        },

        showDetail: function (model, detailTabIndex, caseId) {
            var self = this;
            var detailObjects = model.models;
            // If we have no details, just select the entity
            if (detailObjects === null || detailObjects === undefined || detailObjects.length === 0) {
                FormplayerFrontend.trigger("menu:select", caseId);
                return;
            }
            var detailObject = detailObjects[detailTabIndex];
            var menuListView = Menus.Controller.getDetailList(detailObject);

            var tabModels = _.map(detailObjects, function (detail, index) {
                return {title: detail.get('title'), id: index};
            });
            var tabCollection = new Backbone.Collection();
            tabCollection.reset(tabModels);

            var tabListView = new Menus.Views.DetailTabListView({
                collection: tabCollection,
                showDetail: function (detailTabIndex) {
                    self.showDetail(model, detailTabIndex, caseId);
                },
            });

            $('#select-case').off('click').click(function () {
                FormplayerFrontend.trigger("menu:select", caseId);
            });
            $('#case-detail-modal').find('.js-detail-tabs').html(tabListView.render().el);
            $('#case-detail-modal').find('.js-detail-content').html(menuListView.render().el);
            $('#case-detail-modal').modal('show');

            if (model.isPersistentDetail) {
                $('#case-detail-modal').find('#select-case').hide();
            } else {
                $('#case-detail-modal').find('#select-case').show();
            }
        },

        getDetailList: function (detailObject) {

            if (detailObject.get('entities')) {
                var entities = detailObject.get('entities');
                var listModel = [];
                // we need to map the details and headers JSON to a list for a Backbone Collection
                for (var i = 0; i < entities.length; i++) {
                    var listObj = {};
                    listObj.data = entities[i].data;
                    listObj.id = i;
                    listModel.push(listObj);
                }
                var listCollection = new Backbone.Collection();
                listCollection.reset(listModel);
                var menuData = {
                    collection: listCollection,
                    headers: detailObject.get('headers'),
                    styles: detailObject.get('styles'),
                    title: detailObject.get('title'),
                };
                return new Menus.Views.CaseListDetailView(menuData);
            }

            var headers = detailObject.get('headers');
            var details = detailObject.get('details');
            var styles = detailObject.get('styles');
            var detailModel = [];
            // we need to map the details and headers JSON to a list for a Backbone Collection
            for (var i = 0; i < headers.length; i++) {
                var obj = {};
                obj.data = details[i];
                obj.header = headers[i];
                obj.style = styles[i];
                obj.id = i;
                detailModel.push(obj);
            }
            var detailCollection = new Backbone.Collection();
            detailCollection.reset(detailModel);
            return new Menus.Views.DetailListView({
                collection: detailCollection,
            });
        },

        // return a case tile from a detail object (for persistent case tile)
        getCaseTile: function (detailObject) {
            var detailModel = new Backbone.Model({
                data: detailObject.details,
                id: 0,
            });
            var numEntitiesPerRow = detailObject.numEntitiesPerRow || 1;
            var numRows = detailObject.maxHeight;
            var numColumns = detailObject.maxWidth;
            var useUniformUnits = detailObject.useUniformUnits || false;
            var caseTileStyles = Menus.Views.buildCaseTileStyles(detailObject.tiles, numRows, numColumns,
                numEntitiesPerRow, useUniformUnits, 'persistent');
            // Style the positioning of the elements within a tile (IE element 1 at grid position 1 / 2 / 4 / 3
            $("#persistent-cell-layout-style").html(caseTileStyles[0]).data("css-polyfilled", false);
            // Style the grid (IE each tile has 6 rows, 12 columns)
            $("#persistent-cell-grid-style").html(caseTileStyles[1]).data("css-polyfilled", false);
            return new Menus.Views.PersistentCaseTileView({
                model: detailModel,
                styles: detailObject.styles,
                tiles: detailObject.tiles,
                maxWidth: detailObject.maxWidth,
                maxHeight: detailObject.maxHeight,
                prefix: 'persistent',
                hasInlineTile: detailObject.hasInlineTile,
            });
        },
    };

    Menus.Util = {
        handleLocationRequest: function(optionsFromLastRequest) {
            var success = function(position) {
                Menus.Util.recordPosition(position);
                Menus.Controller.selectMenu(optionsFromLastRequest);
            };

            var error = function(err) {
                var msg;
                switch(err.code) {
                case err.PERMISSION_DENIED:
                    msg = "You denied CommCare HQ permission to read your browser's current location. ";
                    break;
                case err.TIMEOUT:
                    msg = "Your connection was not strong enough to acquire your location. Please try again later. ";
                    break;
                case err.POSITION_UNAVAILABLE:
                default:
                    msg = "Your browser location could not be determined. ";
                    break;
                }
                FormplayerFrontend.trigger('showError',
                    msg + "Without access to your location, computations that rely on the here() function will show up blank.");
            };

            if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(success, error, {timeout: 10000});
            }
        },

        startOrStopLocationWatching: function(shouldWatchLocation) {
            if (navigator.geolocation) {
                var notWatching = typeof sessionStorage.lastLocationWatchId === "undefined" || sessionStorage.lastLocationWatchId === '';
                if (notWatching && shouldWatchLocation) {
                    sessionStorage.lastLocationWatchId = navigator.geolocation.watchPosition(Menus.Util.recordPosition);
                } else if (!notWatching && !shouldWatchLocation) {
                    navigator.geolocation.clearWatch(sessionStorage.lastLocationWatchId);
                    sessionStorage.lastLocationWatchId = '';
                }
            }
        },

        recordPosition: function(position) {
            sessionStorage.locationLat = position.coords.latitude;
            sessionStorage.locationLon = position.coords.longitude;
            sessionStorage.locationAltitude = position.coords.altitude;
            sessionStorage.locationAccuracy = position.coords.accuracy;
        },

        showBreadcrumbs: function (breadcrumbs) {
            var detailCollection,
                breadcrumbModels;

            breadcrumbModels = _.map(breadcrumbs, function(breadcrumb, idx) {
                return {
                    data: breadcrumb,
                    id: idx,
                };
            });

            detailCollection = new Backbone.Collection(breadcrumbModels);
            var breadcrumbView = new Menus.Views.BreadcrumbListView({
                collection: detailCollection,
            });
            FormplayerFrontend.regions.breadcrumb.show(breadcrumbView.render());
        },

        getMenuView: function (menuResponse) {
            var menuData = {
                collection: menuResponse,
                title: menuResponse.title,
                headers: menuResponse.headers,
                widthHints: menuResponse.widthHints,
                actions: menuResponse.actions,
                pageCount: menuResponse.pageCount,
                currentPage: menuResponse.currentPage,
                styles: menuResponse.styles,
                type: menuResponse.type,
                sessionId: menuResponse.sessionId,
                tiles: menuResponse.tiles,
                numEntitiesPerRow: menuResponse.numEntitiesPerRow,
                maxHeight: menuResponse.maxHeight,
                maxWidth: menuResponse.maxWidth,
                useUniformUnits: menuResponse.useUniformUnits,
                isPersistentDetail: menuResponse.isPersistentDetail,
                sortIndices: menuResponse.sortIndices,
            };
            if (menuResponse.type === "commands") {
                return new Menus.Views.MenuListView(menuData);
            } else if (menuResponse.type === "query") {
                return new Menus.Views.QueryListView(menuData);
            }
            else if (menuResponse.type === "entities") {
                if (menuResponse.tiles === null || menuResponse.tiles === undefined) {
                    return new Menus.Views.CaseListView(menuData);
                } else {
                    if (menuResponse.numEntitiesPerRow > 1) {
                        return new Menus.Views.GridCaseTileListView(menuData);
                    } else {
                        return new Menus.Views.CaseTileListView(menuData);
                    }
                }
            }
        },
    };
});
<|endoftext|>


<commit_before>/*
  example.js - custom script for bitbucket-webhook-example
  Copyright (C) 2015 Nishimura Software Studio

  Copying and distribution of this file, with or without modification, are
  permitted in any medium without royalty provided the copyright notice and
  this notice are preserved.  This file is offered as-is, without any warranty.
*/

"use strict";

$(document).ready(function () {
    var accountMenu = $("#account-menu");
    accountMenu.removeClass("pure-menu-allow-hover");
    accountMenu.mouseleave(function (event) {
        $("#account-menu > .pure-menu-children").css("display", "");
    });

    $("#account-menu > .pure-menu-link").click(function (event) {
        var children = $("#account-menu > .pure-menu-children");
        if (children.css("display") !== "block") {
            children.css("display", "block");
        } else {
            accountMenu.mouseleave();
        }
        return false;
    });
});
<commit_msg>Added height adjustment of the nav menu.<commit_after>/*
  example.js - custom script for bitbucket-webhook-example
  Copyright (C) 2015 Nishimura Software Studio

  Copying and distribution of this file, with or without modification, are
  permitted in any medium without royalty provided the copyright notice and
  this notice are preserved.  This file is offered as-is, without any warranty.
*/

"use strict";

$(document).ready(function () {
    var accountMenu = $("#account-menu");
    accountMenu.removeClass("pure-menu-allow-hover");
    accountMenu.mouseleave(function (event) {
        $("#account-menu > .pure-menu-children").css("display", "");
    });

    $("#account-menu > .pure-menu-link").click(function (event) {
        var children = $("#account-menu > .pure-menu-children");
        if (children.css("display") !== "block") {
            children.css("display", "block");
        } else {
            accountMenu.mouseleave();
        }
        return false;
    });

    $(window).resize(function (event) {
        if ($("#nav-menu").width() !== $(document).width()) {
            var height = $(document).height();
            height -= $("#toolbar").height();
            $("#nav-menu").css("min-height", height + "px");
        } else {
            $("#nav-menu").css("min-height", "");
        }
    });
    $(window).resize();
});

$(window).load(function (event) {
    // Triggers a resize event now as the document height might
    // have changed.
    $(window).resize();
});
<|endoftext|>


<commit_before>(function() {

    var entity = JSON.parse(mw.config.get('wbEntity'));
    var seeneps = parseInt(entity['claims']['P28'][0]['mainsnak']['datavalue']['value']['amount']);
    var alleps = parseInt(entity['claims']['P27'][0]['mainsnak']['datavalue']['value']['amount']);

    function seenAddOne() {
        var api = new mw.Api();
        api.get({
            'action': 'wbgetclaims',
            'format': 'json',
            'entity': mw.config.get('wgTitle'),
            'property': 'P28'
        }).then(function(data) {
            var guid = data['claims']['P28'][0]['id'];
            var oldvalue = parseInt(data['claims']['P28'][0]['mainsnak']['datavalue']['value']['amount']);
            var newvalue = oldvalue + 1;

            if (!confirm('已看集數從 ' + oldvalue + ' 改為 ' + newvalue)) {
                mw.notify('已取消');
                return;
            }

            api.postWithEditToken({
                'action': 'wbsetclaimvalue',
                'format': 'json',
                'claim': guid,
                'value': JSON.stringify({
                    'amount': '+' + newvalue,
                    'unit': '1'
                }),
                'snaktype': 'value',
            }).then(function() {
                mw.notify('成功更新');
                location.reload();
            }, function(e) {
                mw.notify('未知錯誤：' + e);
            });

        }, function(e) {
            mw.notify('未知錯誤：' + e);
        });

    }

    if (seeneps !== alleps) {
        $('<button style="margin-left: 10px;">+1</button>')
            .on('click', seenAddOne)
            .appendTo($('div#P28 div.wikibase-snakview-body'));

    }

}
)();
<commit_msg>Revert "Use mw.config to get value"<commit_after>(function() {

    function seenAddOne() {
        var api = new mw.Api();
        api.get({
            'action': 'wbgetclaims',
            'format': 'json',
            'entity': mw.config.get('wgTitle'),
            'property': 'P28'
        }).then(function(data) {
            var guid = data['claims']['P28'][0]['id'];
            var oldvalue = parseInt(data['claims']['P28'][0]['mainsnak']['datavalue']['value']['amount']);
            var newvalue = oldvalue + 1;

            if (!confirm('已看集數從 ' + oldvalue + ' 改為 ' + newvalue)) {
                mw.notify('已取消');
                return;
            }

            api.postWithEditToken({
                'action': 'wbsetclaimvalue',
                'format': 'json',
                'claim': guid,
                'value': JSON.stringify({
                    'amount': '+' + newvalue,
                    'unit': '1'
                }),
                'snaktype': 'value',
            }).then(function() {
                mw.notify('成功更新');
                location.reload();
            }, function(e) {
                mw.notify('未知錯誤：' + e);
            });

        }, function(e) {
            mw.notify('未知錯誤：' + e);
        });

    }

    if ($('div#P28 div.wikibase-snakview-value').text() != $('div#P27 div.wikibase-snakview-value').text()) {
        $('<button style="margin-left: 10px;">+1</button>')
            .on('click', seenAddOne)
            .appendTo($('div#P28 div.wikibase-snakview-body'));

    }

}
)();
<|endoftext|>


<commit_before>girderTest.importPlugin('candela');
girderTest.startApp();

describe('Test the candela UI.', function () {
    it('register a user', girderTest.createUser(
        'johndoe', 'john.doe@email.com', 'John', 'Doe', 'password!'
    ));

    it('uploads the data file', function () {
        runs(function () {
            expect($('#g-user-action-menu.open').length).toBe(0);
            $('.g-user-text>a:first').click();
            expect($('#g-user-action-menu.open').length).toBe(1);
            $('a.g-my-folders').click();
        });

        waitsFor(function () {
            return $('a.g-folder-list-link').length === 2;
        }, 'Public and Private folders to appear');

        runs(function () {
            $('a.g-folder-list-link:contains("Public")').click();
        });
        girderTest.waitForLoad();

        waitsFor(function () {
            return $('ol.breadcrumb>li.active').text() === 'Public' &&
                   $('.g-empty-parent-message:visible').length === 1;
        }, 'descending into Public folder');

        girderTest.binaryUpload('clients/web/test/testFile.csv');

        runs(function () {
            $('.g-item-list-link:first').click();
        });
    });

    it('sets up candela inputs and renders the visualization', function () {
        waitsFor(function () {
            return $('.g-item-candela-component').length === 1;
        }, 'the candela component selector to appear');

        runs(function () {
            expect($('.g-item-candela-component option').length).toBeGreaterThan(5);
            $('.g-item-candela-component').val('BarChart').change();
        });

        waitsFor(function () {
            var inputs = $('.g-candela-inputs-container').children().eq(1).children().children();
            return inputs.length > 3;
        }, 'the bar chart options to be available');

        runs(function () {
            var inputs = $('.g-candela-inputs-container').children().eq(1).children().children();
            expect(inputs.eq(0).find('label').text()).toBe('Width');
            expect(inputs.eq(1).find('label').text()).toBe('Height');
            expect(inputs.eq(2).find('label').text()).toBe('X');
            var values = [];
            for (var i = 0; i < 4; i += 1) {
                values.push(inputs.eq(2).find('option').eq(i).text());
            }
            values.sort();
            expect(values).toEqual(['(none)', 'a_b', 'c', 'id']);
            $('.g-candela-update-vis').click();
        });

        waitsFor(function () {
            return $('.g-candela-vis').find('canvas').length === 1;
        }, 'the vis canvas to be drawn');

        runs(function () {
            $('.g-item-candela-component').val('TreeHeatmap').change();
        });

        waitsFor(function () {
            var inputs = $('.g-candela-inputs-container').children().eq(1).children().children();
            return inputs.length === 9;
        }, 'the visualization type to change to TreeHeatmap');

        runs(function () {
            var inputs = $('.g-candela-inputs-container').children().eq(1).children().children();
            expect(inputs.eq(2).find('label').text()).toBe('Identifier column');
            expect(inputs.eq(3).find('label').text()).toBe('Color scale');
            expect(inputs.eq(3).find('option').eq(1).text()).toBe('row');
        });

        runs(function () {
            $('.g-item-candela-component').val('Histogram').change();
        });

        waitsFor(function () {
            var inputs = $('.g-candela-inputs-container').children().eq(1).children().children();
            return inputs.length > 3;
        }, 'the visualization type to change to BulletChart');

        runs(function () {
            var inputs = $('.g-candela-inputs-container').children().eq(1).children().children();
            expect(inputs.eq(2).find('label').text()).toBe('X');
        });
    });

    it('uploads a bad data file', function () {
        runs(function () {
            expect($('#g-user-action-menu.open').length).toBe(0);
            $('.g-user-text>a:first').click();
        });
        waitsFor(function () {
            return $('#g-user-action-menu.open').length === 1;
        }, 'menu to open');

        runs(function () {
            $('a.g-my-folders').click();
        });
        waitsFor(function () {
            return $('.g-folder-list-link').length > 0;
        }, 'user folder list to load');

        runs(function () {
            $('a.g-folder-list-link:contains("Public")').click();
        });
        girderTest.waitForLoad();
        waitsFor(function () {
            return $('ol.breadcrumb>li.active').text() === 'Public' &&
                   $('.g-item-list-link').length === 1;
        }, 'descending into Public folder');

        girderTest.binaryUpload('clients/web/test/testFileBad.csv');

        runs(function () {
            $('.g-item-list-link').eq(1).click();
        });

        waitsFor(function () {
            return $('.alert-danger').length === 1;
        }, 'the error message to appear');

        runs(function () {
            expect($('.alert-danger').text()).toContain('An error occurred while attempting to read and parse the data file.');
        });
    });
});
<commit_msg>Disable a test that is no longer needed<commit_after>girderTest.importPlugin('candela');
girderTest.startApp();

describe('Test the candela UI.', function () {
    it('register a user', girderTest.createUser(
        'johndoe', 'john.doe@email.com', 'John', 'Doe', 'password!'
    ));

    it('uploads the data file', function () {
        runs(function () {
            expect($('#g-user-action-menu.open').length).toBe(0);
            $('.g-user-text>a:first').click();
            expect($('#g-user-action-menu.open').length).toBe(1);
            $('a.g-my-folders').click();
        });

        waitsFor(function () {
            return $('a.g-folder-list-link').length === 2;
        }, 'Public and Private folders to appear');

        runs(function () {
            $('a.g-folder-list-link:contains("Public")').click();
        });
        girderTest.waitForLoad();

        waitsFor(function () {
            return $('ol.breadcrumb>li.active').text() === 'Public' &&
                   $('.g-empty-parent-message:visible').length === 1;
        }, 'descending into Public folder');

        girderTest.binaryUpload('clients/web/test/testFile.csv');

        runs(function () {
            $('.g-item-list-link:first').click();
        });
    });

    it('sets up candela inputs and renders the visualization', function () {
        waitsFor(function () {
            return $('.g-item-candela-component').length === 1;
        }, 'the candela component selector to appear');

        runs(function () {
            expect($('.g-item-candela-component option').length).toBeGreaterThan(5);
            $('.g-item-candela-component').val('BarChart').change();
        });

        waitsFor(function () {
            var inputs = $('.g-candela-inputs-container').children().eq(1).children().children();
            return inputs.length > 3;
        }, 'the bar chart options to be available');

        runs(function () {
            var inputs = $('.g-candela-inputs-container').children().eq(1).children().children();
            expect(inputs.eq(0).find('label').text()).toBe('Width');
            expect(inputs.eq(1).find('label').text()).toBe('Height');
            expect(inputs.eq(2).find('label').text()).toBe('X');
            var values = [];
            for (var i = 0; i < 4; i += 1) {
                values.push(inputs.eq(2).find('option').eq(i).text());
            }
            values.sort();
            expect(values).toEqual(['(none)', 'a_b', 'c', 'id']);
            $('.g-candela-update-vis').click();
        });

        waitsFor(function () {
            return $('.g-candela-vis').find('canvas').length === 1;
        }, 'the vis canvas to be drawn');

        runs(function () {
            $('.g-item-candela-component').val('TreeHeatmap').change();
        });

        waitsFor(function () {
            var inputs = $('.g-candela-inputs-container').children().eq(1).children().children();
            return inputs.length === 9;
        }, 'the visualization type to change to TreeHeatmap');

        runs(function () {
            var inputs = $('.g-candela-inputs-container').children().eq(1).children().children();
            expect(inputs.eq(2).find('label').text()).toBe('Identifier column');
            expect(inputs.eq(3).find('label').text()).toBe('Color scale');
            expect(inputs.eq(3).find('option').eq(1).text()).toBe('row');
        });

        runs(function () {
            $('.g-item-candela-component').val('Histogram').change();
        });

        waitsFor(function () {
            var inputs = $('.g-candela-inputs-container').children().eq(1).children().children();
            return inputs.length > 3;
        }, 'the visualization type to change to BulletChart');

        runs(function () {
            var inputs = $('.g-candela-inputs-container').children().eq(1).children().children();
            expect(inputs.eq(2).find('label').text()).toBe('X');
        });
    });

    // This test is skipped because this failure mode no longer exists with the
    // updated Candela plugin backing technologies. Specifically, d3-dsv is used
    // for parsing, and that module happily accepts any stream of bytes and will
    // simply parse what it gets, even if that is a zip file or a PNG image or
    // anything else.
    xit('uploads a bad data file', function () {
        runs(function () {
            expect($('#g-user-action-menu.open').length).toBe(0);
            $('.g-user-text>a:first').click();
        });
        waitsFor(function () {
            return $('#g-user-action-menu.open').length === 1;
        }, 'menu to open');

        runs(function () {
            $('a.g-my-folders').click();
        });
        waitsFor(function () {
            return $('.g-folder-list-link').length > 0;
        }, 'user folder list to load');

        runs(function () {
            $('a.g-folder-list-link:contains("Public")').click();
        });
        girderTest.waitForLoad();
        waitsFor(function () {
            return $('ol.breadcrumb>li.active').text() === 'Public' &&
                   $('.g-item-list-link').length === 1;
        }, 'descending into Public folder');

        girderTest.binaryUpload('clients/web/test/testFileBad.csv');

        runs(function () {
            $('.g-item-list-link').eq(1).click();
        });

        waitsFor(function () {
            return $('.alert-danger').length === 1;
        }, 'the error message to appear');

        runs(function () {
            expect($('.alert-danger').text()).toContain('An error occurred while attempting to read and parse the data file.');
        });
    });
});
<|endoftext|>


<commit_before>/* global jsc, describe, it, expect, _ */
(function () {
	"use strict";

	function append(l1, l2) {
		return l1.concat(l2);
	}

	function reverse(l) {
		return l.slice().reverse();
	}

	describe("underscore.js", function () {
		describe("collections", function () {
			describe("map", function () {
				it("map_length: length (map f l) = length l", function () {
					expect(jsc.forall(jsc.fun(), jsc.array(), function (f, l) {
						return _.map(l, f).length === l.length;
					})).toHold();
				});

				it("map_app: map f (l ++ l') = map f l ++ map f l'", function () {
					expect(jsc.forall(jsc.fun(), jsc.array(), jsc.array(), function (f, l1, l2) {
						return _.isEqual(_.map(append(l1, l2), f), append(_.map(l1, f), _.map(l2, f)));
					})).toHold();
				});

				it("map_rev: map f (rev l) = rev (map f l)", function () {
					expect(jsc.forall(jsc.fun(), jsc.array(), function (f, l) {
						return _.isEqual(_.map(reverse(l), f), reverse(_.map(l, f)));
					})).toHold();
				});

				it("map_id: map id l = l", function () {
					expect(jsc.forall(jsc.array(), function (l) {
						return _.isEqual(_.map(l, _.identity), l);
					}));
				});

				it("map_map: map g (map f l) = map (g ∘ f) l", function () {
					// g ∘ f == _.compose(g, f)
					expect(jsc.forall(jsc.fun(), jsc.fun(), jsc.array(), function (f, g, l) {
						return _.isEqual(_.map(_.map(l, f), g), _.map(l, _.compose(g, f)));
					})).toHold();
				});
			});
		});

		describe("utility", function () {
			describe("identity", function () {
				it("identity(x) === x", function () {
					expect(jsc.forall(jsc.value(), function (x) {
						return _.identity(x) === x;
					})).toHold();
				});

				it("returns first argument", function () {
					var nonemptylist = jsc.suchthat(jsc.array(), function (l) {
						return l.length !== 0;
					});

					expect(jsc.forall(nonemptylist, function (l) {
						return _.identity.apply(undefined, l) === l[0];
					})).toHold();
				});
			});
		});
	});
}());<commit_msg>filter_in property<commit_after>/* global jsc, describe, it, expect, _ */
(function () {
	"use strict";

	function append(l1, l2) {
		return l1.concat(l2);
	}

	function reverse(l) {
		return l.slice().reverse();
	}

	describe("underscore.js", function () {
		describe("collections", function () {
			describe("map", function () {
				it("map_length: length (map f l) = length l", function () {
					expect(jsc.forall(jsc.fun(), jsc.array(), function (f, l) {
						return _.map(l, f).length === l.length;
					})).toHold();
				});

				it("map_app: map f (l ++ l') = map f l ++ map f l'", function () {
					expect(jsc.forall(jsc.fun(), jsc.array(), jsc.array(), function (f, l1, l2) {
						return _.isEqual(_.map(append(l1, l2), f), append(_.map(l1, f), _.map(l2, f)));
					})).toHold();
				});

				it("map_rev: map f (rev l) = rev (map f l)", function () {
					expect(jsc.forall(jsc.fun(), jsc.array(), function (f, l) {
						return _.isEqual(_.map(reverse(l), f), reverse(_.map(l, f)));
					})).toHold();
				});

				it("map_id: map id l = l", function () {
					expect(jsc.forall(jsc.array(), function (l) {
						return _.isEqual(_.map(l, _.identity), l);
					}));
				});

				it("map_map: map g (map f l) = map (g ∘ f) l", function () {
					// g ∘ f == _.compose(g, f)
					expect(jsc.forall(jsc.fun(), jsc.fun(), jsc.array(), function (f, g, l) {
						return _.isEqual(_.map(_.map(l, f), g), _.map(l, _.compose(g, f)));
					})).toHold();
				});
			});

			describe("filter", function () {
				it("filter_in", function () {
					expect(jsc.forall(jsc.fun(jsc.bool()), jsc.array(),  function (f, l) {
						var filtered = _.filter(l, f);

						// In x (filter f l) <-> In x l /\ f x = true
						return _.every(filtered, f) && _.every(filtered, function (x) {
							return _.contains(l, x);
						});
					})).toHold();
				});
			});
		});

		describe("utility", function () {
			describe("identity", function () {
				it("identity(x) === x", function () {
					expect(jsc.forall(jsc.value(), function (x) {
						return _.identity(x) === x;
					})).toHold();
				});

				it("returns first argument", function () {
					var nonemptylist = jsc.suchthat(jsc.array(), function (l) {
						return l.length !== 0;
					});

					expect(jsc.forall(nonemptylist, function (l) {
						return _.identity.apply(undefined, l) === l[0];
					})).toHold();
				});
			});
		});
	});
}());<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Media from 'react-media';
import './MobileSimulator.css';
import dragscroll from './util/dragscroll.js';
import topImage from './img/top.png';
import bottomImage from './img/bottom.png';

// CSS adapted from https://framework7.io/examples/
class MobileSimulator extends Component {
  constructor(props) {
    super(props);
    this.renderResponsiveFrame = this.renderResponsiveFrame.bind(this);
    this.onClickFake = this.onClickFake.bind(this);
  }

  onClickFake() {
    alert('Not really...');
  }

  componentDidMount() {
    dragscroll(document.getElementsByClassName('MobileSimulator-dragscroll'));
  }

  render() {
    const {minWidth, minHeight} = this.props;
    const query = `(min-width: ${minWidth}px) and (min-height: ${minHeight}px)`;
    return <Media query={query}>{this.renderResponsiveFrame}</Media>;
  }

  renderResponsiveFrame(isNotWide) {
    const {children} = this.props;
    if (!isNotWide) return children;

    return (

              {children}

    );
  }
}
MobileSimulator.propTypes = {
  minWidth: PropTypes.number.isRequired,
  minHeight: PropTypes.number.isRequired,
  children: PropTypes.node.isRequired
};

export default MobileSimulator;<commit_msg>Tweaking with touching fake iPhone controls<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Media from 'react-media';
import Animated from 'animated/lib/targets/react-dom';
import './MobileSimulator.css';
import dragscroll from './util/dragscroll.js';
import topImage from './img/top.png';
import bottomImage from './img/bottom.png';

// CSS adapted from https://framework7.io/examples/
class MobileSimulator extends Component {
  constructor(props) {
    super(props);
    this.state = {
      animScale: new Animated.Value(1)
    };
    this.renderResponsiveFrame = this.renderResponsiveFrame.bind(this);
    this.onMouseDown = this.onMouseDown.bind(this);
    this.onMouseUp = this.onMouseUp.bind(this);
  }

  onMouseDown() {
    const {animScale} = this.state;
    Animated.spring(animScale, { toValue: 1.1 }).start();
  }

  onMouseUp() {
    const {animScale} = this.state;
    animScale.stopAnimation(value =>
      Animated.spring(animScale, { toValue: 1 }).start()
    );
  }

  componentDidMount() {
    dragscroll(document.getElementsByClassName('MobileSimulator-dragscroll'));
  }

  render() {
    const {minWidth, minHeight} = this.props;
    const query = `(min-width: ${minWidth}px) and (min-height: ${minHeight}px)`;
    return <Media query={query}>{this.renderResponsiveFrame}</Media>;
  }

  renderResponsiveFrame(isNotWide) {
    const {children} = this.props;
    if (!isNotWide) return children;

    const {animScale} = this.state;
    return (

        <Animated.div style={{transform: [{scale: animScale}]}}>

                {children}

        </Animated.div>

    );
  }
}
MobileSimulator.propTypes = {
  minWidth: PropTypes.number.isRequired,
  minHeight: PropTypes.number.isRequired,
  children: PropTypes.node.isRequired
};

export default MobileSimulator;<|endoftext|>


<commit_before>import { xhr, assign, cacheJSON, search2obj, cookie } from './utils.es6.js';
import { Loader } from './loader.es6.js';
import { emitter } from './emitter.es6.js';
import riot from './riot.core.es6.js';
import route from './riot.route.es6.js';

export class RiotApp {

  constructor(options={}){
    // 单例化
    if(!this.instance){
      // window.riot
      window.riot = riot;
      // 可监听化
      emitter(this);
      // 配置信息
      this.config = assign({
        id: 'app', // 项目id
        env: 'dev', // 环境
        staticBase: './static/',
        routeBase: '#!', // route解析分隔符
        mountPage: 'page', // 页面逻辑挂载点
        loginPage: 'login',
        indexPage: 'index',
        errorPage: '500',
        notFoundPage: '404',
        resource: [] // 需要预先加载的资源
      }, options);
      // 记录已经加载的tag
      this.tagMounted = {};
      // 合并组件
      this.route = route;
      this.xhr = xhr;
      this.utils = {
        cookie: cookie
      };
      // 初始化操作
      this.init();
      this.instance = this;
    }
    return this.instance;
  }

  init(){
    const cf = this.config;
    // 初始化必要资源
    cf.resource.push(this.config.env);
    cacheJSON(`${cf.staticBase}${cf.id}.json`, {
      force: cf.env !== 'pro'
    })
    .done(resp => {
      // 记录方便不刷新情况下获取
      this.loaderJSON = resp;
      Loader.alias(this.loaderJSON, cf.resource)
      .then(files => {
        // 开始初始化路由
        route.base(cf.routeBase);
        // 路由解析方式
        route.parser(path => {
          const raw = path.split('?'),
            uri = raw[0].split('/'),
            qs = raw[1];
          if (qs) uri.push(search2obj(qs));
          return uri;
        });
        // 设置路由控制
        this.on('route::change', params => {
          let
            page = params[0] || cf.indexPage,
            pageFile = `${cf.staticBase}riot/${cf.id}/${page}.js`,
            tagName = `${cf.id}-${page}`;
          this.route.params = params;
          Loader.batch(pageFile).then(() => {
            try{
              let tag = riot.mount(cf.mountPage, tagName)[0],
                ctags = (tag) => {
                  for(let childTagName in tag.tags){
                    this.tagMounted[childTagName] = tag.tags[childTagName];
                    ctags(tag.tags[childTagName]);
                  }
                };
              this.tagMounted[tagName] = tag;
              ctags(tag);
            } catch(e) {
              window.location.replace(
                `${cf.routeBase}/${cf.errorPage}?message=${e.message}`
              );
              this.err(e);
            }
          }).catch(() => {
            window.location.replace(cf.routeBase+'/'+cf.notFoundPage);
          });
        });
        // 开始监听路由变化
        route((...args) => {
          this.emit('route::change', args);
        });
        // 启动路由
        route.start(true);

        // 将项目实例导入riot全局app对象
        riot.mixin({ app: this });

        this.emit('init::done', files);
      })
      .catch(files => {
        this.emit('init::fail', files);
      });
    });

  }

  /**
   * 信息打印
   */
  log(...args){
    return this.config.dev !== 'pro' ?
      window.console && window.console.log(...args) : null;
  }
  err(...args){
    return window.console && window.console.error(...args);
  }

  /**
   * 适配项目接口
   * @return {[type]} [description]
   */
  api(method, url, data){
    const prefix = {dev: 'dev.', test: 'test.', pro: ''}[this.config.env];
    return xhr(`//${prefix}h5.sosho.cn/server/${url}`, {
      method: method,
      data: data,
      headers: {}
    });
  }

  /**
   * 追加资源载入
   */
  addResource(resName){
    let existRes;
    if(!this.loaderJSON)
      return Promise.reject();
    if(this.loaderJSON[resName])
      existRes = resName;
    else if(this.loaderJSON[`${resName}.${this.config.env}`])
      existRes = `${resName}.${this.config.env}`;
    return Loader.alias(this.loaderJSON, [existRes]);
  }

}
<commit_msg>no message<commit_after>import { xhr, assign, cacheJSON, search2obj, cookie } from './utils.es6.js';
import { Loader } from './loader.es6.js';
import { emitter } from './emitter.es6.js';
import riot from './riot.core.es6.js';
import route from './riot.route.es6.js';

export class RiotApp {

  constructor(options={}){
    // 单例化
    if(!this.instance){
      // window.riot
      window.riot = riot;
      // 可监听化
      emitter(this);
      // 配置信息
      this.config = assign({
        id: 'app', // 项目id
        env: 'dev', // 环境
        staticBase: './static/',
        routeBase: '#!', // route解析分隔符
        mountPage: 'page', // 页面逻辑挂载点
        loginPage: 'login',
        indexPage: 'index',
        errorPage: '500',
        notFoundPage: '404',
        resource: [] // 需要预先加载的资源
      }, options);
      // 记录已经加载的tag
      this.tagMounted = {};
      // 合并组件
      this.route = route;
      this.xhr = xhr;
      this.utils = {
        cookie: cookie
      };
      // 初始化操作
      this.init();
      this.instance = this;
    }
    return this.instance;
  }

  init(){
    const cf = this.config;
    // 初始化必要资源
    cf.resource.push(this.config.env);
    cacheJSON(`${cf.staticBase}${cf.id}.json`, {
      force: cf.env !== 'pro'
    })
    .done(resp => {
      // 记录方便不刷新情况下获取
      this.loaderJSON = resp;
      Loader.alias(this.loaderJSON, cf.resource)
      .then(files => {
        // 开始初始化路由
        route.base(cf.routeBase);
        // 路由解析方式
        route.parser(path => {
          const raw = path.split('?'),
            uri = raw[0].split('/'),
            qs = raw[1];
          if (qs) uri.push(search2obj(qs));
          return uri;
        });
        // 设置路由控制
        this.on('route::change', params => {
          let
            page = params[0] || cf.indexPage,
            pageFile = `${cf.staticBase}riot/${cf.id}/${page}.js`,
            tagName = `${cf.id}-${page}`;
          this.route.params = params;
          Loader.batch(pageFile).then(() => {
            try{
              let tag = riot.mount(cf.mountPage, tagName)[0],
                ctags = (tag) => {
                  for(let childTagName in tag.tags){
                    this.tagMounted[childTagName] = tag.tags[childTagName];
                    ctags(tag.tags[childTagName]);
                  }
                };
              this.tagMounted[tagName] = tag;
              ctags(tag);
            } catch(e) {
              window.location.replace(
                `${cf.routeBase}/${cf.errorPage}?message=${e.message}`
              );
              this.err(e);
            }
          }).catch(() => {
            window.location.replace(cf.routeBase+'/'+cf.notFoundPage);
          });
        });
        // 开始监听路由变化
        route((...args) => {
          this.emit('route::change', args);
        });
        // 启动路由
        route.start(true);

        // 将项目实例导入riot全局app对象
        riot.mixin({ app: this });

        this.emit('init::done', files);
      })
      .catch(files => {
        this.emit('init::fail', files);
      });
    });

  }

  /**
   * 信息打印
   */
  log(...args){
    return this.config.dev !== 'pro' ?
      window.console && window.console.log(...args) : null;
  }
  err(...args){
    return window.console && window.console.error(...args);
  }

  /**
   * 适配项目接口
   */
  api(){}

  /**
   * 追加资源载入
   */
  addResource(resName){
    let existRes;
    if(!this.loaderJSON)
      return Promise.reject();
    if(this.loaderJSON[resName])
      existRes = resName;
    else if(this.loaderJSON[`${resName}.${this.config.env}`])
      existRes = `${resName}.${this.config.env}`;
    return Loader.alias(this.loaderJSON, [existRes]);
  }

}
<|endoftext|>