<commit_before>var text = document.getElementById('textArea');
var sumbit = document.getElementById('submitButtonArea');

function arrows() {
   thingie = '

';
   // row 1
   thingie += '

	 <button onclick="up()"> ⇑ </button>		';
   thingie += '<button onclick="talk()">talk</button>	';
   thingie += '<button onclick="items()">items</button>
';
   // row 2
   thingie += '
<button onclick="left()">⇐</button>	';
   thingie += '<button onclick="down()"> ⇓ </button>	';
   thingie += '<button onclick="right()">⇒</button>	';
   thingie += '<button onclick="check()">check</button>	';
   thingie += '<button onclick="stats()">status</button>	';
   thingie += '

';

   sumbit.innerHTML = thingie;
}

function dialog(n) {
  var thingie = '';
  var buttons = '';
  switch(n) {
    case 1:
      thingie = 'Fred Paz: Our world has been invaded by aliens. They have been here for centuries. ';
      thingie += 'They have brainwashed much of the populus to believe that they are not capable of doing mathematics. ';
      thingie += 'We have been fortunate enough to have a segment of the population that has been immune to this sinister ';
      thingie += 'plot, and we were able to carry on without too many hiccups in the past.';
      text.innerHTML = thingie;
      buttons = '<button onclick="dialog(3)">Continue</button> <button onclick="dialog(2)">Ask to be dismissed.</button>';
      sumbit.innerHTML = buttons;
      break;
    case 2:
      thingie = 'Fred Paz: That is understandable. Please return when you are ready.';
      text.innerHTML = thingie;
      arrows();
      break;
    case 3:
      thingie = 'Fred Paz: Unfortunately, the aliens have hacked into our cell phones and mobile devices and have been using ';
      thingie += 'the electronic signals from these devices to convince people that they do not need to know how to do math. ';
      thingie += 'This has created a dire problem for our future. It will not be long before the aliens take over.';
      text.innerHTML = thingie;
      buttons = '<button onclick="dialog(3.1)">Continue</button> <button onclick="dialog(2)">Ask to be dismissed.</button>';
      sumbit.innerHTML = buttons;
      break;
    case 3.1:
      thingie = "Fred Paz: We must work to overcome the alien's brainwashing. ";
      thingie += 'Unfortunately, the people who dearly need our help will fight against our efforts.';
      thingie += 'Like the incredibly long fight scene in the movie They Live, the most difficult fight will be ';
      thingie += 'to convince people to challenge their negative thoughts on mathematics. ';
      thingie += 'However, defeating the alines will be a cakewalk  once we do. ';
      thingie += "At least that's what happened in They Live.";
      thingie += "You've seen the movie right?";
      text.innerHTML = thingie;
      buttons = '<button onclick="dialog(4)">Yes</button> <button onclick="dialog(5)">No</button>';
      sumbit.innerHTML = buttons;
      break;
    case 4:
      thingie = "Fred Paz: No, I am not going to give you a pair of sunglasses. ";
      thingie += "What gave you that idea? ";
      thingie += 'However, I do have a business card with the url for ';

      thingie += 'withmathican.com
';
      thingie += '(You recieve the With Math I Can Business Card)
';
      player.items.push({'item':'WMIC card',
        'n':1,
        'desc':'A business card with the withMathIcan.com url. You can carry it in your right hand. Grants 9 attack, 6 defense, and 6 evasion.',
        'atk':9,
        'def':6,
        'eva':6,
         use(){
           text.innerHTML = 'You carry your With Math I Can card in your right hand.';
           player.rightHand = {'item':'WMIC card','atk':9,'def':6,'eva':6};
           player.atk = player.leftHand.atk + player.rightHand.atk;
           player.def = player.head.def + player.leftHand.def + player.rightHand.def + player.torso.def;
           player.def += player.legs.def + player.feet.def;
           player.eva = player.head.eva + player.leftHand.eva + player.rightHand.eva + player.torso.eva;
           player.eva += player.legs.eva + player.feet.eva;
         }
      });
      thingie += " Would you like to equip it?";
      text.innerHTML = thingie;
      buttons = '<button onclick="dialog(6)">Yes</button> <button onclick="dialog(7)">No</button>';
      sumbit.innerHTML = buttons;
      player.questLog.push('Talked to Fred Paz.');
      break;

  case 5:
      thingie = "Fred Paz: I am dreadfully sorry. I did not mean to spoil the movie. ";
      thingie += 'However, I would still recommend watching it.';
      thingie += "With your parents' permission of course.";
      text.innerHTML = thingie;
      buttons = '<button onclick="dialog(5)">Continue</button>';
      sumbit.innerHTML = buttons;
      break;

  case 6:
       thingie = '(You carry your With Math I Can card in your right hand.)
';
       player.rightHand = {'item':'WMIC card','atk':9,'def':6,'eva':6};
       player.atk = player.leftHand.atk + player.rightHand.atk;
       player.def = player.head.def + player.leftHand.def + player.rightHand.def + player.torso.def;
       player.def += player.legs.def + player.feet.def;
       player.eva = player.head.eva + player.leftHand.eva + player.rightHand.eva + player.torso.eva;
       player.eva += player.legs.eva + player.feet.eva;

   case 7:
       thingie += 'Fred Paz: Alright, now get out there and change some minds about math.';
       text.innerHTML = thingie;
       arrows();
       break;
     default:
        thingie = 'Error: My name is Error.';
        text.innerHTML = thingie;
        arrows();
  }

}
<commit_msg>Update dialog.js<commit_after>var text = document.getElementById('textArea');
var sumbit = document.getElementById('submitButtonArea');

function arrows() {
   thingie = '

';
   // row 1
   thingie += '

	 <button onclick="up()"> ⇑ </button>		';
   thingie += '<button onclick="talk()">talk</button>	';
   thingie += '<button onclick="items()">items</button>
';
   // row 2
   thingie += '
<button onclick="left()">⇐</button>	';
   thingie += '<button onclick="down()"> ⇓ </button>	';
   thingie += '<button onclick="right()">⇒</button>	';
   thingie += '<button onclick="check()">check</button>	';
   thingie += '<button onclick="stats()">status</button>	';
   thingie += '

';

   sumbit.innerHTML = thingie;
}

function dialog(n) {
  var thingie = '';
  var buttons = '';
  switch(n) {
    case 1:
      thingie = 'Fred Paz: Our world has been invaded by aliens. They have been here for centuries. ';
      thingie += 'They have brainwashed much of the populus to believe that they are not capable of doing mathematics. ';
      thingie += 'We have been fortunate enough to have a segment of the population that has been immune to this sinister ';
      thingie += 'plot, and we were able to carry on without too many hiccups in the past.';
      text.innerHTML = thingie;
      buttons = '<button onclick="dialog(3)">Continue</button> <button onclick="dialog(2)">Ask to be dismissed.</button>';
      sumbit.innerHTML = buttons;
      break;
    case 2:
      thingie = 'Fred Paz: That is understandable. Please return when you are ready.';
      text.innerHTML = thingie;
      arrows();
      break;
    case 3:
      thingie = 'Fred Paz: Unfortunately, the aliens have hacked into our cell phones and mobile devices and have been using ';
      thingie += 'the electronic signals from these devices to convince people that they do not need to know how to do math. ';
      thingie += 'This has created a dire problem for our future. It will not be long before the aliens take over.';
      text.innerHTML = thingie;
      buttons = '<button onclick="dialog(3.1)">Continue</button> <button onclick="dialog(2)">Ask to be dismissed.</button>';
      sumbit.innerHTML = buttons;
      break;
    case 3.1:
      thingie = "Fred Paz: We must work to overcome the alien's brainwashing. ";
      thingie += 'Unfortunately, the people who dearly need our help will fight against our efforts.';
      thingie += 'Like the incredibly long fight scene in the movie They Live, the most difficult fight will be ';
      thingie += 'to convince people to challenge their negative thoughts on mathematics. ';
      thingie += 'However, defeating the alines will be a cakewalk  once we do. ';
      thingie += "At least that's what happened in They Live.";
      thingie += "You've seen the movie right?";
      text.innerHTML = thingie;
      buttons = '<button onclick="dialog(4)">Yes</button> <button onclick="dialog(5)">No</button>';
      sumbit.innerHTML = buttons;
      break;
    case 4:
      thingie = "Fred Paz: No, I am not going to give you a pair of sunglasses. ";
      thingie += "What gave you that idea? ";
      thingie += 'However, I do have a business card with the url for ';

      thingie += 'withmathican.com
';
      thingie += '(You recieve the With Math I Can Business Card)
';
      player.items.push({'item':'WMIC card',
        'n':1,
        'desc':'A business card with the withMathIcan.com url. You can carry it in your right hand. Grants 9 attack, 6 defense, and 6 evasion.',
        'atk':9,
        'def':6,
        'eva':6,
         use(){
           text.innerHTML = 'You carry your With Math I Can card in your right hand.';
           player.rightHand = {'item':'WMIC card','atk':9,'def':6,'eva':6};
           player.atk = player.leftHand.atk + player.rightHand.atk;
           player.def = player.head.def + player.leftHand.def + player.rightHand.def + player.torso.def;
           player.def += player.legs.def + player.feet.def;
           player.eva = player.head.eva + player.leftHand.eva + player.rightHand.eva + player.torso.eva;
           player.eva += player.legs.eva + player.feet.eva;
         }
      });
      thingie += " Would you like to equip it?";
      text.innerHTML = thingie;
      buttons = '<button onclick="dialog(6)">Yes</button> <button onclick="dialog(7)">No</button>';
      sumbit.innerHTML = buttons;
      player.questLog.push('Talked to Fred Paz.');
      break;

  case 5:
      thingie = "Fred Paz: I am dreadfully sorry. I did not mean to spoil the movie. ";
      thingie += 'However, I would still recommend watching it. ';
      thingie += "With your parents' permission of course.";
      text.innerHTML = thingie;
      buttons = '<button onclick="dialog(4)">Continue</button>';
      sumbit.innerHTML = buttons;
      break;

  case 6:
       thingie = '(You carry your With Math I Can card in your right hand.)
';
       player.rightHand = {'item':'WMIC card','atk':9,'def':6,'eva':6};
       player.atk = player.leftHand.atk + player.rightHand.atk;
       player.def = player.head.def + player.leftHand.def + player.rightHand.def + player.torso.def;
       player.def += player.legs.def + player.feet.def;
       player.eva = player.head.eva + player.leftHand.eva + player.rightHand.eva + player.torso.eva;
       player.eva += player.legs.eva + player.feet.eva;

   case 7:
       thingie += 'Fred Paz: Alright, now get out there and change some minds about math.';
       text.innerHTML = thingie;
       arrows();
       break;
     default:
        thingie = 'Error: My name is Error.';
        text.innerHTML = thingie;
        arrows();
  }

}
<|endoftext|>


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

import {
  ALT_TEXT,
  CONFIGURATION_EVENT,
  ICON_SIZE,
  ORIGIN,
} from '../constants';
import {ConfigManager} from '../config-manager';

import {createElementWithAttributes} from '../../../../src/dom';
import {dict} from '../../../../src/utils/object';
import {getConfigManager} from '../amp-addthis';
import {getDetailsForMeta, getMetaElements} from './../addthis-utils/meta';
import {getKeywordsString} from './../addthis-utils/classify';
import {isDateInFuture} from '../addthis-utils/cuid';
import {toArray} from '../../../../src/types';

