<commit_before>import React, { Component } from 'react';
import { FormattedMessage } from 'react-intl';
import PropTypes from 'prop-types';
import Relay from 'react-relay';
import IconEdit from 'material-ui/svg-icons/image/edit';
import ProjectRoute from '../ProjectRoute';
import Can from '../../components/Can';
import CheckContext from '../../CheckContext';
import { SmallerStyledIconButton } from '../../styles/js/shared';

class ProjectMenu extends Component {
  handleEditClick() {
    const { history } = new CheckContext(this).getContextStore();
    history.push(`${window.location.pathname.match(/.*\/project\/\d+/)[0]}/edit`);
  }

  render() {
    const { project } = this.props;

    const editProjectButton = (
      <SmallerStyledIconButton
        onClick={this.handleEditClick.bind(this)}
        tooltip={<FormattedMessage id="projectMenuRelay.editProject" defaultMessage="Edit project" />}
      >
        <IconEdit />
      </SmallerStyledIconButton>
    );

    return (
      <Can permissions={project.permissions} permission="update Project">
        <div
          key="projectMenuRelay.editProject"
          className="project-menu"
        >
          {editProjectButton}
        </div>
      </Can>
    );
  }
}

ProjectMenu.contextTypes = {
  store: PropTypes.object,
};

const ProjectMenuContainer = Relay.createContainer(ProjectMenu, {
  fragments: {
    project: () => Relay.QL`
      fragment on Project {
        id,
        dbid,
        title,
        description,
        permissions,
        team {
          id,
          dbid,
          slug,
          permissions,
          limits
        }
      }
    `,
  },
});

const ProjectMenuRelay = (props) => {
  if (props.params && props.params.projectId) {
    const route = new ProjectRoute({ contextId: props.params.projectId });
    return <Relay.RootContainer Component={ProjectMenuContainer} route={route} />;
  }
  return null;
};

export default ProjectMenuRelay;
<commit_msg>#6694 Hide Edit project button from Media and Source pages<commit_after>import React, { Component } from 'react';
import { FormattedMessage } from 'react-intl';
import PropTypes from 'prop-types';
import Relay from 'react-relay';
import IconEdit from 'material-ui/svg-icons/image/edit';
import ProjectRoute from '../ProjectRoute';
import Can from '../../components/Can';
import CheckContext from '../../CheckContext';
import { SmallerStyledIconButton } from '../../styles/js/shared';

class ProjectMenu extends Component {
  handleEditClick() {
    const { history } = new CheckContext(this).getContextStore();
    history.push(`${window.location.pathname.match(/.*\/project\/\d+/)[0]}/edit`);
  }

  render() {
    const { project } = this.props;

    const editProjectButton = (
      <SmallerStyledIconButton
        onClick={this.handleEditClick.bind(this)}
        tooltip={<FormattedMessage id="projectMenuRelay.editProject" defaultMessage="Edit project" />}
      >
        <IconEdit />
      </SmallerStyledIconButton>
    );

    return (
      <Can permissions={project.permissions} permission="update Project">
        <div
          key="projectMenuRelay.editProject"
          className="project-menu"
        >
          {editProjectButton}
        </div>
      </Can>
    );
  }
}

ProjectMenu.contextTypes = {
  store: PropTypes.object,
};

const ProjectMenuContainer = Relay.createContainer(ProjectMenu, {
  fragments: {
    project: () => Relay.QL`
      fragment on Project {
        id,
        dbid,
        title,
        description,
        permissions,
        team {
          id,
          dbid,
          slug,
          permissions,
          limits
        }
      }
    `,
  },
});

const ProjectMenuRelay = (props) => {
  const { mediaId, sourceId } = props.params;
  if (mediaId || sourceId) {
    return null;
  }
  if (props.params && props.params.projectId) {
    const route = new ProjectRoute({ contextId: props.params.projectId });
    return <Relay.RootContainer Component={ProjectMenuContainer} route={route} />;
  }
  return null;
};

export default ProjectMenuRelay;
<|endoftext|>


<commit_before>import puppeteer from 'puppeteer';
import { toMatchImageSnapshot } from 'jest-image-snapshot';
import { logger } from '@storybook/node-logger';
import { constructUrl } from './url';

expect.extend({ toMatchImageSnapshot });

// We consider taking the full page is a reasonnable default.
const defaultScreenshotOptions = () => ({ fullPage: true });

const noop = () => {};
const asyncNoop = async () => {};

const defaultConfig = {
  storybookUrl: 'http://localhost:6006',
  chromeExecutablePath: undefined,
  getMatchOptions: noop,
  getScreenshotOptions: defaultScreenshotOptions,
  beforeScreenshot: noop,
  afterScreenshot: noop,
  getGotoOptions: noop,
  customizePage: asyncNoop,
  getCustomBrowser: undefined,
};

export const imageSnapshot = (customConfig = {}) => {
  const {
    storybookUrl,
    chromeExecutablePath,
    getMatchOptions,
    getScreenshotOptions,
    beforeScreenshot,
    afterScreenshot,
    getGotoOptions,
    customizePage,
    getCustomBrowser,
  } = { ...defaultConfig, ...customConfig };

  let browser; // holds ref to browser. (ie. Chrome)
  let page; // Hold ref to the page to screenshot.

  const testFn = async ({ context }) => {
    const { kind, framework, name } = context;
    if (framework === 'rn') {
      // Skip tests since we de not support RN image snapshots.
      logger.error(
        "It seems you are running imageSnapshot on RN app and it's not supported. Skipping test."
      );

      return;
    }
    const url = constructUrl(storybookUrl, kind, name);

    if (!browser || !page) {
      logger.error(
        `Error when generating image snapshot for test ${kind} - ${name} : It seems the headless browser is not running.`
      );

      throw new Error('no-headless-browser-running');
    }

    expect.assertions(1);

    let image;
    try {
      await customizePage(page);
      await page.goto(url, getGotoOptions({ context, url }));
      await beforeScreenshot(page, { context, url });
      image = await page.screenshot(getScreenshotOptions({ context, url }));
      await beforeScreenshot({ image, context });
    } catch (e) {
      logger.error(
        `Error when connecting to ${url}, did you start or build the storybook first? A storybook instance should be running or a static version should be built when using image snapshot feature.`,
        e
      );
      throw e;
    }

    expect(image).toMatchImageSnapshot(getMatchOptions({ context, url }));
  };

  testFn.afterAll = () => {
    if (getCustomBrowser && page) {
      return page.close();
    }

    return browser.close();
  };

  testFn.beforeAll = async () => {
    if (getCustomBrowser) {
      browser = await getCustomBrowser();
    } else {
      // add some options "no-sandbox" to make it work properly on some Linux systems as proposed here: https://github.com/Googlechrome/puppeteer/issues/290#issuecomment-322851507
      browser = await puppeteer.launch({
        args: ['--no-sandbox ', '--disable-setuid-sandbox', '--disable-dev-shm-usage'],
        executablePath: chromeExecutablePath,
      });
    }

    page = await browser.newPage();
  };

  return testFn;
};
<commit_msg>fix typo<commit_after>import puppeteer from 'puppeteer';
import { toMatchImageSnapshot } from 'jest-image-snapshot';
import { logger } from '@storybook/node-logger';
import { constructUrl } from './url';

expect.extend({ toMatchImageSnapshot });

// We consider taking the full page is a reasonnable default.
const defaultScreenshotOptions = () => ({ fullPage: true });

const noop = () => {};
const asyncNoop = async () => {};

const defaultConfig = {
  storybookUrl: 'http://localhost:6006',
  chromeExecutablePath: undefined,
  getMatchOptions: noop,
  getScreenshotOptions: defaultScreenshotOptions,
  beforeScreenshot: noop,
  afterScreenshot: noop,
  getGotoOptions: noop,
  customizePage: asyncNoop,
  getCustomBrowser: undefined,
};

export const imageSnapshot = (customConfig = {}) => {
  const {
    storybookUrl,
    chromeExecutablePath,
    getMatchOptions,
    getScreenshotOptions,
    beforeScreenshot,
    afterScreenshot,
    getGotoOptions,
    customizePage,
    getCustomBrowser,
  } = { ...defaultConfig, ...customConfig };

  let browser; // holds ref to browser. (ie. Chrome)
  let page; // Hold ref to the page to screenshot.

  const testFn = async ({ context }) => {
    const { kind, framework, name } = context;
    if (framework === 'rn') {
      // Skip tests since we de not support RN image snapshots.
      logger.error(
        "It seems you are running imageSnapshot on RN app and it's not supported. Skipping test."
      );

      return;
    }
    const url = constructUrl(storybookUrl, kind, name);

    if (!browser || !page) {
      logger.error(
        `Error when generating image snapshot for test ${kind} - ${name} : It seems the headless browser is not running.`
      );

      throw new Error('no-headless-browser-running');
    }

    expect.assertions(1);

    let image;
    try {
      await customizePage(page);
      await page.goto(url, getGotoOptions({ context, url }));
      await beforeScreenshot(page, { context, url });
      image = await page.screenshot(getScreenshotOptions({ context, url }));
      await afterScreenshot({ image, context });
    } catch (e) {
      logger.error(
        `Error when connecting to ${url}, did you start or build the storybook first? A storybook instance should be running or a static version should be built when using image snapshot feature.`,
        e
      );
      throw e;
    }

    expect(image).toMatchImageSnapshot(getMatchOptions({ context, url }));
  };

  testFn.afterAll = () => {
    if (getCustomBrowser && page) {
      return page.close();
    }

    return browser.close();
  };

  testFn.beforeAll = async () => {
    if (getCustomBrowser) {
      browser = await getCustomBrowser();
    } else {
      // add some options "no-sandbox" to make it work properly on some Linux systems as proposed here: https://github.com/Googlechrome/puppeteer/issues/290#issuecomment-322851507
      browser = await puppeteer.launch({
        args: ['--no-sandbox ', '--disable-setuid-sandbox', '--disable-dev-shm-usage'],
        executablePath: chromeExecutablePath,
      });
    }

    page = await browser.newPage();
  };

  return testFn;
};
<|endoftext|>


