<commit_before>'use strict';

const Enum = require('./enum.js');
const format = require('./format.js');
const template = require('./template.js');
const ProviderManager = require('./providers/manager.js');

/**
 * Return environment value or throw an error if it isn't found
 * @param {String} key
 * @returns {String}
 */
function env(key) {
	let value = process.env[key];
	if (value === undefined) { throw new Error(`Environment value ${key} must be set`); }
	return value;
}

exports.provider = new ProviderManager();

exports.env = env;
/** @type {String} */
exports.proxy = process.env['HTTPS_PROXY'];
/** @type {Number} */
exports.timestamp = new Date().getTime();
/** @type {Boolean} */
exports.isProduction = true; // (process.env['NODE_ENV'] === 'production');
/**
 * Whether to use Persona based wwwhisper authentication
 * @see https://devcenter.heroku.com/articles/wwwhisper
 * @type {Boolean}
 */
exports.usePersona = process.env['WWWHISPER_DISABLE'] !== '1';
/** @type {String} */
exports.logFile = './temp/trail-image.log';
/** @type {Boolean} */
exports.cacheOutput = exports.isProduction;
/** @type {number} */
exports.timezone = -6;
/** @type {String} */
exports.contactEmail = 'contact@trailimage.com';
/** @type {String} */
exports.contactLink = `<a href="mailto:${exports.contactEmail}">Contact</a>`;
/** @type {String} */
exports.repoUrl = null;

exports.style = {
	/**
	 * Post series are identified as those having a common title with differing subtitles
	 * @type {String}
	 */
	subtitleSeparator: ':',
	/**
	 * Photo EXIF is only shown for named artists
	 * @type {String[]}
	 */
	artistNames: ['Abbott','Wright','Bowman','Thomas','Reed']
};

/**
 * @enum {Number|Number[]|Boolean}
 */
exports.map = {
	minimumTrackLength: 0.2,
	minimumTrackPoints: 5,
	/**
	 * Distance a track point must deviate from others to avoid Douglas-Peucker simplification
	 */
	maxDeviationFeet: 0.5,
	/**
	 * Manually adjusted tracks may have infinite speeds between points so throw out anything
	 * over a threshold
	 */
	maxPossibleSpeed: 150,
	/**
	 * Erase tracks around given latitude and longitude
	 * @type {Number[]}
	 */
	privacyCenter: null,  // reverse order from Google map listing
	privacyMiles: 1,
	/**
	 * @type {Boolean}
	 */
	checkPrivacy: false,
	/**
	 * Whether track GPX files can be downloaded
	 * @type {Boolean}
	 */
	allowDownload: true,
	/**
	 * Maximum number of photo markers to show on Google static map
	 * @type {Number}
	 */
	maxMarkers: 70      // max URL is 2048; 160 is used for base URL; each coordinate needs about 26 characters
};

/**
 * @enum {String}
 */
exports.bing = {
	key: process.env['BING_KEY']
};

exports.cacheDuration = Enum.time.day * 2;
exports.retryDelay = Enum.time.second * 30;

/**
 * @enum {string|boolean}
 * @see https://developers.facebook.com/docs/reference/plugins/like/
 * @see https://developers.facebook.com/apps/110860435668134/summary
 */
exports.facebook = {
	appID: '110860435668134',
	pageID: '241863632579825',
	siteID: '578261855525416',
	adminID: '1332883594',
	enabled: true,
	authorURL: 'https://www.facebook.com/jason.e.abbott'
};

/**
 * @see http://code.google.com/apis/console/#project:1033232213688
 * @see http://developers.google.com/maps/documentation/staticmaps/
 * @type {string}
 */
exports.google = {
	apiKey: process.env['GOOGLE_KEY'],
	projectID: '1033232213688',
	analyticsID: '22180727',        // shown as 'UA-22180727-1
	searchEngineID: process.env['GOOGLE_SEARCH_ID'],
	blogID: '118459106898417641'
};

/**
 * Maintain redirects to support previously used URLs
 * @type {Object.<String>}
 * @enum {String}
 */
exports.redirects = {
	'brother-rider-2013-a-night-in-pierce': 'brother-ride-2013',
	'backroads-to-college': 'panhandle-past-and-future',
	'owyhee-snow-and-sands-uplands': 'owyhee-snow-and-sand'
};

/**
 * Match old blog URLs to new
 * Slug is always prefixed by /YYYY/MM/
 * @see http://www.blogger.com/blogger.g?blogID=118459106898417641#allposts
 * @enum {String}
 */
exports.blogRedirects = {
	'juntura-by-desert-dry-creek-gorge': 'juntura-by-desert',
	'juntura-by-desert-owyhee-dam': 'juntura-by-desert',
	'eastern-oregon-club-ride-jordan-craters': 'klr-club-in-the-owyhees',
	'eastern-oregon-club-ride-leslie-gulch': 'klr-club-in-the-owyhees',
	'eastern-oregon-club-ride-lake-owyhee': 'klr-club-in-the-owyhees',
	'autumn-lowman-loop-going-home': 'wintry-backroads-to-lowman',
	'autumn-lowman-loop-overnight': 'wintry-backroads-to-lowman',
	'autumn-lowman-loop-lunch-and-museum': 'wintry-backroads-to-lowman',
	'autumn-lowman-loop-over-hills': 'wintry-backroads-to-lowman',
	'st-joe-hidden-trails-day-5': 'brother-ride-2011/bailout-to-benewah',
	'st-joes-hidden-trails-day-4': 'brother-ride-2011/bailout-to-benewah',
	'st-joe-hidden-trails-day-3': 'brother-ride-2011/exercise-and-elsie-lake',
	'st-joes-hidden-trails-day-2': 'brother-ride-2011/tunnels-to-loop-creek',
	'st-joes-hidden-trails-day-1': 'brother-ride-2011',
	'edge-of-hells-canyon-oregon-side': 'hat-point-above-hells-canyon',
	'edge-of-hells-canyon-from-idaho': 'hat-point-above-hells-canyon',
	'up-to-wazzu-palouse-ohv': 'backroads-to-college',
	'up-to-wazzu-scenic-route': 'backroads-to-college',
	'danskin-with-hunter': 'stalled-in-willow-creek',
	'bruneau-dune-sands-of-time': 'grandma-on-the-big-dune',
	'zeno-loop-petroglyphs': 'zeno-falls-on-ben',
	'zeno-loop-falls': 'zeno-falls-on-ben',
	'zeno-loop-homestead': 'zeno-falls-on-ben',
	'zeno-loop-shoo-fly': 'zeno-falls-on-ben',
	'swan-falls-but-once-birds-of-prey': 'swan-falls-but-once',
	'swan-falls-but-once-to-snake': 'swan-falls-but-once',
	'zeno-canyon-ride-not-taken': '',
	'indian-hot-springs-leaving-there': 'indian-hot-springs',
	'indian-hot-springs-being-there': 'indian-hot-springs',
	'indian-hot-springs-getting-there': 'indian-hot-springs',
	'louie-lake-resplendent-road': 'sleeping-on-the-shore-of-louie-lake',
	'louie-lake-troublesome-trail': 'sleeping-on-the-shore-of-louie-lake',
	'lolo-motorway-and-more-day-4': 'brother-ride-2010/two-breakdowns',
	'lolo-motorway-and-more-day-3': 'brother-ride-2010/thundersnow',
	'lolo-motorway-and-more-day-2': 'brother-ride-2010/cayuse-creek',
	'lolo-motorway-and-more-day-1': 'brother-ride-2010',
	'hunter-meets-captain-bonneville': 'meeting-captain-bonneville',
	'three-national-forests-challis': 'three-national-forests/challis',
	'three-national-forests-sawtooth': 'three-national-forests/sawtooth',
	'three-national-forests-boise': 'three-national-forests',
	'troy-days-and-moscow-mountain': 'troy-days-and-moscow-mountain',
	'silver-city': 'first-ride-to-silver-city',
	'wallowa-valley-2010-out-with-bang': 'wallowa-valley-rally/out-with-a-bang',
	'wallowa-valley-2010-ryan-ride': 'wallowa-valley-rally/ryan-ride',
	'wallowa-valley-2010-being-there': 'wallowa-valley-rally/being-there',
	'wallowa-valley-2010-getting-there': 'wallowa-valley-rally',
	'tuscarora-going-home': 'making-art-in-tuscarora/going-home',
	'tuscarora-in-mountains': 'making-art-in-tuscarora/in-the-mountains',
	'tuscarora-in-hills': 'making-art-in-tuscarora/in-the-hills',
	'tuscarora-town': 'making-art-in-tuscarora/the-town',
	'tuscarora-getting-there': 'making-art-in-tuscarora',
	'jump-creek-to-leslie-gulch-part-1': 'jump-creek-and-leslie-gulch',                 // old link
	'jump-creek-to-leslie-gulch-part-2': 'jump-creek-and-leslie-gulch',
	'jump-creek-to-leslie-gulch-part-3': 'jump-creek-and-leslie-gulch',
	'owyhee-rocks-succor-creek': 'jump-creek-and-leslie-gulch',
	'owyhee-rocks-leslie-gulch': 'jump-creek-and-leslie-gulch',
	'owyhee-rocks-jump-creek-canyon': 'jump-creek-and-leslie-gulch',
	'aptly-named-mud-flat-road': 'rain-on-mud-flat-road',
	'sams-memorial-prairie-poker-run': 'mayfield-skull-rock-y-stop',
	'freezing-in-hells-canyon': 'freezing-in-hells-canyon',
	'pilot-sunset-and-jackson-peaks': 'one-day-three-peaks',
	'lost-lake-crawdads-of-st-joe-day-4': 'brother-ride-2009/crater-peak-reunion',
	'lost-lake-crawdads-of-st-joe-day-3': 'brother-ride-2009/rain-in-avery',
	'lost-lake-crawdads-of-st-joe-day-2': 'brother-ride-2009/lost-lake-crawdads',
	'lost-lake-crawdads-of-st-joe-day-1': 'brother-ride-2009',
	'circumnavigating-oahu': 'circumnavigating-oahu',
	'boise-ridge-with-boy': 'boise-ridge-with-the-boy',
	'three-brothers-three-days-three-loops': 'brother-ride-2008/cold-ride-home',        // old link
	'three-loops-in-st-joe-day-3': 'brother-ride-2008/cold-ride-home',
	'three-loops-in-st-joe-day-2': 'brother-ride-2008/camping-with-cows',
	'three-loops-in-st-joe-day-1': 'brother-ride-2008',
	'to-trinity-and-beyond': 'lunch-at-trinity-lookout',
	'unholy-trinity': 'unholy-trinity',
	'my-eye-my-eye-she-screamed': 'bad-day-at-danskin',
	'thorn-creek-butte-scenic-route': 'arrowrock-to-thorn-creek-butte',
	'paths-around-palouse': 'troy-days-beers-and-bears',
	'spelunking-in-danskin': 'spelunking-in-danskin',
	'lucky-peak-with-laura': 'lucky-peak-with-laura',
	'cricket-ridge-ride': 'cricket-ridge-ride',
	'caterpillar-ridge-ride': 'spring-caterpillars-on-the-boise-ridge'
};

/**
 * @type {string}
 * @const
 */
exports.domain = 'trailimage.com';

/**
 * @type {String}
 * @const
 */
exports.title = 'Trail Image';

/**
 * @type {String}
 * @const
 */
exports.subtitle = 'Adventure Photography by Jason Abbott';

/**
 * @type {String}
 * @const
 */
exports.description = 'Stories, image and videos of small adventure trips in and around the state of Idaho';

/**
 * @type {String}
 * @const
 */
exports.keywords = 'BMW R1200GS, KTM XCW, jeep wrangler, motorcycle, motorcycling, riding, adventure, Jason Abbott, Abbott, outdoors, scenery, idaho, mountains';<commit_msg>remove debug setting<commit_after>'use strict';

const Enum = require('./enum.js');
const format = require('./format.js');
const template = require('./template.js');
const ProviderManager = require('./providers/manager.js');

