<commit_before>// Imports
var isWindow = typeof window !== 'undefined';
var setImmediate = isWindow && window.setImmediate ? window.setImmediate : (function() {
    if (typeof process === 'object' && typeof process.nextTick === 'function') {
        return process.nextTick;
    } else {
        return function(fn) {
            setTimeout(fn, 0);
        };
    }
})();

// Loaders storage
var loaders = {};

function makeLoadPromise(item, increment) {
    var promise = new Promise(function(resolve, reject) {
        if (item instanceof Promise) {
            reject('Item ' + item + ' should not be a promise');
        } else if (typeof item === 'function') {
            // If item is a function pass the resolve & reject
            setImmediate(function() {
                item.call(this, resolve, reject);
            });
        } else {
            // Prepare variables
            var regexExt = /(?:\.([^.]+))?$/,
                ext = regexExt.exec(item)[1],
                loader = loaders[ext] || (function() {
                    throw 'No loader for file ' + ext;
                })();
            if (typeof loader === 'function') {
                setImmediate(function() {
                    loader.call(this, resolve, reject, item);
                });
            } else {
                // Prepare variable for element creation
                var element = document.createElement(loader.tag || _loaderDefaults.tag),
                    parent = loader.parent || _loaderDefaults.parent,
                    attr = loader.attr || _loaderDefaults.attr;
                // Handle events loaded or error
                element.onload = function() {
                    resolve(item);
                };
                element.onerror = function() {
                    reject('Error while loading ' + item);
                };
                // Export element for manipulation before attaching to parent
                loader.config(element);
                // Inject into document to kick off loading
                element[attr] = item;
                document[parent].appendChild(element);
            }
        }
    });
    if (increment) promise.then(increment);
    return promise;
}

function makeLoadAsyncPromise(items, increment) {
    if (typeof items === 'string' || items instanceof String) {
        // String, converting to array of promises by calling makeLoadPromise function
        items = [makeLoadPromise(items, increment)];
    } else if (typeof items === 'function') {
        // Function, converting to array promises
        items = [makeLoadPromise(items, increment)];
    } else {
        // A valid array of strings or functions, converting to array of promises
        for (var i = 0; i < items.length; i++) {
            items[i] = makeLoadPromise(items[i], increment);
        }
    }
    // At this point we should have array of promises
    return Promise.all(items);
}

function getPercent(current, total) {
    return Math.round((current / total) * 100);
}

function load(resources, callback, progress) {
    if (!resources.length > 0) return;

    function increment(result) {
        if (progress && !error) progress(getPercent(counter++, total));
        return result;
    }
    var error = false,
        counter = 0,
        total = resources[0] instanceof Array ? resources[0].length : 1,
        result = callback ? [] : undefined,
        prom = makeLoadAsyncPromise(resources[0], increment);
    resources.forEach(function(item) {
        if (item !== resources[0]) {
            total += item instanceof Array ? item.length : 1;
            prom = prom.then(function(data) {
                if (callback) result.push(data);
                return makeLoadAsyncPromise(item, increment);
            });
        }
    });
    prom.then(function(data) {
        if (callback) {
            result.push(data);
            callback(false, result);
        }
    }).catch(function(err) {
        error = true;
        if (callback) callback(err);
    });
    increment();
    return prom;
}

function addLoader(loader) {
    var i, exts = loader.ext.split(',');
    for (i = exts.length - 1; i > -1; i--) {
        loaders[exts[i]] = 'custom' in loader ? loader.custom : loader;
    }
}

//-----------------------------------------------------------
// Adding predefined loaders
//-----------------------------------------------------------

var _loaderDefaults = {
    tag: 'link',
    parent: 'head',
    attr: 'href'
};

// Javascript
addLoader({
    ext: 'js',
    tag: 'script',
    parent: 'body',
    attr: 'src',
    config: function(el) {
        el.async = false;
    }
});

// Stylesheet
addLoader({
    ext: 'css',
    config: function(el) {
        el.type = 'text/css';
        el.rel = 'stylesheet';
    }
});

// Html
addLoader({
    ext: 'html',
    config: function(el) {
        el.rel = 'import';
    }
});

//-----------------------------------------------------------
// Exports
//-----------------------------------------------------------
// Export for require
exports.load = load;
exports.addLoader = addLoader;
exports.loaders = loaders;
exports.loadOne = makeLoadPromise;
exports.loadMany = makeLoadAsyncPromise;
// Export for window
if (typeof window !== 'undefined' && !window.LoaderJS) {
    window.LoaderJS = exports;
}<commit_msg>Allow null items<commit_after>// Imports
var isWindow = typeof window !== 'undefined';
var setImmediate = isWindow && window.setImmediate ? window.setImmediate : (function() {
  if (typeof process === 'object' && typeof process.nextTick === 'function') {
    return process.nextTick;
  } else {
    return function(fn) {
      setTimeout(fn, 0);
    };
  }
})();

// Loaders storage
var loaders = {};

function makeLoadPromise(item, increment) {
  var promise = new Promise(function(resolve, reject) {
    if (item instanceof Promise) {
      reject('Item ' + item + ' should not be a promise');
    } else if (typeof item === 'function') {
      // If item is a function pass the resolve & reject
      setImmediate(function() {
        item.call(this, resolve, reject);
      });
    } else if (item === null) {
      // Auto resolve if passed a null item
      resolve();
    } else {
      // Prepare variables
      var regexExt = /(?:\.([^.]+))?$/,
        ext = regexExt.exec(item)[1],
        loader = loaders[ext] || (function() {
          throw 'No loader for file ' + ext;
        })();
      if (typeof loader === 'function') {
        setImmediate(function() {
          loader.call(this, resolve, reject, item);
        });
      } else {
        // Prepare variable for element creation
        var element = document.createElement(loader.tag || _loaderDefaults.tag),
          parent = loader.parent || _loaderDefaults.parent,
          attr = loader.attr || _loaderDefaults.attr;
        // Handle events loaded or error
        element.onload = function() {
          resolve(item);
        };
        element.onerror = function() {
          reject('Error while loading ' + item);
        };
        // Export element for manipulation before attaching to parent
        loader.config(element);
        // Inject into document to kick off loading
        element[attr] = item;
        document[parent].appendChild(element);
      }
    }
  });
  if (increment) promise.then(increment);
  return promise;
}

function makeLoadAsyncPromise(items, increment) {
  if (typeof items === 'string' || items instanceof String) {
    // String, converting to array of promises by calling makeLoadPromise function
    items = [makeLoadPromise(items, increment)];
  } else if (typeof items === 'function') {
    // Function, converting to array promises
    items = [makeLoadPromise(items, increment)];
  } else {
    // A valid array of strings or functions, converting to array of promises
    for (var i = 0; i < items.length; i++) {
      items[i] = makeLoadPromise(items[i], increment);
    }
  }
  // At this point we should have array of promises
  return Promise.all(items);
}

function getPercent(current, total) {
  return Math.round((current / total) * 100);
}

function load(resources, callback, progress) {
  if (!resources.length > 0) return;

  function increment(result) {
    if (progress && !error) progress(getPercent(counter++, total));
    return result;
  }
  var error = false,
    counter = 0,
    total = resources[0] instanceof Array ? resources[0].length : 1,
    result = callback ? [] : undefined,
    prom = makeLoadAsyncPromise(resources[0], increment);
  resources.forEach(function(item) {
    if (item !== resources[0]) {
      total += item instanceof Array ? item.length : 1;
      prom = prom.then(function(data) {
        if (callback) result.push(data);
        return makeLoadAsyncPromise(item, increment);
      });
    }
  });
  prom.then(function(data) {
    if (callback) {
      result.push(data);
      callback(false, result);
    }
  }).catch(function(err) {
    error = true;
    if (callback) callback(err);
  });
  increment();
  return prom;
}

function addLoader(loader) {
  var i, exts = loader.ext.split(',');
  for (i = exts.length - 1; i > -1; i--) {
    loaders[exts[i]] = 'custom' in loader ? loader.custom : loader;
  }
}

//-----------------------------------------------------------
// Adding predefined loaders
//-----------------------------------------------------------

var _loaderDefaults = {
  tag: 'link',
  parent: 'head',
  attr: 'href'
};