<commit_before>Date.CultureInfo = {
	/* Culture Name */
    name: "ar-SY",
    englishName: "Arabic (Syria)",
    nativeName: "العربية (سوريا)",

    /* Day Name Strings */
    dayNames: ["الاحد", "الاثنين", "الثلاثاء", "الاربعاء", "الخميس", "الجمعة", "السبت"],
    abbreviatedDayNames: ["الاحد", "الاثنين", "الثلاثاء", "الاربعاء", "الخميس", "الجمعة", "السبت"],
    shortestDayNames: ["أ", "ا", "ث", "أ", "خ", "ج", "س"],
    firstLetterDayNames: ["أ", "ا", "ث", "أ", "خ", "ج", "س"],

    /* Month Name Strings */
    monthNames: ["كانون الثاني", "شباط", "آذار", "نيسان", "أيار", "حزيران", "تموز", "آب", "أيلول", "تشرين الأول", "تشرين الثاني", "كانون الأول"],
    abbreviatedMonthNames: ["كانون الثاني", "شباط", "آذار", "نيسان", "أيار", "حزيران", "تموز", "آب", "أيلول", "تشرين الأول", "تشرين الثاني", "كانون الأول"],

	/* AM/PM Designators */
    amDesignator: "ص",
    pmDesignator: "م",

    firstDayOfWeek: 6,
    twoDigitYearMax: 2029,

    /**
     * The dateElementOrder is based on the order of the
     * format specifiers in the formatPatterns.DatePattern.
     *
     * Example:

     shortDatePattern    dateElementOrder
     ------------------  ----------------
     "M/d/yyyy"          "mdy"
     "dd/MM/yyyy"        "dmy"
     "yyyy-MM-dd"        "ymd"

     *
     * The correct dateElementOrder is required by the parser to
     * determine the expected order of the date elements in the
     * string being parsed.
     */
    dateElementOrder: "dmy",

    /* Standard date and time format patterns */
    formatPatterns: {
        shortDate: "dd/MM/yyyy",
        longDate: "dd MMMM, yyyy",
        shortTime: "hh:mm tt",
        longTime: "hh:mm:ss tt",
        fullDateTime: "dd MMMM, yyyy hh:mm:ss tt",
        sortableDateTime: "yyyy-MM-ddTHH:mm:ss",
        universalSortableDateTime: "yyyy-MM-dd HH:mm:ssZ",
        rfc1123: "ddd, dd MMM yyyy HH:mm:ss GMT",
        monthDay: "dd MMMM",
        yearMonth: "MMMM, yyyy"
    },

    /**
     * NOTE: If a string format is not parsing correctly, but
     * you would expect it parse, the problem likely lies below.
     *
     * The following regex patterns control most of the string matching
     * within the parser.
     *
     * The Month name and Day name patterns were automatically generated
     * and in general should be (mostly) correct.
     *
     * Beyond the month and day name patterns are natural language strings.
     * Example: "next", "today", "months"
     *
     * These natural language string may NOT be correct for this culture.
     * If they are not correct, please translate and edit this file
     * providing the correct regular expression pattern.
     *
     * If you modify this file, please post your revised CultureInfo file
     * to the Datejs Forum located at http://www.datejs.com/forums/.
     *
     * Please mark the subject of the post with [CultureInfo]. Example:
     *    Subject: [CultureInfo] Translated "da-DK" Danish(Denmark)
     *
     * We will add the modified patterns to the master source files.
     *
     * As well, please review the list of "Future Strings" section below.
     */
    regexPatterns: {
        jan: /^كانون الثاني/i,
        feb: /^شباط/i,
        mar: /^آذار/i,
        apr: /^نيسان/i,
        may: /^أيار/i,
        jun: /^حزيران/i,
        jul: /^تموز/i,
        aug: /^آب/i,
        sep: /^أيلول/i,
        oct: /^تشرين الأول/i,
        nov: /^تشرين الثاني/i,
        dec: /^كانون الأول/i,

        sun: /^الاحد/i,
        mon: /^ا(1)?/i,
        tue: /^الثلاثاء/i,
        wed: /^الاربعاء/i,
        thu: /^الخميس/i,
        fri: /^الجمعة/i,
        sat: /^السبت/i,

        future: /^next/i,
        past: /^last|past|prev(ious)?/i,
        add: /^(\+|aft(er)?|from|hence)/i,
        subtract: /^(\-|bef(ore)?|ago)/i,

        yesterday: /^yes(terday)?/i,
        today: /^t(od(ay)?)?/i,
        tomorrow: /^tom(orrow)?/i,
        now: /^n(ow)?/i,

        millisecond: /^ms|milli(second)?s?/i,
        second: /^sec(ond)?s?/i,
        minute: /^mn|min(ute)?s?/i,
		hour: /^h(our)?s?/i,
		week: /^w(eek)?s?/i,
        month: /^m(onth)?s?/i,
        day: /^d(ay)?s?/i,
        year: /^y(ear)?s?/i,

        shortMeridian: /^(a|p)/i,
        longMeridian: /^(a\.?m?\.?|p\.?m?\.?)/i,
        timezone: /^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt|utc)/i,
        ordinalSuffix: /^\s*(st|nd|rd|th)/i,
        timeContext: /^\s*(\:|a(?!u|p)|p)/i
    },

	timezones: [{name:"UTC", offset:"-000"}, {name:"GMT", offset:"-000"}, {name:"EST", offset:"-0500"}, {name:"EDT", offset:"-0400"}, {name:"CST", offset:"-0600"}, {name:"CDT", offset:"-0500"}, {name:"MST", offset:"-0700"}, {name:"MDT", offset:"-0600"}, {name:"PST", offset:"-0800"}, {name:"PDT", offset:"-0700"}]
};

/********************
 ** Future Strings **
 ********************
 *
 * The following list of strings may not be currently being used, but
 * may be incorporated into the Datejs library later.
 *
 * We would appreciate any help translating the strings below.
 *
 * If you modify this file, please post your revised CultureInfo file
 * to the Datejs Forum located at http://www.datejs.com/forums/.
 *
 * Please mark the subject of the post with [CultureInfo]. Example:
 *    Subject: [CultureInfo] Translated "da-DK" Danish(Denmark)b
 *
 * English Name        Translated
 * ------------------  -----------------
 * about               about
 * ago                 ago
 * date                date
 * time                time
 * calendar            calendar
 * show                show
 * hourly              hourly
 * daily               daily
 * weekly              weekly
 * bi-weekly           bi-weekly
 * fortnight           fortnight
 * monthly             monthly
 * bi-monthly          bi-monthly
 * quarter             quarter
 * quarterly           quarterly
 * yearly              yearly
 * annual              annual
 * annually            annually
 * annum               annum
 * again               again
 * between             between
 * after               after
 * from now            from now
 * repeat              repeat
 * times               times
 * per                 per
 * min (abbrev minute) min
 * morning             morning
 * noon                noon
 * night               night
 * midnight            midnight
 * mid-night           mid-night
 * evening             evening
 * final               final
 * future              future
 * spring              spring
 * summer              summer
 * fall                fall
 * winter              winter
 * end of              end of
 * end                 end
 * long                long
 * short               short
 */<commit_msg>[FIX] replace uncommon month names of the ar_SY datejs localization file by more standard ones, courtesy of Ahmad Khayyat<commit_after>Date.CultureInfo = {
	/* Culture Name */
    name: "ar-SY",
    englishName: "Arabic (Syria)",
    nativeName: "العربية (سوريا)",

    /* Day Name Strings */
    dayNames: ["الاحد", "الاثنين", "الثلاثاء", "الاربعاء", "الخميس", "الجمعة", "السبت"],
    abbreviatedDayNames: ["الاحد", "الاثنين", "الثلاثاء", "الاربعاء", "الخميس", "الجمعة", "السبت"],
    shortestDayNames: ["أ", "ا", "ث", "أ", "خ", "ج", "س"],
    firstLetterDayNames: ["أ", "ا", "ث", "أ", "خ", "ج", "س"],

    /* Month Name Strings */
    monthNames: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"],
    abbreviatedMonthNames: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"],

	/* AM/PM Designators */
    amDesignator: "ص",
    pmDesignator: "م",

    firstDayOfWeek: 6,
    twoDigitYearMax: 2029,

    /**
     * The dateElementOrder is based on the order of the
     * format specifiers in the formatPatterns.DatePattern.
     *
     * Example:

     shortDatePattern    dateElementOrder
     ------------------  ----------------
     "M/d/yyyy"          "mdy"
     "dd/MM/yyyy"        "dmy"
     "yyyy-MM-dd"        "ymd"

     *
     * The correct dateElementOrder is required by the parser to
     * determine the expected order of the date elements in the
     * string being parsed.
     */
    dateElementOrder: "dmy",

    /* Standard date and time format patterns */
    formatPatterns: {
        shortDate: "dd/MM/yyyy",
        longDate: "dd MMMM, yyyy",
        shortTime: "hh:mm tt",
        longTime: "hh:mm:ss tt",
        fullDateTime: "dd MMMM, yyyy hh:mm:ss tt",
        sortableDateTime: "yyyy-MM-ddTHH:mm:ss",
        universalSortableDateTime: "yyyy-MM-dd HH:mm:ssZ",
        rfc1123: "ddd, dd MMM yyyy HH:mm:ss GMT",
        monthDay: "dd MMMM",
        yearMonth: "MMMM, yyyy"
    },

    /**
     * NOTE: If a string format is not parsing correctly, but
     * you would expect it parse, the problem likely lies below.
     *
     * The following regex patterns control most of the string matching
     * within the parser.
     *
     * The Month name and Day name patterns were automatically generated
     * and in general should be (mostly) correct.
     *
     * Beyond the month and day name patterns are natural language strings.
     * Example: "next", "today", "months"
     *
     * These natural language string may NOT be correct for this culture.
     * If they are not correct, please translate and edit this file
     * providing the correct regular expression pattern.
     *
     * If you modify this file, please post your revised CultureInfo file
     * to the Datejs Forum located at http://www.datejs.com/forums/.
     *
     * Please mark the subject of the post with [CultureInfo]. Example:
     *    Subject: [CultureInfo] Translated "da-DK" Danish(Denmark)
     *
     * We will add the modified patterns to the master source files.
     *
     * As well, please review the list of "Future Strings" section below.
     */
    regexPatterns: {
        jan: /^يناير/i,
        feb: /^فبراير/i,
        mar: /^مارس/i,
        apr: /^أبريل/i,
        may: /^مايو/i,
        jun: /^يونيو/i,
        jul: /^يوليو/i,
        aug: /^أغسطس/i,
        sep: /^سبتمبر/i,
        oct: /^أكتوبر/i,
        nov: /^نوفمبر/i,
        dec: /^ديسمبر/i,

        sun: /^الاحد/i,
        mon: /^ا(1)?/i,
        tue: /^الثلاثاء/i,
        wed: /^الاربعاء/i,
        thu: /^الخميس/i,
        fri: /^الجمعة/i,
        sat: /^السبت/i,

        future: /^next/i,
        past: /^last|past|prev(ious)?/i,
        add: /^(\+|aft(er)?|from|hence)/i,
        subtract: /^(\-|bef(ore)?|ago)/i,

        yesterday: /^yes(terday)?/i,
        today: /^t(od(ay)?)?/i,
        tomorrow: /^tom(orrow)?/i,
        now: /^n(ow)?/i,

        millisecond: /^ms|milli(second)?s?/i,
        second: /^sec(ond)?s?/i,
        minute: /^mn|min(ute)?s?/i,
		hour: /^h(our)?s?/i,
		week: /^w(eek)?s?/i,
        month: /^m(onth)?s?/i,
        day: /^d(ay)?s?/i,
        year: /^y(ear)?s?/i,

        shortMeridian: /^(a|p)/i,
        longMeridian: /^(a\.?m?\.?|p\.?m?\.?)/i,
        timezone: /^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt|utc)/i,
        ordinalSuffix: /^\s*(st|nd|rd|th)/i,
        timeContext: /^\s*(\:|a(?!u|p)|p)/i
    },

	timezones: [{name:"UTC", offset:"-000"}, {name:"GMT", offset:"-000"}, {name:"EST", offset:"-0500"}, {name:"EDT", offset:"-0400"}, {name:"CST", offset:"-0600"}, {name:"CDT", offset:"-0500"}, {name:"MST", offset:"-0700"}, {name:"MDT", offset:"-0600"}, {name:"PST", offset:"-0800"}, {name:"PDT", offset:"-0700"}]
};