/**
 * Return environment value or throw an error if it isn't found
 * @param {String} key
 * @returns {String}
 */
function env(key) {
	let value = process.env[key];
	if (value === undefined) { throw new Error(`Environment value ${key} must be set`); }
	return value;
}

exports.provider = new ProviderManager();

exports.env = env;
/** @type {String} */
exports.proxy = process.env['HTTPS_PROXY'];
/** @type {Number} */
exports.timestamp = new Date().getTime();
/** @type {Boolean} */
exports.isProduction = (process.env['NODE_ENV'] === 'production');
/**
 * Whether to use Persona based wwwhisper authentication
 * @see https://devcenter.heroku.com/articles/wwwhisper
 * @type {Boolean}
 */
exports.usePersona = process.env['WWWHISPER_DISABLE'] !== '1';
/** @type {String} */
exports.logFile = './temp/trail-image.log';
/** @type {Boolean} */
exports.cacheOutput = exports.isProduction;
/** @type {number} */
exports.timezone = -6;
/** @type {String} */
exports.contactEmail = 'contact@trailimage.com';
/** @type {String} */
exports.contactLink = `<a href="mailto:${exports.contactEmail}">Contact</a>`;
/** @type {String} */
exports.repoUrl = null;

exports.style = {
	/**
	 * Post series are identified as those having a common title with differing subtitles
	 * @type {String}
	 */
	subtitleSeparator: ':',
	/**
	 * Photo EXIF is only shown for named artists
	 * @type {String[]}
	 */
	artistNames: ['Abbott','Wright','Bowman','Thomas','Reed']
};

/**
 * @enum {Number|Number[]|Boolean}
 */
exports.map = {
	minimumTrackLength: 0.2,
	minimumTrackPoints: 5,
	/**
	 * Distance a track point must deviate from others to avoid Douglas-Peucker simplification
	 */
	maxDeviationFeet: 0.5,
	/**
	 * Manually adjusted tracks may have infinite speeds between points so throw out anything
	 * over a threshold
	 */
	maxPossibleSpeed: 150,
	/**
	 * Erase tracks around given latitude and longitude
	 * @type {Number[]}
	 */
	privacyCenter: null,  // reverse order from Google map listing
	privacyMiles: 1,
	/**
	 * @type {Boolean}
	 */
	checkPrivacy: false,
	/**
	 * Whether track GPX files can be downloaded
	 * @type {Boolean}
	 */
	allowDownload: true,
	/**
	 * Maximum number of photo markers to show on Google static map
	 * @type {Number}
	 */
	maxMarkers: 70      // max URL is 2048; 160 is used for base URL; each coordinate needs about 26 characters
};

/**
 * @enum {String}
 */
exports.bing = {
	key: process.env['BING_KEY']
};

exports.cacheDuration = Enum.time.day * 2;
exports.retryDelay = Enum.time.second * 30;

/**
 * @enum {string|boolean}
 * @see https://developers.facebook.com/docs/reference/plugins/like/
 * @see https://developers.facebook.com/apps/110860435668134/summary
 */
exports.facebook = {
	appID: '110860435668134',
	pageID: '241863632579825',
	siteID: '578261855525416',
	adminID: '1332883594',
	enabled: true,
	authorURL: 'https://www.facebook.com/jason.e.abbott'
};

/**
 * @see http://code.google.com/apis/console/#project:1033232213688
 * @see http://developers.google.com/maps/documentation/staticmaps/
 * @type {string}
 */
exports.google = {
	apiKey: process.env['GOOGLE_KEY'],
	projectID: '1033232213688',
	analyticsID: '22180727',        // shown as 'UA-22180727-1
	searchEngineID: process.env['GOOGLE_SEARCH_ID'],
	blogID: '118459106898417641'
};

/**
 * Maintain redirects to support previously used URLs
 * @type {Object.<String>}
 * @enum {String}
 */
exports.redirects = {
	'brother-rider-2013-a-night-in-pierce': 'brother-ride-2013',
	'backroads-to-college': 'panhandle-past-and-future',
	'owyhee-snow-and-sands-uplands': 'owyhee-snow-and-sand'
};

/**
 * Match old blog URLs to new
 * Slug is always prefixed by /YYYY/MM/
 * @see http://www.blogger.com/blogger.g?blogID=118459106898417641#allposts
 * @enum {String}
 */
exports.blogRedirects = {
	'juntura-by-desert-dry-creek-gorge': 'juntura-by-desert',
	'juntura-by-desert-owyhee-dam': 'juntura-by-desert',
	'eastern-oregon-club-ride-jordan-craters': 'klr-club-in-the-owyhees',
	'eastern-oregon-club-ride-leslie-gulch': 'klr-club-in-the-owyhees',
	'eastern-oregon-club-ride-lake-owyhee': 'klr-club-in-the-owyhees',
	'autumn-lowman-loop-going-home': 'wintry-backroads-to-lowman',
	'autumn-lowman-loop-overnight': 'wintry-backroads-to-lowman',
	'autumn-lowman-loop-lunch-and-museum': 'wintry-backroads-to-lowman',
	'autumn-lowman-loop-over-hills': 'wintry-backroads-to-lowman',
	'st-joe-hidden-trails-day-5': 'brother-ride-2011/bailout-to-benewah',
	'st-joes-hidden-trails-day-4': 'brother-ride-2011/bailout-to-benewah',
	'st-joe-hidden-trails-day-3': 'brother-ride-2011/exercise-and-elsie-lake',
	'st-joes-hidden-trails-day-2': 'brother-ride-2011/tunnels-to-loop-creek',
	'st-joes-hidden-trails-day-1': 'brother-ride-2011',
	'edge-of-hells-canyon-oregon-side': 'hat-point-above-hells-canyon',
	'edge-of-hells-canyon-from-idaho': 'hat-point-above-hells-canyon',
	'up-to-wazzu-palouse-ohv': 'backroads-to-college',
	'up-to-wazzu-scenic-route': 'backroads-to-college',
	'danskin-with-hunter': 'stalled-in-willow-creek',
	'bruneau-dune-sands-of-time': 'grandma-on-the-big-dune',
	'zeno-loop-petroglyphs': 'zeno-falls-on-ben',
	'zeno-loop-falls': 'zeno-falls-on-ben',
	'zeno-loop-homestead': 'zeno-falls-on-ben',
	'zeno-loop-shoo-fly': 'zeno-falls-on-ben',
	'swan-falls-but-once-birds-of-prey': 'swan-falls-but-once',
	'swan-falls-but-once-to-snake': 'swan-falls-but-once',
	'zeno-canyon-ride-not-taken': '',
	'indian-hot-springs-leaving-there': 'indian-hot-springs',
	'indian-hot-springs-being-there': 'indian-hot-springs',
	'indian-hot-springs-getting-there': 'indian-hot-springs',
	'louie-lake-resplendent-road': 'sleeping-on-the-shore-of-louie-lake',
	'louie-lake-troublesome-trail': 'sleeping-on-the-shore-of-louie-lake',
	'lolo-motorway-and-more-day-4': 'brother-ride-2010/two-breakdowns',
	'lolo-motorway-and-more-day-3': 'brother-ride-2010/thundersnow',
	'lolo-motorway-and-more-day-2': 'brother-ride-2010/cayuse-creek',
	'lolo-motorway-and-more-day-1': 'brother-ride-2010',
	'hunter-meets-captain-bonneville': 'meeting-captain-bonneville',
	'three-national-forests-challis': 'three-national-forests/challis',
	'three-national-forests-sawtooth': 'three-national-forests/sawtooth',
	'three-national-forests-boise': 'three-national-forests',
	'troy-days-and-moscow-mountain': 'troy-days-and-moscow-mountain',
	'silver-city': 'first-ride-to-silver-city',
	'wallowa-valley-2010-out-with-bang': 'wallowa-valley-rally/out-with-a-bang',
	'wallowa-valley-2010-ryan-ride': 'wallowa-valley-rally/ryan-ride',
	'wallowa-valley-2010-being-there': 'wallowa-valley-rally/being-there',
	'wallowa-valley-2010-getting-there': 'wallowa-valley-rally',
	'tuscarora-going-home': 'making-art-in-tuscarora/going-home',
	'tuscarora-in-mountains': 'making-art-in-tuscarora/in-the-mountains',
	'tuscarora-in-hills': 'making-art-in-tuscarora/in-the-hills',
	'tuscarora-town': 'making-art-in-tuscarora/the-town',
	'tuscarora-getting-there': 'making-art-in-tuscarora',
	'jump-creek-to-leslie-gulch-part-1': 'jump-creek-and-leslie-gulch',                 // old link
	'jump-creek-to-leslie-gulch-part-2': 'jump-creek-and-leslie-gulch',
	'jump-creek-to-leslie-gulch-part-3': 'jump-creek-and-leslie-gulch',
	'owyhee-rocks-succor-creek': 'jump-creek-and-leslie-gulch',
	'owyhee-rocks-leslie-gulch': 'jump-creek-and-leslie-gulch',
	'owyhee-rocks-jump-creek-canyon': 'jump-creek-and-leslie-gulch',
	'aptly-named-mud-flat-road': 'rain-on-mud-flat-road',
	'sams-memorial-prairie-poker-run': 'mayfield-skull-rock-y-stop',
	'freezing-in-hells-canyon': 'freezing-in-hells-canyon',
	'pilot-sunset-and-jackson-peaks': 'one-day-three-peaks',
	'lost-lake-crawdads-of-st-joe-day-4': 'brother-ride-2009/crater-peak-reunion',
	'lost-lake-crawdads-of-st-joe-day-3': 'brother-ride-2009/rain-in-avery',
	'lost-lake-crawdads-of-st-joe-day-2': 'brother-ride-2009/lost-lake-crawdads',
	'lost-lake-crawdads-of-st-joe-day-1': 'brother-ride-2009',
	'circumnavigating-oahu': 'circumnavigating-oahu',
	'boise-ridge-with-boy': 'boise-ridge-with-the-boy',
	'three-brothers-three-days-three-loops': 'brother-ride-2008/cold-ride-home',        // old link
	'three-loops-in-st-joe-day-3': 'brother-ride-2008/cold-ride-home',
	'three-loops-in-st-joe-day-2': 'brother-ride-2008/camping-with-cows',
	'three-loops-in-st-joe-day-1': 'brother-ride-2008',
	'to-trinity-and-beyond': 'lunch-at-trinity-lookout',
	'unholy-trinity': 'unholy-trinity',
	'my-eye-my-eye-she-screamed': 'bad-day-at-danskin',
	'thorn-creek-butte-scenic-route': 'arrowrock-to-thorn-creek-butte',
	'paths-around-palouse': 'troy-days-beers-and-bears',
	'spelunking-in-danskin': 'spelunking-in-danskin',
	'lucky-peak-with-laura': 'lucky-peak-with-laura',
	'cricket-ridge-ride': 'cricket-ridge-ride',
	'caterpillar-ridge-ride': 'spring-caterpillars-on-the-boise-ridge'
};

/**
 * @type {string}
 * @const
 */
exports.domain = 'trailimage.com';

/**
 * @type {String}
 * @const
 */
exports.title = 'Trail Image';

/**
 * @type {String}
 * @const
 */
exports.subtitle = 'Adventure Photography by Jason Abbott';

/**
 * @type {String}
 * @const
 */
exports.description = 'Stories, image and videos of small adventure trips in and around the state of Idaho';

/**
 * @type {String}
 * @const
 */
exports.keywords = 'BMW R1200GS, KTM XCW, jeep wrangler, motorcycle, motorcycling, riding, adventure, Jason Abbott, Abbott, outdoors, scenery, idaho, mountains';<|endoftext|>


<commit_before>'use strict';

var BufferSource = require('./source/buffer-source.js'),
    Effect = require('./effect.js'),
    Emitter = require('./utils/emitter.js'),
    file = require('./utils/file.js'),
    Loader = require('./utils/loader.js'),
    MediaSource = require('./source/media-source.js'),
    MicrophoneSource = require('./source/microphone-source.js'),
    OscillatorSource = require('./source/oscillator-source.js'),
    ScriptSource = require('./source/script-source.js'),
    waveform = require('./utils/waveform.js')();