// Javascript
addLoader({
  ext: 'js',
  tag: 'script',
  parent: 'body',
  attr: 'src',
  config: function(el) {
    el.async = false;
  }
});

// Stylesheet
addLoader({
  ext: 'css',
  config: function(el) {
    el.type = 'text/css';
    el.rel = 'stylesheet';
  }
});

// Html
addLoader({
  ext: 'html',
  config: function(el) {
    el.rel = 'import';
  }
});

//-----------------------------------------------------------
// Exports
//-----------------------------------------------------------
// Export for require
exports.load = load;
exports.addLoader = addLoader;
exports.loaders = loaders;
exports.loadOne = makeLoadPromise;
exports.loadMany = makeLoadAsyncPromise;
// Export for window
if (typeof window !== 'undefined' && !window.LoaderJS) {
  window.LoaderJS = exports;
}<|endoftext|>


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

'use strict';

/**
 * Validate that a given component can actually server-side render
 * with the given properties (specified via a fixture file).
 *
 * Not all react components can be server-side rendered: they may
 * use globals, or access the DOM, or what have you.  This script
 * can be used to validate that the component *can* be server-side
 * rendered.
 *
 * The input is a bit difficult to construct: it's a json-encoded
 * list of objects like so:
 *    {
 *      jsPackages: [[pkg_name, pkg_contents], [pkg_name, pkg_contents], ...],
 *      pathToReactComponent: "./in/require/format.js",
 *      fixtureFile: "/ideally/an/absolute/path",
 *    }
 * passed in via sttdin.
 *
 * We require() the fixture file and try to server-side render the
 * component using each fixture found therein.  jsPackages are the
 * packages needed to render the component (including the package
 * that defines the component!) topologically sorted so no package
 * require()s anything from a package that comes after it.
 */

/* eslint-disable no-console */

const path = require("path");

const render = require("../src/render.js");

// Cribbed from
// https://github.com/facebook/react/blob/92530b4ddcc77be49a50ce4cbffb32ee38a98247/src/renderers/dom/client/ReactMount.js
function firstDifferenceIndex(string1, string2) {
    const minLen = Math.min(string1.length, string2.length);
    for (var i = 0; i < minLen; i++) {
        if (string1.charAt(i) !== string2.charAt(i)) {
            return i;
        }
    }
    return string1.length === string2.length ? -1 : minLen;
}

// Given some html, remove the reactid and react-checksum, which are
// auto-generated and not necessarily consistent between runs.
const normalizeReactOutput = function(html) {
    html = html.replace(/data-reactid="[^"]*"/g,
                        'data-reactid="..."');
    html = html.replace(/data-react-checksum="[^"]*"/g,
                        'data-react-checksum="..."');
    return html;
};

// Returns the number of errors found trying to render the component.
const validate = function(jsPackages, pathToReactComponent, fixtureFile) {
    let allProps;
    try {
        const relativeFixturePath = path.relative(__dirname, fixtureFile);
        allProps = require(relativeFixturePath).instances;
    } catch (err) {
        console.log(`Error reading fixtures from ${fixtureFile}: ${err}`);
        return 1;
    }

    let numErrors = 0;
    allProps.forEach((props, i) => {
        // For each fixture file, we'll try rendering the component three
        // times:
        //
        //  1. Emulating a server-side render
        //  2. Emulating a mobile browser client-side render
        //  3. Emulating a desktop browser client-side render
        //
        // Then we compare the outputs from (1) and (2), and the outputs from
        // (1) and (3). If they differ, it suggests there the client and server
        // would render different things, causing a checksum difference. When
        // the React checksum differs, React will throw away everything in the
        // root container. This causes nasty reflows and would throw away any
        // user input in the server-rendered components.
        //
        // This also helps us find non-determinism in the rendering output
        // (e.g. using random numbers as IDs).
        try {
            const serverHtml = normalizeReactOutput(
                render(jsPackages, pathToReactComponent, props, {},
                       'ignore').html);

            const desktopHtml = normalizeReactOutput(
                render(jsPackages, pathToReactComponent, props, {
                    width: 2000,
                    height: 900,
                    innerWidth: 2000,
                    innerHeight: 900,
                    outerWidth: 2000,
                    outerHeight: 900,
                }, 'ignore').html);
            const mobileHtml = normalizeReactOutput(
                render(jsPackages, pathToReactComponent, props, {
                    width: 400,
                    height: 600,
                    innerWidth: 400,
                    innerHeight: 600,
                    outerWidth: 400,
                    outerHeight: 600,
                    ontouchstart: function() {},
                    onorientationchange: function() {},
                    orientation: 'portrait',
                }, 'ignore').html);

            const mismatchMsg = (
                "There was a mismatch between the server and client rendered" +
                " HTML. Server-side rendered components must not do feature" +
                " feature detection, because the features detected will be" +
                " different on the client and server!\n\n" +
                "Here's where the server and client may differ");

            if (serverHtml !== desktopHtml) {
                const diffIndex = firstDifferenceIndex(serverHtml,
                                                       desktopHtml);
                throw new Error(
                    mismatchMsg +
                    "\n(server) " + serverHtml.substring(diffIndex - 20,
                                                         diffIndex + 40) +
                    "\n(desktop) " + desktopHtml.substring(diffIndex - 20,
                                                           diffIndex + 40));
            } else if (serverHtml !== mobileHtml) {
                const diffIndex = firstDifferenceIndex(serverHtml,
                                                       mobileHtml);
                throw new Error(
                    mismatchMsg +
                    "\n(server) " + serverHtml.substring(diffIndex - 20,
                                                         diffIndex + 40) +
                    "\n(mobile) " + mobileHtml.substring(diffIndex - 20,
                                                         diffIndex + 40));
            }
            console.log(`${pathToReactComponent} #${i}: OK`);
        } catch (err) {
            console.log(`${pathToReactComponent} #${i}: ERROR ${err.stack}`);
            numErrors++;
        }
    });
    return numErrors;
};

const main = function(inputJson) {
    let numErrors = 0;
    inputJson.forEach((oneInput) => {
        numErrors += validate(oneInput.jsPackages,
                              oneInput.pathToReactComponent,
                              oneInput.fixtureFile);
    });
    return numErrors;
};

let inputText = '';
process.stdin.on('data', function(chunk) {
    inputText = inputText + chunk;
});
process.stdin.on('end', function() {
    const inputJson = JSON.parse(inputText);
    const numErrors = main(inputJson);
    console.log('DONE');
    process.exit(numErrors);
});
<commit_msg>Make validate_components.js work asynchronously.<commit_after>#!/usr/bin/env node

'use strict';

/**
 * Validate that a given component can actually server-side render
 * with the given properties (specified via a fixture file).
 *
 * Not all react components can be server-side rendered: they may
 * use globals, or access the DOM, or what have you.  This script
 * can be used to validate that the component *can* be server-side
 * rendered.
 *
 * The input is a bit difficult to construct: it's a json-encoded
 * list of objects like so:
 *    {
 *      jsPackages: [[pkg_name, pkg_contents], [pkg_name, pkg_contents], ...],
 *      pathToReactComponent: "./in/require/format.js",
 *      fixtureFile: "/ideally/an/absolute/path",
 *    }
 * passed in via sttdin.
 *
 * We require() the fixture file and try to server-side render the
 * component using each fixture found therein.  jsPackages are the
 * packages needed to render the component (including the package
 * that defines the component!) topologically sorted so no package
 * require()s anything from a package that comes after it.
 */

/* eslint-disable no-console */

const path = require("path");

const render = require("../src/render.js");

// Cribbed from
// https://github.com/facebook/react/blob/92530b4ddcc77be49a50ce4cbffb32ee38a98247/src/renderers/dom/client/ReactMount.js
function firstDifferenceIndex(string1, string2) {
    const minLen = Math.min(string1.length, string2.length);
    for (let i = 0; i < minLen; i++) {
        if (string1.charAt(i) !== string2.charAt(i)) {
            return i;
        }
    }
    return string1.length === string2.length ? -1 : minLen;
}

// Given some html, remove the reactid and react-checksum, which are
// auto-generated and not necessarily consistent between runs.
const normalizeReactOutput = function(html) {
    html = html.replace(/data-reactid="[^"]*"/g,
                        'data-reactid="..."');
    html = html.replace(/data-react-checksum="[^"]*"/g,
                        'data-react-checksum="..."');
    return html;
};

