<commit_before>// 1. key events

(function() {
    var KeyEvent = function(data, type) {
        this.keyCode = 'keyCode' in data ? data.keyCode : 0;
        this.charCode = 'charCode' in data ? data.charCode : 0;

        var modifiers = 'modifiers' in data ? data.modifiers : [];

        this.ctrlKey = false;
        this.metaKey = false;
        this.altKey = false;
        this.shiftKey = false;

        for (var i = 0; i < modifiers.length; i++) {
            this[modifiers[i] + 'Key'] = true;
        }

        this.type = type || 'keypress';
    };

    KeyEvent.prototype.toNative = function() {
        var event = document.createEventObject ? document.createEventObject() : document.createEvent('Events');

        if (event.initEvent) {
            event.initEvent(this.type, true, true);
        }

        event.keyCode = this.keyCode;
        event.which = this.charCode || this.keyCode;
        event.shiftKey = this.shiftKey;
        event.metaKey = this.metaKey;
        event.altKey = this.altKey;
        event.ctrlKey = this.ctrlKey;

        return event;
    };

    KeyEvent.prototype.fire = function(element) {
        var event = this.toNative();
        if (element.dispatchEvent) {
            element.dispatchEvent(event);
            return;
        }

        element.fireEvent('on' + this.type, event);
    };

    // simulates complete key event as if the user pressed the key in the browser
    // triggers a keydown, then a keypress, then a keyup
    KeyEvent.simulate = function(charCode, keyCode, modifiers, element, repeat) {
        if (modifiers === undefined) {
            modifiers = [];
        }

        if (element === undefined) {
            element = document;
        }

        if (repeat === undefined) {
            repeat = 1;
        }

        var modifierToKeyCode = {
            'shift': 16,
            'ctrl': 17,
            'alt': 18,
            'meta': 91
        };

        // if the key is a modifier then take it out of the regular
        // keypress/keydown
        if (keyCode == 16 || keyCode == 17 || keyCode == 18 || keyCode == 91) {
            repeat = 0;
        }

        var modifiersToInclude = [];
        var keyEvents = [];

        // modifiers would go down first
        for (var i = 0; i < modifiers.length; i++) {
            modifiersToInclude.push(modifiers[i]);
            keyEvents.push(new KeyEvent({
                charCode: 0,
                keyCode: modifierToKeyCode[modifiers[i]],
                modifiers: modifiersToInclude
            }, 'keydown'));
        }

        // @todo factor in duration for these
        while (repeat > 0) {
            keyEvents.push(new KeyEvent({
                charCode: 0,
                keyCode: keyCode,
                modifiers: modifiersToInclude
            }, 'keydown'));

            keyEvents.push(new KeyEvent({
                charCode: charCode,
                keyCode: charCode,
                modifiers: modifiersToInclude
            }, 'keypress'));

            repeat--;
        }

        keyEvents.push(new KeyEvent({
            charCode: 0,
            keyCode: keyCode,
            modifiers: modifiersToInclude
        }, 'keyup'));

        // now lift up the modifier keys
        for (i = 0; i < modifiersToInclude.length; i++) {
            var modifierKeyCode = modifierToKeyCode[modifiersToInclude[i]];
            modifiersToInclude.splice(i, 1);
            keyEvents.push(new KeyEvent({
                charCode: 0,
                keyCode: modifierKeyCode,
                modifiers: modifiersToInclude
            }, 'keyup'));
        }

        for (i = 0; i < keyEvents.length; i++) {
            // console.log('firing', keyEvents[i].type, keyEvents[i].keyCode, keyEvents[i].charCode);
            keyEvents[i].fire(element);
        }
    };

    window.KeyEvent = KeyEvent;
}) ();

// 2. Gary Haran => gary@talkerapp.com
// This code is released under MIT licence
(function($){
  var replacer = function(finder, replacement, element, blackList) {
    if (!finder || typeof replacement === 'undefined') {
      return
    }
    var regex = (typeof finder == 'string') ? new RegExp(finder, 'g') : finder;

    var childNodes = element.childNodes;
    var len = childNodes.length;

    var list = typeof blackList == 'undefined' ? 'html,head,style,title,link,meta,script,object,iframe,pre,a,' : blackList ;

    while (len--) {
      var node = childNodes[len];

      if (node.nodeType === 1 && true || (list.indexOf(node.nodeName.toLowerCase()) === -1)) {
        replacer(finder, replacement, node, list);
      }

      if (node.nodeType !== 3 || !regex.test(node.data)) {
        continue;
      }

      var frag = (function(){
        var html = node.data.replace(regex, replacement);
        var wrap = document.createElement('span');
        var frag = document.createDocumentFragment();

        wrap.innerHTML = html;

        while (wrap.firstChild) {
          frag.appendChild(wrap.firstChild);
        }

        return frag;
      })();

      var parent = node.parentNode;
      parent.insertBefore(frag, node);
      parent.removeChild(node);
    }
  }

  $.fn.replace = function(finder, replacement, blackList) {
    return this.each(function(){
      replacer(finder, replacement, $(this).get(0), blackList);
    });
  }
})(jQuery);
<commit_msg>Create key-event.js<commit_after>// 1. key events

(function() {
    var KeyEvent = function(data, type) {
        this.keyCode = 'keyCode' in data ? data.keyCode : 0;
        this.charCode = 'charCode' in data ? data.charCode : 0;

        var modifiers = 'modifiers' in data ? data.modifiers : [];

        this.ctrlKey = false;
        this.metaKey = false;
        this.altKey = false;
        this.shiftKey = false;

        for (var i = 0; i < modifiers.length; i++) {
            this[modifiers[i] + 'Key'] = true;
        }

        this.type = type || 'keypress';
    };

    KeyEvent.prototype.toNative = function() {
        var event = document.createEventObject ? document.createEventObject() : document.createEvent('Events');

        if (event.initEvent) {
            event.initEvent(this.type, true, true);
        }

        event.keyCode = this.keyCode;
        event.which = this.charCode || this.keyCode;
        event.shiftKey = this.shiftKey;
        event.metaKey = this.metaKey;
        event.altKey = this.altKey;
        event.ctrlKey = this.ctrlKey;

        return event;
    };

    KeyEvent.prototype.fire = function(element) {
        var event = this.toNative();
        if (element.dispatchEvent) {
            element.dispatchEvent(event);
            return;
        }

        element.fireEvent('on' + this.type, event);
    };

    // simulates complete key event as if the user pressed the key in the browser
    // triggers a keydown, then a keypress, then a keyup
    KeyEvent.simulate = function(charCode, keyCode, modifiers, element, repeat) {
        if (modifiers === undefined) {
            modifiers = [];
        }

        if (element === undefined) {
            element = document;
        }

        if (repeat === undefined) {
            repeat = 1;
        }

        var modifierToKeyCode = {
            'shift': 16,
            'ctrl': 17,
            'alt': 18,
            'meta': 91
        };

        // if the key is a modifier then take it out of the regular
        // keypress/keydown
        if (keyCode == 16 || keyCode == 17 || keyCode == 18 || keyCode == 91) {
            repeat = 0;
        }

        var modifiersToInclude = [];
        var keyEvents = [];

        // modifiers would go down first
        for (var i = 0; i < modifiers.length; i++) {
            modifiersToInclude.push(modifiers[i]);
            keyEvents.push(new KeyEvent({
                charCode: 0,
                keyCode: modifierToKeyCode[modifiers[i]],
                modifiers: modifiersToInclude
            }, 'keydown'));
        }

        // @todo factor in duration for these
        while (repeat > 0) {
            keyEvents.push(new KeyEvent({
                charCode: 0,
                keyCode: keyCode,
                modifiers: modifiersToInclude
            }, 'keydown'));

            keyEvents.push(new KeyEvent({
                charCode: charCode,
                keyCode: charCode,
                modifiers: modifiersToInclude
            }, 'keypress'));

            repeat--;
        }

        keyEvents.push(new KeyEvent({
            charCode: 0,
            keyCode: keyCode,
            modifiers: modifiersToInclude
        }, 'keyup'));

        // now lift up the modifier keys
        for (i = 0; i < modifiersToInclude.length; i++) {
            var modifierKeyCode = modifierToKeyCode[modifiersToInclude[i]];
            modifiersToInclude.splice(i, 1);
            keyEvents.push(new KeyEvent({
                charCode: 0,
                keyCode: modifierKeyCode,
                modifiers: modifiersToInclude
            }, 'keyup'));
        }

        for (i = 0; i < keyEvents.length; i++) {
            // console.log('firing', keyEvents[i].type, keyEvents[i].keyCode, keyEvents[i].charCode);
            keyEvents[i].fire(element);
        }
    };

    window.KeyEvent = KeyEvent;
}) ();

// 2. jquery replace
// Gary Haran => gary@talkerapp.com
// This code is released under MIT licence
(function($){
  var replacer = function(finder, replacement, element, blackList) {
    if (!finder || typeof replacement === 'undefined') {
      return
    }
    var regex = (typeof finder == 'string') ? new RegExp(finder, 'g') : finder;

    var childNodes = element.childNodes;
    var len = childNodes.length;

    var list = typeof blackList == 'undefined' ? 'html,head,style,title,link,meta,script,object,iframe,pre,a,' : blackList ;

    while (len--) {
      var node = childNodes[len];

      if (node.nodeType === 1 && true || (list.indexOf(node.nodeName.toLowerCase()) === -1)) {
        replacer(finder, replacement, node, list);
      }

      if (node.nodeType !== 3 || !regex.test(node.data)) {
        continue;
      }

      var frag = (function(){
        var html = node.data.replace(regex, replacement);
        var wrap = document.createElement('span');
        var frag = document.createDocumentFragment();

        wrap.innerHTML = html;

        while (wrap.firstChild) {
          frag.appendChild(wrap.firstChild);
        }

        return frag;
      })();

      var parent = node.parentNode;
      parent.insertBefore(frag, node);
      parent.removeChild(node);
    }
  }

  $.fn.replace = function(finder, replacement, blackList) {
    return this.each(function(){
      replacer(finder, replacement, $(this).get(0), blackList);
    });
  }
})(jQuery);
<|endoftext|>