function Sound(context, destination) {
    var id,
        data,
        effect = new Effect(context),
        gain = effect.gain(),
        isTouchLocked = false,
        loader,
        loop = false,
        playbackRate = 1,
        playWhenReady,
        source,
        sound;

    if(context) {
        effect.setDestination(gain);
        gain.connect(destination || context.destination);
    }

    /*
     * Load
     */

    var load = function(config) {
        var src = file.getSupportedFile(config.src || config.url || config);

        if(source && data && data.tagName) {
            source.load(src);
        }
        else {
            loader = loader || new Loader(src);
            loader.audioContext = !!config.asMediaElement ? null : context;
            loader.isTouchLocked = isTouchLocked;
            loader.once('loaded', function(file) {
                createSource(file);
                sound.emit('loaded', sound);
            });
        }
        return sound;
    };

    /*
     * Controls
     */

    var play = function(delay, offset) {
        if(!source || isTouchLocked) {
            playWhenReady = function() {
                if (source) {
                    play(delay, offset);
                }
            };
            return sound;
        }
        playWhenReady = null;
        effect.setSource(source.sourceNode);

        // update volume needed for no webaudio
        if(!context) { sound.volume = gain.gain.value; }

        source.play(delay, offset);

        if(source.hasOwnProperty('loop')) {
            source.loop = loop;
        }

        sound.emit('play', sound);

        return sound;
    };

    var pause = function() {
        source && source.pause();
        sound.emit('pause', sound);
        return sound;
    };

    var stop = function() {
        source && source.stop();
        sound.emit('stop', sound);
        return sound;
    };

    var seek = function(percent) {
        if(source) {
            source.stop();
            play(0, source.duration * percent);
        }
        return sound;
    };

    var fade = function(volume, duration) {
        if(!source) { return sound; }

        if(context) {
            var  param = gain.gain;
            var time = context.currentTime;
            param.cancelScheduledValues(time);
            param.setValueAtTime(param.value, time);
            param.linearRampToValueAtTime(volume, time + duration);
        }
        else if(typeof source.fade === 'function') {
            source.fade(volume, duration);
        }

        return sound;
    };

    /*
     * Destroy
     */

    var destroy = function() {
        source && source.destroy();
        effect && effect.destroy();
        gain && gain.disconnect();
        loader && loader.destroy();
        sound.off('loaded');
        sound.off('ended');
        gain = null;
        context = null;
        data = null;
        playWhenReady = null;
        source = null;
        effect = null;
        loader = null;
        sound.emit('destroy', sound);
        sound.off('destroy');
    };

    /*
     * Create source
     */

    var createSource = function(value) {
        data = value;

        if(file.isAudioBuffer(data)) {
            source = new BufferSource(data, context, function() {
                sound.emit('ended');
            });
        }
        else if(file.isMediaElement(data)) {
            source = new MediaSource(data, context, function() {
                sound.emit('ended');
            });
        }
        else if(file.isMediaStream(data)) {
            source = new MicrophoneSource(data, context);
        }
        else if(file.isOscillatorType((data && data.type) || data)) {
            source = new OscillatorSource(data.type || data, context);
        }
        else if(file.isScriptConfig(data)) {
            source = new ScriptSource(data, context);
        }
        else {
            throw new Error('Cannot detect data type: ' + data);
        }

        effect.setSource(source.sourceNode);

        sound.emit('ready', sound);

        if(playWhenReady) {
            playWhenReady();
        }
    };

    sound = Object.create(Emitter.prototype, {
        _events: {
            value: {}
        },
        constructor: {
            value: Sound
        },
        play: {
            value: play
        },
        pause: {
            value: pause
        },
        load: {
            value: load
        },
        seek: {
            value: seek
        },
        stop: {
            value: stop
        },
        fade: {
            value: fade
        },
        destroy: {
            value: destroy
        },
        context: {
            value: context
        },
        currentTime: {
            get: function() {
                return source ? source.currentTime : 0;
            },
            set: function(value) {
                // var silent = sound.playing;
                source && source.stop();
                // play(0, value, silent);
                play(0, value);
            }
        },
        data: {
            get: function() {
                return data;
            },
            set : function(value) {
                if(!value) { return; }
                createSource(value);
            }
        },
        duration: {
            get: function() {
                return source ? source.duration : 0;
            }
        },
        effect: {
            value: effect
        },
        ended: {
            get: function() {
                return !!source && source.ended;
            }
        },
        frequency: {
            get: function() {
                return source ? source.frequency : 0;
            },
            set: function(value) {
                if(source && source.hasOwnProperty('frequency')) {
                    source.frequency = value;
                }
            }
        },
        gain: {
            value: gain
        },
        id: {
            get: function() {
                return id;
            },
            set: function(value) {
                id = value;
            }
        },
        isTouchLocked: {
            set: function(value) {
                isTouchLocked = value;
                if(loader) {
                    loader.isTouchLocked = value;
                }
                if(!value && playWhenReady) {
                    playWhenReady();
                }
            }
        },
        loader: {
            get: function() {
                return loader;
            }
        },
        loop: {
            get: function() {
                return loop;
            },
            set: function(value) {
                loop = !!value;

                if(source && source.hasOwnProperty('loop') && source.loop !== loop) {
                  source.loop = loop;
                }
            }
        },
        paused: {
            get: function() {
                return !!source && source.paused;
            }
        },
        playing: {
            get: function() {
                return !!source && source.playing;
            }
        },
        playbackRate: {
            get: function() {
                return playbackRate;
            },
            set: function(value) {
                playbackRate = value;
                if(source) {
                  source.playbackRate = playbackRate;
                }
            }
        },
        progress: {
            get: function() {
                return source ? source.progress : 0;
            }
        },
        volume: {
            get: function() {
                if(context) {
                    return gain.gain.value;
                }
                if(source && source.hasOwnProperty('volume')) {
                    return source.volume;
                }
                return 1;
            },
            set: function(value) {
                if(isNaN(value)) { return; }

                var param = gain.gain;

                if(context) {
                    var time = context.currentTime;
                    param.cancelScheduledValues(time);
                    param.value = value;
                    param.setValueAtTime(value, time);
                }
                else {
                    param.value = value;

                    if(source && source.hasOwnProperty('volume')) {
                        source.volume = value;
                    }
                }
            }
        },
        waveform: {
            value: function(length) {
                if(!data) {
                    sound.once('ready', function() {
                        waveform(data, length);
                    });
                }
                return waveform(data, length);
            }
        }
    });

    return Object.freeze(sound);
}

module.exports = Sound;
<commit_msg>adds delay param to sound stop function<commit_after>'use strict';

var BufferSource = require('./source/buffer-source.js'),
    Effect = require('./effect.js'),
    Emitter = require('./utils/emitter.js'),
    file = require('./utils/file.js'),
    Loader = require('./utils/loader.js'),
    MediaSource = require('./source/media-source.js'),
    MicrophoneSource = require('./source/microphone-source.js'),
    OscillatorSource = require('./source/oscillator-source.js'),
    ScriptSource = require('./source/script-source.js'),
    waveform = require('./utils/waveform.js')();

function Sound(context, destination) {
    var id,
        data,
        effect = new Effect(context),
        gain = effect.gain(),
        isTouchLocked = false,
        loader,
        loop = false,
        playbackRate = 1,
        playWhenReady,
        source,
        sound;

    if(context) {
        effect.setDestination(gain);
        gain.connect(destination || context.destination);
    }

    /*
     * Load
     */

    var load = function(config) {
        var src = file.getSupportedFile(config.src || config.url || config);

        if(source && data && data.tagName) {
            source.load(src);
        }
        else {
            loader = loader || new Loader(src);
            loader.audioContext = !!config.asMediaElement ? null : context;
            loader.isTouchLocked = isTouchLocked;
            loader.once('loaded', function(file) {
                createSource(file);
                sound.emit('loaded', sound);
            });
        }
        return sound;
    };

    /*
     * Controls
     */

    var play = function(delay, offset) {
        if(!source || isTouchLocked) {
            playWhenReady = function() {
                if (source) {
                    play(delay, offset);
                }
            };
            return sound;
        }
        playWhenReady = null;
        effect.setSource(source.sourceNode);

        // update volume needed for no webaudio
        if(!context) { sound.volume = gain.gain.value; }

        source.play(delay, offset);

        if(source.hasOwnProperty('loop')) {
            source.loop = loop;
        }

        sound.emit('play', sound);

        return sound;
    };

    var pause = function() {
        source && source.pause();
        sound.emit('pause', sound);
        return sound;
    };

    var stop = function(delay) {
        source && source.stop(delay || 0);
        sound.emit('stop', sound);
        return sound;
    };

    var seek = function(percent) {
        if(source) {
            source.stop();
            play(0, source.duration * percent);
        }
        return sound;
    };

    var fade = function(volume, duration) {
        if(!source) { return sound; }

        if(context) {
            var  param = gain.gain;
            var time = context.currentTime;
            param.cancelScheduledValues(time);
            param.setValueAtTime(param.value, time);
            param.linearRampToValueAtTime(volume, time + duration);
        }
        else if(typeof source.fade === 'function') {
            source.fade(volume, duration);
        }

        return sound;
    };

    /*
     * Destroy
     */

    var destroy = function() {
        source && source.destroy();
        effect && effect.destroy();
        gain && gain.disconnect();
        loader && loader.destroy();
        sound.off('loaded');
        sound.off('ended');
        gain = null;
        context = null;
        data = null;
        playWhenReady = null;
        source = null;
        effect = null;
        loader = null;
        sound.emit('destroy', sound);
        sound.off('destroy');
    };

    /*
     * Create source
     */

    var createSource = function(value) {
        data = value;

        if(file.isAudioBuffer(data)) {
            source = new BufferSource(data, context, function() {
                sound.emit('ended');
            });
        }
        else if(file.isMediaElement(data)) {
            source = new MediaSource(data, context, function() {
                sound.emit('ended');
            });
        }
        else if(file.isMediaStream(data)) {
            source = new MicrophoneSource(data, context);
        }
        else if(file.isOscillatorType((data && data.type) || data)) {
            source = new OscillatorSource(data.type || data, context);
        }
        else if(file.isScriptConfig(data)) {
            source = new ScriptSource(data, context);
        }
        else {
            throw new Error('Cannot detect data type: ' + data);
        }

        effect.setSource(source.sourceNode);

        sound.emit('ready', sound);

        if(playWhenReady) {
            playWhenReady();
        }
    };

    sound = Object.create(Emitter.prototype, {
        _events: {
            value: {}
        },
        constructor: {
            value: Sound
        },
        play: {
            value: play
        },
        pause: {
            value: pause
        },
        load: {
            value: load
        },
        seek: {
            value: seek
        },
        stop: {
            value: stop
        },
        fade: {
            value: fade
        },
        destroy: {
            value: destroy
        },
        context: {
            value: context
        },
        currentTime: {
            get: function() {
                return source ? source.currentTime : 0;
            },
            set: function(value) {
                // var silent = sound.playing;
                source && source.stop();
                // play(0, value, silent);
                play(0, value);
            }
        },
        data: {
            get: function() {
                return data;
            },
            set : function(value) {
                if(!value) { return; }
                createSource(value);
            }
        },
        duration: {
            get: function() {
                return source ? source.duration : 0;
            }
        },
        effect: {
            value: effect
        },
        ended: {
            get: function() {
                return !!source && source.ended;
            }
        },
        frequency: {
            get: function() {
                return source ? source.frequency : 0;
            },
            set: function(value) {
                if(source && source.hasOwnProperty('frequency')) {
                    source.frequency = value;
                }
            }
        },
        gain: {
            value: gain
        },
        id: {
            get: function() {
                return id;
            },
            set: function(value) {
                id = value;
            }
        },
        isTouchLocked: {
            set: function(value) {
                isTouchLocked = value;
                if(loader) {
                    loader.isTouchLocked = value;
                }
                if(!value && playWhenReady) {
                    playWhenReady();
                }
            }
        },
        loader: {
            get: function() {
                return loader;
            }
        },
        loop: {
            get: function() {
                return loop;
            },
            set: function(value) {
                loop = !!value;

                if(source && source.hasOwnProperty('loop') && source.loop !== loop) {
                  source.loop = loop;
                }
            }
        },
        paused: {
            get: function() {
                return !!source && source.paused;
            }
        },
        playing: {
            get: function() {
                return !!source && source.playing;
            }
        },
        playbackRate: {
            get: function() {
                return playbackRate;
            },
            set: function(value) {
                playbackRate = value;
                if(source) {
                  source.playbackRate = playbackRate;
                }
            }
        },
        progress: {
            get: function() {
                return source ? source.progress : 0;
            }
        },
        volume: {
            get: function() {
                if(context) {
                    return gain.gain.value;
                }
                if(source && source.hasOwnProperty('volume')) {
                    return source.volume;
                }
                return 1;
            },
            set: function(value) {
                if(isNaN(value)) { return; }

                var param = gain.gain;

                if(context) {
                    var time = context.currentTime;
                    param.cancelScheduledValues(time);
                    param.value = value;
                    param.setValueAtTime(value, time);
                }
                else {
                    param.value = value;

                    if(source && source.hasOwnProperty('volume')) {
                        source.volume = value;
                    }
                }
            }
        },
        waveform: {
            value: function(length) {
                if(!data) {
                    sound.once('ready', function() {
                        waveform(data, length);
                    });
                }
                return waveform(data, length);
            }
        }
    });

    return Object.freeze(sound);
}