/********************
 ** Future Strings **
 ********************
 *
 * The following list of strings may not be currently being used, but
 * may be incorporated into the Datejs library later.
 *
 * We would appreciate any help translating the strings below.
 *
 * If you modify this file, please post your revised CultureInfo file
 * to the Datejs Forum located at http://www.datejs.com/forums/.
 *
 * Please mark the subject of the post with [CultureInfo]. Example:
 *    Subject: [CultureInfo] Translated "da-DK" Danish(Denmark)b
 *
 * English Name        Translated
 * ------------------  -----------------
 * about               about
 * ago                 ago
 * date                date
 * time                time
 * calendar            calendar
 * show                show
 * hourly              hourly
 * daily               daily
 * weekly              weekly
 * bi-weekly           bi-weekly
 * fortnight           fortnight
 * monthly             monthly
 * bi-monthly          bi-monthly
 * quarter             quarter
 * quarterly           quarterly
 * yearly              yearly
 * annual              annual
 * annually            annually
 * annum               annum
 * again               again
 * between             between
 * after               after
 * from now            from now
 * repeat              repeat
 * times               times
 * per                 per
 * min (abbrev minute) min
 * morning             morning
 * noon                noon
 * night               night
 * midnight            midnight
 * mid-night           mid-night
 * evening             evening
 * final               final
 * future              future
 * spring              spring
 * summer              summer
 * fall                fall
 * winter              winter
 * end of              end of
 * end                 end
 * long                long
 * short               short
 */
<|endoftext|>


<commit_before>$(document).ready(function(){

  $('a.sidemenu-item#sidemenu-user').click(function() {
    if ($('li.dropdown#sidemenu-user').hasClass('open')) {
        $('li.dropdown#sidemenu-user').removeClass('open');
    } else {
        $('li.dropdown#sidemenu-user').addClass('open');
    }
  });
  $('i.pull-right.fa.fa-angle-left').click(function() {
    if ($('body').hasClass('sidemenu-open')) {
      $('body').removeClass('sidemenu-open');
      $('i.pull-right.fa.fa-angle-left').toggleClass('fa-angle-left fa-angle-right');
      $(".logo-icon").rotate({ angle:0,animateTo:270, duration: 2000, easing: $.easing.easeOutBounce })
    } else {
      $('body').addClass('sidemenu-open');
      $('i.pull-right.fa.fa-angle-right').toggleClass('fa-angle-right fa-angle-left');
      $(".logo-icon").rotate({ angle:270,animateTo:0, duration: 2000, easing: $.easing.easeOutBounce })
    }
  });
});
<commit_msg>[OWL-144] Clicking outside also closes the UIC dropdown menu.<commit_after>$(document).ready(function(){

  $('a.sidemenu-item#sidemenu-user').click(function() {
    if ($('li.dropdown#sidemenu-user').hasClass('open')) {
        $('li.dropdown#sidemenu-user').removeClass('open');
    } else {
        $('li.dropdown#sidemenu-user').addClass('open');
    }
  });
  $('i.pull-right.fa.fa-angle-left').click(function() {
    if ($('body').hasClass('sidemenu-open')) {
      $('body').removeClass('sidemenu-open');
      $('i.pull-right.fa.fa-angle-left').toggleClass('fa-angle-left fa-angle-right');
      $(".logo-icon").rotate({ angle:0,animateTo:270, duration: 2000, easing: $.easing.easeOutBounce })
    } else {
      $('body').addClass('sidemenu-open');
      $('i.pull-right.fa.fa-angle-right').toggleClass('fa-angle-right fa-angle-left');
      $(".logo-icon").rotate({ angle:270,animateTo:0, duration: 2000, easing: $.easing.easeOutBounce })
    }
  });
  $(document).click(function(){
      $('li.dropdown#sidemenu-user').removeClass('open');
  });
  $('li.dropdown#sidemenu-user').click(function(e){
      e.stopPropagation();
  });
});
<|endoftext|>


<commit_before>/**
 * @fileOverview Requirejs module containing HTML5 video and audio media wrapper
 *
 * @preserve Copyright (c) 2013 British Broadcasting Corporation
 * (http://www.bbc.co.uk) and TAL Contributors (1)
 *
 * (1) TAL Contributors are listed in the AUTHORS file and at
 *     https://github.com/fmtvp/TAL/AUTHORS - please extend this file,
 *     not this notice.
 *
 * @license 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.
 *
 * All rights reserved
 * Please contact us for an alternative licence
 */