const mismatchMsg = (
    "There was a mismatch between the server and client rendered" +
    " HTML. Server-side rendered components must not do feature" +
    " feature detection, because the features detected will be" +
    " different on the client and server!\n\n" +
    "Here's where the server and client may differ");

// Returns the number of errors found trying to render the component.
const validate = function(jsPackages, pathToReactComponent, fixtureFile) {
    let allProps;
    try {
        const relativeFixturePath = path.relative(__dirname, fixtureFile);
        allProps = require(relativeFixturePath).instances;
    } catch (err) {
        console.log(`Error reading fixtures from ${fixtureFile}: ${err}`);
        // NOTE(jeresig): We should really be returning 1 here as it is an
        // error, however we now have some fixture tests that do more than
        // just return an object (they build React components and wrappers).
        // The only way to make these run correctly is to bring in the full
        // dev package and run it with all of the dev dependencies. For
        // example right now a fixture that does `require("react")` will fail
        // with "require.withVars not found". Note that this is only an issue
        // with validate_components.js. The code normally runs fine server-
        // side and also runs fine in the normal fixture tests.
        return Promise.resolve(0);
    }

    return Promise.all(allProps.map((props, i) => {
        // For each fixture file, we'll try rendering the component three
        // times:
        //
        //  1. Emulating a server-side render
        //  2. Emulating a mobile browser client-side render
        //  3. Emulating a desktop browser client-side render
        //
        // Then we compare the outputs from (1) and (2), and the outputs from
        // (1) and (3). If they differ, it suggests there the client and server
        // would render different things, causing a checksum difference. When
        // the React checksum differs, React will throw away everything in the
        // root container. This causes nasty reflows and would throw away any
        // user input in the server-rendered components.
        //
        // This also helps us find non-determinism in the rendering output
        // (e.g. using random numbers as IDs).
        return Promise.all([
            render(jsPackages, pathToReactComponent, props, {}, 'ignore'),
            render(jsPackages, pathToReactComponent, props, {
                width: 2000,
                height: 900,
                innerWidth: 2000,
                innerHeight: 900,
                outerWidth: 2000,
                outerHeight: 900,
            }, 'ignore'),
            render(jsPackages, pathToReactComponent, props, {
                width: 400,
                height: 600,
                innerWidth: 400,
                innerHeight: 600,
                outerWidth: 400,
                outerHeight: 600,
                ontouchstart: function() {},
                onorientationchange: function() {},
                orientation: 'portrait',
            }, 'ignore'),
        ]).then(([serverHtml, desktopHtml, mobileHtml]) => {
            serverHtml = normalizeReactOutput(serverHtml.html);
            desktopHtml = normalizeReactOutput(desktopHtml.html);
            mobileHtml = normalizeReactOutput(mobileHtml.html);

            if (serverHtml !== desktopHtml) {
                const diffIndex = firstDifferenceIndex(serverHtml,
                                                       desktopHtml);
                return Promise.reject(new Error(
                    mismatchMsg +
                    "\n(server) " + serverHtml.substring(diffIndex - 20,
                                                         diffIndex + 40) +
                    "\n(desktop) " + desktopHtml.substring(diffIndex - 20,
                                                           diffIndex + 40)));
            } else if (serverHtml !== mobileHtml) {
                const diffIndex = firstDifferenceIndex(serverHtml,
                                                       mobileHtml);
                return Promise.reject(new Error(
                    mismatchMsg +
                    "\n(server) " + serverHtml.substring(diffIndex - 20,
                                                         diffIndex + 40) +
                    "\n(mobile) " + mobileHtml.substring(diffIndex - 20,
                                                         diffIndex + 40)));
            }
        }).then(() => {
            console.log(`${pathToReactComponent} #${i}: OK`);
            return 0;
        }).catch((err) => {
            console.log(`${pathToReactComponent} #${i}: ERROR ${err.stack}`);
            return 1;
        });
    })).then((results) => {
        // Total up all of the errors
        return results.reduce((a, b) => a + b, 0);
    }).catch((err) => {
        // Some uncaught error!? Should hopefully never happen!
        console.log(`${pathToReactComponent}: ERROR ${err.stack}`);
        return 1;
    });
};

const main = function(inputJson) {
    // Run all the validation calls as async promises
    const promises = inputJson.map(
        (oneInput) => validate(oneInput.jsPackages,
            oneInput.pathToReactComponent, oneInput.fixtureFile));

    // Return a promise that has a total number of errors generated
    return Promise.all(promises)
        .then((errors) => errors.reduce((a, b) => a + b, 0));
};

let inputText = '';
process.stdin.on('data', function(chunk) {
    inputText = inputText + chunk;
});
process.stdin.on('end', function() {
    const inputJson = JSON.parse(inputText);
    main(inputJson).then((numErrors) => {
        console.log('DONE');
        process.exit(numErrors);
    }).catch((err) => {
        console.log('UNCAUGHT ERROR', err, err.stack);
        process.exit(1);
    });
});
<|endoftext|>


<commit_before>var Class = require('../../utils/Class');
var BaseSoundManager = require('../BaseSoundManager');
var WebAudioSound = require('./WebAudioSound');
var SoundValueEvent = require('../SoundValueEvent');
//  Phaser.Loader.WebAudioSoundManager
var WebAudioSoundManager = new Class({
    Extends: BaseSoundManager,
    initialize: function WebAudioSoundManager(game) {
        /**
         * Flag indicating if Web Audio implementation is webkit or standards based.
         * There are certain cases where they have to be handled differently.
         *
         * https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Porting_webkitAudioContext_code_to_standards_based_AudioContext
         *
         * @private
         * @property {boolean} webkit
         */
        this.webkit = !!window['webkitAudioContext'] && !window['AudioContext'];
        /**
         * The AudioContext being used for playback.
         *
         * @private
         * @property {AudioContext} context
         */
        this.context = this.createAudioContext(game);
        /**
         * [description]
         *
         * @private
         * @property {GainNode} masterMuteNode
         */
        this.masterMuteNode = (this.context.createGain || this.context.createGainNode).call(this.context);
        /**
         * [description]
         *
         * @private
         * @property {GainNode} masterVolumeNode
         */
        this.masterVolumeNode = (this.context.createGain || this.context.createGainNode).call(this.context);
        this.masterMuteNode.connect(this.masterVolumeNode);
        this.masterVolumeNode.connect(this.context.destination);
        /**
         * Destination node for connecting individual sounds to.
         *
         * @private
         * @property {AudioNode} destination
         */
        this.destination = this.masterMuteNode;
        this.unlock();
        BaseSoundManager.call(this, game);
    },
    /**
     * @private
     * @param game
     * @returns {AudioContext}
     */
    createAudioContext: function (game) {
        var audioConfig = game.config.audio;
        if (audioConfig && audioConfig.context) {
            return audioConfig.context;
        }
        return new (window['AudioContext'] || window['webkitAudioContext'])();
    },
    add: function (key, config) {
        var sound = new WebAudioSound(this, key, config);
        this.sounds.push(sound);
        return sound;
    },
    /**
     * @private
     */
    unlock: function () {
        var _this = this;
        if (this.context.state === 'suspended') {
            var unlock_1 = function () {
                _this.context.resume().then(function () {
                    document.body.removeEventListener('touchstart', unlock_1);
                    document.body.removeEventListener('touchend', unlock_1);
                });
            };
            document.body.addEventListener('touchstart', unlock_1, false);
            document.body.addEventListener('touchend', unlock_1, false);
        }
    },
    onBlur: function () {
        this.context.suspend();
    },
    onFocus: function () {
        this.context.resume();
    }
});
/**
 * Global mute setting.
 * @property {boolean} mute
 */
Object.defineProperty(WebAudioSoundManager.prototype, 'mute', {
    get: function () {
        return this.masterMuteNode.gain.value === 0;
    },
    set: function (value) {
        this.masterMuteNode.gain.setValueAtTime(value ? 0 : 1, 0);
        this.events.dispatch(new SoundValueEvent(this, 'SOUND_MUTE', value));
    }
});
/**
 * Global volume setting.
 * @property {number} volume
 */