module.exports = Sound;
<|endoftext|>


<commit_before>

function FrontPageController($scope, $location) {
    $scope.messages = [];
    $scope.sent = 0;
    $scope.search_key = function () {
        $location.path("/searchindex/search_key/" + $scope.keyword);
    }
}

function HomeController($scope, mcapi) {
    mcapi('/news')
        .success(function (data) {
            $scope.news = data;
        }).jsonp();
}

function ExploreController($scope) {
    $scope.pageDescription = "Explore";
}

function AboutController($scope) {
    $scope.pageDescription = "About";

}

function ContactController($scope) {
    $scope.pageDescription = "Contact";

}

function HelpController($scope) {
    $scope.pageDescription = "Help";

}

function EventController($scope, alertService) {
    $scope.message = '';
    $scope.$on('handleBroadcast', function () {
        $scope.message = {"type": "info",
            "content": alertService.message};
    });

}

function ProvenanceController($scope) {
    $scope.process = [
        {
            name: 'TEM',
            owner: 'Allison',
            inputs: ['TEM-excel-analysis', 'TEM conditions.txt'],
            outputs: ['image-display.jpg', 'TEM-analysis.xls', 'TEM.jpg']
        },
        {
            name: 'pr22',
            owner: 'Emanuelle',
            inputs: ['TEM-analysis.xls', 'a.txt'],
            outputs: ['pr22-excel-analysis', 'a.txt', 'pr22.jpg']
        },
        {
            name: 'SEM',
            owner: 'Emanuelle',
            inputs: ['SEM-excel-analysis', 'a.txt', 'pr22.jpg'],
            outputs: ['TEM-excel-analysis', 'a.txt', 'TEM.jpg', 'file1.txt']
        },
        {
            name: 'P4',
            owner: 'Allison',
            inputs: ['file1.txt', 'file2.txt', 'file4.txt'],
            outputs: ['TEM-excel-analysis', 'a.txt', 'TEM.jpg']
        },
        {
            name: 'P5',
            owner: 'Emanuelle',
            inputs: ['p5-excel-analysis', 'a.txt', 'p5.jpg'],
            outputs: ['TEM-excel-analysis', 'a.txt', 'TEM.jpg']
        }
    ];
    $scope.get_process_details = function (index) {
        $scope.$apply(function () {
            $scope.details = $scope.process[index];

        })
    }
            s
    redraw();
    function redraw() {
        var width = 600;
        var height = 400;

        $scope.g = new Graph();

        /* add a simple node */
        $scope.g.addNode("strawberry");
        $scope.g.addNode("cherry");

        /* add a node with a customized label */
        $scope.g.addNode("1", { label : "Tomato" });

        /* add a node with a customized shape
         (the Raphael graph drawing implementation can draw this shape, please
         consult the RaphaelJS reference for details http://raphaeljs.com/) */
        $scope.render = function(r, n) {
            $scope.label = r.text(0, 30, n.label).attr({opacity:0});
            //the Raphael set is obligatory, containing all you want to display
            $scope.set = r.set().push(
                    r.rect(-30, -13, 62, 86)
                        .attr({"fill": "#fa8",
                            "stroke-width": 2
                            , r : 9 }))
                .push($scope.label);
            // make the label show only on hover
            $scope.set.hover(
                function mouseIn() {
                    $scope.label.animate({opacity:1,"fill-opacity":1}, 500);
                },
                function mouseOut() {
                    $scope.label.animate({opacity:0},300);
                }
            );

            tooltip = r.set()
                .push(
                    r.rect(0, 0, 90, 30).attr({"fill": "#fec", "stroke-width": 1, r : 9 })
                ).push(
                    r.text(25, 15, "overlay").attr({"fill": "#000000"})
                );
            for(i in $scope.set.items) {
                $scope.set.items[i].tooltip(tooltip);
            };
            //            set.tooltip(r.set().push(r.rect(0, 0, 30, 30).attr({"fill": "#fec", "stroke-width": 1, r : "9px"})).hide());
            return $scope.set;
        };

        $scope.g.addNode("id35", {
            label : "meat\nand\ngreed",
            /* filling the shape with a color makes it easier to be dragged */
            /* arguments: r = Raphael object, n : node object */
            //render : render
        });
        //    g.addNode("Wheat", {
        /* filling the shape with a color makes it easier to be dragged */
        /* arguments: r = Raphael object, n : node object */
        //        shapes : [ {
        //                type: "rect",
        //                x: 10,
        //                y: 10,
        //                width: 25,
        //                height: 25,
        //                stroke: "#f00"
        //            }, {
        //                type: "text",
        //                x: 30,
        //                y: 40,
        //                text: "Dump"
        //            }],
        //        overlay : "Hello World!"
        //    });

        $scope.st = { directed: true, label : "Label",
            "label-style" : {
                "font-size": 20
            }
        };
        $scope.g.addEdge("kiwi", "penguin", $scope.st);

        /* connect nodes with edges */
        $scope.g.addEdge("strawberry", "cherry", {directed: true});
        $scope.g.addEdge("cherry", "apple");
        $scope.g.addEdge("cherry", "apple")
        $scope.g.addEdge("1", "id35");
        $scope.g.addEdge("penguin", "id35");
        $scope.g.addEdge("penguin", "apple");
        $scope.g.addEdge("kiwi", "id35");

        /* a directed connection, using an arrow */
        $scope.g.addEdge("1", "cherry", { directed : true } );

        /* customize the colors of that edge */
        $scope.g.addEdge("id35", "apple", { stroke : "#bfa" , fill : "#56f", label : "Meat-to-Apple" });

        /* add an unknown node implicitly by adding an edge */
        $scope.g.addEdge("strawberry", "apple");

        //g.removeNode("1");

        /* layout the graph using the Spring layout implementation */
        $scope.layouter = new Graph.Layout.Spring($scope.g);

        /* draw the graph using the RaphaelJS draw implementation */
        $scope.renderer = new Graph.Renderer.Raphael('canvas', $scope.g, width, height);

            $scope.layouter.layout();
            $scope.renderer.draw();
        $scope.hide = function(id) {
            $scope.g.nodes[id].hide();
        };
        $scope.show = function(id) {
            $scope.g.nodes[id].show();
        };
        //    console.log(g.nodes["kiwi"]);

    }

    };

<commit_msg>commit<commit_after>

function FrontPageController($scope, $location) {
    $scope.messages = [];
    $scope.sent = 0;
    $scope.search_key = function () {
        $location.path("/searchindex/search_key/" + $scope.keyword);
    }
}

function HomeController($scope, mcapi) {
    mcapi('/news')
        .success(function (data) {
            $scope.news = data;
        }).jsonp();
}

function ExploreController($scope) {
    $scope.pageDescription = "Explore";
}

function AboutController($scope) {
    $scope.pageDescription = "About";

}

function ContactController($scope) {
    $scope.pageDescription = "Contact";

}

function HelpController($scope) {
    $scope.pageDescription = "Help";

}

function EventController($scope, alertService) {
    $scope.message = '';
    $scope.$on('handleBroadcast', function () {
        $scope.message = {"type": "info",
            "content": alertService.message};
    });

}

function ProvenanceController($scope) {
    $scope.process = [
        {
            name: 'TEM',
            owner: 'Allison',
            inputs: ['TEM-excel-analysis', 'TEM conditions.txt'],
            outputs: ['image-display.jpg', 'TEM-analysis.xls', 'TEM.jpg']
        },
        {
            name: 'pr22',
            owner: 'Emanuelle',
            inputs: ['TEM-analysis.xls', 'a.txt'],
            outputs: ['pr22-excel-analysis', 'a.txt', 'pr22.jpg']
        },
        {
            name: 'SEM',
            owner: 'Emanuelle',
            inputs: ['SEM-excel-analysis', 'a.txt', 'pr22.jpg'],
            outputs: ['TEM-excel-analysis', 'a.txt', 'TEM.jpg', 'file1.txt']
        },
        {
            name: 'P4',
            owner: 'Allison',
            inputs: ['file1.txt', 'file2.txt', 'file4.txt'],
            outputs: ['TEM-excel-analysis', 'a.txt', 'TEM.jpg']
        },
        {
            name: 'P5',
            owner: 'Emanuelle',
            inputs: ['p5-excel-analysis', 'a.txt', 'p5.jpg'],
            outputs: ['TEM-excel-analysis', 'a.txt', 'TEM.jpg']
        }
    ];
    $scope.get_process_details = function (index) {
        $scope.$apply(function () {
            $scope.details = $scope.process[index];

        })
    }

    redraw();
    function redraw() {
        var width = 600;
        var height = 400;

        $scope.g = new Graph();

        /* add a simple node */
        $scope.g.addNode("strawberry");
        $scope.g.addNode("cherry");

        /* add a node with a customized label */
        $scope.g.addNode("1", { label : "Tomato" });

        /* add a node with a customized shape
         (the Raphael graph drawing implementation can draw this shape, please
         consult the RaphaelJS reference for details http://raphaeljs.com/) */
        $scope.render = function(r, n) {
            $scope.label = r.text(0, 30, n.label).attr({opacity:0});
            //the Raphael set is obligatory, containing all you want to display
            $scope.set = r.set().push(
                    r.rect(-30, -13, 62, 86)
                        .attr({"fill": "#fa8",
                            "stroke-width": 2
                            , r : 9 }))
                .push($scope.label);
            // make the label show only on hover
            $scope.set.hover(
                function mouseIn() {
                    $scope.label.animate({opacity:1,"fill-opacity":1}, 500);
                },
                function mouseOut() {
                    $scope.label.animate({opacity:0},300);
                }
            );

            tooltip = r.set()
                .push(
                    r.rect(0, 0, 90, 30).attr({"fill": "#fec", "stroke-width": 1, r : 9 })
                ).push(
                    r.text(25, 15, "overlay").attr({"fill": "#000000"})
                );
            for(i in $scope.set.items) {
                $scope.set.items[i].tooltip(tooltip);
            };
            //            set.tooltip(r.set().push(r.rect(0, 0, 30, 30).attr({"fill": "#fec", "stroke-width": 1, r : "9px"})).hide());
            return $scope.set;
        };

        $scope.g.addNode("id35", {
            label : "meat\nand\ngreed",
            /* filling the shape with a color makes it easier to be dragged */
            /* arguments: r = Raphael object, n : node object */
            //render : render
        });
        //    g.addNode("Wheat", {
        /* filling the shape with a color makes it easier to be dragged */
        /* arguments: r = Raphael object, n : node object */
        //        shapes : [ {
        //                type: "rect",
        //                x: 10,
        //                y: 10,
        //                width: 25,
        //                height: 25,
        //                stroke: "#f00"
        //            }, {
        //                type: "text",
        //                x: 30,
        //                y: 40,
        //                text: "Dump"
        //            }],
        //        overlay : "Hello World!"
        //    });

        $scope.st = { directed: true, label : "Label",
            "label-style" : {
                "font-size": 20
            }
        };
        $scope.g.addEdge("kiwi", "penguin", $scope.st);

        /* connect nodes with edges */
        $scope.g.addEdge("strawberry", "cherry", {directed: true});
        $scope.g.addEdge("cherry", "apple");
        $scope.g.addEdge("cherry", "apple")
        $scope.g.addEdge("1", "id35");
        $scope.g.addEdge("penguin", "id35");
        $scope.g.addEdge("penguin", "apple");
        $scope.g.addEdge("kiwi", "id35");

        /* a directed connection, using an arrow */
        $scope.g.addEdge("1", "cherry", { directed : true } );

        /* customize the colors of that edge */
        $scope.g.addEdge("id35", "apple", { stroke : "#bfa" , fill : "#56f", label : "Meat-to-Apple" });

        /* add an unknown node implicitly by adding an edge */
        $scope.g.addEdge("strawberry", "apple");

        //g.removeNode("1");

        /* layout the graph using the Spring layout implementation */
        $scope.layouter = new Graph.Layout.Spring($scope.g);

        /* draw the graph using the RaphaelJS draw implementation */
        $scope.renderer = new Graph.Renderer.Raphael('canvas', $scope.g, width, height);

            $scope.layouter.layout();
            $scope.renderer.draw();
        $scope.hide = function(id) {
            $scope.g.nodes[id].hide();
        };
        $scope.show = function(id) {
            $scope.g.nodes[id].show();
        };
        //    console.log(g.nodes["kiwi"]);

    }

    };