require.def(
    'antie/devices/media/html5',
    [
        'antie/devices/device',
        'antie/devices/media/mediainterface',
        'antie/events/mediaevent',
        'antie/events/mediaerrorevent',
        'antie/events/mediasourceerrorevent',
        'antie/mediasource',
        'antie/application'
    ],
    function(Device, MediaInterface, MediaEvent, MediaErrorEvent, MediaSourceErrorEvent, MediaSource, Application) {
        var currentPlayer = null;
        var isMuted = null;
        var currentVolume = -1;

        var HTML5Player = MediaInterface.extend({
            init: function(id, mediaType, eventHandlingCallback) {
                this._super(id);

                this._eventHandlingCallback = eventHandlingCallback;

                if (mediaType == "audio") {
                    this._mediaType = "audio";
                } else if (mediaType == "video") {
                    this._mediaType = "video";
                } else {
                    throw new Error('Unrecognised media type: ' + mediaType);
                }

                // Create the DOM element now so the wrapped functions can modify attributes
                // before it is placed in the Document during rendering.
                var device = Application.getCurrentApplication().getDevice();
                this._mediaElement = device._createElement(this._mediaType, this.id);

                if (currentVolume != -1) {
                    this._mediaElement.volume = currentVolume;
                } else {
                    currentVolume = this._mediaElement.volume;
                }
                if (isMuted !== null) {
                    this._mediaElement.muted = isMuted;
                } else {
                    isMuted = this._mediaElement.muted;
                }

                this._eventWrapper = null;
                this._errorEventWrapper = null;
            },
            render: function(device) {
                if (!this._renderCalled) {
                    this._renderCalled = true;

                    // Convert all media events into our internal representation and bubble them through
                    // the UI widgets
                    var self = this;
                    this._eventWrapper = function(evt) {
                        self._eventHandlingCallback(new MediaEvent(evt.type, self));
                    };
                    this._errorEventWrapper = function(evt) {
                        var errCode = self._mediaElement.error ? self._mediaElement.error.code : MediaInterface.MEDIA_ERR_UNKNOWN;
                        self._eventHandlingCallback(new MediaErrorEvent(self, errCode));
                    };
                    for (var i = 0; i < MediaEvent.TYPES.length; i++) {
                        this._mediaElement.addEventListener(MediaEvent.TYPES[i], this._eventWrapper, true);
                    }
                    this._mediaElement.addEventListener("error", this._errorEventWrapper, true);
                }

                return this._mediaElement;
            },
            // (not part of HTML5 media)
            setWindow: function(left, top, width, height) {
                if (this._mediaType == "audio") {
                    throw new Error('Unable to set window size for HTML5 audio.');
                }
                var device = Application.getCurrentApplication().getDevice();
                device.setElementSize(this._mediaElement, {width:width, height:height});
                device.setElementPosition(this._mediaElement, {left:left, top:top});
            },
            // readonly attribute MediaError error;
            getError: function() {
                return this._mediaElement.error;
            },
            _supportsTypeAttribute: function() {
                return true;
            },
            _requiresWebkitMemoryLeakFix: function() {
                return false;
            },
            // Similar to src attribute or 'source' child elements:
            // attribute DOMString src;
            setSources: function(sources, tags) {
                var self = this;
                var device = Application.getCurrentApplication().getDevice();
                var oldSources = this._mediaElement.getElementsByTagName('source');
                var supportsTypeAttribute = this._supportsTypeAttribute();

                while (oldSources.length) {
                    device.removeElement(oldSources[0]);
                }
                for (var i = 0; i < sources.length; i++) {
                    var source = document.createElement('source');
                    if (supportsTypeAttribute) {
                        source.type = sources[i].getContentType();
                    }
                    source.src = sources[i].getURL(tags);

                    device.appendChildElement(this._mediaElement, source);

                    (function(source) {
                        source._errorEventListener = function(evt) {
                            var errCode = self._mediaElement.error ? self._mediaElement.error.code : MediaInterface.MEDIA_ERR_UNKNOWN;
                            self._eventHandlingCallback(new MediaSourceErrorEvent(
                                self,
                                errCode,
                                source.src,
                                self._mediaElement.networkState === HTMLMediaElement.NETWORK_NO_SOURCE
                            ));
                            evt.stopPropagation();
                        };
                        source.addEventListener("error", source._errorEventListener, true);
                    })(source);
                }
            },
            getSources: function() {
                var sources = [];
                if (this._mediaElement.src) {
                    sources.push(new MediaSource(this._mediaElement.src, this._mediaElement.type));
                } else {
                    var sourceElements = this._mediaElement.getElementsByTagName('source');
                    for (var i = 0; i < sourceElements.length; i++) {
                        sources.push(new MediaSource(sourceElements[i].src, sourceElements[i].type));
                    }
                }
                return sources;
            },
            // readonly attribute DOMString currentSrc;
            getCurrentSource: function() {
                // Some browsers URI encode apostrophes, others don't. Make sure they're all URI encoded.
                return this._mediaElement.currentSrc.replace(/'/g, "%27");
            },
            /*
             const unsigned short NETWORK_EMPTY = 0;
             const unsigned short NETWORK_IDLE = 1;
             const unsigned short NETWORK_LOADING = 2;
             const unsigned short NETWORK_NO_SOURCE = 3;
             readonly attribute unsigned short networkState;
             */
            getNetworkState: function() {
                return this._mediaElement.networkState;
            },
            // attribute DOMString preload;
            // @returns "none", "metadata" or "auto"
            getPreload: function() {
                return this._mediaElement.preload;
            },
            setPreload: function(preload) {
                this._mediaElement.preload = preload;
            },
            // readonly attribute TimeRanges buffered;
            getBuffered: function() {
                return this._mediaElement.buffered;
            },
            // void load();
            load: function() {
                return this._mediaElement.load();
            },
            // DOMString canPlayType(in DOMString type);
            canPlayType: function(type) {
                return this._mediaElement.canPlayType(type);
            },
            /*
             const unsigned short HAVE_NOTHING = 0;
             const unsigned short HAVE_METADATA = 1;
             const unsigned short HAVE_CURRENT_DATA = 2;
             const unsigned short HAVE_FUTURE_DATA = 3;
             const unsigned short HAVE_ENOUGH_DATA = 4;
             readonly attribute unsigned short readyState;
             */
            getReadyState: function() {
                return this._mediaElement.readyState;
            },
            // readonly attribute boolean seeking;
            getSeeking: function() {
                return this._mediaElement.seeking;
            },
            // attribute double currentTime;
            setCurrentTime: function(currentTime) {
                this._mediaElement.currentTime = currentTime;
            },
            getCurrentTime: function() {
                return this._mediaElement.currentTime;
            },
            // readonly attribute double initialTime;
            getInitialTime: function() {
                return this._mediaElement.initialTime;
            },
            // readonly attribute double duration;
            getDuration: function() {
                return this._mediaElement.duration;
            },
            // readonly attribute Date startOffsetTime;
            getStartOffsetTime: function() {
                return this._mediaElement.startOffsetTime;
            },
            // readonly attribute boolean paused;
            getPaused: function() {
                return this._mediaElement.paused;
            },
            // attribute double defaultPlaybackRate;
            getDefaultPlaybackRate: function() {
                return this._mediaElement.defaultPlaybackRate;
            },
            // attribute double playbackRate;
            getPlaybackRate: function() {
                return this._mediaElement.playbackRate;
            },
            setPlaybackRate: function(playbackRate) {
                this._mediaElement.playbackRate = playbackRate;
            },
            // readonly attribute TimeRanges played;
            getPlayed: function() {
                return this._mediaElement.played;
            },
            // readonly attribute TimeRanges seekable;
            getSeekable: function() {
                return this._mediaElement.seekable;
            },
            // readonly attribute boolean ended;
            getEnded: function() {
                return this._mediaElement.ended;
            },
            // attribute boolean autoplay;
            getAutoPlay: function() {
                return this._mediaElement.autoplay;
            },
            setAutoPlay: function(autoplay) {
                this._mediaElement.autoplay = autoplay;
            },
            // attribute boolean loop;
            getLoop: function() {
                return this._mediaElement.loop;
            },
            setLoop: function(loop) {
                this._mediaElement.loop = loop;
            },
            // void play();
            play: function() {
                this._mediaElement.play();
            },
            stop: function() {
                this.pause();
            },
            // void pause();
            pause: function() {
				this._mediaElement.pause();
            },
            // attribute boolean controls;
            setNativeControls: function(controls) {
                this._mediaElement.controls = controls;
            },
            getNativeControls: function() {
                return this._mediaElement.controls;
            },
            destroy: function() {
                this.stop();

                var device = Application.getCurrentApplication().getDevice();
                device.removeElement(this._mediaElement);

                // Remove error event listeners from each source element
                var sourceElements = this._mediaElement.getElementsByTagName("source");

                // Loop through the array backwards as we remove array elements inside the loop body
                var sourceElementsLength = sourceElements.length;
                for (var sourceElementIndex = sourceElementsLength - 1; sourceElementIndex >= 0; sourceElementIndex--) {
                    var sourceElement = sourceElements[sourceElementIndex];
                    sourceElement.removeEventListener('error', sourceElement._errorEventListener, true);
                    device.removeElement(sourceElement);

                    delete sourceElements[sourceElementIndex];
                }

                delete sourceElements;

                // Remove event listeners
                for (var i = 0; i < MediaEvent.TYPES.length; i++) {
                    this._mediaElement.removeEventListener(MediaEvent.TYPES[i], this._eventWrapper, true);
                }
                this._mediaElement.removeEventListener("error", this._errorEventWrapper, true);

                // Trick to abort browser loading threads on certain webkit devices
                if(this._requiresWebkitMemoryLeakFix()) {
                    this.webkitMemoryLeakFix();
                }

                delete this._mediaElement;
                this._mediaElement = null;
                currentPlayer = null;
            },
            webkitMemoryLeakFix : function() {
                // http://stackoverflow.com/questions/5170398/ios-safari-memory-leak-when-loading-unloading-html5-video
				this._mediaElement.removeAttribute("src");
                this._mediaElement.load();
            }
        });

        Device.prototype.createMediaInterface = function(id, mediaType, eventCallback) {
            currentPlayer = new HTML5Player(id, mediaType, eventCallback);
            return currentPlayer;
        };
        Device.prototype.getPlayerEmbedMode = function(mediaType) {
            return MediaInterface.EMBED_MODE_EMBEDDED;
        };
        /**
         * Check to see if volume control is supported on this device.
         * @returns Boolean true if volume control is supported.
         */
        Device.prototype.isVolumeControlSupported = function() {
            return true;
        };
        /**
         * Get the current volume.
         * @returns The current volume (0.0 to 1.0)
         */
        Device.prototype.getVolume = function() {
            if (currentPlayer) {
                return currentPlayer._mediaElement.volume;
            }
            return currentVolume;
        };
        /**
         * Set the current volume.
         * @param {Float} volume The new volume level (0.0 to 1.0).
         */
        Device.prototype.setVolume = function(volume) {
            if (volume > 1.0) {
                this.getLogger().warn("HTML5 setVolume - Invalid volume specified (" + volume + " > 1.0). Clipped to 1.0");
                volume = 1.0;
            } else if (volume < 0.0) {
                this.getLogger().warn("HTML5 setVolume - Invalid volume specified (" + volume + " < 0.0). Clipped to 0.0");
                volume = 0;
            }
            currentVolume = volume;
            if (currentPlayer) {
                currentPlayer._mediaElement.volume = volume;
            }
        };
        /**
         * Check to see if the volume is currently muted.
         * @returns Boolean true if the device is currently muted. Otherwise false.
         */
        Device.prototype.getMuted = function() {
            if (currentPlayer) {
                return currentPlayer._mediaElement.muted;
            }
            return isMuted;
        };
        /**
         * Mute or unmute the device.
         * @param {Boolean} muted The new muted state. Boolean true to mute, false to unmute.
         */
        Device.prototype.setMuted = function(muted) {
            isMuted = muted;
            if (currentPlayer) {
                currentPlayer._mediaElement.muted = muted;
            }
        };
        return HTML5Player;
    }
);
<commit_msg>TVPJSFRMWK-1862 fixing this reference<commit_after>/**
 * @fileOverview Requirejs module containing HTML5 video and audio media wrapper
 *
 * @preserve Copyright (c) 2013 British Broadcasting Corporation
 * (http://www.bbc.co.uk) and TAL Contributors (1)
 *
 * (1) TAL Contributors are listed in the AUTHORS file and at
 *     https://github.com/fmtvp/TAL/AUTHORS - please extend this file,
 *     not this notice.
 *
 * @license 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.
 *
 * All rights reserved
 * Please contact us for an alternative licence
 */

require.def(
    'antie/devices/media/html5',
    [
        'antie/devices/device',
        'antie/devices/media/mediainterface',
        'antie/events/mediaevent',
        'antie/events/mediaerrorevent',
        'antie/events/mediasourceerrorevent',
        'antie/mediasource',
        'antie/application'
    ],
    function(Device, MediaInterface, MediaEvent, MediaErrorEvent, MediaSourceErrorEvent, MediaSource, Application) {
        var currentPlayer = null;
        var isMuted = null;
        var currentVolume = -1;

        var HTML5Player = MediaInterface.extend({
            init: function(id, mediaType, eventHandlingCallback) {
                this._super(id);

                this._eventHandlingCallback = eventHandlingCallback;

                if (mediaType == "audio") {
                    this._mediaType = "audio";
                } else if (mediaType == "video") {
                    this._mediaType = "video";
                } else {
                    throw new Error('Unrecognised media type: ' + mediaType);
                }

                // Create the DOM element now so the wrapped functions can modify attributes
                // before it is placed in the Document during rendering.
                var device = Application.getCurrentApplication().getDevice();
                this._mediaElement = device._createElement(this._mediaType, id);

                if (currentVolume != -1) {
                    this._mediaElement.volume = currentVolume;
                } else {
                    currentVolume = this._mediaElement.volume;
                }
                if (isMuted !== null) {
                    this._mediaElement.muted = isMuted;
                } else {
                    isMuted = this._mediaElement.muted;
                }

                this._eventWrapper = null;
                this._errorEventWrapper = null;
            },
            render: function(device) {
                if (!this._renderCalled) {
                    this._renderCalled = true;

                    // Convert all media events into our internal representation and bubble them through
                    // the UI widgets
                    var self = this;
                    this._eventWrapper = function(evt) {
                        self._eventHandlingCallback(new MediaEvent(evt.type, self));
                    };
                    this._errorEventWrapper = function(evt) {
                        var errCode = self._mediaElement.error ? self._mediaElement.error.code : MediaInterface.MEDIA_ERR_UNKNOWN;
                        self._eventHandlingCallback(new MediaErrorEvent(self, errCode));
                    };
                    for (var i = 0; i < MediaEvent.TYPES.length; i++) {
                        this._mediaElement.addEventListener(MediaEvent.TYPES[i], this._eventWrapper, true);
                    }
                    this._mediaElement.addEventListener("error", this._errorEventWrapper, true);
                }

                return this._mediaElement;
            },
            // (not part of HTML5 media)
            setWindow: function(left, top, width, height) {
                if (this._mediaType == "audio") {
                    throw new Error('Unable to set window size for HTML5 audio.');
                }
                var device = Application.getCurrentApplication().getDevice();
                device.setElementSize(this._mediaElement, {width:width, height:height});
                device.setElementPosition(this._mediaElement, {left:left, top:top});
            },
            // readonly attribute MediaError error;
            getError: function() {
                return this._mediaElement.error;
            },
            _supportsTypeAttribute: function() {
                return true;
            },
            _requiresWebkitMemoryLeakFix: function() {
                return false;
            },
            // Similar to src attribute or 'source' child elements:
            // attribute DOMString src;
            setSources: function(sources, tags) {
                var self = this;
                var device = Application.getCurrentApplication().getDevice();
                var oldSources = this._mediaElement.getElementsByTagName('source');
                var supportsTypeAttribute = this._supportsTypeAttribute();

                while (oldSources.length) {
                    device.removeElement(oldSources[0]);
                }
                for (var i = 0; i < sources.length; i++) {
                    var source = document.createElement('source');
                    if (supportsTypeAttribute) {
                        source.type = sources[i].getContentType();
                    }
                    source.src = sources[i].getURL(tags);

                    device.appendChildElement(this._mediaElement, source);

                    (function(source) {
                        source._errorEventListener = function(evt) {
                            var errCode = self._mediaElement.error ? self._mediaElement.error.code : MediaInterface.MEDIA_ERR_UNKNOWN;
                            self._eventHandlingCallback(new MediaSourceErrorEvent(
                                self,
                                errCode,
                                source.src,
                                self._mediaElement.networkState === HTMLMediaElement.NETWORK_NO_SOURCE
                            ));
                            evt.stopPropagation();
                        };
                        source.addEventListener("error", source._errorEventListener, true);
                    })(source);
                }
            },
            getSources: function() {
                var sources = [];
                if (this._mediaElement.src) {
                    sources.push(new MediaSource(this._mediaElement.src, this._mediaElement.type));
                } else {
                    var sourceElements = this._mediaElement.getElementsByTagName('source');
                    for (var i = 0; i < sourceElements.length; i++) {
                        sources.push(new MediaSource(sourceElements[i].src, sourceElements[i].type));
                    }
                }
                return sources;
            },
            // readonly attribute DOMString currentSrc;
            getCurrentSource: function() {
                // Some browsers URI encode apostrophes, others don't. Make sure they're all URI encoded.
                return this._mediaElement.currentSrc.replace(/'/g, "%27");
            },
            /*
             const unsigned short NETWORK_EMPTY = 0;
             const unsigned short NETWORK_IDLE = 1;
             const unsigned short NETWORK_LOADING = 2;
             const unsigned short NETWORK_NO_SOURCE = 3;
             readonly attribute unsigned short networkState;
             */
            getNetworkState: function() {
                return this._mediaElement.networkState;
            },
            // attribute DOMString preload;
            // @returns "none", "metadata" or "auto"
            getPreload: function() {
                return this._mediaElement.preload;
            },
            setPreload: function(preload) {
                this._mediaElement.preload = preload;
            },
            // readonly attribute TimeRanges buffered;
            getBuffered: function() {
                return this._mediaElement.buffered;
            },
            // void load();
            load: function() {
                return this._mediaElement.load();
            },
            // DOMString canPlayType(in DOMString type);
            canPlayType: function(type) {
                return this._mediaElement.canPlayType(type);
            },
            /*
             const unsigned short HAVE_NOTHING = 0;
             const unsigned short HAVE_METADATA = 1;
             const unsigned short HAVE_CURRENT_DATA = 2;
             const unsigned short HAVE_FUTURE_DATA = 3;
             const unsigned short HAVE_ENOUGH_DATA = 4;
             readonly attribute unsigned short readyState;
             */
            getReadyState: function() {
                return this._mediaElement.readyState;
            },
            // readonly attribute boolean seeking;
            getSeeking: function() {
                return this._mediaElement.seeking;
            },
            // attribute double currentTime;
            setCurrentTime: function(currentTime) {
                this._mediaElement.currentTime = currentTime;
            },
            getCurrentTime: function() {
                return this._mediaElement.currentTime;
            },
            // readonly attribute double initialTime;
            getInitialTime: function() {
                return this._mediaElement.initialTime;
            },
            // readonly attribute double duration;
            getDuration: function() {
                return this._mediaElement.duration;
            },
            // readonly attribute Date startOffsetTime;
            getStartOffsetTime: function() {
                return this._mediaElement.startOffsetTime;
            },
            // readonly attribute boolean paused;
            getPaused: function() {
                return this._mediaElement.paused;
            },
            // attribute double defaultPlaybackRate;
            getDefaultPlaybackRate: function() {
                return this._mediaElement.defaultPlaybackRate;
            },
            // attribute double playbackRate;
            getPlaybackRate: function() {
                return this._mediaElement.playbackRate;
            },
            setPlaybackRate: function(playbackRate) {
                this._mediaElement.playbackRate = playbackRate;
            },
            // readonly attribute TimeRanges played;
            getPlayed: function() {
                return this._mediaElement.played;
            },
            // readonly attribute TimeRanges seekable;
            getSeekable: function() {
                return this._mediaElement.seekable;
            },
            // readonly attribute boolean ended;
            getEnded: function() {
                return this._mediaElement.ended;
            },
            // attribute boolean autoplay;
            getAutoPlay: function() {
                return this._mediaElement.autoplay;
            },
            setAutoPlay: function(autoplay) {
                this._mediaElement.autoplay = autoplay;
            },
            // attribute boolean loop;
            getLoop: function() {
                return this._mediaElement.loop;
            },
            setLoop: function(loop) {
                this._mediaElement.loop = loop;
            },
            // void play();
            play: function() {
                this._mediaElement.play();
            },
            stop: function() {
                this.pause();
            },
            // void pause();
            pause: function() {
				this._mediaElement.pause();
            },
            // attribute boolean controls;
            setNativeControls: function(controls) {
                this._mediaElement.controls = controls;
            },
            getNativeControls: function() {
                return this._mediaElement.controls;
            },
            destroy: function() {
                this.stop();

                var device = Application.getCurrentApplication().getDevice();
                device.removeElement(this._mediaElement);

                // Remove error event listeners from each source element
                var sourceElements = this._mediaElement.getElementsByTagName("source");

                // Loop through the array backwards as we remove array elements inside the loop body
                var sourceElementsLength = sourceElements.length;
                for (var sourceElementIndex = sourceElementsLength - 1; sourceElementIndex >= 0; sourceElementIndex--) {
                    var sourceElement = sourceElements[sourceElementIndex];
                    sourceElement.removeEventListener('error', sourceElement._errorEventListener, true);
                    device.removeElement(sourceElement);

                    delete sourceElements[sourceElementIndex];
                }

                delete sourceElements;

                // Remove event listeners
                for (var i = 0; i < MediaEvent.TYPES.length; i++) {
                    this._mediaElement.removeEventListener(MediaEvent.TYPES[i], this._eventWrapper, true);
                }
                this._mediaElement.removeEventListener("error", this._errorEventWrapper, true);

                // Trick to abort browser loading threads on certain webkit devices
                if(this._requiresWebkitMemoryLeakFix()) {
                    this.webkitMemoryLeakFix();
                }

                delete this._mediaElement;
                this._mediaElement = null;
                currentPlayer = null;
            },
            webkitMemoryLeakFix : function() {
                // http://stackoverflow.com/questions/5170398/ios-safari-memory-leak-when-loading-unloading-html5-video
				this._mediaElement.removeAttribute("src");
                this._mediaElement.load();
            }
        });

        Device.prototype.createMediaInterface = function(id, mediaType, eventCallback) {
            currentPlayer = new HTML5Player(id, mediaType, eventCallback);
            return currentPlayer;
        };
        Device.prototype.getPlayerEmbedMode = function(mediaType) {
            return MediaInterface.EMBED_MODE_EMBEDDED;
        };
        /**
         * Check to see if volume control is supported on this device.
         * @returns Boolean true if volume control is supported.
         */
        Device.prototype.isVolumeControlSupported = function() {
            return true;
        };
        /**
         * Get the current volume.
         * @returns The current volume (0.0 to 1.0)
         */
        Device.prototype.getVolume = function() {
            if (currentPlayer) {
                return currentPlayer._mediaElement.volume;
            }
            return currentVolume;
        };
        /**
         * Set the current volume.
         * @param {Float} volume The new volume level (0.0 to 1.0).
         */
        Device.prototype.setVolume = function(volume) {
            if (volume > 1.0) {
                this.getLogger().warn("HTML5 setVolume - Invalid volume specified (" + volume + " > 1.0). Clipped to 1.0");
                volume = 1.0;
            } else if (volume < 0.0) {
                this.getLogger().warn("HTML5 setVolume - Invalid volume specified (" + volume + " < 0.0). Clipped to 0.0");
                volume = 0;
            }
            currentVolume = volume;
            if (currentPlayer) {
                currentPlayer._mediaElement.volume = volume;
            }
        };
        /**
         * Check to see if the volume is currently muted.
         * @returns Boolean true if the device is currently muted. Otherwise false.
         */
        Device.prototype.getMuted = function() {
            if (currentPlayer) {
                return currentPlayer._mediaElement.muted;
            }
            return isMuted;
        };
        /**
         * Mute or unmute the device.
         * @param {Boolean} muted The new muted state. Boolean true to mute, false to unmute.
         */
        Device.prototype.setMuted = function(muted) {
            isMuted = muted;
            if (currentPlayer) {
                currentPlayer._mediaElement.muted = muted;
            }
        };
        return HTML5Player;
    }
);
<|endoftext|>


<commit_before>'use strict';
var _ = require('underscore');

// Function for parsing ClinVar data for variant object creation
// Derived from:
// https://github.com/standard-analytics/pubmed-schema-org/blob/master/lib/pubmed.js
module.exports.parseClinvar = parseClinvar;
function parseClinvar(xml, extended){
    var variant = {};
    var doc = new DOMParser().parseFromString(xml, 'text/xml');

    var $ClinVarResult = doc.getElementsByTagName('ClinVarResult-Set')[0];
    if ($ClinVarResult) {
        var $VariationReport = $ClinVarResult.getElementsByTagName('VariationReport')[0];
        if ($VariationReport) {
            // Get the ID (just in case) and Preferred Title
            variant.clinvarVariantId = $VariationReport.getAttribute('VariationID');
            variant.clinvarVariantTitle = $VariationReport.getAttribute('VariationName');
            var $Allele = $VariationReport.getElementsByTagName('Allele')[0];
            if ($Allele) {
                var $HGVSlist_raw = $Allele.getElementsByTagName('HGVSlist')[0];
                if ($HGVSlist_raw) {
                    variant.hgvsNames = {};
                    variant.hgvsNames.others = [];
                    // get the HGVS entries
                    var $HGVSlist = $HGVSlist_raw.getElementsByTagName('HGVS');
                    _.map($HGVSlist, $HGVS => {
                        let temp_hgvs = $HGVS.textContent;
                        let assembly = $HGVS.getAttribute('Assembly');
                        if (assembly) {
                            variant.hgvsNames[assembly] = temp_hgvs;
                        } else {
                            variant.hgvsNames.others.push(temp_hgvs);
                        }
                    });
                }
                variant.dbSNPIds = [];
                var $XRefList = $Allele.getElementsByTagName('XRefList')[0];
                var $XRef = $XRefList.getElementsByTagName('XRef');
                for(var i = 0; i < $XRef.length; i++) {
                    if ($XRef[i].getAttribute('DB') === 'dbSNP') {
                        variant.dbSNPIds.push($XRef[i].getAttribute('ID'));
                    }
                }
                // Call to extract more ClinVar data from XML response
                if (extended) {
                    parseClinvarExtended(variant, $Allele, $HGVSlist_raw, $VariationReport);
                }
            }
        }
    }
    return variant;
}

// Function to extract more ClinVar data than what the db stores
function parseClinvarExtended(variant, allele, hgvs_list, dataset) {
    variant.RefSeqTranscripts = {};
    variant.gene = {};
    variant.allele = {};
    variant.allele.SequenceLocation = [];
    variant.allele.ProteinChange = '';
    // Group transcripts by RefSeq nucleotide change, molecular consequence, and protein change
    variant.RefSeqTranscripts.NucleotideChangeList = [];
    variant.RefSeqTranscripts.MolecularConsequenceList = [];
    variant.RefSeqTranscripts.ProteinChangeList = [];
    // Parse <MolecularConsequence> nodes
    var MolecularConsequenceList = allele.getElementsByTagName('MolecularConsequenceList')[0];
    if (MolecularConsequenceList) {
        var MolecularConsequence = MolecularConsequenceList.getElementsByTagName('MolecularConsequence');
        for(let n of MolecularConsequence) {
            // Used for transcript tables on "Basic Information" tab in VCI
            // HGVS property for mapping to transcripts with matching HGVS names
            // SOid and Function properties for UI display
            var MolecularObj = {
                "HGVS": n.getAttribute('HGVS'),
                "SOid": n.getAttribute('SOid'),
                "Function": n.getAttribute('Function')
            };
            variant.RefSeqTranscripts.MolecularConsequenceList.push(MolecularObj);
        }
    }
    // Parse <HGVS> nodes
    var HGVSnodes = hgvs_list.getElementsByTagName('HGVS');
    if (HGVSnodes) {
        for (let x of HGVSnodes) {
            // Used for transcript tables on "Basic Information" tab in VCI
            // Type property for identifying the nucleotide change transcripts
            // and protein change transcripts
            var hgvsObj = {
                "HGVS": x.textContent,
                "Change": x.getAttribute('Change'),
                "AccessionVersion": x.getAttribute('AccessionVersion'),
                "Type": x.getAttribute('Type')
            };
            // nucleotide change
            if (x.getAttribute('Type') === 'HGVS, coding, RefSeq') {
                variant.RefSeqTranscripts.NucleotideChangeList.push(hgvsObj);
            }
            // protein change
            if (x.getAttribute('Type') === 'HGVS, protein, RefSeq') {
                variant.RefSeqTranscripts.ProteinChangeList.push(hgvsObj);
            }
        }
    }
    // Parse <gene> node
    var geneList = dataset.getElementsByTagName('GeneList')[0];
    var geneNode = geneList.getElementsByTagName('Gene')[0];
    variant.gene.symbol = geneNode.getAttribute('Symbol');
    variant.gene.full_name = geneNode.getAttribute('FullName');
    // Evaluate whether a variant has protein change
    // First check whether te <ProteinChange> node exists. If not,
    // then check whether the <HGVS> node with Type="HGVS, protein, RefSeq" attribute exists
    const protein_change = allele.getElementsByTagName('ProteinChange')[0];
    let alt_protein_change;
    if (variant.RefSeqTranscripts.ProteinChangeList.length > 0) {
        const changeAttr = variant.RefSeqTranscripts.ProteinChangeList[0].Change;
        if (changeAttr.length) {
            // Remove 'p.' from string value
            let posStart = changeAttr.indexOf('.') + 1;
            let newAttrValue = changeAttr.slice(posStart);
            // Extract the numbers into a new string
            let num = newAttrValue.match(/[0-9]+(?!.*[0-9])/);
            // Separate groups of letters into arrays
            let stringArray = newAttrValue.split(/[0-9]+(?!.*[0-9])/);
            // Transform string into the format similar to common <ProteinChange> value
            alt_protein_change = stringArray[0] + num + stringArray[1].substr(0, 1);
        }
    }
    if (protein_change) {
        variant.allele.ProteinChange = protein_change.textContent;
    } else if (alt_protein_change) {
        variant.allele.ProteinChange = alt_protein_change;
    } else {
        variant.allele.ProteinChange = null;
    }
    // Parse <SequenceLocation> nodes
    var SequenceLocationNodes = allele.getElementsByTagName('SequenceLocation');
    if (SequenceLocationNodes) {
        for(let y of SequenceLocationNodes) {
            // Properties in SequenceLocationObj are used to construct LinkOut URLs
            // Used primarily for LinkOut links on "Basic Information" tab in VCI
            // referenceAllele and alternateAllele properties are added for Population tab
            var SequenceLocationObj = {
                "Assembly": y.getAttribute('Assembly'),
                "AssemblyAccessionVersion": y.getAttribute('AssemblyAccessionVersion'),
                "AssemblyStatus": y.getAttribute('AssemblyStatus'),
                "Chr": y.getAttribute('Chr'),
                "Accession": y.getAttribute('Accession'),
                "start": y.getAttribute('start'),
                "stop": y.getAttribute('stop'),
                "referenceAllele": y.getAttribute('referenceAllele'),
                "alternateAllele": y.getAttribute('alternateAllele')
            };
            variant.allele.SequenceLocation.push(SequenceLocationObj);
        }
    }
}

// Function for parsing CAR data for variant object creation
module.exports.parseCAR = parseCAR;
function parseCAR(json) {
    var variant = {};
    // set carId in payload, since we'll always have this from a CAR response
    variant.carId = json['@id'].substring(json['@id'].indexOf('CA'));
    if (json.externalRecords) {
        // extract ClinVar data if available
        if (json.externalRecords.ClinVarVariations && json.externalRecords.ClinVarVariations.length > 0) {
            // only need the ClinVar Variation data, since we'll re-ping ClinVar with it, if available
            variant.clinvarVariantId = json.externalRecords.ClinVarVariations[0].variationId;
        }
        // extract dbSNPId data if available
        if (json.externalRecords.dbSNP && json.externalRecords.dbSNP.length > 0) {
            variant.dbSNPIds = [];
            json.externalRecords.dbSNP.map(function(dbSNPentry, i) {
                variant.dbSNPIds.push(dbSNPentry.rs);
            });
        }
    }
    variant.hgvsNames = {};
    if (json.genomicAlleles && json.genomicAlleles.length > 0) {
        json.genomicAlleles.map(function(genomicAllele, i) {
            if (genomicAllele.hgvs && genomicAllele.hgvs.length > 0) {
                // extract the genomicAlleles hgvs terms
                genomicAllele.hgvs.map(function(hgvs_temp, j) {
                    // skip the hgvs term if it starts with 'CM'
                    if (!hgvs_temp.startsWith('CM')) {
                        // if NC, file by referenceGenome
                        if (hgvs_temp.startsWith('NC')) {
                            if (genomicAllele.referenceGenome) {
                                variant.hgvsNames[genomicAllele.referenceGenome] = hgvs_temp;
                            } else {
                                variant = parseCarHgvsHandler(hgvs_temp, variant);
                            }
                        } else {
                            variant = parseCarHgvsHandler(hgvs_temp, variant);
                        }
                    }
                });
            }
        });
    }
    // extract the aminoAcidAlleles hgvs terms
    if (json.aminoAcidAlleles && json.aminoAcidAlleles.length > 0) {
        variant = parseCarHgvsLoop(json.aminoAcidAlleles, variant);
    }
    // extract the transcriptAlleles hgvs terms
    if (json.transcriptAlleles && json.transcriptAlleles.length > 0) {
        variant = parseCarHgvsLoop(json.transcriptAlleles, variant);
    }
    return variant;
}

// helper function for the parseCar() function; loops through some of the CAR's repeating
// data structures to find HGVS terms and add them to the variant object
function parseCarHgvsLoop(alleles, variant) {
    alleles.map(function(allele, i) {
        if (allele.hgvs && allele.hgvs.length > 0) {
            allele.hgvs.map(function(hgvs_temp, j) {
                variant = parseCarHgvsHandler(hgvs_temp, variant);
            });
        }
    });
    return variant;
}

// helper function for the parseCar() function: checks to see if the variant object's hgvsNames'
// others variable is set, creates it if not, and adds an HGVS term to it
function parseCarHgvsHandler(hgvs_temp, variant) {
    if (!variant.hgvsNames.others) {
        variant.hgvsNames.others = [];
    }
    variant.hgvsNames.others.push(hgvs_temp);
    return variant;
}
<commit_msg>Added a comment<commit_after>'use strict';
var _ = require('underscore');

// Function for parsing ClinVar data for variant object creation
// Derived from:
// https://github.com/standard-analytics/pubmed-schema-org/blob/master/lib/pubmed.js
module.exports.parseClinvar = parseClinvar;
function parseClinvar(xml, extended){
    var variant = {};
    var doc = new DOMParser().parseFromString(xml, 'text/xml');

    var $ClinVarResult = doc.getElementsByTagName('ClinVarResult-Set')[0];
    if ($ClinVarResult) {
        var $VariationReport = $ClinVarResult.getElementsByTagName('VariationReport')[0];
        if ($VariationReport) {
            // Get the ID (just in case) and Preferred Title
            variant.clinvarVariantId = $VariationReport.getAttribute('VariationID');
            variant.clinvarVariantTitle = $VariationReport.getAttribute('VariationName');
            var $Allele = $VariationReport.getElementsByTagName('Allele')[0];
            if ($Allele) {
                var $HGVSlist_raw = $Allele.getElementsByTagName('HGVSlist')[0];
                if ($HGVSlist_raw) {
                    variant.hgvsNames = {};
                    variant.hgvsNames.others = [];
                    // get the HGVS entries
                    var $HGVSlist = $HGVSlist_raw.getElementsByTagName('HGVS');
                    _.map($HGVSlist, $HGVS => {
                        let temp_hgvs = $HGVS.textContent;
                        let assembly = $HGVS.getAttribute('Assembly');
                        if (assembly) {
                            variant.hgvsNames[assembly] = temp_hgvs;
                        } else {
                            variant.hgvsNames.others.push(temp_hgvs);
                        }
                    });
                }
                variant.dbSNPIds = [];
                var $XRefList = $Allele.getElementsByTagName('XRefList')[0];
                var $XRef = $XRefList.getElementsByTagName('XRef');
                for(var i = 0; i < $XRef.length; i++) {
                    if ($XRef[i].getAttribute('DB') === 'dbSNP') {
                        variant.dbSNPIds.push($XRef[i].getAttribute('ID'));
                    }
                }
                // Call to extract more ClinVar data from XML response
                if (extended) {
                    parseClinvarExtended(variant, $Allele, $HGVSlist_raw, $VariationReport);
                }
            }
        }
    }
    return variant;
}

// Function to extract more ClinVar data than what the db stores
function parseClinvarExtended(variant, allele, hgvs_list, dataset) {
    variant.RefSeqTranscripts = {};
    variant.gene = {};
    variant.allele = {};
    variant.allele.SequenceLocation = [];
    variant.allele.ProteinChange = '';
    // Group transcripts by RefSeq nucleotide change, molecular consequence, and protein change
    variant.RefSeqTranscripts.NucleotideChangeList = [];
    variant.RefSeqTranscripts.MolecularConsequenceList = [];
    variant.RefSeqTranscripts.ProteinChangeList = [];
    // Parse <MolecularConsequence> nodes
    var MolecularConsequenceList = allele.getElementsByTagName('MolecularConsequenceList')[0];
    if (MolecularConsequenceList) {
        var MolecularConsequence = MolecularConsequenceList.getElementsByTagName('MolecularConsequence');
        for(let n of MolecularConsequence) {
            // Used for transcript tables on "Basic Information" tab in VCI
            // HGVS property for mapping to transcripts with matching HGVS names
            // SOid and Function properties for UI display
            var MolecularObj = {
                "HGVS": n.getAttribute('HGVS'),
                "SOid": n.getAttribute('SOid'),
                "Function": n.getAttribute('Function')
            };
            variant.RefSeqTranscripts.MolecularConsequenceList.push(MolecularObj);
        }
    }
    // Parse <HGVS> nodes
    var HGVSnodes = hgvs_list.getElementsByTagName('HGVS');
    if (HGVSnodes) {
        for (let x of HGVSnodes) {
            // Used for transcript tables on "Basic Information" tab in VCI
            // Type property for identifying the nucleotide change transcripts
            // and protein change transcripts
            var hgvsObj = {
                "HGVS": x.textContent,
                "Change": x.getAttribute('Change'),
                "AccessionVersion": x.getAttribute('AccessionVersion'),
                "Type": x.getAttribute('Type')
            };
            // nucleotide change
            if (x.getAttribute('Type') === 'HGVS, coding, RefSeq') {
                variant.RefSeqTranscripts.NucleotideChangeList.push(hgvsObj);
            }
            // protein change
            if (x.getAttribute('Type') === 'HGVS, protein, RefSeq') {
                variant.RefSeqTranscripts.ProteinChangeList.push(hgvsObj);
            }
        }
    }
    // Parse <gene> node
    var geneList = dataset.getElementsByTagName('GeneList')[0];
    var geneNode = geneList.getElementsByTagName('Gene')[0];
    variant.gene.symbol = geneNode.getAttribute('Symbol');
    variant.gene.full_name = geneNode.getAttribute('FullName');
    // Evaluate whether a variant has protein change
    // First check whether te <ProteinChange> node exists. If not,
    // then check whether the <HGVS> node with Type="HGVS, protein, RefSeq" attribute exists
    const protein_change = allele.getElementsByTagName('ProteinChange')[0];
    let alt_protein_change;
    if (variant.RefSeqTranscripts.ProteinChangeList.length > 0) {
        const changeAttr = variant.RefSeqTranscripts.ProteinChangeList[0].Change;
        if (changeAttr.length) {
            // Remove 'p.' from string value
            let posStart = changeAttr.indexOf('.') + 1;
            let newAttrValue = changeAttr.slice(posStart);
            // Extract the numbers into a new string
            let num = newAttrValue.match(/[0-9]+(?!.*[0-9])/);
            // Separate groups of letters into arrays
            let stringArray = newAttrValue.split(/[0-9]+(?!.*[0-9])/);
            // Transform string into the format similar to common <ProteinChange> value
            alt_protein_change = stringArray[0] + num + stringArray[1].substr(0, 1);
        }
    }
    // Set protein change property value
    if (protein_change) {
        variant.allele.ProteinChange = protein_change.textContent;
    } else if (alt_protein_change) {
        variant.allele.ProteinChange = alt_protein_change;
    } else {
        variant.allele.ProteinChange = null;
    }
    // Parse <SequenceLocation> nodes
    var SequenceLocationNodes = allele.getElementsByTagName('SequenceLocation');
    if (SequenceLocationNodes) {
        for(let y of SequenceLocationNodes) {
            // Properties in SequenceLocationObj are used to construct LinkOut URLs
            // Used primarily for LinkOut links on "Basic Information" tab in VCI
            // referenceAllele and alternateAllele properties are added for Population tab
            var SequenceLocationObj = {
                "Assembly": y.getAttribute('Assembly'),
                "AssemblyAccessionVersion": y.getAttribute('AssemblyAccessionVersion'),
                "AssemblyStatus": y.getAttribute('AssemblyStatus'),
                "Chr": y.getAttribute('Chr'),
                "Accession": y.getAttribute('Accession'),
                "start": y.getAttribute('start'),
                "stop": y.getAttribute('stop'),
                "referenceAllele": y.getAttribute('referenceAllele'),
                "alternateAllele": y.getAttribute('alternateAllele')
            };
            variant.allele.SequenceLocation.push(SequenceLocationObj);
        }
    }
}

// Function for parsing CAR data for variant object creation
module.exports.parseCAR = parseCAR;
function parseCAR(json) {
    var variant = {};
    // set carId in payload, since we'll always have this from a CAR response
    variant.carId = json['@id'].substring(json['@id'].indexOf('CA'));
    if (json.externalRecords) {
        // extract ClinVar data if available
        if (json.externalRecords.ClinVarVariations && json.externalRecords.ClinVarVariations.length > 0) {
            // only need the ClinVar Variation data, since we'll re-ping ClinVar with it, if available
            variant.clinvarVariantId = json.externalRecords.ClinVarVariations[0].variationId;
        }
        // extract dbSNPId data if available
        if (json.externalRecords.dbSNP && json.externalRecords.dbSNP.length > 0) {
            variant.dbSNPIds = [];
            json.externalRecords.dbSNP.map(function(dbSNPentry, i) {
                variant.dbSNPIds.push(dbSNPentry.rs);
            });
        }
    }
    variant.hgvsNames = {};
    if (json.genomicAlleles && json.genomicAlleles.length > 0) {
        json.genomicAlleles.map(function(genomicAllele, i) {
            if (genomicAllele.hgvs && genomicAllele.hgvs.length > 0) {
                // extract the genomicAlleles hgvs terms
                genomicAllele.hgvs.map(function(hgvs_temp, j) {
                    // skip the hgvs term if it starts with 'CM'
                    if (!hgvs_temp.startsWith('CM')) {
                        // if NC, file by referenceGenome
                        if (hgvs_temp.startsWith('NC')) {
                            if (genomicAllele.referenceGenome) {
                                variant.hgvsNames[genomicAllele.referenceGenome] = hgvs_temp;
                            } else {
                                variant = parseCarHgvsHandler(hgvs_temp, variant);
                            }
                        } else {
                            variant = parseCarHgvsHandler(hgvs_temp, variant);
                        }
                    }
                });
            }
        });
    }
    // extract the aminoAcidAlleles hgvs terms
    if (json.aminoAcidAlleles && json.aminoAcidAlleles.length > 0) {
        variant = parseCarHgvsLoop(json.aminoAcidAlleles, variant);
    }
    // extract the transcriptAlleles hgvs terms
    if (json.transcriptAlleles && json.transcriptAlleles.length > 0) {
        variant = parseCarHgvsLoop(json.transcriptAlleles, variant);
    }
    return variant;
}

// helper function for the parseCar() function; loops through some of the CAR's repeating
// data structures to find HGVS terms and add them to the variant object
function parseCarHgvsLoop(alleles, variant) {
    alleles.map(function(allele, i) {
        if (allele.hgvs && allele.hgvs.length > 0) {
            allele.hgvs.map(function(hgvs_temp, j) {
                variant = parseCarHgvsHandler(hgvs_temp, variant);
            });
        }
    });
    return variant;
}

// helper function for the parseCar() function: checks to see if the variant object's hgvsNames'
// others variable is set, creates it if not, and adds an HGVS term to it
function parseCarHgvsHandler(hgvs_temp, variant) {
    if (!variant.hgvsNames.others) {
        variant.hgvsNames.others = [];
    }
    variant.hgvsNames.others.push(hgvs_temp);
    return variant;
}
<|endoftext|>


<commit_before>/*!
 * a2 - oauth2 browser client
 * Copyright(c) 2012 Matti Savolainen <matti@applifier.com>
 * MIT Licensed
 */

/***
 * In browser window is global, exports window.A2. Makes it easy to unit test this.
 */
(function(exports, global) {
  var A2 = exports;
  var options = {
      site : "https://local.host:3113"
    , state : +new Date()+""+Math.floor(Math.random() * 999999)
    , handle : "a2auth"
  };

  function accessToken(token) {
    var storage = global.localStorage;
    if (token === null) {
      return storage.removeItem("A2.accessToken");
    } else if (token === undefined) {
      return storage.getItem("A2.accessToken");
    } else {
      return storage.setItem("A2.accessToken", token);
    }
  }

  /**
   * dialog window for oauth.
   */
  var dialog = null;
  var token = accessToken();

  A2.initialize = function(cfg) {
    if(!cfg.client_id) {
     throw new Error("client_id is required!");
    }
    options.client_id = cfg.client_id;
    options.display = cfg.display || "popup";
    options.scope = cfg.scope || "basic";
    options.response_type = cfg.response_type || "token";
    options.redirect_uri = cfg.redirect_uri;
    options.width = cfg.width;
    options.height = cfg.height;
    console.log(document.location.search + document.location.hash);
    var url = new A2.URL(document.location.search + document.location.hash);
    var params = url.parseParameters();
    if(params.access_token) {
      accessToken(params.access_token);
      document.location.href = document.location.search;
    }
  };

  var auth = A2.auth = null;
  A2.token = accessToken;
  var connectCallbacks = {
      success: function(token) {
        accessToken(token);
      }
    , error: function(error) {
      console.log(error);
    }
    , general: function(what) {
      console.log(what);
    }
    , disconnect: function() {
      accessToken(null);
    }
  };

  function URL(string) {
    this.url = string;
  }

  URL.prototype.mergeParams = function (url, params) {
    if(!params) {
      params = url;
      url = undefined;
    }
    if(!url) {
      url = this.url;
    }
    var baseURL = url.split("?")[0];
    var newParams = this.parseParameters(url.toString());
    params = params || {};
    for (var key in params) {
      if (params.hasOwnProperty(key)) {
        newParams[key] = params[key];
      }
    }
    var queryString = this.buildQueryString(newParams);
    if (queryString.length > 0) {
      queryString = "?" + queryString;
    }
    this.url = baseURL + queryString;
    return this.url;
  };

  URL.prototype.isRelative = function (url) {
    return url === undefined ? (this.url[0] === '/') : (url[0] === "/");
  };

  URL.prototype.buildQueryString = function (params) {
    var queryStringArray = [];
    for (var name in params) {
      if (params.hasOwnProperty(name)) {
        queryStringArray.push(encodeURIComponent(name) + "=" + encodeURIComponent(params[name]));
      }
    }
    return queryStringArray.join("&");
  };

  URL.prototype.open = function(opt, url) {
    url = url || this.url;
    opt = opt || options;
    var left = global.screenX + (global.outerWidth - opt.width) / 2;
    var top = global.screenY + (global.outerHeight - opt.height) / 2;
    var openstr = "location=1, width=" + opt.width + ", height=" + opt.height + ", top=" + top + ", left=" + left + ", toolbar=no,scrollbars=yes";
    this.w = global.open(url, opt.handle || options.handle, openstr);
    return this.w;
  };

  URL.prototype.navigate = function(url) {
    document.location.href = url || this.url;
  };

  URL.prototype.parseParameters = function (uri) {
    if(!uri) {
      uri = this.url;
    }
    var splitted = uri.split(/[&?#]/);
    if (splitted[0].match(/^http/)) {
      splitted.shift();
    }

    var obj = {};
    for (var i in splitted) {
      if (splitted.hasOwnProperty(i)) {
        var kv = splitted[i].split("=");
        if (kv[0]) {
          obj[decodeURIComponent(kv[0])] = decodeURIComponent(kv[1]);
        }
      }
    }
    return obj;
  };

  URL.prototype.get = function() {
    return this.url;
  };

  URL.prototype.secure = function(secure, url) {
    if(!url) {
      url = this.url;
    }
    if(secure === undefined) {
      return url.search(/^https:\/\//) !== -1;
    }
    if(secure === true) {
      url = url.replace(/^http:\/\//,"https://");
    }  else if (secure === false) {
      url = url.replace(/^https:\/\//,"http://");
    }
    return (this.url = url).search(/^https:\/\//) !==-1;
  };

  function Auth(opt) {
    this.token = opt.access_token || options.access_token || accessToken();
    this.client_id = opt.client_id || options.client_id;
    this.response_type = opt.response_type || options.response_type;
    if(options.redirect_uri || opt.redirect_uri) {
      this.redirect_uri = opt.redirect_uri || options.redirect_uri;
    }
    this.scope = opt.scope || options.scope;
    this.state = opt.state || options.state;
  }

  Auth.prototype.connectCallback = function() {
    var popup = A2.auth.handle;
    if(!popup) {
      popup = window;
    }
    var url = new URL(popup.location.search + popup.location.hash);
    var params = url.parseParameters();
    popup.close();

    if (params.error) {
      throw Error("OAuth2 error "+params.error.error_description || params.error.error);
    } else {
      if(this.callback) {
        return this.callback(decodeURIComponent(params.access_token));
      } else {
        return connectCallbacks.success(decodeURIComponent(params.access_token));
      }
    }
    connectCallbacks.general(params.error);
  };

  Auth.prototype.connect = function(callback) {
    connectCallbacks.success = callback;
    if(!this.client_id ) {
      throw new Error("Missing client_id!");
    }
    var url = this.url = new URL(options.site+"/oauth2/authorize");
    var params = {
        client_id:this.client_id
      , response_type:this.response_type
      , display: options.display
      , scope: this.scope
    };
    if(this.redirect_uri) {
      params.redirect_uri = this.redirect_uri;
    }

    url.mergeParams(params);

    this.callback = callback;
    if(params.display === "popup" && params.response_type === "token") {
      this.handle = url.open({
          width:640
        , height: 510
      });
    } else if(!params.display || params.display !== "popup") {
      document.location.href = url.get();
     }
  };

  /**
   * connects, ie gets access token if there is none and fetches player object.
   */
  A2.connect = function(callback) {
    var token = accessToken();
    if(token != null) {
      return callback(token);
    }
    if(!auth) {
      A2.auth = new Auth({});
    }

    A2.auth.connect(function(token) {
      accessToken(token);
      return callback(token);
    });
  }

  global.A2 = A2;
  global.A2.URL = URL;
})('object' === typeof module ? module.exports : (this.A2 = {}), "undefined" === typeof global ? window : global);<commit_msg>removed debugging<commit_after>/*!
 * a2 - oauth2 browser client
 * Copyright(c) 2012 Matti Savolainen <matti@applifier.com>
 * MIT Licensed
 */

/***
 * In browser window is global, exports window.A2. Makes it easy to unit test this.
 */
(function(exports, global) {
  var A2 = exports;
  var options = {
      site : "https://local.host:3113"
    , state : +new Date()+""+Math.floor(Math.random() * 999999)
    , handle : "a2auth"
  };

  function accessToken(token) {
    var storage = global.localStorage;
    if (token === null) {
      return storage.removeItem("A2.accessToken");
    } else if (token === undefined) {
      return storage.getItem("A2.accessToken");
    } else {
      return storage.setItem("A2.accessToken", token);
    }
  }

  /**
   * dialog window for oauth.
   */
  var dialog = null;
  var token = accessToken();

  A2.initialize = function(cfg) {
    if(!cfg.client_id) {
     throw new Error("client_id is required!");
    }
    options.client_id = cfg.client_id;
    options.display = cfg.display || "popup";
    options.scope = cfg.scope || "basic";
    options.response_type = cfg.response_type || "token";
    options.redirect_uri = cfg.redirect_uri;
    options.width = cfg.width;
    options.height = cfg.height;
    var url = new A2.URL(document.location.search + document.location.hash);
    var params = url.parseParameters();
    if(params.access_token) {
      accessToken(params.access_token);
      document.location.href = document.location.search;
    }
  };

  var auth = A2.auth = null;
  A2.token = accessToken;
  var connectCallbacks = {
      success: function(token) {
        accessToken(token);
      }
    , error: function(error) {
      console.log(error);
    }
    , general: function(what) {
      console.log(what);
    }
    , disconnect: function() {
      accessToken(null);
    }
  };

  function URL(string) {
    this.url = string;
  }

  URL.prototype.mergeParams = function (url, params) {
    if(!params) {
      params = url;
      url = undefined;
    }
    if(!url) {
      url = this.url;
    }
    var baseURL = url.split("?")[0];
    var newParams = this.parseParameters(url.toString());
    params = params || {};
    for (var key in params) {
      if (params.hasOwnProperty(key)) {
        newParams[key] = params[key];
      }
    }
    var queryString = this.buildQueryString(newParams);
    if (queryString.length > 0) {
      queryString = "?" + queryString;
    }
    this.url = baseURL + queryString;
    return this.url;
  };

  URL.prototype.isRelative = function (url) {
    return url === undefined ? (this.url[0] === '/') : (url[0] === "/");
  };

  URL.prototype.buildQueryString = function (params) {
    var queryStringArray = [];
    for (var name in params) {
      if (params.hasOwnProperty(name)) {
        queryStringArray.push(encodeURIComponent(name) + "=" + encodeURIComponent(params[name]));
      }
    }
    return queryStringArray.join("&");
  };

  URL.prototype.open = function(opt, url) {
    url = url || this.url;
    opt = opt || options;
    var left = global.screenX + (global.outerWidth - opt.width) / 2;
    var top = global.screenY + (global.outerHeight - opt.height) / 2;
    var openstr = "location=1, width=" + opt.width + ", height=" + opt.height + ", top=" + top + ", left=" + left + ", toolbar=no,scrollbars=yes";
    this.w = global.open(url, opt.handle || options.handle, openstr);
    return this.w;
  };

  URL.prototype.navigate = function(url) {
    document.location.href = url || this.url;
  };

  URL.prototype.parseParameters = function (uri) {
    if(!uri) {
      uri = this.url;
    }
    var splitted = uri.split(/[&?#]/);
    if (splitted[0].match(/^http/)) {
      splitted.shift();
    }

    var obj = {};
    for (var i in splitted) {
      if (splitted.hasOwnProperty(i)) {
        var kv = splitted[i].split("=");
        if (kv[0]) {
          obj[decodeURIComponent(kv[0])] = decodeURIComponent(kv[1]);
        }
      }
    }
    return obj;
  };

  URL.prototype.get = function() {
    return this.url;
  };

  URL.prototype.secure = function(secure, url) {
    if(!url) {
      url = this.url;
    }
    if(secure === undefined) {
      return url.search(/^https:\/\//) !== -1;
    }
    if(secure === true) {
      url = url.replace(/^http:\/\//,"https://");
    }  else if (secure === false) {
      url = url.replace(/^https:\/\//,"http://");
    }
    return (this.url = url).search(/^https:\/\//) !==-1;
  };

  function Auth(opt) {
    this.token = opt.access_token || options.access_token || accessToken();
    this.client_id = opt.client_id || options.client_id;
    this.response_type = opt.response_type || options.response_type;
    if(options.redirect_uri || opt.redirect_uri) {
      this.redirect_uri = opt.redirect_uri || options.redirect_uri;
    }
    this.scope = opt.scope || options.scope;
    this.state = opt.state || options.state;
  }

  Auth.prototype.connectCallback = function() {
    var popup = A2.auth.handle;
    if(!popup) {
      popup = window;
    }
    var url = new URL(popup.location.search + popup.location.hash);
    var params = url.parseParameters();
    popup.close();

    if (params.error) {
      throw Error("OAuth2 error "+params.error.error_description || params.error.error);
    } else {
      if(this.callback) {
        return this.callback(decodeURIComponent(params.access_token));
      } else {
        return connectCallbacks.success(decodeURIComponent(params.access_token));
      }
    }
    connectCallbacks.general(params.error);
  };

  Auth.prototype.connect = function(callback) {
    connectCallbacks.success = callback;
    if(!this.client_id ) {
      throw new Error("Missing client_id!");
    }
    var url = this.url = new URL(options.site+"/oauth2/authorize");
    var params = {
        client_id:this.client_id
      , response_type:this.response_type
      , display: options.display
      , scope: this.scope
    };
    if(this.redirect_uri) {
      params.redirect_uri = this.redirect_uri;
    }

    url.mergeParams(params);

    this.callback = callback;
    if(params.display === "popup" && params.response_type === "token") {
      this.handle = url.open({
          width:640
        , height: 510
      });
    } else if(!params.display || params.display !== "popup") {
      document.location.href = url.get();
     }
  };

  /**
   * connects, ie gets access token if there is none and fetches player object.
   */
  A2.connect = function(callback) {
    var token = accessToken();
    if(token != null) {
      return callback(token);
    }
    if(!auth) {
      A2.auth = new Auth({});
    }

    A2.auth.connect(function(token) {
      accessToken(token);
      return callback(token);
    });
  }

  global.A2 = A2;
  global.A2.URL = URL;
})('object' === typeof module ? module.exports : (this.A2 = {}), "undefined" === typeof global ? window : global);<|endoftext|>