Object.defineProperty(WebAudioSoundManager.prototype, 'volume', {
    get: function () {
        return this.masterVolumeNode.gain.value;
    },
    set: function (value) {
        this.masterVolumeNode.gain.setValueAtTime(value, 0);
        this.events.dispatch(new SoundValueEvent(this, 'SOUND_VOLUME', value));
    }
});
module.exports = WebAudioSoundManager;
<commit_msg>Added check for touch events when trying to unlock web audio on iOS devices<commit_after>var Class = require('../../utils/Class');
var BaseSoundManager = require('../BaseSoundManager');
var WebAudioSound = require('./WebAudioSound');
var SoundValueEvent = require('../SoundValueEvent');
//  Phaser.Loader.WebAudioSoundManager
var WebAudioSoundManager = new Class({
    Extends: BaseSoundManager,
    initialize: function WebAudioSoundManager(game) {
        /**
         * Flag indicating if Web Audio implementation is webkit or standards based.
         * There are certain cases where they have to be handled differently.
         *
         * https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Porting_webkitAudioContext_code_to_standards_based_AudioContext
         *
         * @private
         * @property {boolean} webkit
         */
        this.webkit = !!window['webkitAudioContext'] && !window['AudioContext'];
        /**
         * The AudioContext being used for playback.
         *
         * @private
         * @property {AudioContext} context
         */
        this.context = this.createAudioContext(game);
        /**
         * [description]
         *
         * @private
         * @property {GainNode} masterMuteNode
         */
        this.masterMuteNode = (this.context.createGain || this.context.createGainNode).call(this.context);
        /**
         * [description]
         *
         * @private
         * @property {GainNode} masterVolumeNode
         */
        this.masterVolumeNode = (this.context.createGain || this.context.createGainNode).call(this.context);
        this.masterMuteNode.connect(this.masterVolumeNode);
        this.masterVolumeNode.connect(this.context.destination);
        /**
         * Destination node for connecting individual sounds to.
         *
         * @private
         * @property {AudioNode} destination
         */
        this.destination = this.masterMuteNode;
        this.unlock();
        BaseSoundManager.call(this, game);
    },
    /**
     * @private
     * @param game
     * @returns {AudioContext}
     */
    createAudioContext: function (game) {
        var audioConfig = game.config.audio;
        if (audioConfig && audioConfig.context) {
            return audioConfig.context;
        }
        return new (window['AudioContext'] || window['webkitAudioContext'])();
    },
    add: function (key, config) {
        var sound = new WebAudioSound(this, key, config);
        this.sounds.push(sound);
        return sound;
    },
    /**
     * @private
     */
    unlock: function () {
        var _this = this;
        if (this.context.state === 'suspended' && 'ontouchstart' in window) {
            var unlock_1 = function () {
                _this.context.resume().then(function () {
                    document.body.removeEventListener('touchstart', unlock_1);
                    document.body.removeEventListener('touchend', unlock_1);
                });
            };
            document.body.addEventListener('touchstart', unlock_1, false);
            document.body.addEventListener('touchend', unlock_1, false);
        }
    },
    onBlur: function () {
        this.context.suspend();
    },
    onFocus: function () {
        this.context.resume();
    }
});
/**
 * Global mute setting.
 * @property {boolean} mute
 */
Object.defineProperty(WebAudioSoundManager.prototype, 'mute', {
    get: function () {
        return this.masterMuteNode.gain.value === 0;
    },
    set: function (value) {
        this.masterMuteNode.gain.setValueAtTime(value ? 0 : 1, 0);
        this.events.dispatch(new SoundValueEvent(this, 'SOUND_MUTE', value));
    }
});
/**
 * Global volume setting.
 * @property {number} volume
 */
Object.defineProperty(WebAudioSoundManager.prototype, 'volume', {
    get: function () {
        return this.masterVolumeNode.gain.value;
    },
    set: function (value) {
        this.masterVolumeNode.gain.setValueAtTime(value, 0);
        this.events.dispatch(new SoundValueEvent(this, 'SOUND_VOLUME', value));
    }
});
module.exports = WebAudioSoundManager;
<|endoftext|>