<|endoftext|>


<commit_before>export default {
  el: {
    colorpicker: {
      confirm: 'OK',
      clear: 'Pulisci'
    },
    datepicker: {
      now: 'Ora',
      today: 'Oggi',
      cancel: 'Cancella',
      clear: 'Pulisci',
      confirm: 'OK',
      selectDate: 'Seleziona data',
      selectTime: 'Seleziona ora',
      startDate: 'Data inizio',
      startTime: 'Ora inizio',
      endDate: 'Data fine',
      endTime: 'Ora fine',
      prevYear: 'Anno precedente',
      nextYear: 'Anno successivo',
      prevMonth: 'Mese precedente',
      nextMonth: 'Mese successivo',
      year: 'anno',
      month1: 'Gennaio',
      month2: 'Febbraio',
      month3: 'Marzo',
      month4: 'Aprile',
      month5: 'Maggio',
      month6: 'Giugno',
      month7: 'Luglio',
      month8: 'Agosto',
      month9: 'Settembre',
      month10: 'Ottobre',
      month11: 'Novembre',
      month12: 'Dicembre',
      // week: 'settimana',
      weeks: {
        sun: 'Dom',
        mon: 'Lun',
        tue: 'Mar',
        wed: 'Mer',
        thu: 'Gio',
        fri: 'Ven',
        sat: 'Sab'
      },
      months: {
        jan: 'Gen',
        feb: 'Feb',
        mar: 'Mar',
        apr: 'Apr',
        may: 'Mag',
        jun: 'Giu',
        jul: 'Lug',
        aug: 'Ago',
        sep: 'Set',
        oct: 'Ott',
        nov: 'Nov',
        dec: 'Dic'
      }
    },
    select: {
      loading: 'Caricamento',
      noMatch: 'Nessuna corrispondenza',
      noData: 'Nessun dato',
      placeholder: 'Seleziona'
    },
    cascader: {
      noMatch: 'Nessuna corrispondenza',
      loading: 'Caricamento',
      placeholder: 'Seleziona',
      noData: 'Nessun dato'
    },
    pagination: {
      goto: 'Vai a',
      pagesize: '/pagina',
      total: 'Totale {total}',
      pageClassifier: ''
    },
    messagebox: {
      confirm: 'OK',
      cancel: 'Cancella',
      error: 'Input non valido'
    },
    upload: {
      deleteTip: 'Premi cancella per rimuovere',
      delete: 'Cancella',
      preview: 'Anteprima',
      continue: 'Continua'
    },
    table: {
      emptyText: 'Nessun dato',
      confirmFilter: 'Conferma',
      resetFilter: 'Reset',
      clearFilter: 'Tutti',
      sumText: 'Somma'
    },
    tree: {
      emptyText: 'Nessun dato'
    },
    transfer: {
      noMatch: 'Nessuna corrispondenza',
      noData: 'Nessun dato',
      titles: ['Lista 1', 'Lista 2'],
      filterPlaceholder: 'Inserisci filtro',
      noCheckedFormat: '{total} elementi',
      hasCheckedFormat: '{checked}/{total} selezionati'
    },
    image: {
      error: 'ERRORE'
    },
    pageHeader: {
      title: 'Indietro'
    },
    popconfirm: {
      confirmButtonText: 'Sì',
      cancelButtonText: 'No'
    },
    empty: {
      description: 'Nessun dato'
    }
  }
};
<commit_msg>i18n: fix italian mistake (#21012)<commit_after>export default {
  el: {
    colorpicker: {
      confirm: 'OK',
      clear: 'Pulisci'
    },
    datepicker: {
      now: 'Ora',
      today: 'Oggi',
      cancel: 'Cancella',
      clear: 'Pulisci',
      confirm: 'OK',
      selectDate: 'Seleziona data',
      selectTime: 'Seleziona ora',
      startDate: 'Data inizio',
      startTime: 'Ora inizio',
      endDate: 'Data fine',
      endTime: 'Ora fine',
      prevYear: 'Anno precedente',
      nextYear: 'Anno successivo',
      prevMonth: 'Mese precedente',
      nextMonth: 'Mese successivo',
      year: 'anno',
      month1: 'Gennaio',
      month2: 'Febbraio',
      month3: 'Marzo',
      month4: 'Aprile',
      month5: 'Maggio',
      month6: 'Giugno',
      month7: 'Luglio',
      month8: 'Agosto',
      month9: 'Settembre',
      month10: 'Ottobre',
      month11: 'Novembre',
      month12: 'Dicembre',
      // week: 'settimana',
      weeks: {
        sun: 'Dom',
        mon: 'Lun',
        tue: 'Mar',
        wed: 'Mer',
        thu: 'Gio',
        fri: 'Ven',
        sat: 'Sab'
      },
      months: {
        jan: 'Gen',
        feb: 'Feb',
        mar: 'Mar',
        apr: 'Apr',
        may: 'Mag',
        jun: 'Giu',
        jul: 'Lug',
        aug: 'Ago',
        sep: 'Set',
        oct: 'Ott',
        nov: 'Nov',
        dec: 'Dic'
      }
    },
    select: {
      loading: 'Caricamento',
      noMatch: 'Nessuna corrispondenza',
      noData: 'Nessun dato',
      placeholder: 'Seleziona'
    },
    cascader: {
      noMatch: 'Nessuna corrispondenza',
      loading: 'Caricamento',
      placeholder: 'Seleziona',
      noData: 'Nessun dato'
    },
    pagination: {
      goto: 'Vai a',
      pagesize: '/pagina',
      total: 'Totale {total}',
      pageClassifier: ''
    },
    messagebox: {
      confirm: 'OK',
      cancel: 'Annulla',
      error: 'Input non valido'
    },
    upload: {
      deleteTip: 'Premi cancella per rimuovere',
      delete: 'Cancella',
      preview: 'Anteprima',
      continue: 'Continua'
    },
    table: {
      emptyText: 'Nessun dato',
      confirmFilter: 'Conferma',
      resetFilter: 'Reset',
      clearFilter: 'Tutti',
      sumText: 'Somma'
    },
    tree: {
      emptyText: 'Nessun dato'
    },
    transfer: {
      noMatch: 'Nessuna corrispondenza',
      noData: 'Nessun dato',
      titles: ['Lista 1', 'Lista 2'],
      filterPlaceholder: 'Inserisci filtro',
      noCheckedFormat: '{total} elementi',
      hasCheckedFormat: '{checked}/{total} selezionati'
    },
    image: {
      error: 'ERRORE'
    },
    pageHeader: {
      title: 'Indietro'
    },
    popconfirm: {
      confirmButtonText: 'Sì',
      cancelButtonText: 'No'
    },
    empty: {
      description: 'Nessun dato'
    }
  }
};
<|endoftext|>


<commit_before>import React, { useState, useEffect } from 'react';
import TravelObject from './TravelObject';
import FinalizedHeader from './FinalizedHeader';
import '../styles/TimeLine.css';
import { travelObjectStartDateComparator } from "../scripts/HelperFunctions"

/*Given 2 Date objects, return true if they have the same date; return false otherwise */
const sameDate = (timeA, timeB) => {
  return (timeA.getDate() === timeB.getDate() && timeA.getMonth() === timeB.getMonth() && timeA.getFullYear() === timeB.getFullYear());
}

function OneHourInterval(props) {

  const displayHeightOfADiv = 48.0;
  const padding = 16.0;
  const minPerDiv = 30.0;

  const handleOnClickInterval = (idV) => {
    console.log(idV);
  }

  /*Given startDate and endDate of a TravelObject, return the height of display (unit: pixel) */
  const getHeightPercentage = (startDate, endDate) => {
    let dif = 0;
    if (sameDate(startDate, endDate)) {
      dif = endDate.getHours() * 60 + endDate.getMinutes() - startDate.getHours() * 60 - startDate.getMinutes();

    } else if (sameDate(props.displayDate, startDate)) {
      dif = 24 * 60 - startDate.getHours() * 60 - startDate.getMinutes();
    } else {
      dif = endDate.getHours() * 60 + endDate.getMinutes();
    }
    return dif * displayHeightOfADiv / minPerDiv - padding;
  }

  const getHeightFromMin = (min) => {
    return min * displayHeightOfADiv / minPerDiv - padding;
  }

  /*Given a startDate of a TravelObject, return the top pixel*/
  const getTopPixel = (startDate) => {
    if (!sameDate(props.displayDate, startDate)) {
      return 0;
    }
    let dif = (startDate.getMinutes() < 30) ? startDate.getMinutes() : startDate.getMinutes() - 30;
    return dif / minPerDiv * displayHeightOfADiv;
  }

  var item00 = [];
  var item30 = [];

  if (props.items !== null) {
    props.items.forEach((item) => {
      let height = item.data.type === "hotel"
        ? getHeightFromMin(30)
        : getHeightPercentage(item.data.startDate, item.data.endDate);
      let top = item.data.type === "hotel"
        ? getTopPixel(item.data.endDate)
        : getTopPixel(item.data.startDate);

      let travelObject = <TravelObject
        key={item.data.id}
        data={item.data}
        onRemoveItem={props.onRemoveItem}
        onEditItem={props.onEditItem}
        onAddItem={props.onAddItem}
        styleConfig={{
          top: top.toString() + "px",
          height: height.toString() + "px",
          width: "228px",
          overflowY: "scroll",
          position: "absolute",
          zIndex: props.zIndex.toString()
        }}
      />

      if (item.div === ":00") {
        item00.push(travelObject);
      } else if (item.div === ":30") {
        item30.push(travelObject);
      }
    })
  }
  return (

        {props.idV + ":00"}
         handleOnClickInterval(props.idV + ":00")}>
          {item00.length === 0 ? null : item00}

         handleOnClickInterval(props.idV + ":30")}>
          {item30.length === 0 ? null : item30}

  )
}