describes.realWin('amp-addthis', {
  amp: {
    extensions: ['amp-addthis'],
  },
}, env => {
  const configManager = getConfigManager();
  const pubId = 'ra-5988ef04ee1db125';
  const widgetId = '29nf';
  const floatingPubId = 'ra-5b2947993c86010c';
  const floatingWidgetId = '4hvd';
  let doc;
  let registerStub;
  let unregisterStub;

  beforeEach(() => {
    doc = env.win.document;
    registerStub = env.sandbox.stub(configManager, 'register');
    unregisterStub = env.sandbox.stub(configManager, 'unregister');
  });

  function getAT(configuration, opt_responsive, opt_beforeLayoutCallback) {
    const {pubId, widgetId, shareConfig = {}} = configuration;
    const elementAttributes = dict({
      'data-pub-id': pubId,
      'data-widget-id': widgetId,
      'width': 111,
      'height': 222,
    });
    Object.keys(shareConfig).forEach(key => {
      elementAttributes[`data-share-${key}`] = shareConfig[key];
    });
    const at = createElementWithAttributes(
        doc,
        'amp-addthis',
        elementAttributes
    );
    if (opt_responsive) {
      at.setAttribute('layout', 'responsive');
    }
    doc.body.appendChild(at);
    return at.build().then(() => {
      if (opt_beforeLayoutCallback) {
        opt_beforeLayoutCallback(at);
      }
      // Reference to the promise is kept here so that it can be passed on to
      // and returned by the final callback (for the sake of tests), rather than
      // just added to the chain.
      const atIframeLoadPromise = at.layoutCallback();
      return atIframeLoadPromise.then(() => ({atIframeLoadPromise}));
    }).then(({atIframeLoadPromise}) => ({at, atIframeLoadPromise}));
  }

  function testIframe(iframe) {
    expect(iframe).to.not.equal(null);
    expect(iframe.getAttribute('src'))
        .to.equal(`${ORIGIN}/dc/amp-addthis.html`);
    expect(iframe.getAttribute('title')).to.equal(ALT_TEXT);
  }

  it('renders the iframe', () => {
    return getAT({pubId, widgetId}).then(({at}) => {
      testIframe(at.querySelector('iframe'));
    });
  });

  it('renders a placeholder with an amp-img', () => {
    return getAT({pubId, widgetId}).then(({at}) => {
      const placeholder = at.querySelector('[placeholder]');
      const ampImg = placeholder.querySelector('amp-img');

      expect(placeholder).to.not.equal(null);
      expect(ampImg).to.not.equal(null);
      expect(ampImg.getAttribute('src')).to.match(/cache\.addthiscdn\.com/);
      expect(ampImg.getAttribute('width')).to.equal(ICON_SIZE);
      expect(ampImg.getAttribute('height')).to.equal(ICON_SIZE);
      expect(ampImg.getAttribute('alt')).to.equal(ALT_TEXT);
    });
  });

  it('requires data-pub-id', () => {
    expect(getAT({pubId: '', widgetId})).to.be.rejectedWith(
        /The data\-pub\-id attribute is required for/
    );
  });

  it('requires data-widget-id', () => {
    expect(getAT({pubId, widgetId: ''})).to.be.rejectedWith(
        /The data\-widget\-id attribute is required for/
    );
  });

  it('removes the iframe after unlayoutCallback', () => {
    return getAT({pubId, widgetId}).then(({at}) => {
      const obj = at.implementation_;
      testIframe(at.querySelector('iframe'));
      obj.unlayoutCallback();
      expect(at.querySelector('iframe')).to.equal(null);
      expect(obj.iframe_).to.equal(null);
    });
  });

  it('registers the frame with the configManager on layout', () => {
    return getAT({pubId, widgetId, shareConfig: {}}).then(() => {
      expect(registerStub.calledOnce).to.equal(true);
    });
  });

  it('unregisters the frame with the configManager on unlayoutCallback', () => {
    return getAT({pubId, widgetId}).then(({at}) => {
      const obj = at.implementation_;
      obj.unlayoutCallback();

      expect(unregisterStub.calledOnce).to.equal(true);
    });
  });

  it('accepts and stores shareConfig data via custom attributes', () => {
    const shareConfig = {
      url: 'https://www.addthis.com',
      title: 'AddThis Website Tools',
      media: 'https://i.imgur.com/yNlQWRM.jpg',
      description: 'This is a fake page.',
    };

    return getAT({pubId, widgetId, shareConfig}).then(({at}) => {
      expect(Object.keys(shareConfig).length).to.equal(4);
      Object.keys(shareConfig).forEach(key => {
        expect(at.getAttribute(`data-share-${key}`)).to.equal(shareConfig[key]);
      });
    });
  });

  it('defaults to sharing ownerDocument\'s title and url', () => {
    return getAT({pubId, widgetId}).then(({at}) => {
      const obj = at.implementation_;
      const {shareConfig_} = obj;
      expect(shareConfig_.title).to.equal(doc.title);
      expect(shareConfig_.url).to.equal(doc.location.href);
    });
  });

  it('registers a view at most once per "session"', done => {
    const testConfigManager = new ConfigManager();
    let numPendingRequests = 0;
    let numViewsRegistered = 0;

    return new Promise((resolve, reject) => {
      done();
      const mockIframe = {
        contentWindow: {
          postMessage: json => {
            let receivedJSON;

            numPendingRequests--;

            try {
              receivedJSON = JSON.parse(json);
            } catch (ex) {
              reject(ex);
            }

            if (receivedJSON.registerView === true) {
              numViewsRegistered++;
            }

            if (numPendingRequests === 0) {
              expect(numViewsRegistered).to.equal(1);
              resolve();
            }
          },
        },
      };

      // Fake a number of registered elements.
      for (let i = 0; i < 3; i++) {
        numPendingRequests++;
        testConfigManager.register({
          pubId,
          widgetId,
          iframe: mockIframe,
          iframeLoadPromise: Promise.resolve(),
        });
      }
    });
  });

  it('sends expected JSON config to the iframe after registering', () => {
    const testConfigManager = new ConfigManager();
    const shareConfig = {
      title: 'lol',
    };
    const expectedString = JSON.stringify({
      event: CONFIGURATION_EVENT,
      shareConfig,
      pubId: '1234',
      widgetId,
      configRequestStatus: 0,
      dashboardConfig: undefined,
    });

    return new Promise((resolve, reject) => {
      const mockIframe = {
        contentWindow: {
          postMessage: (json, origin) => {
            try {
              expect(json).to.equal(expectedString);
              expect(origin).to.equal(ORIGIN);
            } catch (ex) {
              reject(ex);
            } finally {
              testConfigManager.unregister({
                pubId,
                iframe: mockIframe,
              });
            }
            resolve();
          },
        },
      };

      testConfigManager.register({
        pubId: '1234',
        widgetId,
        shareConfig,
        iframe: mockIframe,
        iframeLoadPromise: Promise.resolve(),
      });
    });
  });

  it('requests a config exactly once per pubId', () => {
    const testConfigManager = new ConfigManager();
    const firstPubId = '111';
    const secondPubId = '222';
    const thirdPubId = '333';
    const numConfigsRequested = {
      [firstPubId]: 0,
      [secondPubId]: 0,
      [thirdPubId]: 0,
    };
    let numPendingRequests = 0;

    return new Promise((resolve, reject) => {
      const mockIframe = {
        contentWindow: {
          postMessage: json => {
            let receivedJSON;

            numPendingRequests--;

            try {
              receivedJSON = JSON.parse(json);
            } catch (ex) {
              reject(ex);
            }

            if (receivedJSON.configRequestStatus === 0) {
              numConfigsRequested[receivedJSON.pubId]++;
            }

            if (numPendingRequests === 0) {
              expect(numConfigsRequested[firstPubId]).to.equal(1);
              expect(numConfigsRequested[secondPubId]).to.equal(1);
              expect(numConfigsRequested[thirdPubId]).to.equal(1);
              resolve();
            }
          },
        },
      };

      // Fake a number of registered elements.
      // Registers firstPubId once, secondPubId twice, and thirdPubId thrice.
      for (let i = 0; i < 6; i++) {
        numPendingRequests++;
        testConfigManager.register({
          pubId: i === 0 ? firstPubId : (i < 3 ? secondPubId : thirdPubId),
          widgetId,
          iframe: mockIframe,
          iframeLoadPromise: Promise.resolve(),
        });
      }
    });
  });

  it('gets meta elements from document', () => {
    const meta1 = document.createElement('meta');
    window.document.head.appendChild(meta1);
    expect(toArray(getMetaElements(window.document)).length).to.equal(1);
    const meta2 = document.createElement('meta');
    window.document.head.appendChild(meta2);
    expect(toArray(getMetaElements(window.document)).length).to.equal(2);
  });

  it('gets 0 meta elements from document when there are none', () => {
    expect(toArray(getMetaElements(window.document)).length).to.equal(0);
  });

  it('gets details for meta tag with name in lower case', () => {
    const meta1 = document.createElement('meta');
    meta1.name = 'KEYWORDS';
    meta1.content = 'this,that';
    const details = getDetailsForMeta(meta1);
    expect(details.name).to.equal(meta1.name.toLowerCase());
    expect(details.name).not.to.equal(meta1.name);
    expect(details.content).to.equal(meta1.content);
  });

  it('gets keywords from meta tags', () => {
    const meta1 = document.createElement('meta');
    meta1.name = 'keywords';
    meta1.content = 'this,that';
    expect(getKeywordsString([meta1])).to.equal(meta1.content);
    const meta2 = document.createElement('meta');
    meta2.name = 'keywords';
    meta2.content = 'a,b';
    expect(getKeywordsString([meta1, meta2]))
        .to.equal(`${meta1.content},${meta2.content}`);
  });

  it('can tell future dates from past dates', () => {
    const nextYear = new Date();
    nextYear.setFullYear(nextYear.getFullYear() + 1);
    expect(isDateInFuture(nextYear)).to.equal(true);

    const nextMonth = new Date();
    nextMonth.setMonth(nextMonth.getMonth() + 1);
    expect(isDateInFuture(nextMonth)).to.equal(true);

    const tomorrow = new Date();
    tomorrow.setDate(tomorrow.getDate() + 1);
    expect(isDateInFuture(tomorrow)).to.equal(true);

    const today = new Date();
    expect(isDateInFuture(today)).to.equal(false);

    const yesterday = new Date();
    yesterday.setDate(yesterday.getDate() - 1);
    expect(isDateInFuture(yesterday)).to.equal(false);

    const lastYear = new Date();
    lastYear.setFullYear(lastYear.getFullYear() - 1);
    expect(isDateInFuture(lastYear)).to.equal(false);
  });

  it('gives id for iframe if floating tool loaded', () => {
    return getAT({pubId: floatingPubId, widgetId: floatingWidgetId}).then(
        ({at}) => {
          testIframe(at.querySelector('iframe'));
          const iframe = at.querySelector('iframe');
          expect(iframe.getAttribute('id')).to.equal(floatingWidgetId);
        }
    );
  });
});
<commit_msg>fixes some unit tests that were previously failing (#19594)<commit_after>/**
 * Copyright 2018 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {
  ALT_TEXT,
  CONFIGURATION_EVENT,
  ICON_SIZE,
  ORIGIN,
} from '../constants';
import {ConfigManager} from '../config-manager';

import {createElementWithAttributes} from '../../../../src/dom';
import {dict} from '../../../../src/utils/object';
import {getConfigManager} from '../amp-addthis';
import {getDetailsForMeta, getMetaElements} from './../addthis-utils/meta';
import {getKeywordsString} from './../addthis-utils/classify';
import {isDateInFuture} from '../addthis-utils/cuid';
import {toArray} from '../../../../src/types';

describes.realWin('amp-addthis', {
  amp: {
    extensions: ['amp-addthis'],
  },
}, env => {
  const configManager = getConfigManager();
  const pubId = 'ra-5988ef04ee1db125';
  const widgetId = '29nf';
  const floatingPubId = 'ra-5b2947993c86010c';
  const floatingWidgetId = '4hvd';
  let doc;
  let registerStub;
  let unregisterStub;

  beforeEach(() => {
    doc = env.win.document;
    registerStub = env.sandbox.stub(configManager, 'register');
    unregisterStub = env.sandbox.stub(configManager, 'unregister');
  });

  function getAT(configuration, opt_responsive, opt_beforeLayoutCallback) {
    const {pubId, widgetId, shareConfig = {}} = configuration;
    const elementAttributes = dict({
      'data-pub-id': pubId,
      'data-widget-id': widgetId,
      'width': 111,
      'height': 222,
    });
    Object.keys(shareConfig).forEach(key => {
      elementAttributes[`data-share-${key}`] = shareConfig[key];
    });
    const at = createElementWithAttributes(
        doc,
        'amp-addthis',
        elementAttributes
    );
    if (opt_responsive) {
      at.setAttribute('layout', 'responsive');
    }
    doc.body.appendChild(at);
    return at.build().then(() => {
      if (opt_beforeLayoutCallback) {
        opt_beforeLayoutCallback(at);
      }
      // Reference to the promise is kept here so that it can be passed on to
      // and returned by the final callback (for the sake of tests), rather than
      // just added to the chain.
      const atIframeLoadPromise = at.layoutCallback();
      return atIframeLoadPromise.then(() => ({atIframeLoadPromise}));
    }).then(({atIframeLoadPromise}) => ({at, atIframeLoadPromise}));
  }

  function testIframe(iframe) {
    expect(iframe).to.not.equal(null);
    expect(iframe.getAttribute('src'))
        .to.equal(`${ORIGIN}/dc/amp-addthis.html`);
    expect(iframe.getAttribute('title')).to.equal(ALT_TEXT);
  }

  it('renders the iframe', () => {
    return getAT({pubId, widgetId}).then(({at}) => {
      testIframe(at.querySelector('iframe'));
    });
  });

  it('renders a placeholder with an amp-img', () => {
    return getAT({pubId, widgetId}).then(({at}) => {
      const placeholder = at.querySelector('[placeholder]');
      const ampImg = placeholder.querySelector('amp-img');

      expect(placeholder).to.not.equal(null);
      expect(ampImg).to.not.equal(null);
      expect(ampImg.getAttribute('src')).to.match(/cache\.addthiscdn\.com/);
      expect(ampImg.getAttribute('width')).to.equal(ICON_SIZE);
      expect(ampImg.getAttribute('height')).to.equal(ICON_SIZE);
      expect(ampImg.getAttribute('alt')).to.equal(ALT_TEXT);
    });
  });

  it('requires data-pub-id', () => {
    allowConsoleError(() => {
      expect(getAT({pubId: '', widgetId})).to.be.rejectedWith(
          /The data\-pub\-id attribute is required for/
      );
    });
  });

  it('requires data-widget-id', () => {
    allowConsoleError(() => {
      expect(getAT({pubId, widgetId: ''})).to.be.rejectedWith(
          /The data\-widget\-id attribute is required for/
      );
    });
  });

  it('removes the iframe after unlayoutCallback', () => {
    return getAT({pubId, widgetId}).then(({at}) => {
      const obj = at.implementation_;
      testIframe(at.querySelector('iframe'));
      obj.unlayoutCallback();
      expect(at.querySelector('iframe')).to.equal(null);
      expect(obj.iframe_).to.equal(null);
    });
  });

  it('registers the frame with the configManager on layout', () => {
    return getAT({pubId, widgetId, shareConfig: {}}).then(() => {
      expect(registerStub.calledOnce).to.equal(true);
    });
  });

  it('unregisters the frame with the configManager on unlayoutCallback', () => {
    return getAT({pubId, widgetId}).then(({at}) => {
      const obj = at.implementation_;
      obj.unlayoutCallback();

      expect(unregisterStub.calledOnce).to.equal(true);
    });
  });

  it('accepts and stores shareConfig data via custom attributes', () => {
    const shareConfig = {
      url: 'https://www.addthis.com',
      title: 'AddThis Website Tools',
      media: 'https://i.imgur.com/yNlQWRM.jpg',
      description: 'This is a fake page.',
    };

    return getAT({pubId, widgetId, shareConfig}).then(({at}) => {
      expect(Object.keys(shareConfig).length).to.equal(4);
      Object.keys(shareConfig).forEach(key => {
        expect(at.getAttribute(`data-share-${key}`)).to.equal(shareConfig[key]);
      });
    });
  });

  it('defaults to sharing ownerDocument\'s title and url', () => {
    return getAT({pubId, widgetId}).then(({at}) => {
      const obj = at.implementation_;
      const {shareConfig_} = obj;
      expect(shareConfig_.title).to.equal(doc.title);
      expect(shareConfig_.url).to.equal(doc.location.href);
    });
  });

  it('registers a view at most once per "session"', done => {
    const testConfigManager = new ConfigManager();
    let numPendingRequests = 0;
    let numViewsRegistered = 0;

    return new Promise((resolve, reject) => {
      done();
      const mockIframe = {
        contentWindow: {
          postMessage: json => {
            let receivedJSON;

            numPendingRequests--;

            try {
              receivedJSON = JSON.parse(json);
            } catch (ex) {
              reject(ex);
            }

            if (receivedJSON.registerView === true) {
              numViewsRegistered++;
            }

            if (numPendingRequests === 0) {
              expect(numViewsRegistered).to.equal(1);
              resolve();
            }
          },
        },
      };

      // Fake a number of registered elements.
      for (let i = 0; i < 3; i++) {
        numPendingRequests++;
        testConfigManager.register({
          pubId,
          widgetId,
          iframe: mockIframe,
          iframeLoadPromise: Promise.resolve(),
        });
      }
    });
  });

  it('sends expected JSON config to the iframe after registering', () => {
    const testConfigManager = new ConfigManager();
    const shareConfig = {
      title: 'lol',
    };
    const expectedString = JSON.stringify({
      event: CONFIGURATION_EVENT,
      shareConfig,
      pubId: '1234',
      widgetId,
      configRequestStatus: 0,
      dashboardConfig: undefined,
    });

    return new Promise((resolve, reject) => {
      const mockIframe = {
        contentWindow: {
          postMessage: (json, origin) => {
            try {
              expect(json).to.equal(expectedString);
              expect(origin).to.equal(ORIGIN);
            } catch (ex) {
              reject(ex);
            } finally {
              testConfigManager.unregister({
                pubId,
                iframe: mockIframe,
              });
            }
            resolve();
          },
        },
      };

      testConfigManager.register({
        pubId: '1234',
        widgetId,
        shareConfig,
        iframe: mockIframe,
        iframeLoadPromise: Promise.resolve(),
      });
    });
  });

  it('requests a config exactly once per pubId', () => {
    const testConfigManager = new ConfigManager();
    const firstPubId = '111';
    const secondPubId = '222';
    const thirdPubId = '333';
    const numConfigsRequested = {
      [firstPubId]: 0,
      [secondPubId]: 0,
      [thirdPubId]: 0,
    };
    let numPendingRequests = 0;

    return new Promise((resolve, reject) => {
      const mockIframe = {
        contentWindow: {
          postMessage: json => {
            let receivedJSON;

            numPendingRequests--;

            try {
              receivedJSON = JSON.parse(json);
            } catch (ex) {
              reject(ex);
            }

            if (receivedJSON.configRequestStatus === 0) {
              numConfigsRequested[receivedJSON.pubId]++;
            }

            if (numPendingRequests === 0) {
              expect(numConfigsRequested[firstPubId]).to.equal(1);
              expect(numConfigsRequested[secondPubId]).to.equal(1);
              expect(numConfigsRequested[thirdPubId]).to.equal(1);
              resolve();
            }
          },
        },
      };

      // Fake a number of registered elements.
      // Registers firstPubId once, secondPubId twice, and thirdPubId thrice.
      for (let i = 0; i < 6; i++) {
        numPendingRequests++;
        testConfigManager.register({
          pubId: i === 0 ? firstPubId : (i < 3 ? secondPubId : thirdPubId),
          widgetId,
          iframe: mockIframe,
          iframeLoadPromise: Promise.resolve(),
        });
      }
    });
  });

  it('gets meta elements from document', () => {
    const meta1 = document.createElement('meta');
    window.document.head.appendChild(meta1);
    expect(toArray(getMetaElements(window.document)).length).to.equal(1);
    const meta2 = document.createElement('meta');
    window.document.head.appendChild(meta2);
    expect(toArray(getMetaElements(window.document)).length).to.equal(2);
  });

  it('gets 0 meta elements from document when there are none', () => {
    expect(toArray(getMetaElements(window.document)).length).to.equal(0);
  });

  it('gets details for meta tag with name in lower case', () => {
    const meta1 = document.createElement('meta');
    meta1.name = 'KEYWORDS';
    meta1.content = 'this,that';
    const details = getDetailsForMeta(meta1);
    expect(details.name).to.equal(meta1.name.toLowerCase());
    expect(details.name).not.to.equal(meta1.name);
    expect(details.content).to.equal(meta1.content);
  });

  it('gets keywords from meta tags', () => {
    const meta1 = document.createElement('meta');
    meta1.name = 'keywords';
    meta1.content = 'this,that';
    expect(getKeywordsString([meta1])).to.equal(meta1.content);
    const meta2 = document.createElement('meta');
    meta2.name = 'keywords';
    meta2.content = 'a,b';
    expect(getKeywordsString([meta1, meta2]))
        .to.equal(`${meta1.content},${meta2.content}`);
  });

  it('can tell future dates from past dates', () => {
    const nextYear = new Date();
    nextYear.setFullYear(nextYear.getFullYear() + 1);
    expect(isDateInFuture(nextYear)).to.equal(true);

    const nextMonth = new Date();
    nextMonth.setMonth(nextMonth.getMonth() + 1);
    expect(isDateInFuture(nextMonth)).to.equal(true);

    const tomorrow = new Date();
    tomorrow.setDate(tomorrow.getDate() + 1);
    expect(isDateInFuture(tomorrow)).to.equal(true);

    const today = new Date();
    expect(isDateInFuture(today)).to.equal(false);

    const yesterday = new Date();
    yesterday.setDate(yesterday.getDate() - 1);
    expect(isDateInFuture(yesterday)).to.equal(false);

    const lastYear = new Date();
    lastYear.setFullYear(lastYear.getFullYear() - 1);
    expect(isDateInFuture(lastYear)).to.equal(false);
  });

  it('gives id for iframe if floating tool loaded', () => {
    return getAT({pubId: floatingPubId, widgetId: floatingWidgetId}).then(
        ({at}) => {
          testIframe(at.querySelector('iframe'));
          const iframe = at.querySelector('iframe');
          expect(iframe.getAttribute('id')).to.equal(floatingWidgetId);
        }
    );
  });
});
<|endoftext|>


<commit_before>H5P.InteractiveVideoDialog = (function ($, EventDispatcher) {

  /**
   * Controls the dialog in the interactive video.
   *
   * @class H5P.InteractiveVideoDialog
   * @param {H5P.jQuery} $container for dialog
   * @param {H5P.jQuery} $videoWrapper needed for positioning of dialog
   */
  function Dialog($container, $videoWrapper) {
    var self = this;

    // Initialize event inheritance
    EventDispatcher.call(self);

    // Create DOM elements for dialog
    var $wrapper = $('<div/>', {
      'class': 'h5p-dialog-wrapper h5p-ie-transparent-background h5p-hidden',
      on: {
        click: function () {
          if (!self.disableOverlay)  {
            self.close();
          }
        }
      }
    });
    var $dialog = $('<div/>', {
      'class': 'h5p-dialog h5p-big',
      on: {
        click: function (event) {
          event.stopPropagation();
        }
      }
    }).appendTo($wrapper);

    // Create title bar
    var $titleBar = $('<div/>', {
      'class': 'h5p-dialog-titlebar',
      appendTo: $dialog
    });
    var $title = $('<div/>', {
      'class': 'h5p-dialog-title',
      appendTo: $titleBar
    });
    var $close = $('<div/>', {
      'class': 'h5p-dialog-close',
      tabindex: 0,
      on: {
        click: function () {
          if (event.which === 1) {
            self.close();
          }
        },
        keypress: function (event) {
          if (event.which === 32) {
            self.close();
          }
        }
      },
      appendTo: $titleBar
    });

    // Used instead of close
    var $customButtons;

    // Create inner DOM elements for dialog
    var $inner = $('<div/>', {
      'class': 'h5p-dialog-inner'
    }).appendTo($dialog);

    // Add all to DOM
    $wrapper.appendTo($container);

    /**
     * Reset the dialog's positioning
     *
     * @private
     */
    var resetPosition = function () {
      // Reset positioning
      $dialog.css({
        left: '',
        top: '',
        height: '',
        width: '',
        fontSize: '',
        bottom: ''
      });
      $inner.css({
        width: '',
        height: '',
        overflow: ''
      });
    };

    /**
     * Display overlay.
     *
     * @private
     * @param {function} next callback
     */
    var showOverlay = function (next) {
      $wrapper.show();
      setTimeout(function () {
        // Remove class on next tick to ensure css animation
        $wrapper.removeClass('h5p-hidden');
        if (next) {
          next();
        }
      }, 0);
    };

    /**
     * Close overlay.
     *
     * @private
     * @param {function} next callback
     */
    var hideOverlay = function (next) {
      $wrapper.addClass('h5p-hidden');
      setTimeout(function () {
        // Hide when animation is done
        $wrapper.hide();
        if (next) {
          next();
        }
      }, 200);
    };

    /**
     * Opens a new dialog. Displays the given element.
     *
     * @param {H5P.jQuery} $element
     * @param {string} [title] Label for the dialog
     * @param {string} [classes] For styling
     * @param {H5P.jQuery} [$buttons] Use custom buttons for dialog
     */
    self.open = function ($element, title, classes, $buttons) {
      showOverlay();
      $inner.children().detach().end().append($element);

      // Reset positioning
      resetPosition();
      $dialog.addClass('h5p-big');
      $title.attr('class', 'h5p-dialog-title' + (classes ? ' ' + classes : ''));

      // Add label
      if (!title) {
        title = '';
      }
      $title.html(title);

      // Clean up after previous custom buttons
      if ($customButtons) {
        $customButtons.remove();
        $close.show();
      }

      // Add new custom buttons
      if ($buttons) {
        $customButtons = $buttons;

        // Hide default close button
        $close.hide();

        // Add custom buttons
        $buttons.appendTo($titleBar);
      }

      self.resize();

      self.trigger('open');
    };

    self.resize = function () {
      var fontSize = toNum($inner.css('fontSize'));
      var titleBarHeight = ($titleBar.outerHeight() / fontSize);

      // Same as height
      var maxHeight = $container.height();
      // minus dialog margins
      maxHeight -= Number($dialog.css('top').replace('px', '')) * 2;

      $inner.css({
        width: '100%',
        maxHeight: ((maxHeight / fontSize) - titleBarHeight) + 'em',
        marginTop: titleBarHeight + 'em'
      });
      $dialog.css({
        bottom: 'auto',
        maxHeight: ''
      });
    };

    /**
     * Adds a name to the dialog for identifying what it contains.
     *
     * @param {string} machineName Name of library inside dialog.
     */
    self.addLibraryClass = function (machineName) {
      $dialog.attr('data-lib', machineName);
    };

    self.isOpen = function () {
      return $wrapper.is(':visible');
    };

    /**
     * Reposition the currently open dialog relative to the given button.
     *
     * @param {H5P.jQuery} $button
     * @param {Object} [size] Sets a size for the dialog, useful for images.
     */
    self.position = function ($button, size) {
      var minWidth = 100;
      var minHeight = 75;
      resetPosition();
      $dialog.removeClass('h5p-big');
      var titleBarHeight = Number($inner[0].style.marginTop.replace('em', ''));

      if (size) {
        var fontSizeRatio = 16 / toNum($container.css('fontSize'));
        size.width = (size.width * fontSizeRatio);
        size.height = (size.height * fontSizeRatio);

        // Set minimum sizes
        if (size.width < minWidth / 16 * fontSizeRatio) {
          size.width = minWidth / 16 * fontSizeRatio;
        }

        if (size.height < (minHeight / 16 * fontSizeRatio)) {
          size.height = (minHeight / 16 * fontSizeRatio);
        }

        // Use a fixed size
        $dialog.css({
          width: size.width + 'em',
          height: (size.height + titleBarHeight) + 'em'
        });
        $inner.css({
          height: 'calc(100% - ' + titleBarHeight + 'em)',
          width: 'auto',
          overflow: 'hidden'
        });
      }

      var buttonWidth = $button.outerWidth(true);
      var buttonPosition = $button.position();
      var containerWidth = $container.width();
      var containerHeight = $container.height();

      // Position dialog horizontally
      var left = buttonPosition.left;
      var dialogWidth = $dialog.outerWidth(true);

      if (dialogWidth > containerWidth) {
        // If dialog is too big to fit within the container, display as h5p-big instead.
        $dialog.addClass('h5p-big');
        return;
      }

      if (buttonPosition.left > (containerWidth / 2) - (buttonWidth / 2)) {
        // Show on left
        left -= dialogWidth - buttonWidth;
      }

      // Make sure the dialog is within the video on the right.
      if ((left + dialogWidth) > containerWidth) {
        left = containerWidth - dialogWidth;
      }

      var marginLeft = parseInt($videoWrapper.css('marginLeft'));
      if (isNaN(marginLeft)) {
        marginLeft = 0;
      }

      // And finally, make sure we're within bounds on the left hand side too...
      if (left < marginLeft) {
        left = marginLeft;
      }

      // Position dialog vertically
      var marginTop = parseInt($videoWrapper.css('marginTop'));
      if (isNaN(marginTop)) {
        marginTop = 0;
      }

      var top = buttonPosition.top + marginTop;
      var totalHeight = top + $dialog.outerHeight(true);
      if (totalHeight > containerHeight) {
        top -= totalHeight - containerHeight;
      }
      var maxHeight = $container.height() - top + $dialog.height() - $dialog.outerHeight(true);
      // Set dialog size
      $dialog.css({
        top: (top / (containerHeight / 100)) + '%',
        left: (left / (containerWidth / 100)) + '%',
        width: $dialog.width(),
        maxHeight: maxHeight
      });
      $inner.css('maxHeight', maxHeight - $titleBar.outerHeight(true));
    };

    /**
     * Find max available space inside dialog when positioning relative to
     * given button.
     *
     * @param {H5P.jQuery} $button
     * @param {Boolean} fullScreen True if dialog fills whole parent
     * @returns {Object} Attrs: width, height
     */
    self.getMaxSize = function ($button, fullScreen) {
      var buttonWidth = $button.outerWidth(true);
      var buttonPosition = $button.position();
      var containerWidth = $container.width();

      var max = {};
      max.height = Number($inner.css('maxHeight').replace('px', ''));
      if (fullScreen) {
        max.width = containerWidth;
      } else {
        if (buttonPosition.left > (containerWidth / 2) - (buttonWidth / 2)) {
          // Space to the left of the button minus margin
          max.width = buttonPosition.left;
        }
        else {
          // Space to the right of the button minus margin
          max.width = (containerWidth - buttonPosition.left - buttonWidth);
        }
      }

      // Use em
      var fontSize = toNum($container.css('fontSize'));
      max.width = (max.width / fontSize) * (fontSize / 16);
      max.height = (max.height / fontSize) * (fontSize / 16);

      return max;
    };

    /**
     * Scroll to given position in current dialog.
     *
     * @param {number} to Scroll position
     * @param {number} ms Time the animation takes.
     */
    self.scroll = function (to, ms) {
      $inner.stop().animate({
        scrollTop: to
      }, ms);
    };

    /**
     * Close the currently open dialog.
     */
    self.close = function () {
      $wrapper.addClass('h5p-hidden');

      setTimeout(function () {
        $wrapper.hide();
        self.disableOverlay = false;
        $close.show();
      }, 201);

      self.trigger('close');
    };

    /**
     * Open overlay only.
     */
    self.openOverlay = function () {
      self.disableOverlay = true;
      $dialog.hide();
      showOverlay();
    };

    /**
     * Close overlay only.
     */
    self.closeOverlay = function () {
      $wrapper.addClass('h5p-hidden');
      hideOverlay(function () {
        $dialog.show();
        self.disableOverlay = false;
      });
    };

    /**
     * Removes the close button from the current dialog.
     */
    self.hideCloseButton = function () {
      $close.hide();
    };

    this.on('resize', this.resize, this);
  }

  // Extends the event dispatcher
  Dialog.prototype = Object.create(EventDispatcher.prototype);
  Dialog.prototype.constructor = Dialog;

  /**
   * Converts css px value to number.
   *
   * @private
   * @param {string} num
   * @returns {Number}
   */
  var toNum = function (num) {
    return Number(num.replace('px',''));
  };

  return Dialog;
})(H5P.jQuery, H5P.EventDispatcher);
<commit_msg>Fixed closing dialog in firefox. close click tried to use event without defining it first. HFJ-963<commit_after>H5P.InteractiveVideoDialog = (function ($, EventDispatcher) {

  /**
   * Controls the dialog in the interactive video.
   *
   * @class H5P.InteractiveVideoDialog
   * @param {H5P.jQuery} $container for dialog
   * @param {H5P.jQuery} $videoWrapper needed for positioning of dialog
   */
  function Dialog($container, $videoWrapper) {
    var self = this;

    // Initialize event inheritance
    EventDispatcher.call(self);

    // Create DOM elements for dialog
    var $wrapper = $('<div/>', {
      'class': 'h5p-dialog-wrapper h5p-ie-transparent-background h5p-hidden',
      on: {
        click: function () {
          if (!self.disableOverlay)  {
            self.close();
          }
        }
      }
    });
    var $dialog = $('<div/>', {
      'class': 'h5p-dialog h5p-big',
      on: {
        click: function (event) {
          event.stopPropagation();
        }
      }
    }).appendTo($wrapper);

    // Create title bar
    var $titleBar = $('<div/>', {
      'class': 'h5p-dialog-titlebar',
      appendTo: $dialog
    });
    var $title = $('<div/>', {
      'class': 'h5p-dialog-title',
      appendTo: $titleBar
    });
    var $close = $('<div/>', {
      'class': 'h5p-dialog-close',
      tabindex: 0,
      on: {
        click: function (event) {
          if (event.which === 1) {
            self.close();
          }
        },
        keypress: function (event) {
          if (event.which === 32) {
            self.close();
          }
        }
      },
      appendTo: $titleBar
    });

    // Used instead of close
    var $customButtons;

    // Create inner DOM elements for dialog
    var $inner = $('<div/>', {
      'class': 'h5p-dialog-inner'
    }).appendTo($dialog);

    // Add all to DOM
    $wrapper.appendTo($container);

    /**
     * Reset the dialog's positioning
     *
     * @private
     */
    var resetPosition = function () {
      // Reset positioning
      $dialog.css({
        left: '',
        top: '',
        height: '',
        width: '',
        fontSize: '',
        bottom: ''
      });
      $inner.css({
        width: '',
        height: '',
        overflow: ''
      });
    };

    /**
     * Display overlay.
     *
     * @private
     * @param {function} next callback
     */
    var showOverlay = function (next) {
      $wrapper.show();
      setTimeout(function () {
        // Remove class on next tick to ensure css animation
        $wrapper.removeClass('h5p-hidden');
        if (next) {
          next();
        }
      }, 0);
    };

    /**
     * Close overlay.
     *
     * @private
     * @param {function} next callback
     */
    var hideOverlay = function (next) {
      $wrapper.addClass('h5p-hidden');
      setTimeout(function () {
        // Hide when animation is done
        $wrapper.hide();
        if (next) {
          next();
        }
      }, 200);
    };

    /**
     * Opens a new dialog. Displays the given element.
     *
     * @param {H5P.jQuery} $element
     * @param {string} [title] Label for the dialog
     * @param {string} [classes] For styling
     * @param {H5P.jQuery} [$buttons] Use custom buttons for dialog
     */
    self.open = function ($element, title, classes, $buttons) {
      showOverlay();
      $inner.children().detach().end().append($element);

      // Reset positioning
      resetPosition();
      $dialog.addClass('h5p-big');
      $title.attr('class', 'h5p-dialog-title' + (classes ? ' ' + classes : ''));

      // Add label
      if (!title) {
        title = '';
      }
      $title.html(title);

      // Clean up after previous custom buttons
      if ($customButtons) {
        $customButtons.remove();
        $close.show();
      }

      // Add new custom buttons
      if ($buttons) {
        $customButtons = $buttons;

        // Hide default close button
        $close.hide();

        // Add custom buttons
        $buttons.appendTo($titleBar);
      }

      self.resize();

      self.trigger('open');
    };

    self.resize = function () {
      var fontSize = toNum($inner.css('fontSize'));
      var titleBarHeight = ($titleBar.outerHeight() / fontSize);

      // Same as height
      var maxHeight = $container.height();
      // minus dialog margins
      maxHeight -= Number($dialog.css('top').replace('px', '')) * 2;

      $inner.css({
        width: '100%',
        maxHeight: ((maxHeight / fontSize) - titleBarHeight) + 'em',
        marginTop: titleBarHeight + 'em'
      });
      $dialog.css({
        bottom: 'auto',
        maxHeight: ''
      });
    };

    /**
     * Adds a name to the dialog for identifying what it contains.
     *
     * @param {string} machineName Name of library inside dialog.
     */
    self.addLibraryClass = function (machineName) {
      $dialog.attr('data-lib', machineName);
    };

    self.isOpen = function () {
      return $wrapper.is(':visible');
    };

    /**
     * Reposition the currently open dialog relative to the given button.
     *
     * @param {H5P.jQuery} $button
     * @param {Object} [size] Sets a size for the dialog, useful for images.
     */
    self.position = function ($button, size) {
      var minWidth = 100;
      var minHeight = 75;
      resetPosition();
      $dialog.removeClass('h5p-big');
      var titleBarHeight = Number($inner[0].style.marginTop.replace('em', ''));

      if (size) {
        var fontSizeRatio = 16 / toNum($container.css('fontSize'));
        size.width = (size.width * fontSizeRatio);
        size.height = (size.height * fontSizeRatio);

        // Set minimum sizes
        if (size.width < minWidth / 16 * fontSizeRatio) {
          size.width = minWidth / 16 * fontSizeRatio;
        }

        if (size.height < (minHeight / 16 * fontSizeRatio)) {
          size.height = (minHeight / 16 * fontSizeRatio);
        }

        // Use a fixed size
        $dialog.css({
          width: size.width + 'em',
          height: (size.height + titleBarHeight) + 'em'
        });
        $inner.css({
          height: 'calc(100% - ' + titleBarHeight + 'em)',
          width: 'auto',
          overflow: 'hidden'
        });
      }

      var buttonWidth = $button.outerWidth(true);
      var buttonPosition = $button.position();
      var containerWidth = $container.width();
      var containerHeight = $container.height();

      // Position dialog horizontally
      var left = buttonPosition.left;
      var dialogWidth = $dialog.outerWidth(true);

      if (dialogWidth > containerWidth) {
        // If dialog is too big to fit within the container, display as h5p-big instead.
        $dialog.addClass('h5p-big');
        return;
      }

      if (buttonPosition.left > (containerWidth / 2) - (buttonWidth / 2)) {
        // Show on left
        left -= dialogWidth - buttonWidth;
      }

      // Make sure the dialog is within the video on the right.
      if ((left + dialogWidth) > containerWidth) {
        left = containerWidth - dialogWidth;
      }

      var marginLeft = parseInt($videoWrapper.css('marginLeft'));
      if (isNaN(marginLeft)) {
        marginLeft = 0;
      }

      // And finally, make sure we're within bounds on the left hand side too...
      if (left < marginLeft) {
        left = marginLeft;
      }

      // Position dialog vertically
      var marginTop = parseInt($videoWrapper.css('marginTop'));
      if (isNaN(marginTop)) {
        marginTop = 0;
      }

      var top = buttonPosition.top + marginTop;
      var totalHeight = top + $dialog.outerHeight(true);
      if (totalHeight > containerHeight) {
        top -= totalHeight - containerHeight;
      }
      var maxHeight = $container.height() - top + $dialog.height() - $dialog.outerHeight(true);
      // Set dialog size
      $dialog.css({
        top: (top / (containerHeight / 100)) + '%',
        left: (left / (containerWidth / 100)) + '%',
        width: $dialog.width(),
        maxHeight: maxHeight
      });
      $inner.css('maxHeight', maxHeight - $titleBar.outerHeight(true));
    };

    /**
     * Find max available space inside dialog when positioning relative to
     * given button.
     *
     * @param {H5P.jQuery} $button
     * @param {Boolean} fullScreen True if dialog fills whole parent
     * @returns {Object} Attrs: width, height
     */
    self.getMaxSize = function ($button, fullScreen) {
      var buttonWidth = $button.outerWidth(true);
      var buttonPosition = $button.position();
      var containerWidth = $container.width();

      var max = {};
      max.height = Number($inner.css('maxHeight').replace('px', ''));
      if (fullScreen) {
        max.width = containerWidth;
      } else {
        if (buttonPosition.left > (containerWidth / 2) - (buttonWidth / 2)) {
          // Space to the left of the button minus margin
          max.width = buttonPosition.left;
        }
        else {
          // Space to the right of the button minus margin
          max.width = (containerWidth - buttonPosition.left - buttonWidth);
        }
      }

      // Use em
      var fontSize = toNum($container.css('fontSize'));
      max.width = (max.width / fontSize) * (fontSize / 16);
      max.height = (max.height / fontSize) * (fontSize / 16);

      return max;
    };

    /**
     * Scroll to given position in current dialog.
     *
     * @param {number} to Scroll position
     * @param {number} ms Time the animation takes.
     */
    self.scroll = function (to, ms) {
      $inner.stop().animate({
        scrollTop: to
      }, ms);
    };

    /**
     * Close the currently open dialog.
     */
    self.close = function () {
      $wrapper.addClass('h5p-hidden');

      setTimeout(function () {
        $wrapper.hide();
        self.disableOverlay = false;
        $close.show();
      }, 201);

      self.trigger('close');
    };

    /**
     * Open overlay only.
     */
    self.openOverlay = function () {
      self.disableOverlay = true;
      $dialog.hide();
      showOverlay();
    };

    /**
     * Close overlay only.
     */
    self.closeOverlay = function () {
      $wrapper.addClass('h5p-hidden');
      hideOverlay(function () {
        $dialog.show();
        self.disableOverlay = false;
      });
    };

    /**
     * Removes the close button from the current dialog.
     */
    self.hideCloseButton = function () {
      $close.hide();
    };

    this.on('resize', this.resize, this);
  }

  // Extends the event dispatcher
  Dialog.prototype = Object.create(EventDispatcher.prototype);
  Dialog.prototype.constructor = Dialog;

  /**
   * Converts css px value to number.
   *
   * @private
   * @param {string} num
   * @returns {Number}
   */
  var toNum = function (num) {
    return Number(num.replace('px',''));
  };

  return Dialog;
})(H5P.jQuery, H5P.EventDispatcher);
<|endoftext|>


<commit_before>foam.CLASS({
  package: 'foam.nanos.auth',
  name: 'EnabledCheckAuthService',
  extends: 'foam.nanos.auth.ProxyAuthService',
  flags: ['java'],

  javaImports: [
    'foam.dao.DAO',
    'foam.nanos.session.Session'
  ],

  methods: [
    {
      name: 'check',
      javaCode: `
        if ( x == null || permission == null ) return false;

        // Check if session exists and there's a user id set for it.
        Session session = x.get(Session.class);
        if ( session == null || session.getUserId() == 0 ) return false;

        // Check if user exists and is enabled.
        User user = (User) x.get("user");
        if ( user == null || ! user.getEnabled() ) return false;

        // Check if agent exists and is enabled.
        User agent = (User) x.get("agent");
        if ( agent != null && ! agent.getEnabled() ) return false;

        // Check if group and all ancestor groups are enabled.
        Group group = getCurrentGroup(x);
        DAO localGroupDAO = ((DAO) x.get("localGroupDAO")).inX(x);
        while ( group != null ) {
          if ( ! group.getEnabled() ) return false;
          group = (Group) localGroupDAO.find(group.getParent());
        }

        return super.check(x, permission);
      `
    }
  ]
});
<commit_msg>Explain difference in conditions<commit_after>foam.CLASS({
  package: 'foam.nanos.auth',
  name: 'EnabledCheckAuthService',
  extends: 'foam.nanos.auth.ProxyAuthService',
  flags: ['java'],

  javaImports: [
    'foam.dao.DAO',
    'foam.nanos.session.Session'
  ],

  methods: [
    {
      name: 'check',
      javaCode: `
        if ( x == null || permission == null ) return false;

        // Check if session exists and there's a user id set for it.
        Session session = x.get(Session.class);
        if ( session == null || session.getUserId() == 0 ) return false;

        // Check if user exists and is enabled.
        User user = (User) x.get("user");
        if ( user == null || ! user.getEnabled() ) return false;

        // Check if agent exists and is enabled. Note that it isn't mandatory
        // that an agent always be there, so it's fine if the agent is null.
        // However, if the agent _is_ there, then it needs to be enabled.
        User agent = (User) x.get("agent");
        if ( agent != null && ! agent.getEnabled() ) return false;

        // Check if group and all ancestor groups are enabled.
        Group group = getCurrentGroup(x);
        DAO localGroupDAO = ((DAO) x.get("localGroupDAO")).inX(x);
        while ( group != null ) {
          if ( ! group.getEnabled() ) return false;
          group = (Group) localGroupDAO.find(group.getParent());
        }

        return super.check(x, permission);
      `
    }
  ]
});
<|endoftext|>


<commit_before>var path = require('path');
var chalk = require('chalk');
var shell = require('shelljs');

var doctor = module.exports = {
  errors: [],

  run: function () {
    this.checkNodePath();
    this.logErrors();
  },

  logErrors: function () {
    if (!this.errors.length) {
      console.log(chalk.green('[Yeoman Doctor] Everything looks alright!'));
      console.log();
      return;
    }

    console.log(chalk.red('[Yeoman Doctor] Uh oh, I found potential errors on your machine\n---------------\n'));
    this.errors.forEach(function (errMsg) {
      console.log('[' + chalk.red('Error') + '] ' + errMsg);
      console.log();
    });
  },

  checkNodePath: function () {
    if (!process.env.NODE_PATH) {
      return;
    }

    var nodePaths = process.env.NODE_PATH.split(path.delimiter).map(path.normalize);
    var npmRoot = shell.exec('npm -g root', { silent: true }).output;

    npmRoot = path.normalize(npmRoot.trim());

    if (nodePaths.indexOf(npmRoot) < 0) {
      this.nodePathMismatch({
        nodePaths: nodePaths,
        npmRoot: npmRoot
      });
    }
  },

  nodePathMismatch: function (val) {
    var output = '';
    output += 'npm root value is not in your NODE_PATH\n';
    output += '  [' + chalk.cyan('info') + ']\n';
    output += [
      '    NODE_PATH = ' + val.nodePaths.join(path.delimiter),
      '    npm root  = ' + val.npmRoot
    ].join('\n');
    output += '\n\n  [' + chalk.cyan('Fix') + '] Append the npm root value to your NODE_PATH variable\n';

    if (process.platform === 'win32') {
      output += [
        '    If you\'re using cmd.exe, run this command to fix the issue:',
        '      setx NODE_PATH "%NODE_PATH%;' + val.npmRoot + '"',
        '    Then restart your command line. Otherwise, you can setup NODE_PATH manually:',
        '      https://github.com/sindresorhus/guides/blob/master/set-environment-variables.md#windows'
      ].join('\n');
    } else {
      output += [
        '    Add this line to your .bashrc',
        '      export NODE_PATH=$NODE_PATH:' + val.npmRoot,
        '    Or run this command',
        '      echo "export NODE_PATH=$NODE_PATH:' + val.npmRoot + '" >> ~/.bashrc && source ~/.bashrc'
      ].join('\n');
    }

    this.errors.push(output);
  }
};

doctor.run();
<commit_msg>Fix spelling of "all right".<commit_after>var path = require('path');
var chalk = require('chalk');
var shell = require('shelljs');

var doctor = module.exports = {
  errors: [],

  run: function () {
    this.checkNodePath();
    this.logErrors();
  },

  logErrors: function () {
    if (!this.errors.length) {
      console.log(chalk.green('[Yeoman Doctor] Everything looks all right!'));
      console.log();
      return;
    }

    console.log(chalk.red('[Yeoman Doctor] Uh oh, I found potential errors on your machine\n---------------\n'));
    this.errors.forEach(function (errMsg) {
      console.log('[' + chalk.red('Error') + '] ' + errMsg);
      console.log();
    });
  },

  checkNodePath: function () {
    if (!process.env.NODE_PATH) {
      return;
    }

    var nodePaths = process.env.NODE_PATH.split(path.delimiter).map(path.normalize);
    var npmRoot = shell.exec('npm -g root', { silent: true }).output;

    npmRoot = path.normalize(npmRoot.trim());

    if (nodePaths.indexOf(npmRoot) < 0) {
      this.nodePathMismatch({
        nodePaths: nodePaths,
        npmRoot: npmRoot
      });
    }
  },

  nodePathMismatch: function (val) {
    var output = '';
    output += 'npm root value is not in your NODE_PATH\n';
    output += '  [' + chalk.cyan('info') + ']\n';
    output += [
      '    NODE_PATH = ' + val.nodePaths.join(path.delimiter),
      '    npm root  = ' + val.npmRoot
    ].join('\n');
    output += '\n\n  [' + chalk.cyan('Fix') + '] Append the npm root value to your NODE_PATH variable\n';

    if (process.platform === 'win32') {
      output += [
        '    If you\'re using cmd.exe, run this command to fix the issue:',
        '      setx NODE_PATH "%NODE_PATH%;' + val.npmRoot + '"',
        '    Then restart your command line. Otherwise, you can setup NODE_PATH manually:',
        '      https://github.com/sindresorhus/guides/blob/master/set-environment-variables.md#windows'
      ].join('\n');
    } else {
      output += [
        '    Add this line to your .bashrc',
        '      export NODE_PATH=$NODE_PATH:' + val.npmRoot,
        '    Or run this command',
        '      echo "export NODE_PATH=$NODE_PATH:' + val.npmRoot + '" >> ~/.bashrc && source ~/.bashrc'
      ].join('\n');
    }

    this.errors.push(output);
  }
};

doctor.run();
<|endoftext|>


<commit_before>if("undefined"==typeof OGX)var OGX=function(){};OGX.prototype.MobileBaseView=function(i){"use strict";function e(i){var e=h.el.width(),n=h.el.height(),t=(e-i.width)/2,o=$(window).height()-h.el.position().top-(n/2-i.height/2),s='

';h.el.parent(0).append(s),c=h.el.parent(0).children(".ogx_view_loading:last")}function n(i){i?(r=new MutationObserver(function(i,e){i.forEach(function(i){h.el.trigger(OGX.MobileBaseView.RENDER)})}),r.observe(h.el[0],{childList:!0,subtree:!0})):(r.disconnect(),r=null)}function t(){for(var i in l)h.config.hasOwnProperty(i)||(h.config[i]=l[i]);h.el=s=$(h.config.container)}function o(){t(),n(!0),h.render()}var s,r,c,h=this,l={};this.config=i,this.el=null,this.constructor=function(){},this.scopes=function(){return h.config.scopes},this.focus=function(){},this.blur=function(){},this.destroyInternal=function(){this.showLoading(!1),n(!1),this.ux(!1),s.empty()},this.ux=function(i){},this.render=function(i){"undefined"==typeof i?h.config.hasOwnProperty("file")?s.load(h.config.file):h.config.hasOwnProperty("html")&&s.html(h.config.html):s.html(i)},this.showLoading=function(i,n){i?e(n):c&&(c.remove(),c=null)},o()},OGX.MobileBaseView=function(i){"use strict";return new OGX.prototype.MobileBaseView(i)},OGX.MobileBaseView.DESTROY="destroy",OGX.MobileBaseView.RENDER="render";<commit_msg><commit_after>if("undefined"==typeof OGX)var OGX=function(){};OGX.prototype.MobileBaseView=function(i){"use strict";function e(i){var e=f.el.width(),t=f.el.height(),n=(e-i.width)/2,o=$(window).height()-f.el.position().top-(t/2-i.height/2),r='

';f.el.parent(0).append(r),c=f.el.parent(0).children(".ogx_view_loading:last")}function t(i){i?s||(s=new MutationObserver(function(i,e){i.forEach(function(i){f.el.trigger(OGX.MobileBaseView.RENDER)})}),s.observe(f.el[0],{childList:!0,subtree:!0})):s&&(s.disconnect(),s=null)}function n(){for(var i in h)f.config.hasOwnProperty(i)||(f.config[i]=h[i]);f.el=r=$(f.config.container)}function o(){n(),config.base_view_trigger&&t(!0),f.render()}var r,s,c,f=this,h={base_view_trigger:!0};this.config=i,this.el=null,this.constructor=function(){},this.scopes=function(){return f.config.scopes},this.focus=function(){},this.blur=function(){},this.destroyInternal=function(){this.showLoading(!1),config.base_view_trigger&&t(!1),this.ux(!1),r.empty()},this.ux=function(i){},this.render=function(i){"undefined"==typeof i?f.config.hasOwnProperty("file")?r.load(f.config.file):f.config.hasOwnProperty("html")&&r.html(f.config.html):r.html(i)},this.showLoading=function(i,t){i?e(t):c&&(c.remove(),c=null)},o()},OGX.MobileBaseView=function(i){"use strict";return new OGX.prototype.MobileBaseView(i)},OGX.MobileBaseView.DESTROY="destroy",OGX.MobileBaseView.RENDER="render";<|endoftext|>


<commit_before>function writeHeader() {
    return '\
    \

\
        ICSME 2019\
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">\
            \
        </button>\
\

\

\
            \
\

\
                Venue & Travel\

\
                    Hotel Venue\
                    Traveling to Cleveland\
                    Visa Invitation\
                    \

\

\
\

\
                Program\

\
                    Keynotes\
                    Accepted Papers\

\

\
\

\
                Call for Papers\

\
                    Research Track\
                    Short Paper Track\
                    Late Breaking Ideas Track\
                    Tool Demo Track\
                    Industry Track\
                    Artifacts Track\
                    Journal First Track\
                    Doctoral Symposium\

\

\
\

\
                Team\

\
                    Organizing Committee\
                    Program Committee\

\

\
\

\
                Co-Located Events\

\
                    SCAM\
                    VISSOFT\

\

\
\
            \
\
            \
\
            \
\
            \
\

\

\

\
    \
\
    \

\
    ';
}
<commit_msg>Add student volunteer to menu<commit_after>function writeHeader() {
    return '\
    \

\
        ICSME 2019\
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">\
            \
        </button>\
\

\

\
            \
\

\
                Venue & Travel\

\
                    Hotel Venue\
                    Traveling to Cleveland\
                    Visa Invitation\
                    Student Volunteer Application\

\

\
\

\
                Program\

\
                    Keynotes\
                    Accepted Papers\

\

\
\

\
                Call for Papers\

\
                    Research Track\
                    Short Paper Track\
                    Late Breaking Ideas Track\
                    Tool Demo Track\
                    Industry Track\
                    Artifacts Track\
                    Journal First Track\
                    Doctoral Symposium\

\

\
\

\
                Team\

\
                    Organizing Committee\
                    Program Committee\

\

\
\

\
                Co-Located Events\

\
                    SCAM\
                    VISSOFT\

\

\
\
            \
\
            \
\
            \
\
            \
\

\

\

\
    \
\
    \

\
    ';
}
<|endoftext|>


<commit_before><commit_msg>Add functionality to card to map over passed object and display definition list<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import Button from '../Button/Button';

const Card = ( { nounObject } ) => {
  const mappedNounObject = Object.keys( nounObject ).map( key => {
    return (

        {key}

        {nountObject[key]}

    )
  });

  return (

{nounObject[name]}

        <Button />

        {mappedNounObject}

  )
}

export default Card;
<|endoftext|>


<commit_before>'use strict';

const program = require('commander');
const fs = require('fs');
const analyze = require('../lib/analyze');

function cli () {

program
  .version('0.0.1')
  .usage('[options] <dir>')
  .option('-s, --scan <file>', 'Directory or file', scanCommand);

  //start
  program.parse(process.argv);

function scanCommand(dir) {
  scan(dir.length ? dir[0] : './'); //default to current folder
}

  //
  /**
   * Analyze and process a file
   * @param  {string}    filename
   * @return {void}      stdout
   */
  function scanFile (file) {
    let deprecateds = analyze(file, {});
  	stdOut(deprecateds);
  }

  /**
   * Print result to stdout
   * @param  {object} out The return from analyzer()
   * @return {void}     print out results
   */
  function stdOut (out) {
    console.log(out);
  }

  /**
   * Scan a file or folder
   * @param  {string} path The full path to a file or folder
   * @return {void}      stdout
   */
  function scan (path){
  	let stats = fs.statSync(path);

  	if (stats.isFile()) {
  		console.log('Analyzing file: ' + path.replace('//', '/'));
  		scanFile(path);
  	}
  	else if (stats.isDirectory()){
  		console.log('=== ' + path + ' >>>');
  	 	let files = fs.readdirSync(path);

  		if (files.length) {
  			files.forEach(function (file){
  				let filename = path + '/' + file;
  				scan(filename);
  			});
  			console.log('<<< ' + path + ' ===');
  		}
  	}
  }
}

module.exports = cli;
<commit_msg>add missing space #16<commit_after>'use strict';

const program = require('commander');
const fs = require('fs');
const analyze = require('../lib/analyze');

function cli () {

program
  .version('0.0.1')
  .usage('[options] <dir>')
  .option('-s, --scan <file>', 'Directory or file', scanCommand);

  //start
  program.parse(process.argv);

function scanCommand (dir) {
  scan(dir.length ? dir[0] : './'); //default to current folder
}

  //
  /**
   * Analyze and process a file
   * @param  {string}    filename
   * @return {void}      stdout
   */
  function scanFile (file) {
    let deprecateds = analyze(file, {});
  	stdOut(deprecateds);
  }

  /**
   * Print result to stdout
   * @param  {object} out The return from analyzer()
   * @return {void}     print out results
   */
  function stdOut (out) {
    console.log(out);
  }

  /**
   * Scan a file or folder
   * @param  {string} path The full path to a file or folder
   * @return {void}      stdout
   */
  function scan (path){
  	let stats = fs.statSync(path);

  	if (stats.isFile()) {
  		console.log('Analyzing file: ' + path.replace('//', '/'));
  		scanFile(path);
  	}
  	else if (stats.isDirectory()){
  		console.log('=== ' + path + ' >>>');
  	 	let files = fs.readdirSync(path);

  		if (files.length) {
  			files.forEach(function (file){
  				let filename = path + '/' + file;
  				scan(filename);
  			});
  			console.log('<<< ' + path + ' ===');
  		}
  	}
  }
}

module.exports = cli;
<|endoftext|>


<commit_before>#!/usr/bin/env node

cube2csv = require('../lib/index');

var argv = require('optimist')
        .usage('Usage: $0 [metric, event, types] {OPTIONS}')
        .wrap(80)
        .option('expression', {
          alias : 'e',
          desc : 'Expression to be evaluated by Cube'
        })
        .option('host', {
          alias : 'H',
          desc : 'Cube evaluator host',
          default: 'localhost:8081'
        })
        .option('request', {
          alias : 'r',
          desc : 'Ouput only the computed query',
          default : false,
          boolean : true
        })
        .option('help', {
          alias : 'h',
          desc : 'Display this message'
        })
        .check(function(argv) {
          if(argv.help) throw '';
          if(['types', 'metric', 'event'].indexOf(argv._[0] ) === -1)
            throw 'Specify \'types\', \'metric\' or \'event\'' ;
        })
        .argv;

switch(argv._[0]) {
  case 'types':
    if(argv.request)
      console.log(cube2csv.types.buildQuery(argv.host));
    else
      cube2csv.types(argv.host, console.log);
    break;

  case 'event':
    break;

  case 'metric':
    break;
}<commit_msg>Correct indentation<commit_after>#!/usr/bin/env node

cube2csv = require('../lib/index');

var argv = require('optimist')
        .usage('Usage: $0 [metric, event, types] {OPTIONS}')
        .wrap(80)
        .option('expression', {
          alias  : 'e',
          desc   : 'Expression to be evaluated by Cube'
        })
        .option('host', {
          alias  : 'H',
          desc   : 'Cube evaluator host',
          default: 'localhost:8081'
        })
        .option('request', {
          alias  : 'r',
          desc   : 'Ouput only the computed query',
          default: false,
          boolean: true
        })
        .option('help', {
          alias  : 'h',
          desc   : 'Display this message'
        })
        .check(function(argv) {
          if(argv.help) throw '';
          if(['types', 'metric', 'event'].indexOf(argv._[0] ) === -1)
            throw 'Specify \'types\', \'metric\' or \'event\'' ;
        })
        .argv;

switch(argv._[0]) {
  case 'types':
    if(argv.request)
      console.log(cube2csv.types.buildQuery(argv.host));
    else
      cube2csv.types(argv.host, console.log);
    break;

  case 'event':
    break;

  case 'metric':
    break;
}<|endoftext|>


<commit_before>#!/usr/bin/env node
var dateFormat = require('dateformat')
  , argv = require('optimist').boolean(['billable', 'b'])
                              .default('date', dateFormat(new Date(), 'yyyy-mm-dd'))
                              .default('hours', 8)
                              .default('description', '')
                              .argv
  , futures = require('futures')
  , config = require('../config')
  , intervals = require('../intervals')
;

function addTime(options, client) {
    return function(next, project) {
        var dates = options.dates;
        delete options.dates;
        dates.forEach(function(date) {
            options.date = date;
            console.log('Add '+ options.time + ' ' +
                        (options.billable ? 'billable' : 'non billable') +
                        ' hours for '+ options.date);
            intervals.addTime(project, options, client, function (err, res) {
                if (err) throw err;
                if (res.status != 201) throw res.body;
                console.log('Success! Time added.');
            });
        });
        next(project);
    };
}

function askForToken(callback) {
    config.read(function(err, value) {
        if (err) {
            if (err.code == 'ENOENT') {
                process.stdout.write('Please enter your token (go to https://xx.timetask.com/account/api/ and generate a new one): ');
                intervals.readInput(function(input) {
                    config.write({token: input}, function(err) {
                        if (err) throw err;
                        console.log('token saved in '+ config.path);
                        callback({token: input});
                    });
                });
            } else {
                throw err;
            }
        } else {
            callback(value);
        }
    });
}

/**
 * Ask user to save the project
 */
function askForSave(conf) {
    return function(next, project) {
        process.stdout.write('Do you yant to save this project combinaison: (y/N)');
        intervals.readInput(function(input) {
            if (input == 'y') {
                process.stdout.write('Name of this combinaison: ');
                intervals.readInput(function(input) {
                    conf.projects ? '': conf.projects = [];
                    project.name = input;
                    conf.projects.push(project);
                    config.write(conf, function(err) {
                        if (err) throw err;
                        console.log('ok. You can add time to this combinaison with intervals --project '+ input);
                        next();
                    })
                });
            } else {
                next();
            }
        });
    }
}

/**
 * Extract options from argv
 */
function optionsFrom(argv) {
    var date     = argv.date,
        dates    = (Array.isArray(date)) ? date : [date],
        options  = { time: argv.hours,
                     dates: dates,
                     billable: argv.billable || argv.b,
                     description: argv.description };
    return options;
}

function loadProject(conf, argv) {
    return function(next) {
        for (var i in conf.projects) {
            if (conf.projects[i].name == argv.project) {
                var project = conf.projects[i];
                delete project.name;
                next(project);
            }
        }
    }
}

if (argv._.length > 1) {
    return require('../help')();
}
if (argv._.length == 0) {
    argv._.push('add-time');
}
var cmd = argv._[0];

if (argv.version || cmd == 'version') {
    return require('../version')();
} else if (argv.help || cmd == 'help') {
    return require('../help')();
} else if (cmd == 'list-projects') {
    askForToken(function(conf) {
        if (Array.isArray(conf.projects) && conf.projects.length) {
            conf.projects.forEach(function(project) {
                console.log(project.name, ':\n', config.toYaml(project.human, '  '));
            });
        } else {
            console.log('no projects found. Register a new one with intervals add-time');
        }
    });
} else if (cmd == 'add-time') {
    askForToken(function(conf) {
        var options  = optionsFrom(argv),
            sequence = null;

        console.log('Add '+ options.time + ' ' +
                    (options.billable ? 'billable' : 'non billable') +
                    ' hours for '+ options.dates.join(' and '));
        var client = intervals.createClient(conf.token);
        var sequence = futures.sequence();
        if (argv.project) {
            sequence.then(loadProject(conf, argv))
                    .then(addTime(options, client));
        } else {
            sequence.then(intervals.askForProject(client))
                    .then(addTime(options, client))
                    .then(askForSave(conf));
        }
    });
} else {
    return require('../help')();
}
<commit_msg>Add -v as shortcut for --version.<commit_after>#!/usr/bin/env node
var dateFormat = require('dateformat')
  , argv = require('optimist').boolean(['billable', 'b'])
                              .default('date', dateFormat(new Date(), 'yyyy-mm-dd'))
                              .default('hours', 8)
                              .default('description', '')
                              .argv
  , futures = require('futures')
  , config = require('../config')
  , intervals = require('../intervals')
;

function addTime(options, client) {
    return function(next, project) {
        var dates = options.dates;
        delete options.dates;
        dates.forEach(function(date) {
            options.date = date;
            console.log('Add '+ options.time + ' ' +
                        (options.billable ? 'billable' : 'non billable') +
                        ' hours for '+ options.date);
            intervals.addTime(project, options, client, function (err, res) {
                if (err) throw err;
                if (res.status != 201) throw res.body;
                console.log('Success! Time added.');
            });
        });
        next(project);
    };
}

function askForToken(callback) {
    config.read(function(err, value) {
        if (err) {
            if (err.code == 'ENOENT') {
                process.stdout.write('Please enter your token (go to https://xx.timetask.com/account/api/ and generate a new one): ');
                intervals.readInput(function(input) {
                    config.write({token: input}, function(err) {
                        if (err) throw err;
                        console.log('token saved in '+ config.path);
                        callback({token: input});
                    });
                });
            } else {
                throw err;
            }
        } else {
            callback(value);
        }
    });
}

/**
 * Ask user to save the project
 */
function askForSave(conf) {
    return function(next, project) {
        process.stdout.write('Do you yant to save this project combinaison: (y/N)');
        intervals.readInput(function(input) {
            if (input == 'y') {
                process.stdout.write('Name of this combinaison: ');
                intervals.readInput(function(input) {
                    conf.projects ? '': conf.projects = [];
                    project.name = input;
                    conf.projects.push(project);
                    config.write(conf, function(err) {
                        if (err) throw err;
                        console.log('ok. You can add time to this combinaison with intervals --project '+ input);
                        next();
                    })
                });
            } else {
                next();
            }
        });
    }
}

/**
 * Extract options from argv
 */
function optionsFrom(argv) {
    var date     = argv.date,
        dates    = (Array.isArray(date)) ? date : [date],
        options  = { time: argv.hours,
                     dates: dates,
                     billable: argv.billable || argv.b,
                     description: argv.description };
    return options;
}

function loadProject(conf, argv) {
    return function(next) {
        for (var i in conf.projects) {
            if (conf.projects[i].name == argv.project) {
                var project = conf.projects[i];
                delete project.name;
                next(project);
            }
        }
    }
}

if (argv._.length > 1) {
    return require('../help')();
}
if (argv._.length == 0) {
    argv._.push('add-time');
}
var cmd = argv._[0];

if (argv.version || cmd == 'version' || argv.v) {
    return require('../version')();
} else if (argv.help || cmd == 'help') {
    return require('../help')();
} else if (cmd == 'list-projects') {
    askForToken(function(conf) {
        if (Array.isArray(conf.projects) && conf.projects.length) {
            conf.projects.forEach(function(project) {
                console.log(project.name, ':\n', config.toYaml(project.human, '  '));
            });
        } else {
            console.log('no projects found. Register a new one with intervals add-time');
        }
    });
} else if (cmd == 'add-time') {
    askForToken(function(conf) {
        var options  = optionsFrom(argv),
            sequence = null;

        console.log('Add '+ options.time + ' ' +
                    (options.billable ? 'billable' : 'non billable') +
                    ' hours for '+ options.dates.join(' and '));
        var client = intervals.createClient(conf.token);
        var sequence = futures.sequence();
        if (argv.project) {
            sequence.then(loadProject(conf, argv))
                    .then(addTime(options, client));
        } else {
            sequence.then(intervals.askForProject(client))
                    .then(addTime(options, client))
                    .then(askForSave(conf));
        }
    });
} else {
    return require('../help')();
}
<|endoftext|>


<commit_before>import { swalClasses, iconTypes } from './classes.js';

export var defaultParams = {
  title: '',
  text: '',
  html: '',
  type: null,
  animation: true,
  allowOutsideClick: true,
  allowEscapeKey: true,
  showConfirmButton: true,
  showCancelButton: false,
  preConfirm: null,
  confirmButtonText: 'OK',
  confirmButtonColor: '#3085d6',
  confirmButtonClass: null,
  cancelButtonText: 'Cancel',
  cancelButtonColor: '#aaa',
  cancelButtonClass: null,
  buttonsStyling: true,
  reverseButtons: false,
  showCloseButton: false,
  showLoaderOnConfirm: false,
  imageUrl: null,
  imageWidth: null,
  imageHeight: null,
  imageClass: null,
  timer: null,
  width: 500,
  padding: 20,
  background: '#fff',
  input: null, // 'text' | 'email' | 'password' | 'select' | 'radio' | 'checkbox' | 'textarea' | 'file'
  inputPlaceholder: '',
  inputValue: '',
  inputOptions: {},
  inputAutoTrim: true,
  inputClass: null,
  inputAttributes: {},
  inputValidator: null,
  onOpen: null,
  onClose: null,
};

export var sweetHTML = '

' +
  '
' +
    '
' +
      '' +
    '
' +
    '
?
' +
    '
!
' +
    '
i
' +
    '
' +
      ' ' +
      '

' +
    '
' +
    '' +
    '

' +
    '

' +
    '<input class="' + swalClasses.input + '">' +
    '<select class="' + swalClasses.select + '"></select>' +
    '

' +
    '' +
      '<input type="checkbox" id="' + swalClasses.checkbox + '">' +
    '' +
    '<textarea class="' + swalClasses.textarea + '"></textarea>' +
    '

' +
    '
' +
    '<button class="' + swalClasses.confirm + '">OK</button>' +
    '<button class="' + swalClasses.cancel + '">Cancel</button>' +
    '×' +
  '
';
<commit_msg>Add missed default parameter customClass, fix #237<commit_after>import { swalClasses, iconTypes } from './classes.js';

export var defaultParams = {
  title: '',
  text: '',
  html: '',
  type: null,
  customClass: '',
  animation: true,
  allowOutsideClick: true,
  allowEscapeKey: true,
  showConfirmButton: true,
  showCancelButton: false,
  preConfirm: null,
  confirmButtonText: 'OK',
  confirmButtonColor: '#3085d6',
  confirmButtonClass: null,
  cancelButtonText: 'Cancel',
  cancelButtonColor: '#aaa',
  cancelButtonClass: null,
  buttonsStyling: true,
  reverseButtons: false,
  showCloseButton: false,
  showLoaderOnConfirm: false,
  imageUrl: null,
  imageWidth: null,
  imageHeight: null,
  imageClass: null,
  timer: null,
  width: 500,
  padding: 20,
  background: '#fff',
  input: null, // 'text' | 'email' | 'password' | 'select' | 'radio' | 'checkbox' | 'textarea' | 'file'
  inputPlaceholder: '',
  inputValue: '',
  inputOptions: {},
  inputAutoTrim: true,
  inputClass: null,
  inputAttributes: {},
  inputValidator: null,
  onOpen: null,
  onClose: null,
};

export var sweetHTML = '

' +
  '
' +
    '
' +
      '' +
    '
' +
    '
?
' +
    '
!
' +
    '
i
' +
    '
' +
      ' ' +
      '

' +
    '
' +
    '' +
    '

' +
    '

' +
    '<input class="' + swalClasses.input + '">' +
    '<select class="' + swalClasses.select + '"></select>' +
    '

' +
    '' +
      '<input type="checkbox" id="' + swalClasses.checkbox + '">' +
    '' +
    '<textarea class="' + swalClasses.textarea + '"></textarea>' +
    '

' +
    '
' +
    '<button class="' + swalClasses.confirm + '">OK</button>' +
    '<button class="' + swalClasses.cancel + '">Cancel</button>' +
    '×' +
  '
';
<|endoftext|>


<commit_before>#!/usr/bin/env node
var Avrgirl = require('../avrgirl-arduino');
var boards = require('../boards');
var parseArgs = require('minimist');
var path = require('path');
var child = require('child_process');
var testPilot = require('../lib/test-pilot-checker');

var args = (process.argv.slice(2));
var argv = parseArgs(args, {});
var userAction = argv._[0];
var help = 'Usage:\n' +
  '  avrgirl-arduino flash -f <file> -a <arduino name> [-p <port>] [-v]\n' +
  '  avrgirl-arduino boards\n' +
  '  avrgirl-arduino list\n' +
  '  avrgirl-arduino test-pilot';

function showHelp() {
  console.log(help);
}

function flash(file, options) {
  var avrgirl = new Avrgirl(options);
  var filepath = path.resolve(process.cwd(), file);

  avrgirl.flash(filepath, function(error) {
    if (error) {
      console.error(error);
      process.exit(1);
    }
  });
}

function handleInput(action, argz) {
  switch (action) {
    case 'flash': {
      if (!argz.f || !argz.a) {
        showHelp();
        process.exit(1);
      } else if (!boards.byName[argz.a]) {
        console.error(new Error('Oops! That board is not supported, sorry.'));
        process.exit(1);
      } else {
        // run flash function here if all is well
        var options = {
          board: argz.a,
          port: argz.p || '',
          debug: argz.v || false
        };

        flash(argz.f, options);
      }

      break;
    }

    case 'boards': {
      var boardNames = Object.keys(boards.byName).sort();
      console.log('Supported Boards:\n - ' + boardNames.join('\n - '));
      break;
    }

    case 'list': {
      Avrgirl.listPorts(function(err, ports) {
        console.log(ports);
      });

      break;
    }

    case 'help': {
      showHelp();
      process.exit();
      break;
    }

    case 'test-pilot': {
      console.log('running preflight check...');
      testPilot.checkForInstall(function(err, isInstalled) {
        if (isInstalled) {
          testPilot.run();
        } else {
          console.log('installing test pilot, won\'t be long...');
          testPilot.install(function(err) {
            if (err) {
              var msg = err;
              if (err.code === 'EACCES' || err.code === 'EPERM') {
                msg = new Error('Oops! We ran into a permissions issue... you might want to check out this resource https://docs.npmjs.com/getting-started/fixing-npm-permissions');
              }
              return console.log(msg);
            } else {
              testPilot.run();
            }
          });
        }
      });
      break;
    }

    default: {
      // Invalid or no argument specified, show help and exit with an error status
      showHelp();
      process.exit(9);
      break;
    }
  }
}

handleInput(userAction, argv);
<commit_msg>fix board referencing bug in cli<commit_after>#!/usr/bin/env node
var Avrgirl = require('../avrgirl-arduino');
var boards = require('../boards');
var parseArgs = require('minimist');
var path = require('path');
var child = require('child_process');
var testPilot = require('../lib/test-pilot-checker');

var args = (process.argv.slice(2));
var argv = parseArgs(args, {});
var userAction = argv._[0];
var help = 'Usage:\n' +
  '  avrgirl-arduino flash -f <file> -a <arduino name> [-p <port>] [-v]\n' +
  '  avrgirl-arduino boards\n' +
  '  avrgirl-arduino list\n' +
  '  avrgirl-arduino test-pilot';

function showHelp() {
  console.log(help);
}

function flash(file, options) {
  var avrgirl = new Avrgirl(options);
  var filepath = path.resolve(process.cwd(), file);

  avrgirl.flash(filepath, function(error) {
    if (error) {
      console.error(error);
      process.exit(1);
    }
  });
}

function handleInput(action, argz) {
  switch (action) {
    case 'flash': {
      if (!argz.f || !argz.a) {
        showHelp();
        process.exit(1);
      } else if (!boards[argz.a]) {
        console.error(new Error('Oops! That board is not supported, sorry.'));
        process.exit(1);
      } else {
        // run flash function here if all is well
        var options = {
          board: argz.a,
          port: argz.p || '',
          debug: argz.v || false
        };

        flash(argz.f, options);
      }

      break;
    }

    case 'boards': {
      var boardNames = Object.keys(boards).sort();
      console.log('Supported Boards:\n - ' + boardNames.join('\n - '));
      break;
    }

    case 'list': {
      Avrgirl.listPorts(function(err, ports) {
        console.log(ports);
      });

      break;
    }

    case 'help': {
      showHelp();
      process.exit();
      break;
    }

    case 'test-pilot': {
      console.log('running preflight check...');
      testPilot.checkForInstall(function(err, isInstalled) {
        if (isInstalled) {
          testPilot.run();
        } else {
          console.log('installing test pilot, won\'t be long...');
          testPilot.install(function(err) {
            if (err) {
              var msg = err;
              if (err.code === 'EACCES' || err.code === 'EPERM') {
                msg = new Error('Oops! We ran into a permissions issue... you might want to check out this resource https://docs.npmjs.com/getting-started/fixing-npm-permissions');
              }
              return console.log(msg);
            } else {
              testPilot.run();
            }
          });
        }
      });
      break;
    }

    default: {
      // Invalid or no argument specified, show help and exit with an error status
      showHelp();
      process.exit(9);
      break;
    }
  }
}

handleInput(userAction, argv);
<|endoftext|>