<commit_before>$(function() {
    var label = $("#cart-label");

    if ($(location).attr('href').indexOf('cart') > 0 && $("#cart-item-number").val() > 0) {
        // add new address
        $("#edit-address").dialog({
            autoOpen: false,
            width: 350,
            height: 400
        });

        $("#new-address").click(function(event){
            console.log(1122);
            event.preventDefault();
            $("#edit-address").dialog("open");
        })
        setOrderInfo();

    }

    function setOrderInfo()
    {
        // get cart weight
        var weight = 0;
        $("input[id^='weight-']").each(function() {
            var index = this.id.lastIndexOf('-');
            var lid = this.id.substring(index + 1);
            var amount = $("#quantity-" + lid).val();
            weight = weight + parseInt($(this).val() * amount);
        })

        // set minimum weight 1kg
        if (weight < 1000 && weight > 0) {
            weight = 1000;
        }

        // ceiling weight to 0.1kg
        weight = Math.ceil(weight / 100) / 10;

        // set delivery fee display
        var id = $("#shipping-method").val() + '-price';
        var shippingPrice = $("#" + id).val();
        var deliveryFee = shippingPrice.replace(/[^0-9\.]+/g,"") * weight;
        var deliveryFeeDisplay = shippingPrice.replace(/[0-9\.]+/g,"") +  deliveryFee.toFixed(2);
        $("#carrier-price").html(deliveryFeeDisplay);

        // set order total price
        var subtotal = $("#cart-price").html().replace(/[^0-9\.]+/g,"");
        var total = parseFloat(subtotal) + deliveryFee;
        var totalDisplay = shippingPrice.replace(/[0-9\.]+/g,"") + total.toFixed(2);
        $("#total-price").html(totalDisplay);
    }

    $("a[id^='add-cart']").click(function(event){
        var id = this.id.substring(9);
        var display = $("#cart-amount").html();

        // send request to server if logined in and stock > 0
        if (!display && display !== 0) {
            var url = Routing.generate('zh-CN__RG__' + 'best365_store_login');
            window.location.replace(url);
        } else if ($("#stock-" + id).val() > 0) {
            //send request to server
            var amount = 1;
            if ($("#cart-quantity") && parseInt($("#cart-quantity").val()) > 1) {
                amount = $("#cart-quantity").val();
            }

            var url = Routing.generate('zh-CN__RG__' + 'best365_store_cart_add_product', {id: id, quantity: amount});
            // var url = 'http://localhost/michael/new_best365/web/app_dev.php/best365/cart/add/'+id+'/'+amount;
            $.ajax({
                url: url,
                type: 'GET',
                success: function(result){
                    if (result == 'success') {
                        // update cart amount display
                        label.fadeOut();
                        setTimeout(function() {
                            $("#cart-amount").html(parseInt(display) + amount);
                        }, 500);
                        label.fadeIn();
                    } else {
                        console.log(result);
                        alert('failed to add product to cart.');
                    }
                },
                error: function(jqXHR, textStatus, errorThrown) {
                    console.log(jqXHR);
                    console.log(textStatus);
                    console.log(errorThrown);
                    alert('failed to add product to cart.');
                }
            });
        }
    });
    $("#cart-quantity").keypress(function(event) {
        event.preventDefault();
    }).change(function() {
        var href = $(location).attr('href');
        var index = href.lastIndexOf('/');
        var id = href.substring(index + 1);
        var amount = $(this).val();
        var stock = $("#stock-" + id).val();

        // check stock
        if (parseInt(amount) > parseInt(stock)) {
            var msg = $("#sold-out-msg").val();
            $("#stock-label").html(' ' + msg);
        } else {
            var msg = $("#in-stock-msg").val();
            $("#stock-label").html(' ' + msg);
        }
    })

    $("input[id^='quantity-']").keypress(function(event){
        event.preventDefault();
    }).change(function(){
        var lid = this.id.substring(9);
        var amount = $(this).val();
        if (amount <= 0) {
            amount = 1;
        }
        var stock = $("#stock-" + lid).val();
        console.log(stock);
        if (amount > parseInt(stock)) {
            // change msg to sold out
            var msg = $("#sold-out-msg").val();
            $("#stock-label").html(
                ' ' + msg
            );

            // disable checkout button
            $("#payment").addClass('disabled');
        } else {
            // change msg back to in stock
            var msg = $("#in-stock-msg").val();
            $("#stock-label").html(
                ' ' + msg
            );

            // remove checkout button disable class
            $("#payment").removeClass('disabled');

            // send request to server
            var url = Routing.generate('zh-CN__RG__' + 'best365_store_cart_update_line', {lid: lid, quantity: amount});
            $.ajax({
                url: url,
                type: 'GET',
                success: function(result){
                    if (result == 'success') {
                        var display = $("#cart-amount").html();
                        // update cart amount display
                        label.fadeOut();
                        setTimeout(function() {
                            var cartAmount = 0;
                            $("input[id^='quantity-']").each(function() {
                                cartAmount = cartAmount + parseInt($(this).val());
                            })
                            $("#cart-amount").html(cartAmount);
                        }, 500);
                        label.fadeIn();

                        // update line amount
                        var unitPrice = $("#unit-price-" + lid).html().trim();
                        var price = unitPrice.replace(/[^\d.]/g, '');
                        var index = unitPrice.indexOf(price);
                        var linePrice = unitPrice.substring(0, index) + (price * amount).toFixed(2);
                        $("#line-price-"+lid).html(linePrice);

                        // update cart amount
                        var cartPrice = 0;
                        $("span[id^='line-price-']").each(function() {
                            cartPrice += parseFloat($(this).html().replace(/[^\d.]/g, ''));
                        });
                        $("#cart-price").html(unitPrice.substring(0, index) + cartPrice.toFixed(2));

                        // update order info
                        setOrderInfo();

                    } else {
                        alert('failed to add product to cart.');
                    }
                },
                error: function(jqXHR, textStatus, errorThrown) {
                    console.log(jqXHR);
                    console.log(textStatus);
                    console.log(errorThrown);
                    alert('failed to add product to cart.');
                }
            });
        }
    })

    $("#shipping-method").change(function() {
        setOrderInfo();
    })

    $("#shipping-address").change(function () {
        var aid = $(this).val();
        var url = Routing.generate('zh-CN__RG__' + 'best365_store_cart_delivery', {aid: aid});
        $.ajax({
            url: url,
            type: 'GET',
            success: function(result){
                var json = JSON.parse(result);
                console.log(json);
                var optionsAsString = "";
                for (var i = 0; i < json.length; i++) {
                    optionsAsString += "<option value='" + json[i].id + "'>" + json[i].name + "</option>";
                }
                $("#shipping-method").find('option').remove().end().append($(optionsAsString));
            },
            error: function(jqXHR, textStatus, errorThrown) {
                console.log(jqXHR);
                console.log(textStatus);
                console.log(errorThrown);
            }
        });

        setOrderInfo();
    })
});<commit_msg>fixing update order info<commit_after>$(function() {
    var label = $("#cart-label");

    if ($(location).attr('href').indexOf('cart') > 0 && $("#cart-item-number").val() > 0) {
        // add new address
        $("#edit-address").dialog({
            autoOpen: false,
            width: 350,
            height: 400
        });

        $("#new-address").click(function(event){
            event.preventDefault();
            $("#edit-address").dialog("open");
        })
        setOrderInfo();

    }

    function setOrderInfo()
    {
        // get cart weight
        var weight = 0;
        $("input[id^='weight-']").each(function() {
            var index = this.id.lastIndexOf('-');
            var lid = this.id.substring(index + 1);
            var amount = $("#quantity-" + lid).val();
            weight = weight + parseInt($(this).val() * amount);
        })

        // set minimum weight 1kg
        if (weight < 1000 && weight > 0) {
            weight = 1000;
        }

        // ceiling weight to 0.1kg
        weight = Math.ceil(weight / 100) / 10;

        // set delivery fee display
        var id = $("#shipping-method").val() + '-price';
        var shippingPrice = $("#" + id).val();
        var deliveryFee = shippingPrice.replace(/[^0-9\.]+/g,"") * weight;
        var deliveryFeeDisplay = shippingPrice.replace(/[0-9\.]+/g,"") +  deliveryFee.toFixed(2);
        $("#carrier-price").html(deliveryFeeDisplay);

        // set order total price
        var subtotal = $("#cart-price").html().replace(/[^0-9\.]+/g,"");
        var total = parseFloat(subtotal) + deliveryFee;
        var totalDisplay = shippingPrice.replace(/[0-9\.]+/g,"") + total.toFixed(2);
        $("#total-price").html(totalDisplay);
    }

    $("a[id^='add-cart']").click(function(event){
        var id = this.id.substring(9);
        var display = $("#cart-amount").html();

        // send request to server if logined in and stock > 0
        if (!display && display !== 0) {
            var url = Routing.generate('zh-CN__RG__' + 'best365_store_login');
            window.location.replace(url);
        } else if ($("#stock-" + id).val() > 0) {
            //send request to server
            var amount = 1;
            if ($("#cart-quantity") && parseInt($("#cart-quantity").val()) > 1) {
                amount = $("#cart-quantity").val();
            }

            var url = Routing.generate('zh-CN__RG__' + 'best365_store_cart_add_product', {id: id, quantity: amount});
            // var url = 'http://localhost/michael/new_best365/web/app_dev.php/best365/cart/add/'+id+'/'+amount;
            $.ajax({
                url: url,
                type: 'GET',
                success: function(result){
                    if (result == 'success') {
                        // update cart amount display
                        label.fadeOut();
                        setTimeout(function() {
                            $("#cart-amount").html(parseInt(display) + amount);
                        }, 500);
                        label.fadeIn();
                    } else {
                        alert('failed to add product to cart.');
                    }
                },
                error: function(jqXHR, textStatus, errorThrown) {
                    console.log(jqXHR);
                    console.log(textStatus);
                    console.log(errorThrown);
                    alert('failed to add product to cart.');
                }
            });
        }
    });
    $("#cart-quantity").keypress(function(event) {
        event.preventDefault();
    }).change(function() {
        var href = $(location).attr('href');
        var index = href.lastIndexOf('/');
        var id = href.substring(index + 1);
        var amount = $(this).val();
        var stock = $("#stock-" + id).val();

        // check stock
        if (parseInt(amount) > parseInt(stock)) {
            var msg = $("#sold-out-msg").val();
            $("#stock-label").html(' ' + msg);
        } else {
            var msg = $("#in-stock-msg").val();
            $("#stock-label").html(' ' + msg);
        }
    })

    $("input[id^='quantity-']").keypress(function(event){
        event.preventDefault();
    }).change(function(){
        var lid = this.id.substring(9);
        var amount = $(this).val();
        if (amount <= 0) {
            amount = 1;
        }
        var stock = $("#stock-" + lid).val();
        if (amount > parseInt(stock)) {
            // change msg to sold out
            var msg = $("#sold-out-msg").val();
            $("#stock-label").html(
                ' ' + msg
            );

            // disable checkout button
            $("#payment").addClass('disabled');
        } else {
            // change msg back to in stock
            var msg = $("#in-stock-msg").val();
            $("#stock-label").html(
                ' ' + msg
            );

            // remove checkout button disable class
            $("#payment").removeClass('disabled');

            // send request to server
            var url = Routing.generate('zh-CN__RG__' + 'best365_store_cart_update_line', {lid: lid, quantity: amount});
            $.ajax({
                url: url,
                type: 'GET',
                success: function(result){
                    if (result == 'success') {
                        var display = $("#cart-amount").html();
                        // update cart amount display
                        label.fadeOut();
                        setTimeout(function() {
                            var cartAmount = 0;
                            $("input[id^='quantity-']").each(function() {
                                cartAmount = cartAmount + parseInt($(this).val());
                            })
                            $("#cart-amount").html(cartAmount);
                        }, 500);
                        label.fadeIn();

                        // update line amount
                        var unitPrice = $("#unit-price-" + lid).html().trim();
                        var price = unitPrice.replace(/[^\d.]/g, '');
                        var index = unitPrice.indexOf(price);
                        var linePrice = unitPrice.substring(0, index) + (price * amount).toFixed(2);
                        $("#line-price-"+lid).html(linePrice);

                        // update cart amount
                        var cartPrice = 0;
                        $("span[id^='line-price-']").each(function() {
                            cartPrice += parseFloat($(this).html().replace(/[^\d.]/g, ''));
                        });
                        $("#cart-price").html(unitPrice.substring(0, index) + cartPrice.toFixed(2));

                        // update order info
                        setOrderInfo();

                    } else {
                        alert('failed to add product to cart.');
                    }
                },
                error: function(jqXHR, textStatus, errorThrown) {
                    console.log(jqXHR);
                    console.log(textStatus);
                    console.log(errorThrown);
                    alert('failed to add product to cart.');
                }
            });
        }
    })

    $("#shipping-method").change(function() {
        setOrderInfo();
    })

    $("#shipping-address").change(function () {
        var aid = $(this).val();
        var url = Routing.generate('zh-CN__RG__' + 'best365_store_cart_delivery', {aid: aid});
        $.ajax({
            url: url,
            type: 'GET',
            success: function(result){
                var json = JSON.parse(result);
                var optionsAsString = "";
                for (var i = 0; i < json.length; i++) {
                    optionsAsString += "<option value='" + json[i].id + "'>" + json[i].name + "</option>";
                    if (i == 0) {
                        var first = json[i].id;
                    }
                }
                $("#shipping-method").find('option').remove().end().append($(optionsAsString));
                setOrderInfo();
            },
            error: function(jqXHR, textStatus, errorThrown) {
                console.log(jqXHR);
                console.log(textStatus);
                console.log(errorThrown);
            }
        });
    })
});<|endoftext|>