export default function TimeLine(props) {
  const intervals = [];
  const [displayDate, setDisplayDate] = useState(props.displayDate);
  const date2Items = new Map();

  /*Given a date and an item, put the item to the list of items belonging to the given date. */
  const addItemToDate = (item, dateKey) => {
    if (!date2Items.has(dateKey)) {
      date2Items.set(dateKey, [item]);
    }
    else {
      let items = date2Items.get(dateKey);
      items.push(item);
    }
  }
  /*Given a list of items (props.list), split the items into the its dates */
  const separateDates = () => {
    for (let i = 0; i < props.list.length; i++) {
      let item = props.list[i];
      let startDate = item.startDate;
      let endDate = item.endDate;
      addItemToDate(item, startDate.toDateString());

      if (!sameDate(startDate, endDate)) {
        addItemToDate(item, endDate.toDateString());
      }
    }
  }

  /*Sort all lists of items in the hashMap: date2Items */
  const sortItemList = () => {
    const iterator = date2Items[Symbol.iterator]();
    for (let date2items of iterator) {
      let items = date2items[1];
      items.sort(travelObjectStartDateComparator);
    }
  }

  /* Handling rendering starts HERE */
  separateDates();
  sortItemList();

  var displayItems = (date2Items.has(displayDate.toDateString())) ? date2Items.get(displayDate.toDateString()) : [];
  var nextItemIndex = 0;
  console.log("display items length: ", displayItems.length)
  for (var i = 0; i < 24; i++) {
    if (nextItemIndex < displayItems.length) {
      var nextItem = displayItems[nextItemIndex];
      var nextItemStartDate = nextItem.startDate;
      // End date within current display date
      if (!sameDate(displayDate, nextItemStartDate) && (nextItem.type !== "hotel" || nextItem.endDate.getHour === i)) {
        nextItemIndex++;
        intervals.push(<OneHourInterval
          idV={nextItem.type === "hotel" ? nextItem.endDate.getHours() : 0}
          items={[{data: nextItem, div: ":00"}]}
          zIndex={nextItemIndex}
          displayDate={displayDate}
          onRemoveItem={props.onRemoveItem}
          onEditItem={props.onEditItem}
          onAddItem={props.onAddItem}
        />);
      }
      else {
        var items = [];
        var div = null;
        while (nextItemIndex < displayItems.length && displayItems[nextItemIndex].startDate.getHours() === i) {
          var item = displayItems[nextItemIndex];
          nextItemStartDate = item.startDate;
          var nextItemMinutes = nextItemStartDate.getMinutes();

          if (nextItemMinutes < 30) {
            div = ":00";
          }
          else {
            div = ":30";
          }

          items.push({ data: item, div: div });

          nextItemIndex++;
        }
        intervals.push(<OneHourInterval
          idV={i.toString()}
          items={items.length === 0 ? null : items}
          displayDate={displayDate}
          zIndex={nextItemIndex}
          onRemoveItem={props.onRemoveItem}
          onEditItem={props.onEditItem}
          onAddItem={props.onAddItem}
        />);
      }
    }
    else {
      intervals.push(<OneHourInterval
        idV={i.toString()}
        items={null}
        displayDate={displayDate}
        zIndex={0}
        onRemoveItem={props.onRemoveItem}
        onEditItem={props.onEditItem}
        onAddItem={props.onAddItem}
      />);

    }
  }

  useEffect(() => {
    setDisplayDate(props.displayDate);
  }, [props.displayDate]);

  return (

      <FinalizedHeader
        displayDate={props.displayDate}
        onChangeDisplayDate={props.onChangeDisplayDate}
      />

{intervals}

  );
}<commit_msg>Remove console logging<commit_after>import React, { useState, useEffect } from 'react';
import TravelObject from './TravelObject';
import FinalizedHeader from './FinalizedHeader';
import '../styles/TimeLine.css';
import { travelObjectStartDateComparator } from "../scripts/HelperFunctions"

/*Given 2 Date objects, return true if they have the same date; return false otherwise */
const sameDate = (timeA, timeB) => {
  return (timeA.getDate() === timeB.getDate() && timeA.getMonth() === timeB.getMonth() && timeA.getFullYear() === timeB.getFullYear());
}

function OneHourInterval(props) {

  const displayHeightOfADiv = 48.0;
  const padding = 16.0;
  const minPerDiv = 30.0;

  const handleOnClickInterval = (idV) => {
    console.log(idV);
  }

  /*Given startDate and endDate of a TravelObject, return the height of display (unit: pixel) */
  const getHeightPercentage = (startDate, endDate) => {
    let dif = 0;
    if (sameDate(startDate, endDate)) {
      dif = endDate.getHours() * 60 + endDate.getMinutes() - startDate.getHours() * 60 - startDate.getMinutes();

    } else if (sameDate(props.displayDate, startDate)) {
      dif = 24 * 60 - startDate.getHours() * 60 - startDate.getMinutes();
    } else {
      dif = endDate.getHours() * 60 + endDate.getMinutes();
    }
    return dif * displayHeightOfADiv / minPerDiv - padding;
  }

  const getHeightFromMin = (min) => {
    return min * displayHeightOfADiv / minPerDiv - padding;
  }

  /*Given a startDate of a TravelObject, return the top pixel*/
  const getTopPixel = (startDate) => {
    if (!sameDate(props.displayDate, startDate)) {
      return 0;
    }
    let dif = (startDate.getMinutes() < 30) ? startDate.getMinutes() : startDate.getMinutes() - 30;
    return dif / minPerDiv * displayHeightOfADiv;
  }

  var item00 = [];
  var item30 = [];

  if (props.items !== null) {
    props.items.forEach((item) => {
      let height = item.data.type === "hotel"
        ? getHeightFromMin(30)
        : getHeightPercentage(item.data.startDate, item.data.endDate);
      let top = item.data.type === "hotel"
        ? getTopPixel(item.data.endDate)
        : getTopPixel(item.data.startDate);

      let travelObject = <TravelObject
        key={item.data.id}
        data={item.data}
        onRemoveItem={props.onRemoveItem}
        onEditItem={props.onEditItem}
        onAddItem={props.onAddItem}
        styleConfig={{
          top: top.toString() + "px",
          height: height.toString() + "px",
          width: "228px",
          overflowY: "scroll",
          position: "absolute",
          zIndex: props.zIndex.toString()
        }}
      />

      if (item.div === ":00") {
        item00.push(travelObject);
      } else if (item.div === ":30") {
        item30.push(travelObject);
      }
    })
  }
  return (

        {props.idV + ":00"}
         handleOnClickInterval(props.idV + ":00")}>
          {item00.length === 0 ? null : item00}

         handleOnClickInterval(props.idV + ":30")}>
          {item30.length === 0 ? null : item30}

  )
}

export default function TimeLine(props) {
  const intervals = [];
  const [displayDate, setDisplayDate] = useState(props.displayDate);
  const date2Items = new Map();

  /*Given a date and an item, put the item to the list of items belonging to the given date. */
  const addItemToDate = (item, dateKey) => {
    if (!date2Items.has(dateKey)) {
      date2Items.set(dateKey, [item]);
    }
    else {
      let items = date2Items.get(dateKey);
      items.push(item);
    }
  }
  /*Given a list of items (props.list), split the items into the its dates */
  const separateDates = () => {
    for (let i = 0; i < props.list.length; i++) {
      let item = props.list[i];
      let startDate = item.startDate;
      let endDate = item.endDate;
      addItemToDate(item, startDate.toDateString());

      if (!sameDate(startDate, endDate)) {
        addItemToDate(item, endDate.toDateString());
      }
    }
  }

  /*Sort all lists of items in the hashMap: date2Items */
  const sortItemList = () => {
    const iterator = date2Items[Symbol.iterator]();
    for (let date2items of iterator) {
      let items = date2items[1];
      items.sort(travelObjectStartDateComparator);
    }
  }

  /* Handling rendering starts HERE */
  separateDates();
  sortItemList();

  var displayItems = (date2Items.has(displayDate.toDateString())) ? date2Items.get(displayDate.toDateString()) : [];
  var nextItemIndex = 0;

  for (var i = 0; i < 24; i++) {
    if (nextItemIndex < displayItems.length) {
      var nextItem = displayItems[nextItemIndex];
      var nextItemStartDate = nextItem.startDate;
      // End date within current display date
      if (!sameDate(displayDate, nextItemStartDate) && (nextItem.type !== "hotel" || nextItem.endDate.getHour === i)) {
        nextItemIndex++;
        intervals.push(<OneHourInterval
          idV={nextItem.type === "hotel" ? nextItem.endDate.getHours() : 0}
          items={[{data: nextItem, div: ":00"}]}
          zIndex={nextItemIndex}
          displayDate={displayDate}
          onRemoveItem={props.onRemoveItem}
          onEditItem={props.onEditItem}
          onAddItem={props.onAddItem}
        />);
      }
      else {
        var items = [];
        var div = null;
        while (nextItemIndex < displayItems.length && displayItems[nextItemIndex].startDate.getHours() === i) {
          var item = displayItems[nextItemIndex];
          nextItemStartDate = item.startDate;
          var nextItemMinutes = nextItemStartDate.getMinutes();

          if (nextItemMinutes < 30) {
            div = ":00";
          }
          else {
            div = ":30";
          }

          items.push({ data: item, div: div });

          nextItemIndex++;
        }
        intervals.push(<OneHourInterval
          idV={i.toString()}
          items={items.length === 0 ? null : items}
          displayDate={displayDate}
          zIndex={nextItemIndex}
          onRemoveItem={props.onRemoveItem}
          onEditItem={props.onEditItem}
          onAddItem={props.onAddItem}
        />);
      }
    }
    else {
      intervals.push(<OneHourInterval
        idV={i.toString()}
        items={null}
        displayDate={displayDate}
        zIndex={0}
        onRemoveItem={props.onRemoveItem}
        onEditItem={props.onEditItem}
        onAddItem={props.onAddItem}
      />);

    }
  }

  useEffect(() => {
    setDisplayDate(props.displayDate);
  }, [props.displayDate]);

  return (

      <FinalizedHeader
        displayDate={props.displayDate}
        onChangeDisplayDate={props.onChangeDisplayDate}
      />

{intervals}

  );
}<|endoftext|>


<commit_before>const express = require('express')
const next = require('next')