<commit_before>define([
    'require',
    '../../lib/chosen.jquery',
    '../logging'
], function(require) {
    var log = require('../logging').getLogger('breadcrumbs');

    var init = function($el, opts) {
        // wrap elements in a DIV that will be shifted around
        var $content = $el.children()
                .wrapAll('

').parent();

        // set fixed width on content
        var width = $content.children().toArray().reduce(function(acc, el) {
            return acc + $(el).outerWidth(true);
        }, 0);
        $content.width(width);

        // shift ctrl
        var $ctrl = $('shift')
                .prependTo($el);

        var shifted = false,
            shifting = false,
            difference = 0;
        var shifter = function(toggle) {
            return function() {
                var margin;
                if (toggle) {
                    margin = shifted ? 0 : difference;
                    $content.animate({"margin-left": margin}, function() {
                        $ctrl.toggleClass('shift-right shift-left');
                        shifted = !shifted;
                    });
                } else {
                    margin = shifted ? difference : 0;
                    $content.css({"margin-left": margin});
                }
            };
        };

        var maybeshift = function() {
            // account for other stuff on the same line (100px)
            difference = $el.innerWidth() - $content.width() - 100;

            if (difference < 0) {
                // we should be shifting
                if (!shifting) {
                    shifting = true;
                    $el.addClass('shifting');
                    $ctrl.addClass('shift-left');
                    $ctrl.on('click.breadcrumbs', shifter(true));
                    $ctrl.click();
                } else {
                    // a shifter that keeps state
                    shifter(false)();
                }
            } else {
                // we should not be shifting
                if (shifting) {
                    if (shifted) $ctrl.click();
                    shifting = false;
                    $el.removeClass('shifting');
                    $ctrl.removeClass('shift-left shift-right');
                    $ctrl.off('.breadcrumbs');
                }
            }
        };
        maybeshift();
        $(window).on('resize.breadcrumbs', maybeshift);
    };

    var pattern = {
        markup_trigger: 'nav.breadcrumbs',
        init: init
    };
    return pattern;
});<commit_msg>fix breadcrumbs shifting classes<commit_after>define([
    'require',
    '../../lib/chosen.jquery',
    '../logging'
], function(require) {
    var log = require('../logging').getLogger('breadcrumbs');

    var init = function($el, opts) {
        // wrap elements in a DIV that will be shifted around
        var $content = $el.children()
                .wrapAll('

').parent();

        // set fixed width on content
        var width = $content.children().toArray().reduce(function(acc, el) {
            return acc + $(el).outerWidth(true);
        }, 0);
        $content.width(width);

        // shift ctrl
        var $ctrl = $('shift')
                .prependTo($el);

        var shifted = false,
            shifting = false,
            difference = 0;
        var shifter = function(toggle) {
            return function() {
                var margin;
                if (toggle) {
                    margin = shifted ? 0 : difference;
                    $content.animate({"margin-left": margin}, function() {
                        $ctrl.toggleClass('shift-right shift-left');
                        shifted = !shifted;
                    });
                } else {
                    margin = shifted ? difference : 0;
                    $content.css({"margin-left": margin});
                }
            };
        };

        var maybeshift = function() {
            // account for other stuff on the same line (100px)
            difference = $el.innerWidth() - $content.width() - 100;

            if (difference < 0) {
                // we should be shifting
                if (!shifting) {
                    shifting = true;
                    $el.addClass('shifting');
                    $ctrl.removeClass('shift-right');
                    $ctrl.addClass('shift-left');
                    $ctrl.on('click.breadcrumbs', shifter(true));
                    $ctrl.click();
                } else {
                    // a shifter that keeps state
                    shifter(false)();
                }
            } else {
                // we should not be shifting
                if (shifting) {
                    $content.animate({"margin-left": 0}, function() {
                        shifted = false;
                        shifting = false;
                        $el.removeClass('shifting');
                        $ctrl.removeClass('shift-left shift-right');
                        $ctrl.off('.breadcrumbs');
                    });
                }
            }
        };
        maybeshift();
        $(window).on('resize.breadcrumbs', maybeshift);
    };

    var pattern = {
        markup_trigger: 'nav.breadcrumbs',
        init: init
    };
    return pattern;
});<|endoftext|>


<commit_before>// commands.js

//
const auth = require('./auth.json');
const YOUTUBE_API_KEY = auth['youtube_api_key'];

// Import modules
const Discord = require('discord.js');
const ytdl = require('ytdl-core');
const request = require('request');

// Global vars

// Music variables
// Keep a queue of songs to playStream
var audioQueue = [];
var audioConn = null;
var audioHandler = null;
var audioVolume = 0.3;
var audioPaused = false;
var audioCurrent = null;

module.exports = {
/*
	'change-name': {
		name: 'change-name',
		process: (msg, args) => {
			msg.client.user.setUsername(args);
		}
	},
	'create-channel': {
		name: 'create-channel',
		process: (msg, args) => {
			var channelType = args.split(' ')[0];

			if (channelType === 'voice' || channelType === 'text') {
				msg.guild.createChannel(args.substring(channelType.length + 1), channelType);
			} else {
				msg.guild.createChannel(args, 'text');
			}
		}
	},
	'delete-channel': {
		name: 'delete-channel',
		process: (msg, args) => {
			var channelType = args.split(' ')[0];

			if (channelType === 'voice') {
				var channelName = args.substring(channelType.length + 1);
				for (let [channelId, channel] of msg.guild.channels) {
					if (channel.name === channelName && channel instanceof Discord.VoiceChannel) {
						channel.delete();
						break;
					}
				}
			} else if (channelType === 'text') {
				var channelName = args.substring(channelType.length + 1);
				for (let [channelId, channel] of msg.guild.channels) {
					if (channel.name === channelName && channel instanceof Discord.TextChannel) {
						channel.delete();
						break;
					}
				}
			} else {
				for (let [channelId, channel] of msg.guild.channels) {
					if (channel.name === args) {
						channel.delete();
						break;
					}
				}
			}
		}
	},
*/
    'move' : {
		name: 'move',
		process: (msg) => {
			var voiceChannel = msg.guild.members.get(msg.author.id).voiceChannel;
			if (voiceChannel) {
				voiceChannel.join().then(conn => {
					audioConn = conn;
				}).catch(console.error);
			}
		}
	},
	'now-playing': {
		name: 'now-playing',
		shortcut: 'np',
		process: (msg) => {
			msg.channel.sendEmbed({
				color: 3447003,
				author: {
					name: 'Now Playing:',
				},
				thumbnail: {
					url: audioCurrent['thumbnail'],
				},
				title: audioCurrent['title'],
				url: audioCurrent['url'],
				footer: {
					text: 'Vol: ' + audioVolume * 100 + ' | Req: ' + audioCurrent['requester'],
				}
			});
		}
	},
	'list-queue': {
		name: 'list-queue',
		shortcut: 'lq',
		process: (msg) => {
			if (audioQueue.length === 0 && audioCurrent === null) {
				const embed = new Discord.RichEmbed()
				  .setDescription(`${msg.author}, I don't have music queued.`);

				msg.channel.send('', {embed : embed});
			} else {
				const embed = new Discord.RichEmbed()
				  .setColor(0xFF8243)
				  .setThumbnail('https://i.imgur.com/doEnUr3.png')
				  .setAuthor('Music Queue - Mango Beats','https://i.imgur.com/RKT5C86.png')
				  .setDescription(`Now: [${audioCurrent.title}](${audioCurrent.url})\n${audioCurrent.requester}`);

				var i = 1;
				for (let songInfo of audioQueue) {
					embed.addField('\u200B', `[${songInfo.title}](${songInfo.url})\n${songInfo.requester}`);
					i++;
					if (i === 25) break;
				}

				msg.channel.send('', {embed : embed});
			}
		}
	},
	'queue': {
		name: 'queue-song',
		process: (msg, args) => {
			// TODO: Regex for playlist / Youtube Search
			// queueSong(msg, args);
			searchSong(msg, args);
		}
	},
	'queue-playlist': {
		name: 'queue-playlist',
		process: (msg, args) => {
			var re = /https?:\/\/www.youtube.com\/playlist\?list\=(\w+)$/;
			var result = re.exec(args);

			request('https://www.googleapis.com/youtube/v3/playlistItems?part=contentDetails&maxResults=50&playlistId=' + result[1] + '&fields=items%2FcontentDetails%2FvideoId&key=' + YOUTUBE_API_KEY, (err, res, body) => {
				var json = JSON.parse(body);

				if ('error' in json) {
					msg.reply('Mang I just got rekt!');
				} else if (json.items.length === 0) {
					msg.reply('Mang youtube dont have my thing');
				} else {
					//msg.reply(json.items[0].id['videoId']);
					for (let item of json.items) {
						queueSong(msg, 'https://www.youtube.com/watch?v=' + item.contentDetails['videoId']);
					}
				}
			}
);
		}
	},
	'remove-song:': {
		name: 'remove-song',
		process: (msg, args) => {
			var removed = audioQueue.splice(args, 1);
			msg.reply('is remove' + removed);
		}
	},
	'skip-song': {
		name: 'skip-song',
		process: () => {
			audioHandler.end('skip-song');
		}
	},
	'set-volume': {
		name: 'set-volume',
		process: (msg, args) => {
			if (isNaN(args)) {
				msg.reply('Mang do you even int?');
			} else if (args < 0 || args > 100) {
				msg.reply('Mang these numbers are a bit spicy...')
			} else {
				audioVolume = args / 100;
				if (audioHandler !== null) {
					audioHandler.setVolume(audioVolume);
				}
			}
		}
	},
	'pause': {
		name: 'pause',
		process: (msg) => {
			if (audioPaused) {
				audioPaused = false;
				audioHandler.resume();
			} else {
				audioPaused = true;
				audioHandler.pause();
			}
		}
	},
	'reorder-song': {
		name: 'reorder-song',
		process: (msg, args) => {
			var x = args.split(",")[0];
			var y = args.split(",")[1];

			//expecting the format x,y
			var temp = audioQueue[x];
			audioQueue[x] = audioQueue[y];
			audioQueue[y] = temp;
		}
	}
};

function searchSong(msg, args) {
	request('https://www.googleapis.com/youtube/v3/search?part=id&type=video&maxResults=5&order=relevance&q=' + encodeURIComponent(args) + '&key=' + YOUTUBE_API_KEY, (err, res, body) => {
		var json = JSON.parse(body);

		if ('error' in json) {
			msg.reply('Mang I just got rekt!');
		} else if (json.items.length === 0) {
			msg.reply('Mang youtube dont have my thing');
		} else {
			//msg.reply(json.items[0].id['videoId']);
			queueSong(msg, 'https://www.youtube.com/watch?v=' + json.items[0].id['videoId']);
		}
	});
}

function queueSong(msg, args) {
	if (audioConn === null) {
		var voiceChannel = msg.guild.members.get(msg.author.id).voiceChannel;
		if (voiceChannel) {
			voiceChannel.join().then(conn => {
				audioConn = conn;
			}).catch(console.error);
		}
	}

	ytdl.getInfo(args, (err, info) => {
		if (err) {
			msg.reply('Cant queue dis mang!');
		} else {
			var songInfo = {
				title: info['title'],
				url: info['video_url'],
				thumbnail: info['thumbnail_url'],
				requester: msg.author.username,
			}

			audioQueue.push(songInfo);

			const embed = new Discord.RichEmbed()
			  .setColor(0xFF8243)
			  .setAuthor(`Queue Song: #${audioQueue.length}`)
			  .setThumbnail(songInfo['thumbnail'])
			  .setTitle(songInfo['title'])
			  .setURL(songInfo['url']);

			msg.channel.send('', {embed : embed});

			if (audioHandler === null && audioQueue.length === 1) {
				playNextSong();
			}
		}
	});
}

function playNextSong() {
	var song = audioQueue[0]['url'];
	//console.log(audioQueue[0]['title']);

	var stream = ytdl(song, {filter : 'audioonly'});
	setTimeout(() => {
		audioHandler = audioConn.playStream(stream, {volume: audioVolume});
		audioCurrent = audioQueue[0];

		audioHandler.once('end', reason => {
			audioHandler = null;
			if (audioQueue.length !== 0 && !audioPaused) {
				playNextSong();
			}
		});

		audioQueue.splice(0, 1);
	}, 1000);
}<commit_msg>fixed crash when trying to remove song<commit_after>// commands.js

//
const auth = require('./auth.json');
const YOUTUBE_API_KEY = auth['youtube_api_key'];

// Import modules
const Discord = require('discord.js');
const ytdl = require('ytdl-core');
const request = require('request');

// Global vars

// Music variables
// Keep a queue of songs to playStream
var audioQueue = [];
var audioConn = null;
var audioHandler = null;
var audioVolume = 0.3;
var audioPaused = false;
var audioCurrent = null;

module.exports = {
/*
	'change-name': {
		name: 'change-name',
		process: (msg, args) => {
			msg.client.user.setUsername(args);
		}
	},
	'create-channel': {
		name: 'create-channel',
		process: (msg, args) => {
			var channelType = args.split(' ')[0];

			if (channelType === 'voice' || channelType === 'text') {
				msg.guild.createChannel(args.substring(channelType.length + 1), channelType);
			} else {
				msg.guild.createChannel(args, 'text');
			}
		}
	},
	'delete-channel': {
		name: 'delete-channel',
		process: (msg, args) => {
			var channelType = args.split(' ')[0];

			if (channelType === 'voice') {
				var channelName = args.substring(channelType.length + 1);
				for (let [channelId, channel] of msg.guild.channels) {
					if (channel.name === channelName && channel instanceof Discord.VoiceChannel) {
						channel.delete();
						break;
					}
				}
			} else if (channelType === 'text') {
				var channelName = args.substring(channelType.length + 1);
				for (let [channelId, channel] of msg.guild.channels) {
					if (channel.name === channelName && channel instanceof Discord.TextChannel) {
						channel.delete();
						break;
					}
				}
			} else {
				for (let [channelId, channel] of msg.guild.channels) {
					if (channel.name === args) {
						channel.delete();
						break;
					}
				}
			}
		}
	},
*/
    'move' : {
		name: 'move',
		process: (msg) => {
			var voiceChannel = msg.guild.members.get(msg.author.id).voiceChannel;
			if (voiceChannel) {
				voiceChannel.join().then(conn => {
					audioConn = conn;
				}).catch(console.error);
			}
		}
	},
	'now-playing': {
		name: 'now-playing',
		shortcut: 'np',
		process: (msg) => {
			msg.channel.sendEmbed({
				color: 3447003,
				author: {
					name: 'Now Playing:',
				},
				thumbnail: {
					url: audioCurrent['thumbnail'],
				},
				title: audioCurrent['title'],
				url: audioCurrent['url'],
				footer: {
					text: 'Vol: ' + audioVolume * 100 + ' | Req: ' + audioCurrent['requester'],
				}
			});
		}
	},
	'list-queue': {
		name: 'list-queue',
		shortcut: 'lq',
		process: (msg) => {
			if (audioQueue.length === 0 && audioCurrent === null) {
				const embed = new Discord.RichEmbed()
				  .setDescription(`${msg.author}, I don't have music queued.`);

				msg.channel.send('', {embed : embed});
			} else {
				const embed = new Discord.RichEmbed()
				  .setColor(0xFF8243)
				  .setThumbnail('https://i.imgur.com/doEnUr3.png')
				  .setAuthor('Music Queue - Mango Beats','https://i.imgur.com/RKT5C86.png')
				  .setDescription(`Now: [${audioCurrent.title}](${audioCurrent.url})\n${audioCurrent.requester}`);

				var i = 1;
				for (let songInfo of audioQueue) {
					embed.addField('\u200B', `[${songInfo.title}](${songInfo.url})\n${songInfo.requester}`);
					i++;
					if (i === 25) break;
				}

				msg.channel.send('', {embed : embed});
			}
		}
	},
	'queue': {
		name: 'queue-song',
		process: (msg, args) => {
			// TODO: Regex for playlist / Youtube Search
			// queueSong(msg, args);
			searchSong(msg, args);
		}
	},
	'queue-playlist': {
		name: 'queue-playlist',
		process: (msg, args) => {
			var re = /https?:\/\/www.youtube.com\/playlist\?list\=(\w+)$/;
			var result = re.exec(args);

			request('https://www.googleapis.com/youtube/v3/playlistItems?part=contentDetails&maxResults=50&playlistId=' + result[1] + '&fields=items%2FcontentDetails%2FvideoId&key=' + YOUTUBE_API_KEY, (err, res, body) => {
				var json = JSON.parse(body);

				if ('error' in json) {
					msg.reply('Mang I just got rekt!');
				} else if (json.items.length === 0) {
					msg.reply('Mang youtube dont have my thing');
				} else {
					//msg.reply(json.items[0].id['videoId']);
					for (let item of json.items) {
						queueSong(msg, 'https://www.youtube.com/watch?v=' + item.contentDetails['videoId']);
					}
				}
			}
);
		}
	},
	'remove-song:': {
		name: 'remove-song',
		process: (msg, args) => {
			var removed = audioQueue.splice(args, 1);
			msg.reply('is remove' + removed['title']);
		}
	},
	'skip-song': {
		name: 'skip-song',
		process: () => {
			audioHandler.end('skip-song');
		}
	},
	'set-volume': {
		name: 'set-volume',
		process: (msg, args) => {
			if (isNaN(args)) {
				msg.reply('Mang do you even int?');
			} else if (args < 0 || args > 100) {
				msg.reply('Mang these numbers are a bit spicy...')
			} else {
				audioVolume = args / 100;
				if (audioHandler !== null) {
					audioHandler.setVolume(audioVolume);
				}
			}
		}
	},
	'pause': {
		name: 'pause',
		process: (msg) => {
			if (audioPaused) {
				audioPaused = false;
				audioHandler.resume();
			} else {
				audioPaused = true;
				audioHandler.pause();
			}
		}
	},
	'reorder-song': {
		name: 'reorder-song',
		process: (msg, args) => {
			var x = args.split(",")[0];
			var y = args.split(",")[1];

			//expecting the format x,y
			var temp = audioQueue[x];
			audioQueue[x] = audioQueue[y];
			audioQueue[y] = temp;
		}
	}
};

function searchSong(msg, args) {
	request('https://www.googleapis.com/youtube/v3/search?part=id&type=video&maxResults=5&order=relevance&q=' + encodeURIComponent(args) + '&key=' + YOUTUBE_API_KEY, (err, res, body) => {
		var json = JSON.parse(body);

		if ('error' in json) {
			msg.reply('Mang I just got rekt!');
		} else if (json.items.length === 0) {
			msg.reply('Mang youtube dont have my thing');
		} else {
			//msg.reply(json.items[0].id['videoId']);
			queueSong(msg, 'https://www.youtube.com/watch?v=' + json.items[0].id['videoId']);
		}
	});
}

function queueSong(msg, args) {
	if (audioConn === null) {
		var voiceChannel = msg.guild.members.get(msg.author.id).voiceChannel;
		if (voiceChannel) {
			voiceChannel.join().then(conn => {
				audioConn = conn;
			}).catch(console.error);
		}
	}

	ytdl.getInfo(args, (err, info) => {
		if (err) {
			msg.reply('Cant queue dis mang!');
		} else {
			var songInfo = {
				title: info['title'],
				url: info['video_url'],
				thumbnail: info['thumbnail_url'],
				requester: msg.author.username,
			}

			audioQueue.push(songInfo);

			const embed = new Discord.RichEmbed()
			  .setColor(0xFF8243)
			  .setAuthor(`Queue Song: #${audioQueue.length}`)
			  .setThumbnail(songInfo['thumbnail'])
			  .setTitle(songInfo['title'])
			  .setURL(songInfo['url']);

			msg.channel.send('', {embed : embed});

			if (audioHandler === null && audioQueue.length === 1) {
				playNextSong();
			}
		}
	});
}

function playNextSong() {
	var song = audioQueue[0]['url'];
	//console.log(audioQueue[0]['title']);

	var stream = ytdl(song, {filter : 'audioonly'});
	setTimeout(() => {
		audioHandler = audioConn.playStream(stream, {volume: audioVolume});
		audioCurrent = audioQueue[0];

		audioHandler.once('end', reason => {
			audioHandler = null;
			if (audioQueue.length !== 0 && !audioPaused) {
				playNextSong();
			}
		});

		audioQueue.splice(0, 1);
	}, 1000);
}<|endoftext|>


<commit_before>/*globals define, WebGMEGlobal*/
/*jshint browser: true*/

/**
 * Generated by VisualizerGenerator 0.1.0 from webgme on Sat Apr 16 2016 08:51:41 GMT-0700 (PDT).
 */

define([
    // HTML
    'text!./CodeEditor.html',
    // Codemirror
    'rosmod/Libs/cm/lib/codemirror',
    // Syntax highlighting
    'rosmod/Libs/cm/mode/clike/clike',
    'rosmod/Libs/cm/mode/markdown/markdown',
    // Keymaps
    'rosmod/Libs/cm/keymap/emacs',
    'rosmod/Libs/cm/keymap/sublime',
    'rosmod/Libs/cm/keymap/vim',
    // Addons
    'rosmod/Libs/cm/addon/display/fullscreen',
    'rosmod/Libs/cm/addon/fold/foldcode',
    'rosmod/Libs/cm/addon/fold/foldgutter',
    'rosmod/Libs/cm/addon/fold/brace-fold',
    'rosmod/Libs/cm/addon/fold/xml-fold',
    'rosmod/Libs/cm/addon/fold/markdown-fold',
    'rosmod/Libs/cm/addon/fold/comment-fold',
    // CSS
    'css!./styles/CodeEditorWidget.css',
    'css!rosmod/Libs/cm/addon/display/fullscreen.css',
    'css!rosmod/Libs/cm/theme/night.css',
    'css!rosmod/Libs/cm/lib/codemirror.css',
    'css!rosmod/Libs/cm/theme/3024-day.css',
    'css!rosmod/Libs/cm/theme/3024-night.css',
    'css!rosmod/Libs/cm/theme/abcdef.css',
    'css!rosmod/Libs/cm/theme/ambiance.css',
    'css!rosmod/Libs/cm/theme/base16-dark.css',
    'css!rosmod/Libs/cm/theme/bespin.css',
    'css!rosmod/Libs/cm/theme/base16-light.css',
    'css!rosmod/Libs/cm/theme/blackboard.css',
    'css!rosmod/Libs/cm/theme/cobalt.css',
    'css!rosmod/Libs/cm/theme/colorforth.css',
    'css!rosmod/Libs/cm/theme/dracula.css',
    'css!rosmod/Libs/cm/theme/eclipse.css',
    'css!rosmod/Libs/cm/theme/elegant.css',
    'css!rosmod/Libs/cm/theme/erlang-dark.css',
    'css!rosmod/Libs/cm/theme/hopscotch.css',
    'css!rosmod/Libs/cm/theme/icecoder.css',
    'css!rosmod/Libs/cm/theme/isotope.css',
    'css!rosmod/Libs/cm/theme/lesser-dark.css',
    'css!rosmod/Libs/cm/theme/liquibyte.css',
    'css!rosmod/Libs/cm/theme/material.css',
    'css!rosmod/Libs/cm/theme/mbo.css',
    'css!rosmod/Libs/cm/theme/mdn-like.css',
    'css!rosmod/Libs/cm/theme/midnight.css',
    'css!rosmod/Libs/cm/theme/monokai.css',
    'css!rosmod/Libs/cm/theme/neat.css',
    'css!rosmod/Libs/cm/theme/neo.css',
    'css!rosmod/Libs/cm/theme/night.css',
    'css!rosmod/Libs/cm/theme/paraiso-dark.css',
    'css!rosmod/Libs/cm/theme/paraiso-light.css',
    'css!rosmod/Libs/cm/theme/pastel-on-dark.css',
    'css!rosmod/Libs/cm/theme/railscasts.css',
    'css!rosmod/Libs/cm/theme/rubyblue.css',
    'css!rosmod/Libs/cm/theme/seti.css',
    'css!rosmod/Libs/cm/theme/solarized.css',
    'css!rosmod/Libs/cm/theme/the-matrix.css',
    'css!rosmod/Libs/cm/theme/tomorrow-night-bright.css',
    'css!rosmod/Libs/cm/theme/tomorrow-night-eighties.css',
    'css!rosmod/Libs/cm/theme/ttcn.css',
    'css!rosmod/Libs/cm/theme/twilight.css',
    'css!rosmod/Libs/cm/theme/vibrant-ink.css',
    'css!rosmod/Libs/cm/theme/xq-dark.css',
    'css!rosmod/Libs/cm/theme/xq-light.css',
    'css!rosmod/Libs/cm/theme/yeti.css',
    'css!rosmod/Libs/cm/theme/zenburn.css',
    'css!rosmod/Libs/cm/addon/fold/foldgutter'
], function (
    CodeEditorHtml,
    CodeMirror,
    // Syntax Highlighting
    CodeMirrorModeClike,
    CodeMirrorModeMarkdown,
    // Keymaps
    CodeMirrorEmacsKeymap,
    CodeMirrorSublimeKeymap,
    CodeMirrorVimKeymap,
    // Addons
    CodeMirrorFullScreen,
    CodeMirrorFoldCode,
    CodeMirrorFoldGutter,
    CodeMirrorBraceFold,
    CodeMirrorXMLFold,
    CodeMirrorMarkdownFold,
    CodeMirrorCommentFold) {
    'use strict';

    var CodeEditorWidget,
    WIDGET_CLASS = 'code-editor',
    cmPercent = '94%';

    CodeEditorWidget = function (logger, container, client) {
        this._logger = logger.fork('Widget');
	this._client = client;
        this._el = container;

	$(this._el).css({
	    'padding': '0'
	});

        this.nodes = {};
        this._initialize();

        this._logger.debug('ctor finished');
    };

    CodeEditorWidget.prototype._initialize = function () {
        var width = this._el.width(),
        height = this._el.height(),
        self = this;

        // set widget class
        //this._el.addClass(WIDGET_CLASS);

        // Create the CodeEditor and options
	this._fullscreen = false;
        this._el.append(CodeEditorHtml);
	this._container = this._el.find('#CODE_EDITOR_DIV').first();
	this._codearea = this._el.find('#codearea').first();
	this._title = this._el.find('#code_editor_title');
	this.selectedAttribute = '';
	this.selectedNode = '';

	var CodeMirrorEditorOptions = {
	    lineNumbers: true,
	    matchBrackets: true,
	    //viewPortMargin: Infinity,
	    keyMap: 'sublime',
	    path: 'rosmod/Libs/cm/lib/',
	    theme: 'default',
	    fullscreen: false,
	    foldGutter: true,
	    gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
	};
	this.editor = new CodeMirror.fromTextArea(
	    this._codearea.get(0),
	    CodeMirrorEditorOptions
	);

	this.editor.on(
	    'changes',
	    _.debounce(this.saveChanges.bind(this), 250) // make sure this doesn't fire more than every 250 ms
	);

	var self=this;
	this.editor.setOption("extraKeys", {
	    'F11': function(cm) {
		//cm.setOption('fullScreen', !cm.getOption('fullScreen'));
		self.fullScreen(!self._fullScreen);
	    },
	    'Esc': function(cm) {
		//cm.setOption('fullScreen', false);
		self.fullScreen(false);
	    },
	    "Ctrl-Q": function(cm){
		cm.foldCode(cm.getCursor());
	    }
	});

	this.editor.foldCode(CodeMirror.Pos(0, 0));
	// THEME SELECT
	this.theme_select = this._el.find("#theme_select").first();
	this.theme_select.on('change', this.selectTheme.bind(this));

	// KEY MAP SELECTION
	this.kb_select = this._el.find("#kb_select").first();
	this.kb_select.on('change', this.selectKeyBinding.bind(this));

	this.buffer_select = this._el.find("#buffer_select").first();
	this.buffer_select.on('change', this.selectBuffer.bind(this));

	this.text = '';
	this.docs = {};
	$('.CodeMirror').css({
	    height: cmPercent
	});
    };

    CodeEditorWidget.prototype.fullScreen = function(toFullScreen) {
	if (toFullScreen) {
	    var container = $(document).find('#CODE_EDITOR_DIV').first();
	    $(container).css({
		position: 'fixed',
		top: '0',
		left: '0',
		width: '100%',
		height: '100%'
	    });
	    $(container).zIndex(9999);
	    $(container).appendTo(document.body);
	    $('.CodeMirror').css({
		height: cmPercent
	    });
	    this.editor.focus();
	    this._fullScreen = true;
	}
	else {
	    var container = $(document).find('#CODE_EDITOR_DIV').first();
	    $(container).css({
		position: '',
		top: '',
		left: '',
		width: '100%',
		height: '100%'
	    });
	    $(container).zIndex('auto');
	    $(container).appendTo(this._el);
	    $('.CodeMirror').css({
		height: cmPercent
	    });
	    this.editor.focus();
	    this._fullScreen = false;
	}
	this.editor.refresh();
    };

    CodeEditorWidget.prototype.saveChanges = function(cm, changes) {
	try {
	    this._client.setAttributes(this.selectedNode, this.selectedAttribute, cm.getValue());
	}
	catch (e) {
	    this._logger.error('Saving META failed!');
	}
    };

    CodeEditorWidget.prototype.updateText = function(newText) {
	this.text = newText;
    };

    CodeEditorWidget.prototype.selectBuffer = function(event) {
	var buffer_select = event.target;
	var newAttribute = buffer_select.options[buffer_select.selectedIndex].textContent;
	if (newAttribute) {
	    var newDoc = this.docs[newAttribute];
	    this.docs[this.selectedAttribute] = this.editor.swapDoc(newDoc);
	    this.selectedAttribute = newAttribute;
	    this.editor.refresh();
	}
    };

    CodeEditorWidget.prototype.selectTheme = function(event) {
	var theme_select = event.target;
	var theme = theme_select.options[theme_select.selectedIndex].textContent;
	this.editor.setOption("theme", theme);
    };

    CodeEditorWidget.prototype.selectKeyBinding = function(event) {
	var kb_select = event.target;
	var binding = kb_select.options[kb_select.selectedIndex].textContent;
	this.editor.setOption("keyMap", binding);
    };

    CodeEditorWidget.prototype.onWidgetContainerResize = function (width, height) {
        console.log('Widget is resizing...');
    };

    // create an event here (lodash?) that listens to key presses or changes in the editor text
    // to automatically save back to the model

    // Adding/Removing/Updating items
    CodeEditorWidget.prototype.addNode = function (desc) {
	var self = this;
        if (desc) {
	    $(self._title).append(desc.name);
	    var attributeNames = Object.keys(desc.codeAttributes);
	    if (attributeNames.length > 0) {
		self.nodes[desc.id] = desc;
		self.selectedNode = desc.id;
		attributeNames.map(function(attributeName) {
		    // add the attributes to buffers
		    self.docs[attributeName] = new CodeMirror.Doc(desc.codeAttributes[attributeName].value,
								  desc.codeAttributes[attributeName].mode);
		    $(self.buffer_select).append(new Option(attributeName, attributeName));
		});
		// select the first attribute?
		self.selectedAttribute = attributeNames[0];
		self.editor.swapDoc(self.docs[self.selectedAttribute]);
		self.editor.refresh();
	    }
        }
    };

    CodeEditorWidget.prototype.removeNode = function (gmeId) {
        var desc = this.nodes[gmeId];
	// NEED TO MAKE SURE I HANDLE REMOVE NODE HERE
        delete this.nodes[gmeId];
    };

    CodeEditorWidget.prototype.updateNode = function (desc) {
        if (desc) {
            // console.log('Updating node:', desc);
	    // NEED TO UPDATE THE ATTRIBUTES HERE!
        }
    };

    /* * * * * * * * Visualizer event handlers * * * * * * * */

    CodeEditorWidget.prototype.onNodeClick = function (id) {
        // This currently changes the active node to the given id and
        // this is overridden in the controller.
    };

    /* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
    CodeEditorWidget.prototype.destroy = function () {
    };

    CodeEditorWidget.prototype.onActivate = function () {
        console.log('CodeEditorWidget has been activated');
    };

    CodeEditorWidget.prototype.onDeactivate = function () {
        console.log('CodeEditorWidget has been deactivated');
    };

    return CodeEditorWidget;
});
<commit_msg>updated codeEditor to respect projects read-only setting. closes #72<commit_after>/*globals define, WebGMEGlobal*/
/*jshint browser: true*/

/**
 * Generated by VisualizerGenerator 0.1.0 from webgme on Sat Apr 16 2016 08:51:41 GMT-0700 (PDT).
 */

define([
    // HTML
    'text!./CodeEditor.html',
    // Codemirror
    'rosmod/Libs/cm/lib/codemirror',
    // Syntax highlighting
    'rosmod/Libs/cm/mode/clike/clike',
    'rosmod/Libs/cm/mode/markdown/markdown',
    // Keymaps
    'rosmod/Libs/cm/keymap/emacs',
    'rosmod/Libs/cm/keymap/sublime',
    'rosmod/Libs/cm/keymap/vim',
    // Addons
    'rosmod/Libs/cm/addon/display/fullscreen',
    'rosmod/Libs/cm/addon/fold/foldcode',
    'rosmod/Libs/cm/addon/fold/foldgutter',
    'rosmod/Libs/cm/addon/fold/brace-fold',
    'rosmod/Libs/cm/addon/fold/xml-fold',
    'rosmod/Libs/cm/addon/fold/markdown-fold',
    'rosmod/Libs/cm/addon/fold/comment-fold',
    // CSS
    'css!./styles/CodeEditorWidget.css',
    'css!rosmod/Libs/cm/addon/display/fullscreen.css',
    'css!rosmod/Libs/cm/theme/night.css',
    'css!rosmod/Libs/cm/lib/codemirror.css',
    'css!rosmod/Libs/cm/theme/3024-day.css',
    'css!rosmod/Libs/cm/theme/3024-night.css',
    'css!rosmod/Libs/cm/theme/abcdef.css',
    'css!rosmod/Libs/cm/theme/ambiance.css',
    'css!rosmod/Libs/cm/theme/base16-dark.css',
    'css!rosmod/Libs/cm/theme/bespin.css',
    'css!rosmod/Libs/cm/theme/base16-light.css',
    'css!rosmod/Libs/cm/theme/blackboard.css',
    'css!rosmod/Libs/cm/theme/cobalt.css',
    'css!rosmod/Libs/cm/theme/colorforth.css',
    'css!rosmod/Libs/cm/theme/dracula.css',
    'css!rosmod/Libs/cm/theme/eclipse.css',
    'css!rosmod/Libs/cm/theme/elegant.css',
    'css!rosmod/Libs/cm/theme/erlang-dark.css',
    'css!rosmod/Libs/cm/theme/hopscotch.css',
    'css!rosmod/Libs/cm/theme/icecoder.css',
    'css!rosmod/Libs/cm/theme/isotope.css',
    'css!rosmod/Libs/cm/theme/lesser-dark.css',
    'css!rosmod/Libs/cm/theme/liquibyte.css',
    'css!rosmod/Libs/cm/theme/material.css',
    'css!rosmod/Libs/cm/theme/mbo.css',
    'css!rosmod/Libs/cm/theme/mdn-like.css',
    'css!rosmod/Libs/cm/theme/midnight.css',
    'css!rosmod/Libs/cm/theme/monokai.css',
    'css!rosmod/Libs/cm/theme/neat.css',
    'css!rosmod/Libs/cm/theme/neo.css',
    'css!rosmod/Libs/cm/theme/night.css',
    'css!rosmod/Libs/cm/theme/paraiso-dark.css',
    'css!rosmod/Libs/cm/theme/paraiso-light.css',
    'css!rosmod/Libs/cm/theme/pastel-on-dark.css',
    'css!rosmod/Libs/cm/theme/railscasts.css',
    'css!rosmod/Libs/cm/theme/rubyblue.css',
    'css!rosmod/Libs/cm/theme/seti.css',
    'css!rosmod/Libs/cm/theme/solarized.css',
    'css!rosmod/Libs/cm/theme/the-matrix.css',
    'css!rosmod/Libs/cm/theme/tomorrow-night-bright.css',
    'css!rosmod/Libs/cm/theme/tomorrow-night-eighties.css',
    'css!rosmod/Libs/cm/theme/ttcn.css',
    'css!rosmod/Libs/cm/theme/twilight.css',
    'css!rosmod/Libs/cm/theme/vibrant-ink.css',
    'css!rosmod/Libs/cm/theme/xq-dark.css',
    'css!rosmod/Libs/cm/theme/xq-light.css',
    'css!rosmod/Libs/cm/theme/yeti.css',
    'css!rosmod/Libs/cm/theme/zenburn.css',
    'css!rosmod/Libs/cm/addon/fold/foldgutter'
], function (
    CodeEditorHtml,
    CodeMirror,
    // Syntax Highlighting
    CodeMirrorModeClike,
    CodeMirrorModeMarkdown,
    // Keymaps
    CodeMirrorEmacsKeymap,
    CodeMirrorSublimeKeymap,
    CodeMirrorVimKeymap,
    // Addons
    CodeMirrorFullScreen,
    CodeMirrorFoldCode,
    CodeMirrorFoldGutter,
    CodeMirrorBraceFold,
    CodeMirrorXMLFold,
    CodeMirrorMarkdownFold,
    CodeMirrorCommentFold) {
    'use strict';

    var CodeEditorWidget,
    WIDGET_CLASS = 'code-editor',
    cmPercent = '94%';

    CodeEditorWidget = function (logger, container, client) {
        this._logger = logger.fork('Widget');
	this._client = client;
        this._el = container;

	$(this._el).css({
	    'padding': '0'
	});

        this.nodes = {};
        this._initialize();

        this._logger.debug('ctor finished');
    };

    CodeEditorWidget.prototype._initialize = function () {
        var width = this._el.width(),
        height = this._el.height(),
        self = this;

        // set widget class
        //this._el.addClass(WIDGET_CLASS);

        // Create the CodeEditor and options
	this._readOnly = this._client.isProjectReadOnly();
	this._fullscreen = false;
        this._el.append(CodeEditorHtml);
	this._container = this._el.find('#CODE_EDITOR_DIV').first();
	this._codearea = this._el.find('#codearea').first();
	this._title = this._el.find('#code_editor_title');
	this.selectedAttribute = '';
	this.selectedNode = '';

	var CodeMirrorEditorOptions = {
	    readOnly: this._readOnly,
	    lineNumbers: true,
	    matchBrackets: true,
	    //viewPortMargin: Infinity,
	    keyMap: 'sublime',
	    path: 'rosmod/Libs/cm/lib/',
	    theme: 'default',
	    fullscreen: false,
	    foldGutter: true,
	    gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
	};
	this.editor = new CodeMirror.fromTextArea(
	    this._codearea.get(0),
	    CodeMirrorEditorOptions
	);

	this.editor.on(
	    'changes',
	    _.debounce(this.saveChanges.bind(this), 250) // make sure this doesn't fire more than every 250 ms
	);

	var self=this;
	this.editor.setOption("extraKeys", {
	    'F11': function(cm) {
		//cm.setOption('fullScreen', !cm.getOption('fullScreen'));
		self.fullScreen(!self._fullScreen);
	    },
	    'Esc': function(cm) {
		//cm.setOption('fullScreen', false);
		self.fullScreen(false);
	    },
	    "Ctrl-Q": function(cm){
		cm.foldCode(cm.getCursor());
	    }
	});

	this.editor.foldCode(CodeMirror.Pos(0, 0));
	// THEME SELECT
	this.theme_select = this._el.find("#theme_select").first();
	this.theme_select.on('change', this.selectTheme.bind(this));

	// KEY MAP SELECTION
	this.kb_select = this._el.find("#kb_select").first();
	this.kb_select.on('change', this.selectKeyBinding.bind(this));

	this.buffer_select = this._el.find("#buffer_select").first();
	this.buffer_select.on('change', this.selectBuffer.bind(this));

	this.text = '';
	this.docs = {};
	$('.CodeMirror').css({
	    height: cmPercent
	});
    };

    CodeEditorWidget.prototype.fullScreen = function(toFullScreen) {
	if (toFullScreen) {
	    var container = $(document).find('#CODE_EDITOR_DIV').first();
	    $(container).css({
		position: 'fixed',
		top: '0',
		left: '0',
		width: '100%',
		height: '100%'
	    });
	    $(container).zIndex(9999);
	    $(container).appendTo(document.body);
	    $('.CodeMirror').css({
		height: cmPercent
	    });
	    this.editor.focus();
	    this._fullScreen = true;
	}
	else {
	    var container = $(document).find('#CODE_EDITOR_DIV').first();
	    $(container).css({
		position: '',
		top: '',
		left: '',
		width: '100%',
		height: '100%'
	    });
	    $(container).zIndex('auto');
	    $(container).appendTo(this._el);
	    $('.CodeMirror').css({
		height: cmPercent
	    });
	    this.editor.focus();
	    this._fullScreen = false;
	}
	this.editor.refresh();
    };

    CodeEditorWidget.prototype.saveChanges = function(cm, changes) {
	try {
	    this._client.setAttributes(this.selectedNode, this.selectedAttribute, cm.getValue());
	}
	catch (e) {
	    this._logger.error('Saving META failed!');
	}
    };

    CodeEditorWidget.prototype.updateText = function(newText) {
	this.text = newText;
    };

    CodeEditorWidget.prototype.selectBuffer = function(event) {
	var buffer_select = event.target;
	var newAttribute = buffer_select.options[buffer_select.selectedIndex].textContent;
	if (newAttribute) {
	    var newDoc = this.docs[newAttribute];
	    this.docs[this.selectedAttribute] = this.editor.swapDoc(newDoc);
	    this.selectedAttribute = newAttribute;
	    this.editor.refresh();
	}
    };

    CodeEditorWidget.prototype.selectTheme = function(event) {
	var theme_select = event.target;
	var theme = theme_select.options[theme_select.selectedIndex].textContent;
	this.editor.setOption("theme", theme);
    };

    CodeEditorWidget.prototype.selectKeyBinding = function(event) {
	var kb_select = event.target;
	var binding = kb_select.options[kb_select.selectedIndex].textContent;
	this.editor.setOption("keyMap", binding);
    };

    CodeEditorWidget.prototype.onWidgetContainerResize = function (width, height) {
        console.log('Widget is resizing...');
    };

    // Adding/Removing/Updating items
    CodeEditorWidget.prototype.addNode = function (desc) {
	var self = this;
        if (desc) {
	    $(self._title).append(desc.name);
	    var attributeNames = Object.keys(desc.codeAttributes);
	    if (attributeNames.length > 0) {
		self.nodes[desc.id] = desc;
		self.selectedNode = desc.id;
		attributeNames.map(function(attributeName) {
		    // add the attributes to buffers
		    self.docs[attributeName] = new CodeMirror.Doc(desc.codeAttributes[attributeName].value,
								  desc.codeAttributes[attributeName].mode);
		    $(self.buffer_select).append(new Option(attributeName, attributeName));
		});
		// select the first attribute?
		self.selectedAttribute = attributeNames[0];
		self.editor.swapDoc(self.docs[self.selectedAttribute]);
		self.editor.refresh();
	    }
        }
    };

    CodeEditorWidget.prototype.removeNode = function (gmeId) {
        var desc = this.nodes[gmeId];
	// NEED TO MAKE SURE I HANDLE REMOVE NODE HERE
        delete this.nodes[gmeId];
    };

    CodeEditorWidget.prototype.updateNode = function (desc) {
        if (desc) {
            // console.log('Updating node:', desc);
	    // NEED TO UPDATE THE ATTRIBUTES HERE!
        }
    };

    /* * * * * * * * Visualizer event handlers * * * * * * * */

    CodeEditorWidget.prototype.onNodeClick = function (id) {
        // This currently changes the active node to the given id and
        // this is overridden in the controller.
    };

    /* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
    CodeEditorWidget.prototype.destroy = function () {
    };

    CodeEditorWidget.prototype.onActivate = function () {
        console.log('CodeEditorWidget has been activated');
    };

    CodeEditorWidget.prototype.onDeactivate = function () {
        console.log('CodeEditorWidget has been deactivated');
    };

    return CodeEditorWidget;
});
<|endoftext|>


<commit_before>
'use strict';

angular.module('core').directive('scrolly', function ($window) {
  return function(scope, element, attrs) {

    var tmp;
    var section_one;
    var section_two;
    var section_three;
    var section_four;
    var section_five;

    var full_section_two;
    var full_section_three;
    var full_section_four;
    var full_section_five;

    var offset;
    angular.element(document.getElementById('content')).bind('scroll', function() {

      tmp = angular.element(document.getElementById('section_one')).prop('clientHeight');

      if (!section_one || tmp !== section_one) {
        section_one = angular.element(document.getElementById('section_one')).prop('clientHeight');
        section_two = angular.element(document.getElementById('about_section')).prop('clientHeight');
        section_three = angular.element(document.getElementById('platform_section')).prop('clientHeight');
        section_four = angular.element(document.getElementById('endors_section')).prop('clientHeight');
        section_five = angular.element(document.getElementById('volunteer_section')).prop('clientHeight');

        full_section_two = section_one + section_two;
        full_section_three = full_section_two + section_three;
        full_section_four = full_section_three + section_four;
        full_section_five = full_section_four + section_five;
      }

      offset = angular.element(document.getElementById('content')).scrollTop();

      if(offset >= section_one && offset < full_section_two) {
        angular.element(document.querySelector('#meetTb')).addClass('active');
      } else {
        angular.element(document.querySelector('#meetTb')).removeClass('active');
      }

      if (offset >= full_section_two && offset < full_section_three) {
        angular.element(document.querySelector('#missionTb')).addClass('active');
      } else {
        angular.element(document.querySelector('#missionTb')).removeClass('active');
      }

      if (offset >= full_section_three && offset < full_section_four) {
        angular.element(document.querySelector('#endorsTb')).addClass('active');
      } else {
        angular.element(document.querySelector('#endorsTb')).removeClass('active');
      }

      if (offset >= full_section_four && offset < full_section_five) {
        angular.element(document.querySelector('#volunteerTb')).addClass('active');
      } else {
        angular.element(document.querySelector('#volunteerTb')).removeClass('active');
      }

      if (offset >= full_section_five) {
        angular.element(document.querySelector('#socialTb')).addClass('active');
      } else {
        angular.element(document.querySelector('#socialTb')).removeClass('active');
      }

      scope.visible = false;
      scope.$apply();
    });
  };
});<commit_msg>scroll directive<commit_after>
'use strict';

angular.module('core').directive('scrolly', function ($window) {
  return function(scope, element, attrs) {

    var tmp;
    var section_one;
    var section_two;
    var section_three;
    var section_four;
    var section_five;

    var full_section_two;
    var full_section_three;
    var full_section_four;
    var full_section_five;

    var offset;
    angular.element($window).bind('scroll', function() {

      tmp = angular.element(document.getElementById('section_one')).prop('clientHeight');

      if (!section_one || tmp !== section_one) {
        section_one = angular.element(document.getElementById('section_one')).prop('clientHeight');
        section_two = angular.element(document.getElementById('about_section')).prop('clientHeight');
        section_three = angular.element(document.getElementById('platform_section')).prop('clientHeight');
        section_four = angular.element(document.getElementById('endors_section')).prop('clientHeight');
        section_five = angular.element(document.getElementById('volunteer_section')).prop('clientHeight');

        full_section_two = section_one + section_two;
        full_section_three = full_section_two + section_three;
        full_section_four = full_section_three + section_four;
        full_section_five = full_section_four + section_five;
      }

      offset = angular.element($window).scrollTop();

      if(offset >= section_one && offset < full_section_two) {
        angular.element(document.querySelector('#meetTb')).addClass('active');
      } else {
        angular.element(document.querySelector('#meetTb')).removeClass('active');
      }

      if (offset >= full_section_two && offset < full_section_three) {
        angular.element(document.querySelector('#missionTb')).addClass('active');
      } else {
        angular.element(document.querySelector('#missionTb')).removeClass('active');
      }

      if (offset >= full_section_three && offset < full_section_four) {
        angular.element(document.querySelector('#endorsTb')).addClass('active');
      } else {
        angular.element(document.querySelector('#endorsTb')).removeClass('active');
      }

      if (offset >= full_section_four && offset < full_section_five) {
        angular.element(document.querySelector('#volunteerTb')).addClass('active');
      } else {
        angular.element(document.querySelector('#volunteerTb')).removeClass('active');
      }

      if (offset >= full_section_five) {
        angular.element(document.querySelector('#socialTb')).addClass('active');
      } else {
        angular.element(document.querySelector('#socialTb')).removeClass('active');
      }

      scope.visible = false;
      scope.$apply();
    });
  };
});<|endoftext|>


<commit_before>/* eslint-disable no-restricted-syntax */
import { ORESSupportedWiki } from './article_finder_language_mappings';
import { queryUrl } from './article_finder_utils';
import { chunk } from 'lodash-es';
import { getReferencesCount } from './revision_utils';

import promiseLimit from 'promise-limit';

const limit = promiseLimit(5);

// given a particular wiki, find all the references added for each revision in it
const fetchReferencesAddedFromWiki = async (wiki_url, revisions) => {
  // eslint-disable-next-line no-console
  console.log(`Fetching references information from ${wiki_url}`);

  const list = wiki_url.split('.');
  let wiki;
  if (list.length === 3) {
    wiki = { language: list[0], project: list[1] };
  } else {
    wiki = { project: list[0] };
  }
  if (
    !ORESSupportedWiki.projects.includes(wiki.project)
  && !ORESSupportedWiki.languages.includes(wiki.language)
  ) {
    // wiki does not support ORES
    return;
  }
  let models;
  let suffix;
  if (wiki.project === 'wikidata') {
    suffix = 'wikidatawiki';
    models = 'itemquality';
  } else {
    suffix = `${wiki.language}wiki`;
    models = 'articlequality';
  }
  const API_URL = `https://ores.wikimedia.org/v3/scores/${suffix}`;
  const revids = revisions.filter(revision => revision.ns === 0).map(revision => `${revision.parentid}|${revision.revid}`);
  const chunks = chunk(revids, 25);

  const values = (await Promise.all(chunks.map((revid_chunk) => {
    // at max 10 requests at a time
    return limit(() => {
      const params = {
        revids: revid_chunk.join('|'),
        features: true,
        models
      };
      return queryUrl(`${API_URL}`, params).catch(() => undefined); // resolve to undefined if fails
    });
  }))).filter(item => item).map(data => data?.[suffix]?.scores);

  // merge the array of objects into one object
  const combinedObject = Object.assign({}, ...values);

  const referencesAdded = {};

  for (const revision of revisions) {
    const references = getReferencesCount(combinedObject?.[revision.revid], wiki.project === 'wikidata');
    if (references !== undefined) {
      referencesAdded[revision.revid] = references - (getReferencesCount(combinedObject?.[revision.parentid]) || 0);
    }
  }
  return referencesAdded;
};

export const fetchReferencesAdded = async (wikiMap) => {
  const referencesPromises = [];
  for (const [wiki_url, revisionsOfWiki] of wikiMap) {
    referencesPromises.push(fetchReferencesAddedFromWiki(wiki_url, revisionsOfWiki));
  }
  const resolvedValues = await Promise.all(referencesPromises);

  // merge array of objects into one object and return
  return Object.assign({}, ...resolvedValues);
};
<commit_msg>fixed function call<commit_after>/* eslint-disable no-restricted-syntax */
import { ORESSupportedWiki } from './article_finder_language_mappings';
import { queryUrl } from './article_finder_utils';
import { chunk } from 'lodash-es';
import { getReferencesCount } from './revision_utils';

import promiseLimit from 'promise-limit';

const limit = promiseLimit(5);

// given a particular wiki, find all the references added for each revision in it
const fetchReferencesAddedFromWiki = async (wiki_url, revisions) => {
  // eslint-disable-next-line no-console
  console.log(`Fetching references information from ${wiki_url}`);

  const list = wiki_url.split('.');
  let wiki;
  if (list.length === 3) {
    wiki = { language: list[0], project: list[1] };
  } else {
    wiki = { project: list[0] };
  }
  if (
    !ORESSupportedWiki.projects.includes(wiki.project)
  && !ORESSupportedWiki.languages.includes(wiki.language)
  ) {
    // wiki does not support ORES
    return;
  }
  let models;
  let suffix;
  if (wiki.project === 'wikidata') {
    suffix = 'wikidatawiki';
    models = 'itemquality';
  } else {
    suffix = `${wiki.language}wiki`;
    models = 'articlequality';
  }
  const API_URL = `https://ores.wikimedia.org/v3/scores/${suffix}`;
  const revids = revisions.filter(revision => revision.ns === 0).map(revision => `${revision.parentid}|${revision.revid}`);
  const chunks = chunk(revids, 25);

  const values = (await Promise.all(chunks.map((revid_chunk) => {
    // at max 10 requests at a time
    return limit(() => {
      const params = {
        revids: revid_chunk.join('|'),
        features: true,
        models
      };
      return queryUrl(`${API_URL}`, params).catch(() => undefined); // resolve to undefined if fails
    });
  }))).filter(item => item).map(data => data?.[suffix]?.scores);

  // merge the array of objects into one object
  const combinedObject = Object.assign({}, ...values);

  const referencesAdded = {};

  for (const revision of revisions) {
    const references = getReferencesCount(combinedObject?.[revision.revid], wiki.project === 'wikidata');
    if (references !== undefined) {
      referencesAdded[revision.revid] = references - (getReferencesCount(combinedObject?.[revision.parentid], wiki.project === 'wikidata') || 0);
    }
  }
  return referencesAdded;
};

export const fetchReferencesAdded = async (wikiMap) => {
  const referencesPromises = [];
  for (const [wiki_url, revisionsOfWiki] of wikiMap) {
    referencesPromises.push(fetchReferencesAddedFromWiki(wiki_url, revisionsOfWiki));
  }
  const resolvedValues = await Promise.all(referencesPromises);

  // merge array of objects into one object and return
  return Object.assign({}, ...resolvedValues);
};
<|endoftext|>


<commit_before>angular.module( 'moviematch.showmatch', [] )

  .controller( 'ShowmatchController', function( $scope, FetchMovies, Session, Auth, $routeParams ) {
    if (!Auth.isAuth()) {
      $location.path('/signin');
    } else {
      Session.getSession()
      .then( function( session ) {
        $scope.session = session;
      });
      $scope.user = {};
      $scope.user.name = Auth.getUserName();
      $scope.imgPath = 'http://image.tmdb.org/t/p/w500';

      $scope.currMovie = {};
      var id = parseInt( $routeParams.id );

      FetchMovies.getMovie( id )
      .then( function( movie ) {
        $scope.currMovie = movie;
      });
  }

  });
<commit_msg>show match requires auth too<commit_after>angular.module( 'moviematch.showmatch', [] )

  .controller( 'ShowmatchController', function( $scope, FetchMovies, Session, Auth, $routeParams, $location ) {
    if (!Auth.isAuth()) {
      $location.path('/signin');
    } else {
      Session.getSession()
      .then( function( session ) {
        $scope.session = session;
      });
      $scope.user = {};
      $scope.user.name = Auth.getUserName();
      $scope.imgPath = 'http://image.tmdb.org/t/p/w500';

      $scope.currMovie = {};
      var id = parseInt( $routeParams.id );

      FetchMovies.getMovie( id )
      .then( function( movie ) {
        $scope.currMovie = movie;
      });
  }

  });
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2012, Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
 */

/*global phantom, YSLOW*/
/*jslint browser: true, evil: true, sloppy: true, regexp: true*/

/**
 * JSLint is tolerating evil because there's a Function constructor needed to
 * inject the content coming from phantom arguments and page resources which is
 * later evaluated into the page in order to run YSlow.
 */

// For using yslow in phantomjs, see instructions @ https://github.com/marcelduran/yslow/wiki/PhantomJS

// parse args
var i, arg, page, urlCount, viewport,
    webpage = require('webpage'),
    args = phantom.args,
    len = args.length,
    urls = [],
    yslowArgs = {
        info: 'all',
        format: 'json',
        ruleset: 'ydefault',
        beacon: false,
        ua: false,
        viewport: false,
        headers: false,
        console: 0,
        threshold: 80
    },
    unaryArgs = {
        help: false,
        version: false,
        dict: false,
        verbose: false
    },
    argsAlias = {
        i: 'info',
        f: 'format',
        r: 'ruleset',
        h: 'help',
        V: 'version',
        d: 'dict',
        u: 'ua',
        vp: 'viewport',
        c: 'console',
        b: 'beacon',
        v: 'verbose',
        t: 'threshold',
        ch: 'headers'
    };

// loop args
for (i = 0; i < len; i += 1) {
    arg = args[i];
    if (arg[0] !== '-') {
        // url, normalize if needed
        if (arg.indexOf('http') !== 0) {
            arg = 'http://' + arg;
        }
        urls.push(arg);
    }
    arg = arg.replace(/^\-\-?/, '');
    if (yslowArgs.hasOwnProperty(arg)) {
        // yslow argument
        i += 1;
        yslowArgs[arg] = args[i];
    } else if (yslowArgs.hasOwnProperty(argsAlias[arg])) {
        // yslow argument alias
        i += 1;
        yslowArgs[argsAlias[arg]] = args[i];
    } else if (unaryArgs.hasOwnProperty(arg)) {
        // unary argument
        unaryArgs[arg] = true;
    } else if (unaryArgs.hasOwnProperty(argsAlias[arg])) {
        // unary argument alias
        unaryArgs[argsAlias[arg]] = true;
    }
}
urlCount = urls.length;

// check for version
if (unaryArgs.version) {
    console.log('{{YSLOW_VERSION}}');
    phantom.exit();
}

// print usage
if (len === 0 || urlCount === 0 || unaryArgs.help) {
    console.log([
        '',
        '  Usage: phantomjs [phantomjs options] ' + phantom.scriptName + ' [yslow options] [url ...]',
        '',
        '  PhantomJS Options:',
        '',
        '    http://y.ahoo.it/phantomjs/options',
        '',
        '  YSlow Options:',
        '',
        '    -h, --help               output usage information',
        '    -V, --version            output the version number',
        '    -i, --info <info>        specify the information to display/log (basic|grade|stats|comps|all) [all]',
        '    -f, --format <format>    specify the output results format (json|xml|plain|tap|junit) [json]',
        '    -r, --ruleset <ruleset>  specify the YSlow performance ruleset to be used (ydefault|yslow1|yblog) [ydefault]',
        '    -b, --beacon <url>       specify an URL to log the results',
        '    -d, --dict               include dictionary of results fields',
        '    -v, --verbose            output beacon response information',
        '    -t, --threshold <score>  for test formats, the threshold to test scores ([0-100]|[A-F]|{JSON}) [80]',
        '                             e.g.: -t B or -t 75 or -t \'{"overall": "B", "ycdn": "F", "yexpires": 85}\'',
        '    -u, --ua "<user agent>"  specify the user agent string sent to server when the page requests resources',
        '    -vp, --viewport <WxH>    specify page viewport size WxY, where W = width and H = height [400x300]',
        '    -ch, --headers <JSON>    specify custom request headers, e.g.: -ch \'{"Cookie": "foo=bar"}\'',
        '    -c, --console <level>    output page console messages (0: none, 1: message, 2: message + line + source) [0]',
        '',
        '  Examples:',
        '',
        '    phantomjs ' + phantom.scriptName + ' http://yslow.org',
        '    phantomjs ' + phantom.scriptName + ' -i grade -f xml www.yahoo.com www.cnn.com www.nytimes.com',
        '    phantomjs ' + phantom.scriptName + ' -info all --format plain --ua "MSIE 9.0" http://yslow.org',
        '    phantomjs ' + phantom.scriptName + ' -i basic --rulseset yslow1 -d http://yslow.org',
        '    phantomjs ' + phantom.scriptName + ' -i grade -b http://www.showslow.com/beacon/yslow/ -v yslow.org',
        '    phantomjs --load-plugins=yes ' + phantom.scriptName + ' -vp 800x600 http://www.yahoo.com',
        '    phantomjs ' + phantom.scriptName + ' -i grade -f tap -t 85 http://yslow.org',
        ''
    ].join('\n'));
    phantom.exit();
}

// set yslow unary args
yslowArgs.dict = unaryArgs.dict;
yslowArgs.verbose = unaryArgs.verbose;

// loop through urls
urls.forEach(function (url) {
    var page = webpage.create();

    page.resources = {};

    // allow x-domain requests, used to retrieve components content
    page.settings.webSecurityEnabled = false;

    // request
    page.onResourceRequested = function (req) {
        page.resources[req.url] = {
            request: req
        };
    };

    // response
    page.onResourceReceived = function (res) {
        var info,
            resp = page.resources[res.url].response;

        if (!resp) {
            page.resources[res.url].response = res;
        } else {
            for (info in res) {
                if (res.hasOwnProperty(info)) {
                    resp[info] = res[info];
                }
            }
        }
    };

    // enable console output, useful for debugging
    yslowArgs.console = parseInt(yslowArgs.console, 10) || 0;
    if (yslowArgs.console) {
        if (yslowArgs.console === 1) {
            page.onConsoleMessage = function (msg) {
                console.log(msg);
            };
        } else {
            page.onConsoleMessage = function (msg, line, source) {
                console.log(JSON.stringify({
                    message: msg,
                    lineNumber: line,
                    source: source
                }, null, 4));
            };
        }
    }

    // set user agent string
    if (yslowArgs.ua) {
        page.settings.userAgent = yslowArgs.ua;
    }

    // set page viewport
    if (yslowArgs.viewport) {
        viewport = yslowArgs.viewport.toLowerCase();
        page.viewportSize = {
            width: parseInt(viewport.slice(0, viewport.indexOf('x')), 10) ||
                page.viewportSize.width,
            height: parseInt(viewport.slice(viewport.indexOf('x') + 1), 10) ||
                page.viewportSize.height
        };
    }

    // set custom headers
    if (yslowArgs.headers) {
        try {
            page.customHeaders = JSON.parse(yslowArgs.headers);
        } catch (err) {
            console.log('Invalid custom headers: ' + err);
        }
    }

    // open page
    page.startTime = new Date();
    page.open(url, function (status) {
        var yslow, ysphantomjs, controller, evalFunc, loadTime, url, resp,
            startTime = page.startTime,
            resources = page.resources;

        if (status !== 'success') {
            console.log('FAIL to load ' + url);
        } else {
            // page load time
            loadTime = new Date() - startTime;

            // set resources response time
            for (url in resources) {
                if (resources.hasOwnProperty(url)) {
                    resp = resources[url].response;
                    if (resp) {
                        resp.time = new Date(resp.time) - startTime;
                    }
                }
            }

            // yslow wrapper to be evaluated by page
            yslow = function () {
                //YSLOW HERE
            };

            // serialize YSlow phantomjs object
            // resources, yslow args and page load time
            ysphantomjs = 'YSLOW.phantomjs = {' +
                'resources: ' + JSON.stringify(resources) + ',' +
                'args: ' + JSON.stringify(yslowArgs) + ',' +
                'loadTime: ' + JSON.stringify(loadTime) + '};';

            // YSlow phantomjs controller
            controller = function () {
                YSLOW.phantomjs.run = function () {
                    try {
                        var results, xhr, output, threshold,
                            doc = document,
                            ys = YSLOW,
                            yscontext = new ys.context(doc),
                            yspeeler = ys.peeler,
                            comps = yspeeler.peel(doc),
                            baseHref = yspeeler.getBaseHref(doc),
                            cset = new ys.ComponentSet(doc),
                            ysphantomjs = ys.phantomjs,
                            resources = ysphantomjs.resources,
                            args = ysphantomjs.args,
                            ysutil = ys.util,

                            // format out with appropriate content type
                            formatOutput = function (content) {
                                var format = (args.format || '').toLowerCase(),
                                    harness = {
                                        'tap': {
                                            func: ysutil.formatAsTAP,
                                            contentType: 'text/plain'
                                        },
                                        'junit': {
                                            func: ysutil.formatAsJUnit,
                                            contentType: 'text/xml'
                                        }
                                    };

                                switch (format) {
                                case 'xml':
                                    return {
                                        content: ysutil.objToXML(content),
                                        contentType: 'text/xml'
                                    };
                                case 'plain':
                                    return {
                                        content: ysutil.prettyPrintResults(
                                            content
                                        ),
                                        contentType: 'text/plain'
                                    };
                                // test formats
                                case 'tap':
                                case 'junit':
                                    try {
                                        threshold = JSON.parse(args.threshold);
                                    } catch (err) {
                                        threshold = args.threshold;
                                    }
                                    return {
                                        content: harness[format].func(
                                            ysutil.testResults(
                                                content,
                                                threshold
                                            )
                                        ),
                                        contentType: harness[format].contentType
                                    };
                                default:
                                    return {
                                        content: JSON.stringify(content),
                                        contentType: 'application/json'
                                    };
                                }
                            },

                            // format raw headers into object
                            formatHeaders = function (headers) {
                                var reHeader = /^([^:]+):\s*([\s\S]+)$/,
                                    reLineBreak = /[\n\r]/g,
                                    header = {};

                                headers.split('\n').forEach(function (h) {
                                    var m = reHeader.exec(
                                            h.replace(reLineBreak, '')
                                        );

                                    if (m) {
                                        header[m[1]] = m[2];
                                    }
                                });

                                return header;
                            };

                        comps.forEach(function (comp) {
                            var res = resources[comp.href] || {};

                            cset.addComponent(
                                comp.href,
                                comp.type,
                                comp.base || baseHref,
                                {
                                    obj: comp.obj,
                                    request: res.request,
                                    response: res.response
                                }
                            );
                        });

                        // refinement
                        cset.inline = ysutil.getInlineTags(doc);
                        cset.domElementsCount = ysutil.countDOMElements(doc);
                        cset.cookies = cset.doc_comp.cookie;
                        cset.components = ysutil.setInjected(doc,
                            cset.components, cset.doc_comp.body);

                        // run analysis
                        yscontext.component_set = cset;
                        ys.controller.lint(doc, yscontext, args.ruleset);
                        yscontext.result_set.url = baseHref;
                        yscontext.PAGE.t_done = ysphantomjs.loadTime;
                        yscontext.collectStats();
                        results = ysutil.getResults(yscontext, args.info);

                        // prepare output results
                        if (args.dict && args.format !== 'plain') {
                            results.dictionary = ysutil.getDict(args.info,
                                args.ruleset);
                        }
                        output = formatOutput(results);

                        // send beacon
                        if (args.beacon) {
                            try {
                                xhr = new XMLHttpRequest();
                                xhr.onreadystatechange = function () {
                                    // in verbose mode, include
                                    // beacon response info
                                    if (xhr.readyState === 4 && args.verbose) {
                                        results.beacon = {
                                            status: xhr.status,
                                            headers: formatHeaders(
                                                xhr.getAllResponseHeaders()
                                            ),
                                            body: xhr.responseText
                                        };
                                        output = formatOutput(results);
                                    }
                                };
                                xhr.open('POST', args.beacon, false);
                                xhr.setRequestHeader('Content-Type',
                                    output.contentType);
                                xhr.send(output.content);
                            } catch (xhrerr) {
                                // include error on beacon
                                if (args.verbose) {
                                    results.beacon = {
                                        error: xhrerr
                                    };
                                    output = formatOutput(results);
                                }
                            }
                        }

                        return output.content;
                    } catch (err) {
                        return err;
                    }
                };

                return YSLOW.phantomjs.run();
            };

            // serialize then combine:
            // YSlow + page resources + args + loadtime + controller
            yslow = yslow.toString();
            yslow = yslow.slice(13, yslow.length - 1);
            // minification removes last ';'
            if (yslow.slice(yslow.length - 1) !== ';') {
                yslow += ';';
            }
            controller = controller.toString();
            controller = controller.slice(13, controller.length - 1);
            evalFunc = new Function(yslow + ysphantomjs + controller);

            // evaluate script and log results
            console.log(page.evaluate(evalFunc));
        }

        // finish phantomjs
        urlCount -= 1;
        if (urlCount === 0) {
            phantom.exit();
        }
    });
});
<commit_msg>added onError handing for phantomjs to avoid page errors being passed through<commit_after>/**
 * Copyright (c) 2012, Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
 */

/*global phantom, YSLOW*/
/*jslint browser: true, evil: true, sloppy: true, regexp: true*/

/**
 * JSLint is tolerating evil because there's a Function constructor needed to
 * inject the content coming from phantom arguments and page resources which is
 * later evaluated into the page in order to run YSlow.
 */

// For using yslow in phantomjs, see instructions @ https://github.com/marcelduran/yslow/wiki/PhantomJS

// parse args
var i, arg, page, urlCount, viewport,
    webpage = require('webpage'),
    args = phantom.args,
    len = args.length,
    urls = [],
    yslowArgs = {
        info: 'all',
        format: 'json',
        ruleset: 'ydefault',
        beacon: false,
        ua: false,
        viewport: false,
        headers: false,
        console: 0,
        threshold: 80
    },
    unaryArgs = {
        help: false,
        version: false,
        dict: false,
        verbose: false
    },
    argsAlias = {
        i: 'info',
        f: 'format',
        r: 'ruleset',
        h: 'help',
        V: 'version',
        d: 'dict',
        u: 'ua',
        vp: 'viewport',
        c: 'console',
        b: 'beacon',
        v: 'verbose',
        t: 'threshold',
        ch: 'headers'
    };

// loop args
for (i = 0; i < len; i += 1) {
    arg = args[i];
    if (arg[0] !== '-') {
        // url, normalize if needed
        if (arg.indexOf('http') !== 0) {
            arg = 'http://' + arg;
        }
        urls.push(arg);
    }
    arg = arg.replace(/^\-\-?/, '');
    if (yslowArgs.hasOwnProperty(arg)) {
        // yslow argument
        i += 1;
        yslowArgs[arg] = args[i];
    } else if (yslowArgs.hasOwnProperty(argsAlias[arg])) {
        // yslow argument alias
        i += 1;
        yslowArgs[argsAlias[arg]] = args[i];
    } else if (unaryArgs.hasOwnProperty(arg)) {
        // unary argument
        unaryArgs[arg] = true;
    } else if (unaryArgs.hasOwnProperty(argsAlias[arg])) {
        // unary argument alias
        unaryArgs[argsAlias[arg]] = true;
    }
}
urlCount = urls.length;

// check for version
if (unaryArgs.version) {
    console.log('{{YSLOW_VERSION}}');
    phantom.exit();
}

// print usage
if (len === 0 || urlCount === 0 || unaryArgs.help) {
    console.log([
        '',
        '  Usage: phantomjs [phantomjs options] ' + phantom.scriptName + ' [yslow options] [url ...]',
        '',
        '  PhantomJS Options:',
        '',
        '    http://y.ahoo.it/phantomjs/options',
        '',
        '  YSlow Options:',
        '',
        '    -h, --help               output usage information',
        '    -V, --version            output the version number',
        '    -i, --info <info>        specify the information to display/log (basic|grade|stats|comps|all) [all]',
        '    -f, --format <format>    specify the output results format (json|xml|plain|tap|junit) [json]',
        '    -r, --ruleset <ruleset>  specify the YSlow performance ruleset to be used (ydefault|yslow1|yblog) [ydefault]',
        '    -b, --beacon <url>       specify an URL to log the results',
        '    -d, --dict               include dictionary of results fields',
        '    -v, --verbose            output beacon response information',
        '    -t, --threshold <score>  for test formats, the threshold to test scores ([0-100]|[A-F]|{JSON}) [80]',
        '                             e.g.: -t B or -t 75 or -t \'{"overall": "B", "ycdn": "F", "yexpires": 85}\'',
        '    -u, --ua "<user agent>"  specify the user agent string sent to server when the page requests resources',
        '    -vp, --viewport <WxH>    specify page viewport size WxY, where W = width and H = height [400x300]',
        '    -ch, --headers <JSON>    specify custom request headers, e.g.: -ch \'{"Cookie": "foo=bar"}\'',
        '    -c, --console <level>    output page console messages (0: none, 1: message, 2: message + line + source) [0]',
        '',
        '  Examples:',
        '',
        '    phantomjs ' + phantom.scriptName + ' http://yslow.org',
        '    phantomjs ' + phantom.scriptName + ' -i grade -f xml www.yahoo.com www.cnn.com www.nytimes.com',
        '    phantomjs ' + phantom.scriptName + ' -info all --format plain --ua "MSIE 9.0" http://yslow.org',
        '    phantomjs ' + phantom.scriptName + ' -i basic --rulseset yslow1 -d http://yslow.org',
        '    phantomjs ' + phantom.scriptName + ' -i grade -b http://www.showslow.com/beacon/yslow/ -v yslow.org',
        '    phantomjs --load-plugins=yes ' + phantom.scriptName + ' -vp 800x600 http://www.yahoo.com',
        '    phantomjs ' + phantom.scriptName + ' -i grade -f tap -t 85 http://yslow.org',
        ''
    ].join('\n'));
    phantom.exit();
}

// set yslow unary args
yslowArgs.dict = unaryArgs.dict;
yslowArgs.verbose = unaryArgs.verbose;

// loop through urls
urls.forEach(function (url) {
    var page = webpage.create();

    page.resources = {};

    // allow x-domain requests, used to retrieve components content
    page.settings.webSecurityEnabled = false;

    // request
    page.onResourceRequested = function (req) {
        page.resources[req.url] = {
            request: req
        };
    };

    // response
    page.onResourceReceived = function (res) {
        var info,
            resp = page.resources[res.url].response;

        if (!resp) {
            page.resources[res.url].response = res;
        } else {
            for (info in res) {
                if (res.hasOwnProperty(info)) {
                    resp[info] = res[info];
                }
            }
        }
    };

    // enable console output, useful for debugging
    yslowArgs.console = parseInt(yslowArgs.console, 10) || 0;
    if (yslowArgs.console) {
        if (yslowArgs.console === 1) {
            page.onConsoleMessage = function (msg) {
                console.log(msg);
            };
            page.onError = function (msg) {
                console.error(msg);
            };
        } else {
            page.onConsoleMessage = function (msg, line, source) {
                console.log(JSON.stringify({
                    message: msg,
                    lineNumber: line,
                    source: source
                }, null, 4));
            };
            page.onError = function (msg, trace) {
                console.error(JSON.stringify({
                    message: msg,
                    stacktrace: trace
                }));
            };
        }
    } else {
        page.onError = function () {
            // catch uncaught error from the page
        };
    }

    // set user agent string
    if (yslowArgs.ua) {
        page.settings.userAgent = yslowArgs.ua;
    }

    // set page viewport
    if (yslowArgs.viewport) {
        viewport = yslowArgs.viewport.toLowerCase();
        page.viewportSize = {
            width: parseInt(viewport.slice(0, viewport.indexOf('x')), 10) ||
                page.viewportSize.width,
            height: parseInt(viewport.slice(viewport.indexOf('x') + 1), 10) ||
                page.viewportSize.height
        };
    }

    // set custom headers
    if (yslowArgs.headers) {
        try {
            page.customHeaders = JSON.parse(yslowArgs.headers);
        } catch (err) {
            console.log('Invalid custom headers: ' + err);
        }
    }

    // open page
    page.startTime = new Date();
    page.open(url, function (status) {
        var yslow, ysphantomjs, controller, evalFunc, loadTime, url, resp,
            startTime = page.startTime,
            resources = page.resources;

        if (status !== 'success') {
            console.log('FAIL to load ' + url);
        } else {
            // page load time
            loadTime = new Date() - startTime;

            // set resources response time
            for (url in resources) {
                if (resources.hasOwnProperty(url)) {
                    resp = resources[url].response;
                    if (resp) {
                        resp.time = new Date(resp.time) - startTime;
                    }
                }
            }

            // yslow wrapper to be evaluated by page
            yslow = function () {
                //YSLOW HERE
            };

            // serialize YSlow phantomjs object
            // resources, yslow args and page load time
            ysphantomjs = 'YSLOW.phantomjs = {' +
                'resources: ' + JSON.stringify(resources) + ',' +
                'args: ' + JSON.stringify(yslowArgs) + ',' +
                'loadTime: ' + JSON.stringify(loadTime) + '};';

            // YSlow phantomjs controller
            controller = function () {
                YSLOW.phantomjs.run = function () {
                    try {
                        var results, xhr, output, threshold,
                            doc = document,
                            ys = YSLOW,
                            yscontext = new ys.context(doc),
                            yspeeler = ys.peeler,
                            comps = yspeeler.peel(doc),
                            baseHref = yspeeler.getBaseHref(doc),
                            cset = new ys.ComponentSet(doc),
                            ysphantomjs = ys.phantomjs,
                            resources = ysphantomjs.resources,
                            args = ysphantomjs.args,
                            ysutil = ys.util,

                            // format out with appropriate content type
                            formatOutput = function (content) {
                                var format = (args.format || '').toLowerCase(),
                                    harness = {
                                        'tap': {
                                            func: ysutil.formatAsTAP,
                                            contentType: 'text/plain'
                                        },
                                        'junit': {
                                            func: ysutil.formatAsJUnit,
                                            contentType: 'text/xml'
                                        }
                                    };

                                switch (format) {
                                case 'xml':
                                    return {
                                        content: ysutil.objToXML(content),
                                        contentType: 'text/xml'
                                    };
                                case 'plain':
                                    return {
                                        content: ysutil.prettyPrintResults(
                                            content
                                        ),
                                        contentType: 'text/plain'
                                    };
                                // test formats
                                case 'tap':
                                case 'junit':
                                    try {
                                        threshold = JSON.parse(args.threshold);
                                    } catch (err) {
                                        threshold = args.threshold;
                                    }
                                    return {
                                        content: harness[format].func(
                                            ysutil.testResults(
                                                content,
                                                threshold
                                            )
                                        ),
                                        contentType: harness[format].contentType
                                    };
                                default:
                                    return {
                                        content: JSON.stringify(content),
                                        contentType: 'application/json'
                                    };
                                }
                            },

                            // format raw headers into object
                            formatHeaders = function (headers) {
                                var reHeader = /^([^:]+):\s*([\s\S]+)$/,
                                    reLineBreak = /[\n\r]/g,
                                    header = {};

                                headers.split('\n').forEach(function (h) {
                                    var m = reHeader.exec(
                                            h.replace(reLineBreak, '')
                                        );

                                    if (m) {
                                        header[m[1]] = m[2];
                                    }
                                });

                                return header;
                            };

                        comps.forEach(function (comp) {
                            var res = resources[comp.href] || {};

                            cset.addComponent(
                                comp.href,
                                comp.type,
                                comp.base || baseHref,
                                {
                                    obj: comp.obj,
                                    request: res.request,
                                    response: res.response
                                }
                            );
                        });

                        // refinement
                        cset.inline = ysutil.getInlineTags(doc);
                        cset.domElementsCount = ysutil.countDOMElements(doc);
                        cset.cookies = cset.doc_comp.cookie;
                        cset.components = ysutil.setInjected(doc,
                            cset.components, cset.doc_comp.body);

                        // run analysis
                        yscontext.component_set = cset;
                        ys.controller.lint(doc, yscontext, args.ruleset);
                        yscontext.result_set.url = baseHref;
                        yscontext.PAGE.t_done = ysphantomjs.loadTime;
                        yscontext.collectStats();
                        results = ysutil.getResults(yscontext, args.info);

                        // prepare output results
                        if (args.dict && args.format !== 'plain') {
                            results.dictionary = ysutil.getDict(args.info,
                                args.ruleset);
                        }
                        output = formatOutput(results);

                        // send beacon
                        if (args.beacon) {
                            try {
                                xhr = new XMLHttpRequest();
                                xhr.onreadystatechange = function () {
                                    // in verbose mode, include
                                    // beacon response info
                                    if (xhr.readyState === 4 && args.verbose) {
                                        results.beacon = {
                                            status: xhr.status,
                                            headers: formatHeaders(
                                                xhr.getAllResponseHeaders()
                                            ),
                                            body: xhr.responseText
                                        };
                                        output = formatOutput(results);
                                    }
                                };
                                xhr.open('POST', args.beacon, false);
                                xhr.setRequestHeader('Content-Type',
                                    output.contentType);
                                xhr.send(output.content);
                            } catch (xhrerr) {
                                // include error on beacon
                                if (args.verbose) {
                                    results.beacon = {
                                        error: xhrerr
                                    };
                                    output = formatOutput(results);
                                }
                            }
                        }

                        return output.content;
                    } catch (err) {
                        return err;
                    }
                };

                return YSLOW.phantomjs.run();
            };

            // serialize then combine:
            // YSlow + page resources + args + loadtime + controller
            yslow = yslow.toString();
            yslow = yslow.slice(13, yslow.length - 1);
            // minification removes last ';'
            if (yslow.slice(yslow.length - 1) !== ';') {
                yslow += ';';
            }
            controller = controller.toString();
            controller = controller.slice(13, controller.length - 1);
            evalFunc = new Function(yslow + ysphantomjs + controller);

            // evaluate script and log results
            console.log(page.evaluate(evalFunc));
        }

        // finish phantomjs
        urlCount -= 1;
        if (urlCount === 0) {
            phantom.exit();
        }
    });
});
<|endoftext|>