<commit_before>/***********************************************************************

    Check in, check uit

    Copyright 2010, Martijn Vermaat <martijn@vermaat.name>

      http://checkincheckuit.nl
      http://svn.vermaat.name/checkincheckuit

    Licensed under the MIT license, see the LICENSE file

      http://en.wikipedia.org/wiki/Mit_license

    Some of the Twitter handling code was adapted from the jQuery
    plugin Tweet!, found at http://tweet.seaofclouds.com/

    This code uses:
      jQuery          http://jquery.com
      jQuery Timers   http://plugins.jquery.com/project/timers

***********************************************************************/

$(document).ready(function() {

    var twitterSearch = 'ovchipkaart OR chipkaart OR ovchip';
    var twitterCount = 50;
    var twitterBlacklist = ['Regio_Alphen',
                            'Regio_Leiden',
                            'LeidenNL',
                            'Regio_Duin_Bol',
                            'Edestad',
                            'nieuwsede',
                            'edenieuwspunt.nl',
                            'nieuwsinutrecht',
                            'UtrechtNL',
                            'rtvutrecht',
                            'echo_utrecht',
                            'regio_nieuws',
                            'hetlokalenieuws',
                            'Nieuwsbekijken',
                            'totaalnieuwsweb',
                            'De_Pers',
                            '123nieuws',
                            'doormijverloren',
                            'doormijgevonden',
                            'ov_chipkaart'];
    var twitterDisplayTime = 1000 * 8;
    var twitterFadeTime = 800;
    /*
      There seems to be a bug, where animations are not smooth when the
      interval is specified as a string, e.g. '5s'.
    */
    var twitterReloadTime = 1000 * 60 * 5;

    var deliciousUser = 'checkuitcheckin';
    var deliciousTag = 'nieuws';
    var deliciousCount = 10;

    // Unfortunately, twitter query cannot exceed 140 characters
    var twitterUrl = 'http://search.twitter.com/search?&q='
        + encodeURIComponent(twitterSearch);
    var twitterApiUrl = 'http://search.twitter.com/search.json?&q='
        + encodeURIComponent(twitterSearch)
        + '&rpp=' + twitterCount + '&callback=?';
    var initialTweet = true;
    var tweets = [];
    var currentTweet = 0;

    var deliciousUrl = 'http://delicious.com/' + deliciousUser
        + '/' + deliciousTag;
    var deliciousApiUrl = 'http://feeds.delicious.com/v2/json/'
        + deliciousUser + '/' + deliciousTag
        + '?count=' + deliciousCount + '&callback=?';

    // Load Twitter search results and call callback function
    function updateTwitter(callback) {

        // http://apiwiki.twitter.com/Return-Values

        $.getJSON(twitterApiUrl, function(data) {

            currentTweet = 0;
            tweets = [];

            $.each((data.results || data), function(i, tweet) {
                var user = tweet.from_user || tweet.user.screen_name;
                if (twitterBlacklist.indexOf(user) == -1) {
                    tweets.push({
                        text    : twittify(tweet.text),
                        user    : user,
                        date    : relativeTime(tweet.created_at),
                        url     : 'http://twitter.com/' + user
                                  + '/statuses/' + tweet.id,
                        userUrl : 'http://twitter.com/' + user
                    });
                }
            });

            if ($.isFunction(callback)) callback();

        });

    }

    // Load Delicious links and show them on the page
    function updateDelicious() {

        // http://delicious.com/help/feeds

        $.getJSON(deliciousApiUrl, function(data) {
            var list = $('
').appendTo($('#delicious'));
            $.each((data.results || data), function(i, item) {
                list.append($('
').text(shortDate(item.dt)));
                list.append($('
').append(
                    $('').attr('href', item.u).text(item.d)));
            });
            $('#delicious').append($('
').append(
                $('Meer nieuwsberichten...').attr('href', deliciousUrl)));
        });

    }

    // Advance to the next twee
    function showNextTweet() {
        if (tweets.length < 1) return;
        currentTweet = (currentTweet + 1) % tweets.length;
        showTweet();
    }

    // Like the function above, with a minor difference
    function showPreviousTweet() {
        if (tweets.length < 1) return;
        currentTweet = (tweets.length + currentTweet - 1) % tweets.length;
        showTweet();
    }

    /*
      Show the current tweet on the page. If this is the first twee we show,
      do just that. Otherwise fadeout the old tweet and fadein the new.
    */
    function showTweet() {

        var show = function() {
            var tweet = tweets[currentTweet];
            var pane = $('#content .tweet');
            /*
              The documentation (and experience) tells us we get the tweet
              text 'escaped and HTML encoded'.
              I still don't like to .html() this into the page, but being more
              cautious would make twittify() much more involved.

              http://apiwiki.twitter.com/Return-Values
            */
            pane.find('.text').html(tweet.text);
            pane.find('h2').empty().append(
                $('').attr('href', tweet.userUrl).text('@' + tweet.user));
            pane.find('h2').append(
                $('').attr('href', tweet.url).text(tweet.date).addClass(
                    'date'));
        }

        if (initialTweet)
            show();
        else
            $("#content .tweet").fadeOut(twitterFadeTime, function () {
                show();
                $("#content .tweet").fadeIn(twitterFadeTime);
            });

        initialTweet = false;

    }

    // Setup the Twitter stream
    function setupTwitter() {

        // Get tweets, show the first one, and skip to next tweet every 5 seconds
        updateTwitter(function() {

            if (tweets.length > 0)
                showTweet();

            if (tweets.length > 1) {

                $(document).everyTime(twitterDisplayTime,
                                      'next',
                                      showNextTweet);

                // We add navigation links and reset the skip timer on click
                $('#content').append($('
').append(
                    $('
<
').click(function() {
                        showPreviousTweet();
                        $(document).stopTime('next');
                        $(document).everyTime(twitterDisplayTime,
                                              'next',
                                              showNextTweet);
                    })
                ).append(
                    $('
>
').click(function() {
                        showNextTweet();
                        $(document).stopTime('next');
                        $(document).everyTime(twitterDisplayTime,
                                              'next',
                                              showNextTweet);
                    })
                ));

            }

        });

        // Every 5 minutes, get tweets and start at the latest tweet again
        $(document).everyTime(twitterReloadTime, 'reload', updateTwitter);

        // Show link to Twitter search results
        $('#content').append($('
').append(
            $('meer...').attr('href', twitterUrl)));

        // Pause auto advancing of tweets on mouse hover
        $('#content .tweet').hover(function() {
            $(document).stopTime('next');
        }, function() {
            if (tweets.length > 1) {
                // If we directly want to advance on hover-out, uncomment this
                //showNextTweet();
                $(document).everyTime(twitterDisplayTime,
                                      'next',
                                      showNextTweet);
            }
        });

    }

    // Show Delicious links
    updateDelicious();

    // If this is the index page, setup the Twitter stream
    if ($('body').hasClass('index'))
        setupTwitter();

});

// Create links for urls, users, and hashtags
function twittify(tweet) {

    var linkUrl = function(s) {
        var returning = [];
        var regexp = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi;
        return s.replace(regexp,"$1");
    }

    var linkUser = function(s) {
        var returning = [];
        var regexp = /[\@]+([A-Za-z0-9-_]+)/gi;
        return s.replace(regexp,"@$1");
    }

    var linkHash = function(s) {
        var returning = [];
        var regexp = / [\#]+([A-Za-z0-9-_]+)/gi;
        return s.replace(regexp, ' #$1');
    }

    return linkHash(linkUser(linkUrl(tweet)));

}

/*
  The non-search twitter APIs return inconsistently-formatted dates, which
  Date.parse cannot handle in IE. We therefore perform the following
  transformation:

  Wed Apr 29 08:53:31 +0000 2009
  =>
  Wed, Apr 29 2009 08:53:31 +0000
*/
function parseDate(s) {
    return Date.parse(s.replace(/^([a-z]{3})( [a-z]{3} \d\d?)(.*)( \d{4})$/i,
                                '$1,$2$4$3'));
}

// Turn a date/time string into a relative time
function relativeTime(time) {

    var parsedDate = parseDate(time);
    var relativeTo = (arguments.length > 1) ? arguments[1] : new Date();
    var delta = parseInt((relativeTo.getTime() - parsedDate) / 1000);

    var pluralize = function(singular, n) {
        var plurals = {
            'minuut' : 'minuten',
            'uur'    : 'uur',
            'dag'    : 'dagen'
        };
        return '' + n + ' ' + (n == 1 ? singular : plurals[singular]);
    };

    if (delta < 60)
        return 'seconden geleden';
    else if (delta < (60 * 60))
        return pluralize('minuut', parseInt(delta / 60)) + ' geleden';
    else if (delta < (24 * 60 * 60))
        return pluralize('uur', parseInt(delta / 3600)) + ' geleden';
    else
        return pluralize('dag', parseInt(delta / 86400)) + ' geleden';

}

// Create a short description from a date string
function shortDate(s) {

    var months = ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun',
                  'jul', 'aug', 'sep', 'okt', 'nov', 'dec'];

    if (!s)
        return (new Date).getDate() + ' ' + months[(new Date).getMonth() + 1];

    var d = s.match(/^\d{4}-(\d{2})-(\d{2}).*$/);
    if (d != null)
        return d[2] + ' ' + months[parseInt(d[1]) - 1];

    return '';

}
<commit_msg>Blacklist.<commit_after>/***********************************************************************

    Check in, check uit

    Copyright 2010, Martijn Vermaat <martijn@vermaat.name>

      http://checkincheckuit.nl
      http://svn.vermaat.name/checkincheckuit

    Licensed under the MIT license, see the LICENSE file

      http://en.wikipedia.org/wiki/Mit_license

    Some of the Twitter handling code was adapted from the jQuery
    plugin Tweet!, found at http://tweet.seaofclouds.com/

    This code uses:
      jQuery          http://jquery.com
      jQuery Timers   http://plugins.jquery.com/project/timers

***********************************************************************/

$(document).ready(function() {

    var twitterSearch = 'ovchipkaart OR chipkaart OR ovchip';
    var twitterCount = 50;
    var twitterBlacklist = ['Regio_Alphen',
                            'Regio_Leiden',
                            'LeidenNL',
                            'Regio_Duin_Bol',
                            'Edestad',
                            'nieuwsede',
                            'edenieuwspunt.nl',
                            'nieuwsinutrecht',
                            'UtrechtNL',
                            'rtvutrecht',
                            'echo_utrecht',
                            'regio_nieuws',
                            'hetlokalenieuws',
                            'Nieuwsbekijken',
                            'totaalnieuwsweb',
                            'De_Pers',
                            '123nieuws',
                            'nieuwsnld',
                            'economie_nieuws',
                            'treinreizigernl',
                            'doormijverloren',
                            'doormijgevonden',
                            'ov_chipkaart'];
    var twitterDisplayTime = 1000 * 8;
    var twitterFadeTime = 800;
    /*
      There seems to be a bug, where animations are not smooth when the
      interval is specified as a string, e.g. '5s'.
    */
    var twitterReloadTime = 1000 * 60 * 5;

    var deliciousUser = 'checkuitcheckin';
    var deliciousTag = 'nieuws';
    var deliciousCount = 10;

    // Unfortunately, twitter query cannot exceed 140 characters
    var twitterUrl = 'http://search.twitter.com/search?&q='
        + encodeURIComponent(twitterSearch);
    var twitterApiUrl = 'http://search.twitter.com/search.json?&q='
        + encodeURIComponent(twitterSearch)
        + '&rpp=' + twitterCount + '&callback=?';
    var initialTweet = true;
    var tweets = [];
    var currentTweet = 0;

    var deliciousUrl = 'http://delicious.com/' + deliciousUser
        + '/' + deliciousTag;
    var deliciousApiUrl = 'http://feeds.delicious.com/v2/json/'
        + deliciousUser + '/' + deliciousTag
        + '?count=' + deliciousCount + '&callback=?';

    // Load Twitter search results and call callback function
    function updateTwitter(callback) {

        // http://apiwiki.twitter.com/Return-Values

        $.getJSON(twitterApiUrl, function(data) {

            currentTweet = 0;
            tweets = [];

            $.each((data.results || data), function(i, tweet) {
                var user = tweet.from_user || tweet.user.screen_name;
                if (twitterBlacklist.indexOf(user) == -1) {
                    tweets.push({
                        text    : twittify(tweet.text),
                        user    : user,
                        date    : relativeTime(tweet.created_at),
                        url     : 'http://twitter.com/' + user
                                  + '/statuses/' + tweet.id,
                        userUrl : 'http://twitter.com/' + user
                    });
                }
            });

            if ($.isFunction(callback)) callback();

        });

    }

    // Load Delicious links and show them on the page
    function updateDelicious() {

        // http://delicious.com/help/feeds

        $.getJSON(deliciousApiUrl, function(data) {
            var list = $('
').appendTo($('#delicious'));
            $.each((data.results || data), function(i, item) {
                list.append($('
').text(shortDate(item.dt)));
                list.append($('
').append(
                    $('').attr('href', item.u).text(item.d)));
            });
            $('#delicious').append($('
').append(
                $('Meer nieuwsberichten...').attr('href', deliciousUrl)));
        });

    }

    // Advance to the next twee
    function showNextTweet() {
        if (tweets.length < 1) return;
        currentTweet = (currentTweet + 1) % tweets.length;
        showTweet();
    }

    // Like the function above, with a minor difference
    function showPreviousTweet() {
        if (tweets.length < 1) return;
        currentTweet = (tweets.length + currentTweet - 1) % tweets.length;
        showTweet();
    }

    /*
      Show the current tweet on the page. If this is the first twee we show,
      do just that. Otherwise fadeout the old tweet and fadein the new.
    */
    function showTweet() {

        var show = function() {
            var tweet = tweets[currentTweet];
            var pane = $('#content .tweet');
            /*
              The documentation (and experience) tells us we get the tweet
              text 'escaped and HTML encoded'.
              I still don't like to .html() this into the page, but being more
              cautious would make twittify() much more involved.

              http://apiwiki.twitter.com/Return-Values
            */
            pane.find('.text').html(tweet.text);
            pane.find('h2').empty().append(
                $('').attr('href', tweet.userUrl).text('@' + tweet.user));
            pane.find('h2').append(
                $('').attr('href', tweet.url).text(tweet.date).addClass(
                    'date'));
        }

        if (initialTweet)
            show();
        else
            $("#content .tweet").fadeOut(twitterFadeTime, function () {
                show();
                $("#content .tweet").fadeIn(twitterFadeTime);
            });

        initialTweet = false;

    }

    // Setup the Twitter stream
    function setupTwitter() {

        // Get tweets, show the first one, and skip to next tweet every 5 seconds
        updateTwitter(function() {

            if (tweets.length > 0)
                showTweet();

            if (tweets.length > 1) {

                $(document).everyTime(twitterDisplayTime,
                                      'next',
                                      showNextTweet);

                // We add navigation links and reset the skip timer on click
                $('#content').append($('
').append(
                    $('
<
').click(function() {
                        showPreviousTweet();
                        $(document).stopTime('next');
                        $(document).everyTime(twitterDisplayTime,
                                              'next',
                                              showNextTweet);
                    })
                ).append(
                    $('
>
').click(function() {
                        showNextTweet();
                        $(document).stopTime('next');
                        $(document).everyTime(twitterDisplayTime,
                                              'next',
                                              showNextTweet);
                    })
                ));

            }

        });

        // Every 5 minutes, get tweets and start at the latest tweet again
        $(document).everyTime(twitterReloadTime, 'reload', updateTwitter);

        // Show link to Twitter search results
        $('#content').append($('
').append(
            $('meer...').attr('href', twitterUrl)));

        // Pause auto advancing of tweets on mouse hover
        $('#content .tweet').hover(function() {
            $(document).stopTime('next');
        }, function() {
            if (tweets.length > 1) {
                // If we directly want to advance on hover-out, uncomment this
                //showNextTweet();
                $(document).everyTime(twitterDisplayTime,
                                      'next',
                                      showNextTweet);
            }
        });

    }

    // Show Delicious links
    updateDelicious();

    // If this is the index page, setup the Twitter stream
    if ($('body').hasClass('index'))
        setupTwitter();

});

// Create links for urls, users, and hashtags
function twittify(tweet) {

    var linkUrl = function(s) {
        var returning = [];
        var regexp = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi;
        return s.replace(regexp,"$1");
    }

    var linkUser = function(s) {
        var returning = [];
        var regexp = /[\@]+([A-Za-z0-9-_]+)/gi;
        return s.replace(regexp,"@$1");
    }

    var linkHash = function(s) {
        var returning = [];
        var regexp = / [\#]+([A-Za-z0-9-_]+)/gi;
        return s.replace(regexp, ' #$1');
    }

    return linkHash(linkUser(linkUrl(tweet)));

}

/*
  The non-search twitter APIs return inconsistently-formatted dates, which
  Date.parse cannot handle in IE. We therefore perform the following
  transformation:

  Wed Apr 29 08:53:31 +0000 2009
  =>
  Wed, Apr 29 2009 08:53:31 +0000
*/
function parseDate(s) {
    return Date.parse(s.replace(/^([a-z]{3})( [a-z]{3} \d\d?)(.*)( \d{4})$/i,
                                '$1,$2$4$3'));
}

// Turn a date/time string into a relative time
function relativeTime(time) {

    var parsedDate = parseDate(time);
    var relativeTo = (arguments.length > 1) ? arguments[1] : new Date();
    var delta = parseInt((relativeTo.getTime() - parsedDate) / 1000);

    var pluralize = function(singular, n) {
        var plurals = {
            'minuut' : 'minuten',
            'uur'    : 'uur',
            'dag'    : 'dagen'
        };
        return '' + n + ' ' + (n == 1 ? singular : plurals[singular]);
    };

    if (delta < 60)
        return 'seconden geleden';
    else if (delta < (60 * 60))
        return pluralize('minuut', parseInt(delta / 60)) + ' geleden';
    else if (delta < (24 * 60 * 60))
        return pluralize('uur', parseInt(delta / 3600)) + ' geleden';
    else
        return pluralize('dag', parseInt(delta / 86400)) + ' geleden';

}

// Create a short description from a date string
function shortDate(s) {

    var months = ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun',
                  'jul', 'aug', 'sep', 'okt', 'nov', 'dec'];

    if (!s)
        return (new Date).getDate() + ' ' + months[(new Date).getMonth() + 1];

    var d = s.match(/^\d{4}-(\d{2})-(\d{2}).*$/);
    if (d != null)
        return d[2] + ' ' + months[parseInt(d[1]) - 1];

    return '';

}
<|endoftext|>


<commit_before>function addClearOnClick(tag, target) {
  tag.onclick = function() {
    target.value = '';
  }
}
function addViewOnClick(tag, target) {
  var href;
  tag.onclick = function() {
    href = target.value;
    if(href)
      window.open(href, 'sfMediaBrowserViewFile', '');
  }
}

HTMLElement.prototype.getElementByTagName = function(tag_name, index) {
  index = index ? index : 0;
  var tags = this.getElementsByTagName(tag_name);
  return tags[index];
}

HTMLElement.prototype.getElementsByClassName = function(class_name) {
  var tags = this.getElementsByTagName('*');
  var matches = [], i=0; tag;
  for(i; i<tags.length;++i) {
    tag = tags[i];
    if(tag.hasAttribute('class') && tag.getAttribute('class') == class_name)
      matches.push(tag);
  }
  return matches;
}

HTMLElement.prototype.getElementByClassName = function(class_name, index) {
  index = index ? index : 0;
  var tags = this.getElementsByClassName(class_name);
  return tags[index];
}

window.onload = function() {
  var wrappers = document.getElementsByClassName('sf_media_browser_input_file');

  var wrapper, i=0, delete_link, view_link, input;
  for(i; i<wrappers.length;++i) {
    wrapper = wrappers[i];
    input = wrapper.getElementByTagName('input');
    delete_link = wrapper.getElementByClassName('delete');
    view_link = wrapper.getElementByClassName('view');
    addClearOnClick(delete_link, input);
    addViewOnClick(view_link, input);
  }

}<commit_msg>fixed js error 'tag' not found<commit_after>function addClearOnClick(tag, target) {
  tag.onclick = function() {
    target.value = '';
  }
}
function addViewOnClick(tag, target) {
  var href;
  tag.onclick = function() {
    href = target.value;
    if(href)
      window.open(href, 'sfMediaBrowserViewFile', '');
  }
}

HTMLElement.prototype.getElementByTagName = function(tag_name, index) {
  index = index ? index : 0;
  var tags = this.getElementsByTagName(tag_name);
  return tags[index];
}

HTMLElement.prototype.getElementsByClassName = function(class_name) {
  var tags = this.getElementsByTagName('*');
  var matches = [], i=0, tag;
  for(i; i<tags.length;++i) {
    tag = tags[i];
    if(tag.hasAttribute('class') && tag.getAttribute('class') == class_name)
      matches.push(tag);
  }
  return matches;
}

HTMLElement.prototype.getElementByClassName = function(class_name, index) {
  index = index ? index : 0;
  var tags = this.getElementsByClassName(class_name);
  return tags[index];
}

window.onload = function() {
  var wrappers = document.getElementsByClassName('sf_media_browser_input_file');

  var wrapper, i=0, delete_link, view_link, input;
  for(i; i<wrappers.length;++i) {
    wrapper = wrappers[i];
    input = wrapper.getElementByTagName('input');
    delete_link = wrapper.getElementByClassName('delete');
    view_link = wrapper.getElementByClassName('view');
    addClearOnClick(delete_link, input);
    addViewOnClick(view_link, input);
  }

}<|endoftext|>


<commit_before>// Copyright © 2015-2018 Esko Luontola
// This software is released under the Apache License 2.0.
// The license text is at http://www.apache.org/licenses/LICENSE-2.0

/* @flow */

import * as React from 'react';
import history from "../history";

function handleClick(event: MouseEvent) {
  event.preventDefault();
  const target = ((event.currentTarget: any): HTMLAnchorElement);
  history.push({
    pathname: target.pathname,
    search: target.search
  });
}

const Link = ({href, children, ...props}: {
  href: string,
  children?: React.Node
}) => (
  {children}
);

export default Link;
<commit_msg>Link: handle modifier keys and custom link target<commit_after>// Copyright © 2015-2019 Esko Luontola
// This software is released under the Apache License 2.0.
// The license text is at http://www.apache.org/licenses/LICENSE-2.0

/* @flow */

import * as React from 'react';
import history from "../history";

const LEFT_MOUSE_BUTTON = 0;

function openInCurrentTab(event: MouseEvent) {
  const link = ((event.currentTarget: any): HTMLAnchorElement);
  return (!link.target || link.target === "_self");
}

function modifierKeysPressed(event: MouseEvent) {
  return !!(event.ctrlKey || event.altKey || event.shiftKey || event.metaKey);
}

function handleClick(event: MouseEvent) {
  if (event.button === LEFT_MOUSE_BUTTON && openInCurrentTab(event) && !modifierKeysPressed(event)) {
    event.preventDefault();
    const link = ((event.currentTarget: any): HTMLAnchorElement);
    history.push({
      pathname: link.pathname,
      search: link.search
    });
  }
}

const Link = ({href, children, ...props}: {
  href: string,
  children?: React.Node
}) => (
  {children}
);

export default Link;
<|endoftext|>