const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare().then(() => {
  const server = express()

  server.all('*', (req, res) => {
    return handle(req, res)
  })

  server.listen(port, (err) => {
    if (err) throw err
    console.log(`> Ready on http://localhost:${port}`)
  })
})
<commit_msg>custom-server-express fix type definition and eliminate dead code (#37054)<commit_after>const express = require('express')
const next = require('next')

const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare().then(() => {
  const server = express()

  server.all('*', (req, res) => {
    return handle(req, res)
  })

  server.listen(port, () => {
    console.log(`> Ready on http://localhost:${port}`)
  })
})
<|endoftext|>


<commit_before>/*
Mag.JS AddOns v0.21
(c) Michael Glazer
https://github.com/magnumjs/mag.js
*/

var mag = mag || {}

/*
module library creation with single global namespace / package names
(function(namespace) {

  var mod = {
    controller:function(props){
    },
    view: function(state, props) {
    }
  }

  namespace.CommentBox = mod;

})(mag.namespace('mglazer.mods.comments'));
*/
mag.namespace = function (ns, obj) {
   var   levels = ns.split('.'), first = levels.shift();
  obj = obj || this; //if no object argument supplied declare a global property
  obj[first] = obj[first] || {}; // initialize the "level"
  if (levels.length) { // recursion condition
    return mag.namespace(levels.join('.'), obj[first]);
  }
  return obj[first]; // return a reference to the top level object
}

//UTILITY
// mag.utils.copy - now in core
// mag.utils.merge - now in core

mag.copy = mag.utils.copy
mag.merge = mag.utils.merge

/*
controller:function(props)
  // if props has a property 'isVisible' when true will display entire module on before updates
  mag.show(this,'isVisible')
}
http://jsbin.com/fegizubime/edit?html,js,output
*/

mag.show = function(context, conditionName) {
  if (typeof context !== 'object') {
    var obj = {
      _config: function(node) {
        node.style.display = context ? 'block' : 'none'
      }
    }
    if (typeof conditionName == 'object') {
      mag.merge(conditionName, obj)
    }
    return obj
  } else {
    context.willupdate = function(event, node, inprops) {
      node.style.display = inprops[conditionName] ? 'block' : 'none'
    }
  }
}

mag.addons = {};

// return object of getter values
mag.addons.getProp = function(data) {
  var newData = {}
  Object.keys(data).forEach(function(k) {
    if (data[k].type == 'fun' && typeof data[k] == 'function') newData[k] = data[k]()
  })
  return newData
}

// show hide

// remove class hide to given context/this
// show(this) inside controller
mag.addons.show = function(condition) {
  if (typeof condition === 'boolean') {
    return {
      _config: function(n) {
        if (!condition) n.style.display = 'none';
        else n.style.display = 'block';
      }
    };
  } else if (typeof condition === 'object') {
    condition.willload = function(e, n) {
      n.style.display = 'block'
    }
  } else if (arguments.length == 0) {
    return function(e, n) {
      // next didupdate event
      n.style.display = 'block'
    }
  }
}

mag.addons.hide = function(condition) {
  if (typeof condition === 'boolean') {
    return {
      _config: function(n) {
        if (condition) n.style.display = 'none';
        else n.style.display = 'block';
      }
    }
  } else if (typeof condition === 'object') {
    condition.willload = function(e, n) {
      n.style.display = 'none';
    }
  } else if (arguments.length == 0) {
    return function(e, n) {
      // next didupdate event
      n.style.display = 'none'
    }
  }
}

// promises

/*
var d = mag.deferred()

d.promise.then(function() {
  console.log('success', arguments)
}, function() {
  console.log('failure', arguments)
})
d.reject({
  things: false
})
d.resolve({
  things: []
})
*/

mag.deferred = function() {
  var Deferred = {}
  Deferred.promise = new Promise(function(resolve, reject) {
    Deferred.resolve = resolve
    Deferred.reject = reject
  })
  return Deferred
}

mag.addons.when = function(arrayOfPromises, callback) {
  Promise.all(arrayOfPromises).then(callback)
}

mag.addons.requestWithFeedback = function(args) {
  var key = JSON.stringify(args)
  if (!mag.addons.requestWithFeedback.cache[key]) {

    var loaders = document.querySelectorAll(".loader")

    //show icons
    for (var i = 0, loader; loader = loaders[i]; i++) loader.style.display = "block"

    var expire = function(data) {
      delete mag.addons.requestWithFeedback.cache[key]

      if (Object.keys(mag.addons.requestWithFeedback.cache).length == 0) {
        //hide icons
        for (var i = 0, loader; loader = loaders[i]; i++) loader.style.display = "none"
      }
      return data
    }
    mag.addons.requestWithFeedback.cache[key] = mag.request(args).then(expire, function(error) {
      expire(error)
      throw error
    })
  }
  return mag.addons.requestWithFeedback.cache[key]
}
mag.addons.requestWithFeedback.cache = {}

// hookins

mag.hookin('attributes', 'key', function(data) {
  // remove system key from being added to attributes in html
  //  data.value = null
})

mag.hookin('attributes', 'className', function(data) {
  data.key = 'class'
  var newClass = data.value

  if (typeof data.value == 'string') {
    newClass = data.value.split(' ')
  } else if(typeof data.value == 'object') {
    for (var k in newClass) {
      data.node.classList.toggle(k, newClass[k])
    }
    data.value = data.node.classList + ''
    return
  }

  data.value = data.node.classList + ''

  for (var k in newClass) {
    var cls = newClass[k]
    if (cls.trim() && data.node.classList.length > 0 && !data.node.classList.contains(cls.trim())) {
      data.value = data.node.classList + ' ' + cls

    } else if (cls.trim() && data.node.classList.length == 0) {
      data.value += cls + ' '
    }
  }

  data.value = data.value.trim()
})

// disable add to config
// http://jsbin.com/qutudiqife/3/edit?js,output
// define condition func
// this.show = mag.prop(false);

//define context
// mag.addons.disable.call(this, 'other', this.show);
//TODO: change to mag.ui.disable
mag.addons.disable = function(selector, condition) {

  if (typeof this[selector] !== 'object') {
    // create object
    this[selector] = {
      _value: this[selector]
    };
  }

  // add or merge to config if not exists
  var orig = this[selector]._config ? this[selector]._config : function() {};

  this[selector]._config = function(n) {
    orig.call(this, arguments);
    if (condition()) n.setAttribute('disabled', 'disabled');
    else n.removeAttribute('disabled');
  };
}

// TODO: change to mag.find
mag.addons.get = function(parentRootId, selector) {
  var parent = document.getElementById(parentRootId);
  return mag.fill.find(parent, selector)
}

// mag.addons.toMenu(['one', 'two', 'three'], state.selected())
// http://jsbin.com/mapuwojumu/3/edit?js,output
//TODO change to mag.ui.menu
mag.addons.toMenu = function(maps, selected) {
  return maps.map(function(v, k) {
    return {
      _text: v,
      _value: k,
      _selected: selected === k || selected === v ? true : null
    }
  })
}
<commit_msg>Update mag.addons.0.2.js<commit_after>/*
Mag.JS AddOns v0.21
(c) Michael Glazer
https://github.com/magnumjs/mag.js
*/

var mag = mag || {}

// helper
mag.noop = function(){}

/*
module library creation with single global namespace / package names
(function(namespace) {

  var mod = {
    controller:function(props){
    },
    view: function(state, props) {
    }
  }

  namespace.CommentBox = mod;

})(mag.namespace('mglazer.mods.comments'));
*/
mag.namespace = function (ns, obj) {
   var   levels = ns.split('.'), first = levels.shift();
  obj = obj || this; //if no object argument supplied declare a global property
  obj[first] = obj[first] || {}; // initialize the "level"
  if (levels.length) { // recursion condition
    return mag.namespace(levels.join('.'), obj[first]);
  }
  return obj[first]; // return a reference to the top level object
}

//UTILITY
// mag.utils.copy - now in core
// mag.utils.merge - now in core

mag.copy = mag.utils.copy
mag.merge = mag.utils.merge

/*
controller:function(props)
  // if props has a property 'isVisible' when true will display entire module on before updates
  mag.show(this,'isVisible')
}
http://jsbin.com/fegizubime/edit?html,js,output
*/

mag.show = function(context, conditionName) {
  if (typeof context !== 'object') {
    var obj = {
      _config: function(node) {
        node.style.display = context ? 'block' : 'none'
      }
    }
    if (typeof conditionName == 'object') {
      mag.merge(conditionName, obj)
    }
    return obj
  } else {
    context.willupdate = function(event, node, inprops) {
      node.style.display = inprops[conditionName] ? 'block' : 'none'
    }
  }
}

mag.addons = {};

// return object of getter values
mag.addons.getProp = function(data) {
  var newData = {}
  Object.keys(data).forEach(function(k) {
    if (data[k].type == 'fun' && typeof data[k] == 'function') newData[k] = data[k]()
  })
  return newData
}

// show hide

// remove class hide to given context/this
// show(this) inside controller
mag.addons.show = function(condition) {
  if (typeof condition === 'boolean') {
    return {
      _config: function(n) {
        if (!condition) n.style.display = 'none';
        else n.style.display = 'block';
      }
    };
  } else if (typeof condition === 'object') {
    condition.willload = function(e, n) {
      n.style.display = 'block'
    }
  } else if (arguments.length == 0) {
    return function(e, n) {
      // next didupdate event
      n.style.display = 'block'
    }
  }
}

mag.addons.hide = function(condition) {
  if (typeof condition === 'boolean') {
    return {
      _config: function(n) {
        if (condition) n.style.display = 'none';
        else n.style.display = 'block';
      }
    }
  } else if (typeof condition === 'object') {
    condition.willload = function(e, n) {
      n.style.display = 'none';
    }
  } else if (arguments.length == 0) {
    return function(e, n) {
      // next didupdate event
      n.style.display = 'none'
    }
  }
}

// promises

/*
var d = mag.deferred()

d.promise.then(function() {
  console.log('success', arguments)
}, function() {
  console.log('failure', arguments)
})
d.reject({
  things: false
})
d.resolve({
  things: []
})
*/

mag.deferred = function() {
  var Deferred = {}
  Deferred.promise = new Promise(function(resolve, reject) {
    Deferred.resolve = resolve
    Deferred.reject = reject
  })
  return Deferred
}

mag.addons.when = function(arrayOfPromises, callback) {
  Promise.all(arrayOfPromises).then(callback)
}

mag.addons.requestWithFeedback = function(args) {
  var key = JSON.stringify(args)
  if (!mag.addons.requestWithFeedback.cache[key]) {

    var loaders = document.querySelectorAll(".loader")

    //show icons
    for (var i = 0, loader; loader = loaders[i]; i++) loader.style.display = "block"

    var expire = function(data) {
      delete mag.addons.requestWithFeedback.cache[key]

      if (Object.keys(mag.addons.requestWithFeedback.cache).length == 0) {
        //hide icons
        for (var i = 0, loader; loader = loaders[i]; i++) loader.style.display = "none"
      }
      return data
    }
    mag.addons.requestWithFeedback.cache[key] = mag.request(args).then(expire, function(error) {
      expire(error)
      throw error
    })
  }
  return mag.addons.requestWithFeedback.cache[key]
}
mag.addons.requestWithFeedback.cache = {}

// hookins

mag.hookin('attributes', 'key', function(data) {
  // remove system key from being added to attributes in html
  //  data.value = null
})

mag.hookin('attributes', 'className', function(data) {
  data.key = 'class'
  var newClass = data.value

  if (typeof data.value == 'string') {
    newClass = data.value.split(' ')
  } else if(typeof data.value == 'object') {
    for (var k in newClass) {
      data.node.classList.toggle(k, newClass[k])
    }
    data.value = data.node.classList + ''
    return
  }

  data.value = data.node.classList + ''

  for (var k in newClass) {
    var cls = newClass[k]
    if (cls.trim() && data.node.classList.length > 0 && !data.node.classList.contains(cls.trim())) {
      data.value = data.node.classList + ' ' + cls

    } else if (cls.trim() && data.node.classList.length == 0) {
      data.value += cls + ' '
    }
  }

  data.value = data.value.trim()
})

// disable add to config
// http://jsbin.com/qutudiqife/3/edit?js,output
// define condition func
// this.show = mag.prop(false);

//define context
// mag.addons.disable.call(this, 'other', this.show);
//TODO: change to mag.ui.disable
mag.addons.disable = function(selector, condition) {

  if (typeof this[selector] !== 'object') {
    // create object
    this[selector] = {
      _value: this[selector]
    };
  }

  // add or merge to config if not exists
  var orig = this[selector]._config ? this[selector]._config : function() {};

  this[selector]._config = function(n) {
    orig.call(this, arguments);
    if (condition()) n.setAttribute('disabled', 'disabled');
    else n.removeAttribute('disabled');
  };
}

// TODO: change to mag.find
mag.addons.get = function(parentRootId, selector) {
  var parent = document.getElementById(parentRootId);
  return mag.fill.find(parent, selector)
}

// mag.addons.toMenu(['one', 'two', 'three'], state.selected())
// http://jsbin.com/mapuwojumu/3/edit?js,output
//TODO change to mag.ui.menu
mag.addons.toMenu = function(maps, selected) {
  return maps.map(function(v, k) {
    return {
      _text: v,
      _value: k,
      _selected: selected === k || selected === v ? true : null
    }
  })
}
<|endoftext|>


<commit_before>/*
Mag.JS AddOns v0.21
(c) Michael Glazer
https://github.com/magnumjs/mag.js
*/

var mag = mag || {}

/*
module library creation with single global namespace / package names
(function(namespace) {

  var mod = {
    controller:function(props){
    },
    view: function(state, props) {
    }
  }

  namespace.CommentBox = mod;

})(mag.namespace('mglazer.mods.comments'));
*/
mag.namespace = function (ns, obj) {
   var   levels = ns.split('.'), first = levels.shift();
  obj = obj || this; //if no object argument supplied declare a global property
  obj[first] = obj[first] || {}; // initialize the "level"
  if (levels.length) { // recursion condition
    return mag.namespace(levels.join('.'), obj[first]);
  }
  return obj[first]; // return a reference to the top level object
}

//UTILITY
// mag.utils.copy - now in core
// mag.utils.merge - now in core

mag.copy = mag.utils.copy
mag.merge = mag.utils.merge

/*
controller:function(props)
  // if props has a property 'isVisible' when true will display entire module on before updates
  mag.show(this,'isVisible')
}
http://jsbin.com/miqobiqedu/edit?html,js,output
*/
mag.show = function(context, conditionName) {
  if (typeof context !== 'object') {
    var obj = {
      _config: function(node) {
        node.style.display = context ? 'block' : 'none'
      }
    }
    if (typeof conditionName == 'object') {
      mag.merge(conditionName, obj)
    }
    return obj
  } else {
    context.willupdate = function(event, node, inprops) {
      node.style.display = inprops[conditionName] ? 'block' : 'none'
    }
  }
}

mag.addons = {};

// return object of getter values
mag.addons.getProp = function(data) {
  var newData = {}
  Object.keys(data).forEach(function(k) {
    if (data[k].type == 'fun' && typeof data[k] == 'function') newData[k] = data[k]()
  })
  return newData
}

// show hide

// remove class hide to given context/this
// show(this) inside controller
mag.addons.show = function(condition) {
  if (typeof condition === 'boolean') {
    return {
      _config: function(n) {
        if (!condition) n.style.display = 'none';
        else n.style.display = 'block';
      }
    };
  } else if (typeof condition === 'object') {
    condition.willload = function(e, n) {
      n.style.display = 'block'
    }
  } else if (arguments.length == 0) {
    return function(e, n) {
      // next didupdate event
      n.style.display = 'block'
    }
  }
}

mag.addons.hide = function(condition) {
  if (typeof condition === 'boolean') {
    return {
      _config: function(n) {
        if (condition) n.style.display = 'none';
        else n.style.display = 'block';
      }
    }
  } else if (typeof condition === 'object') {
    condition.willload = function(e, n) {
      n.style.display = 'none';
    }
  } else if (arguments.length == 0) {
    return function(e, n) {
      // next didupdate event
      n.style.display = 'none'
    }
  }
}

// promises

/*
var d = mag.deferred()

d.promise.then(function() {
  console.log('success', arguments)
}, function() {
  console.log('failure', arguments)
})
d.reject({
  things: false
})
d.resolve({
  things: []
})
*/

mag.deferred = function() {
  var Deferred = {}
  Deferred.promise = new Promise(function(resolve, reject) {
    Deferred.resolve = resolve
    Deferred.reject = reject
  })
  return Deferred
}

mag.addons.when = function(arrayOfPromises, callback) {
  Promise.all(arrayOfPromises).then(callback)
}

mag.addons.requestWithFeedback = function(args) {
  var key = JSON.stringify(args)
  if (!mag.addons.requestWithFeedback.cache[key]) {

    var loaders = document.querySelectorAll(".loader")

    //show icons
    for (var i = 0, loader; loader = loaders[i]; i++) loader.style.display = "block"

    var expire = function(data) {
      delete mag.addons.requestWithFeedback.cache[key]

      if (Object.keys(mag.addons.requestWithFeedback.cache).length == 0) {
        //hide icons
        for (var i = 0, loader; loader = loaders[i]; i++) loader.style.display = "none"
      }
      return data
    }
    mag.addons.requestWithFeedback.cache[key] = mag.request(args).then(expire, function(error) {
      expire(error)
      throw error
    })
  }
  return mag.addons.requestWithFeedback.cache[key]
}
mag.addons.requestWithFeedback.cache = {}

// hookins

mag.hookin('attributes', 'key', function(data) {
  // remove system key from being added to attributes in html
  //  data.value = null
})

mag.hookin('attributes', 'className', function(data) {
  data.key = 'class'
  var newClass = data.value

  if (typeof data.value == 'string') {
    newClass = data.value.split(' ')
  } else if(typeof data.value == 'object') {
    for (var k in newClass) {
      data.node.classList.toggle(k, newClass[k])
    }
    data.value = data.node.classList + ''
    return
  }

  data.value = data.node.classList + ''

  for (var k in newClass) {
    var cls = newClass[k]
    if (cls.trim() && data.node.classList.length > 0 && !data.node.classList.contains(cls.trim())) {
      data.value = data.node.classList + ' ' + cls

    } else if (cls.trim() && data.node.classList.length == 0) {
      data.value += cls + ' '
    }
  }

  data.value = data.value.trim()
})

// disable add to config
// http://jsbin.com/qutudiqife/3/edit?js,output
// define condition func
// this.show = mag.prop(false);

//define context
// mag.addons.disable.call(this, 'other', this.show);
//TODO: change to mag.ui.disable
mag.addons.disable = function(selector, condition) {

  if (typeof this[selector] !== 'object') {
    // create object
    this[selector] = {
      _value: this[selector]
    };
  }

  // add or merge to config if not exists
  var orig = this[selector]._config ? this[selector]._config : function() {};

  this[selector]._config = function(n) {
    orig.call(this, arguments);
    if (condition()) n.setAttribute('disabled', 'disabled');
    else n.removeAttribute('disabled');
  };
}

// TODO: change to mag.find
mag.addons.get = function(parentRootId, selector) {
  var parent = document.getElementById(parentRootId);
  return mag.fill.find(parent, selector)
}

// mag.addons.toMenu(['one', 'two', 'three'], state.selected())
// http://jsbin.com/mapuwojumu/3/edit?js,output
//TODO change to mag.ui.menu
mag.addons.toMenu = function(maps, selected) {
  return maps.map(function(v, k) {
    return {
      _text: v,
      _value: k,
      _selected: selected === k || selected === v ? true : null
    }
  })
}
<commit_msg>Update mag.addons.0.2.js<commit_after>/*
Mag.JS AddOns v0.21
(c) Michael Glazer
https://github.com/magnumjs/mag.js
*/

var mag = mag || {}

/*
module library creation with single global namespace / package names
(function(namespace) {

  var mod = {
    controller:function(props){
    },
    view: function(state, props) {
    }
  }

  namespace.CommentBox = mod;

})(mag.namespace('mglazer.mods.comments'));
*/
mag.namespace = function (ns, obj) {
   var   levels = ns.split('.'), first = levels.shift();
  obj = obj || this; //if no object argument supplied declare a global property
  obj[first] = obj[first] || {}; // initialize the "level"
  if (levels.length) { // recursion condition
    return mag.namespace(levels.join('.'), obj[first]);
  }
  return obj[first]; // return a reference to the top level object
}

//UTILITY
// mag.utils.copy - now in core
// mag.utils.merge - now in core

mag.copy = mag.utils.copy
mag.merge = mag.utils.merge

/*
controller:function(props)
  // if props has a property 'isVisible' when true will display entire module on before updates
  mag.show(this,'isVisible')
}
http://jsbin.com/fegizubime/edit?html,js,output
*/

mag.show = function(context, conditionName) {
  if (typeof context !== 'object') {
    var obj = {
      _config: function(node) {
        node.style.display = context ? 'block' : 'none'
      }
    }
    if (typeof conditionName == 'object') {
      mag.merge(conditionName, obj)
    }
    return obj
  } else {
    context.willupdate = function(event, node, inprops) {
      node.style.display = inprops[conditionName] ? 'block' : 'none'
    }
  }
}

mag.addons = {};

// return object of getter values
mag.addons.getProp = function(data) {
  var newData = {}
  Object.keys(data).forEach(function(k) {
    if (data[k].type == 'fun' && typeof data[k] == 'function') newData[k] = data[k]()
  })
  return newData
}

// show hide

// remove class hide to given context/this
// show(this) inside controller
mag.addons.show = function(condition) {
  if (typeof condition === 'boolean') {
    return {
      _config: function(n) {
        if (!condition) n.style.display = 'none';
        else n.style.display = 'block';
      }
    };
  } else if (typeof condition === 'object') {
    condition.willload = function(e, n) {
      n.style.display = 'block'
    }
  } else if (arguments.length == 0) {
    return function(e, n) {
      // next didupdate event
      n.style.display = 'block'
    }
  }
}

mag.addons.hide = function(condition) {
  if (typeof condition === 'boolean') {
    return {
      _config: function(n) {
        if (condition) n.style.display = 'none';
        else n.style.display = 'block';
      }
    }
  } else if (typeof condition === 'object') {
    condition.willload = function(e, n) {
      n.style.display = 'none';
    }
  } else if (arguments.length == 0) {
    return function(e, n) {
      // next didupdate event
      n.style.display = 'none'
    }
  }
}

// promises

/*
var d = mag.deferred()

d.promise.then(function() {
  console.log('success', arguments)
}, function() {
  console.log('failure', arguments)
})
d.reject({
  things: false
})
d.resolve({
  things: []
})
*/

mag.deferred = function() {
  var Deferred = {}
  Deferred.promise = new Promise(function(resolve, reject) {
    Deferred.resolve = resolve
    Deferred.reject = reject
  })
  return Deferred
}

mag.addons.when = function(arrayOfPromises, callback) {
  Promise.all(arrayOfPromises).then(callback)
}

mag.addons.requestWithFeedback = function(args) {
  var key = JSON.stringify(args)
  if (!mag.addons.requestWithFeedback.cache[key]) {

    var loaders = document.querySelectorAll(".loader")

    //show icons
    for (var i = 0, loader; loader = loaders[i]; i++) loader.style.display = "block"

    var expire = function(data) {
      delete mag.addons.requestWithFeedback.cache[key]

      if (Object.keys(mag.addons.requestWithFeedback.cache).length == 0) {
        //hide icons
        for (var i = 0, loader; loader = loaders[i]; i++) loader.style.display = "none"
      }
      return data
    }
    mag.addons.requestWithFeedback.cache[key] = mag.request(args).then(expire, function(error) {
      expire(error)
      throw error
    })
  }
  return mag.addons.requestWithFeedback.cache[key]
}
mag.addons.requestWithFeedback.cache = {}

// hookins

mag.hookin('attributes', 'key', function(data) {
  // remove system key from being added to attributes in html
  //  data.value = null
})

mag.hookin('attributes', 'className', function(data) {
  data.key = 'class'
  var newClass = data.value

  if (typeof data.value == 'string') {
    newClass = data.value.split(' ')
  } else if(typeof data.value == 'object') {
    for (var k in newClass) {
      data.node.classList.toggle(k, newClass[k])
    }
    data.value = data.node.classList + ''
    return
  }

  data.value = data.node.classList + ''

  for (var k in newClass) {
    var cls = newClass[k]
    if (cls.trim() && data.node.classList.length > 0 && !data.node.classList.contains(cls.trim())) {
      data.value = data.node.classList + ' ' + cls

    } else if (cls.trim() && data.node.classList.length == 0) {
      data.value += cls + ' '
    }
  }

  data.value = data.value.trim()
})

// disable add to config
// http://jsbin.com/qutudiqife/3/edit?js,output
// define condition func
// this.show = mag.prop(false);

//define context
// mag.addons.disable.call(this, 'other', this.show);
//TODO: change to mag.ui.disable
mag.addons.disable = function(selector, condition) {

  if (typeof this[selector] !== 'object') {
    // create object
    this[selector] = {
      _value: this[selector]
    };
  }

  // add or merge to config if not exists
  var orig = this[selector]._config ? this[selector]._config : function() {};

  this[selector]._config = function(n) {
    orig.call(this, arguments);
    if (condition()) n.setAttribute('disabled', 'disabled');
    else n.removeAttribute('disabled');
  };
}

// TODO: change to mag.find
mag.addons.get = function(parentRootId, selector) {
  var parent = document.getElementById(parentRootId);
  return mag.fill.find(parent, selector)
}

// mag.addons.toMenu(['one', 'two', 'three'], state.selected())
// http://jsbin.com/mapuwojumu/3/edit?js,output
//TODO change to mag.ui.menu
mag.addons.toMenu = function(maps, selected) {
  return maps.map(function(v, k) {
    return {
      _text: v,
      _value: k,
      _selected: selected === k || selected === v ? true : null
    }
  })
}
<|endoftext|>