<commit_before>var isJango = (window.location.hostname.toLowerCase().indexOf('jango') >= 0 ? true : false),
	isJangoPlayer = (isJango && $('#player_info').length ? true : false),
	scroblr;

if (!isJango || isJangoPlayer) {

	scroblr = (function () {

		var host = '',
			interval = '',
			song = {
				album: '',
				artist: 'undefined',
				duration: 0,
				elapsed: 0,
				host: host,
				image: '',
				loved: false,
				name: 'undefined',
				score: 50,
				stopped: false,
				tags: [],
				timestamp: null,
				url: '',
				url_album: '',
				url_artist: ''
			};

		function calculateDuration (timestring) {
			var seconds = 0;
			for (var i = 0, max = arguments.length; i < max; i += 1) {
				if (arguments[i].toString().length) {
					timeSegments = arguments[i].split(':');
					// Iterate over timeSegments in reverse calculating the number
					// of seconds represented by the seconds, minutes, and hours
					// fields.
					for (var j = timeSegments.length - 1, pow = 0; (j >= 0) && (j >= (timeSegments.length - 3)); j -= 1, pow += 1) {
						seconds += parseFloat(timeSegments[j].replace('-', '')) * Math.pow(60, pow);
					}
				}
			}
			return seconds * 1000;
		}

		function getCurrentSongInfo () {
			var currentsong = {
					album: '',
					artist: '',
					duration: 0,
					elapsed: 0,
					host: host,
					image: '',
					loved: false,
					name: '',
					score: 50,
					stopped: false,
					tags: [],
					timestamp: Math.round((new Date()).getTime() / 1000.0),
					url: '',
					url_album: '',
					url_artist: ''
				},
				scrape = {

					accuradio: function () {
						return {
							album: $('#span_information_album').text(),
							artist: $('#span_information_artist').text(),
							name: $('#span_information_title').text(),
							stopped: $('#player_lowest_controls_wrapper #play').length ? true : false
						};
					},

					amazon: function () {
						return {
							artist: $('#nowPlayingSection .currentSongDetails .title').next().text().substring(3),
							duration: calculateDuration($('#nowPlayingSection .currentSongStatus #currentTime').next().next().text()),
							name: $('#nowPlayingSection .currentSongDetails .title').text(),
							stopped: $('#mp3Player .mp3Player-MasterControl .mp3MasterPlayGroup').hasClass('paused')
						};
					},

					bandcamp: function () {
						var discover, info;

						discover = (window.location.pathname.slice(1) === "discover" ? true : false);
						info = {
							stopped: (!$('.inline_player .playbutton').hasClass('playing'))
						};

						if (!info.stopped) {
							if (discover) {
								info.artist = $("#detail_body_container .itemsubtext a").text();
							} else {
								info.artist = $('span[itemprop="byArtist"]').text();
							}
							info.name = $('.track_info .title').first().text();
							info.duration = calculateDuration($('.inline_player .track_info .time_total').text());
							info.elapsed = calculateDuration($('.inline_player .track_info .time_elapsed').text());

							if (info.name === '') {
								info.name = $('.trackTitle').first().text();
							}
						}
						return info;
					},

					google: function () {
						return {
							artist: $('#playerArtist .fade-out-content').attr('title'),
							duration: calculateDuration($('#duration').text()),
							name: $('#playerSongTitle .fade-out-content').attr('title'),
							stopped: ($('#playPause').attr('title') == 'Play')
						};
					},

					grooveshark: function () {
						return {
							album: $('#playerDetails_nowPlaying .album').attr('title'),
							artist: $('#playerDetails_nowPlaying .artist').attr('title'),
							duration: calculateDuration($('#player #player_duration').text()),
							name: $('#playerDetails_nowPlaying .currentSongLink').attr('title'),
							stopped: $('#player #player_play_pause').hasClass('play')
						};
					},

					jango: function () {
						return {
							artist: $('#player_info #player_current_artist').contents().last().text(),
							duration: calculateDuration($('#player_info #timer').text().substring(1)),
							name: $('#player_info #current-song').text().replace(/^\s+/, '').replace(/\s+$/, ''),
							stopped: $('#btn-playpause').hasClass('pause')
						};
					},

					pandora: function () {
						function stripChildrensLabel (string) {
							return string.replace(/\s+\(Children's\)$/i, '');
						}
						function stripHolidayLabel (string) {
							return string.replace(/\s+\(Holiday\)$/i, '');
						}
						function cleanseArtist (string) {
							var artist = stripChildrensLabel(string);
							return stripHolidayLabel(artist);
						}
						return {
							album: $('#playerBar .playerBarAlbum').text(),
							artist: cleanseArtist($('#playerBar .playerBarArtist').text()),
							duration: calculateDuration($('#playbackControl .elapsedTime').text(), $('#playbackControl .remainingTime').text()),
							elapsed: calculateDuration($('#playbackControl .elapsedTime').text()),
							name: $('#playerBar .playerBarSong').text(),
							stopped: $('#playerBar .playButton').is(':visible')
						};
					},

					playerfm: function() {

						var elapsedString       = $('.permaplayer .current .play-monitor .time-elapsed').text();
						var timeRemainingString = $('.permaplayer .current .play-monitor .time-remaining').text();

						return {
							artist:   $('.permaplayer .track-wrapper .current-series-link').text(),
							name:     $('.permaplayer .track-wrapper .current-episode-link').text(),
							elapsed:  calculateDuration(elapsedString),
							duration: calculateDuration(elapsedString, timeRemainingString),
							stopped:  $('.container .mainflow .playpause .icon-play').is(':visible')
						};
					},

					rhapsody: function () {
						return {
							artist: $('#player-artist-link').text(),
							duration: calculateDuration($('#player-total-time').text()),
							elapsed: calculateDuration($('#player-current-time').text()),
							name: $('#player-track-link').text(),
							stopped: ($('#player-play').css('display') == 'block')
						};
					},

					songza: function () {
						return {
							artist: $('#player .szi-roll-song .szi-info .szi-artist').text(),
							name: $('#player .szi-roll-song .szi-info .szi-title').text(),
							percent: parseFloat($('#player .szi-progress .szi-bar').width() / $('#player .szi-progress').width()),
							stopped: ($('#player .sz-player-state-pause').length > 0)
						};
					},

					soundcloud: function() {
						var soundcloudNext = $('body > #app').length > 0;

						if (soundcloudNext) {
							var playing = $('.sc-button-play.sc-button-pause'),
									info = {
										stopped: (playing.length == 0)
									};

							if (!info.stopped) {
								var player = playing.parents('.sound');

								info.artist = player.find('.soundTitle__username').text();
								info.duration = calculateDuration(player.find('.timeIndicator__total').text().replace('.', ':'));
								info.elapsed = calculateDuration(player.find('.timeIndicator__current').text().replace('.', ':'));
								info.name = player.find('.soundTitle__title').text();
							}
							return info;
						}
						else {
							var playing = $('.play.playing'),
								info = {
									stopped: (playing.length == 0)
								};

							if (!info.stopped) {
								var player = playing.parents('div.player');

								info.artist = player.find('.user-name').text();
								info.duration = calculateDuration(player.find('.timecodes span:last').text().replace('.', ':'));
								info.elapsed = calculateDuration(player.find('.timecodes span:first').text().replace('.', ':'));
								info.name = player.find('h3 a').text();
							}
							return info;
						}
					},

					thisismyjam: function () {
						var info = {
								stopped: $('#playPause').hasClass('paused')
							};
						if (!info.stopped) {
							info.artist = $('#artist-name').text();
							info.duration = calculateDuration($('#totalTime').text().substring(3));
							info.elapsed = calculateDuration($('#currentTime').text());
							info.name = $('#track-title').text();
						}
						return info;
					},

					turntable: function () {
						var info = {};
						if ($('#songboard_artist').text().length) {
							info.artist = $('#room-info-tab .song:first-child .details div:first-child').text().split(' - ');
							info.duration = calculateDuration(info.artist.pop());
							info.artist = info.artist.join(' - ');
							info.name = $('#room-info-tab .song:first-child .title').text();
							info.score = parseFloat($('#room-info-tab .song:first-child .details div.score').text().replace(/[^0-9]+/g, ''));
						}
						return info;
					},

					twonky: function () {
						if ($('.meta_title').text().length) {
							return {
								album: $('.meta_album').text(),
								artist: $('.meta_artist').text(),
								duration: calculateDuration($('.meta_duration').text()),
								name: $('.meta_title').text(),
								stopped: $('.trackPlayerButtonIcon').hasClass('play')
							};
						}
					},

					we7: function () {
						return {
							artist: $('#track-marquee #track-title a').eq(0).text(),
							name: $('#track-marquee #track-title a').eq(1).text(),
							duration: calculateDuration($('#elapsed').text(), $('#remaining').text()),
							elapsed: calculateDuration($('#elapsed').text())
						};
					}

				};

			return $.extend(currentsong, scrape[host]());

		}

		function getElapsedTime (data) {
			var elapsed = data.elapsed;
			if (elapsed === 0) {
				var now = (new Date()).getTime() / 1000.0;
				elapsed = Math.round(now - song.timestamp) * 1000;
			}
			return elapsed;
		}

		function getHost () {

			var host, hostname;

			host = false;
			hostname = window.location.hostname.toLowerCase();

			if (hostname.indexOf('accuradio') >= 0) {
				host = 'accuradio';
			}
			else if (hostname.indexOf('amazon') >= 0 && window.location.pathname.indexOf('music') >= 0) {
				host = 'amazon';
			}
			else if (hostname.indexOf('bandcamp') >= 0) {
				host = 'bandcamp';
			}
			else if (hostname.indexOf('google') >= 0) {
				host = 'google';
			}
			else if (hostname.indexOf('grooveshark') >= 0) {
				host = 'grooveshark';
			}
			else if (hostname.indexOf('jango') >= 0) {
				host = 'jango';
			}
			else if (hostname.indexOf('pandora') >= 0) {
				host = 'pandora';
			}
			else if (hostname.indexOf('player.fm') >= 0) {
				host = 'playerfm';
			}
			else if (hostname.indexOf('rhapsody') >= 0 || hostname.indexOf('napster') >= 0) {
				if ($('#container').length) {
					host = 'rhapsody';
				}
			}
			else if (hostname.indexOf('songza') >= 0) {
				if ($('#player').length) {
					host = 'songza';
				}
			}
			else if (hostname.indexOf('soundcloud') >= 0) {
				host = 'soundcloud';
			}
			else if (hostname.indexOf('thisismyjam') >= 0) {
				host = 'thisismyjam';
			}
			else if (hostname.indexOf('turntable') >= 0) {
				host = 'turntable';
			}
			else if (hostname.indexOf('twonky') >= 0) {
				if ($('body.musicDashboard').length) {
					host = 'twonky';
				}
			}
			else if (hostname.indexOf('we7') >= 0) {
				if ($('#player-section').length) {
					host = 'we7';
				}
			}
			return host;
		}

		function init () {
			host = getHost();
			if (host === false) {
				return false;
			}
			interval = window.setInterval(pollSongInfo, 5000);
		}

		function pollSongInfo () {
			var currentsong = getCurrentSongInfo(),
				currentsong_update_object = {};

			currentsong.album = $.trim(currentsong.album);
			currentsong.artist = $.trim(currentsong.artist);
			currentsong.name = $.trim(currentsong.name);

			if (currentsong.name != song.name || currentsong.artist != song.artist) {
				song = currentsong;
				sendMessage('nowPlaying', song);
			}
			else if (currentsong.name.length && currentsong.artist.length) {
				if (currentsong.hasOwnProperty('percent') && currentsong.duration === 0) {
					currentsong.duration = Math.round((currentsong.timestamp * 1000 - song.timestamp * 1000) / currentsong.percent);
					currentsong.elapsed = Math.round(currentsong.duration * currentsong.percent);
				}
				if (currentsong.duration > song.duration || song.duration - currentsong.duration > 200000) {
					currentsong_update_object.duration = song.duration = currentsong.duration;
				}
				if (currentsong.score != song.score) {
					currentsong_update_object.score = song.score = currentsong.score;
				}
				currentsong_update_object.elapsed = song.elapsed = getElapsedTime(currentsong);
				sendMessage('updateCurrentSong', currentsong_update_object);
			}
			sendMessage('keepAlive', null);
		}

		function sendMessage (name, message) {
			if (typeof chrome != 'undefined') {
				chrome.extension.sendMessage({
					name: name,
					message: message
				});
			}
			else if (typeof safari != 'undefined') {
				safari.self.tab.dispatchMessage(name, message);
			}
		}

		// Initialize on document ready
		$(function () {
			init();
		});

		return {
			getCurrentSongInfo: getCurrentSongInfo
		};

	}());

}

<commit_msg>FIxed issue that caused Jango to not properly scrobble the artist correctly.<commit_after>var isJango = (window.location.hostname.toLowerCase().indexOf('jango') >= 0 ? true : false),
	isJangoPlayer = (isJango && $('#player_info').length ? true : false),
	scroblr;

if (!isJango || isJangoPlayer) {

	scroblr = (function () {

		var host = '',
			interval = '',
			song = {
				album: '',
				artist: 'undefined',
				duration: 0,
				elapsed: 0,
				host: host,
				image: '',
				loved: false,
				name: 'undefined',
				score: 50,
				stopped: false,
				tags: [],
				timestamp: null,
				url: '',
				url_album: '',
				url_artist: ''
			};

		function calculateDuration (timestring) {
			var seconds = 0;
			for (var i = 0, max = arguments.length; i < max; i += 1) {
				if (arguments[i].toString().length) {
					timeSegments = arguments[i].split(':');
					// Iterate over timeSegments in reverse calculating the number
					// of seconds represented by the seconds, minutes, and hours
					// fields.
					for (var j = timeSegments.length - 1, pow = 0; (j >= 0) && (j >= (timeSegments.length - 3)); j -= 1, pow += 1) {
						seconds += parseFloat(timeSegments[j].replace('-', '')) * Math.pow(60, pow);
					}
				}
			}
			return seconds * 1000;
		}

		function getCurrentSongInfo () {
			var currentsong = {
					album: '',
					artist: '',
					duration: 0,
					elapsed: 0,
					host: host,
					image: '',
					loved: false,
					name: '',
					score: 50,
					stopped: false,
					tags: [],
					timestamp: Math.round((new Date()).getTime() / 1000.0),
					url: '',
					url_album: '',
					url_artist: ''
				},
				scrape = {

					accuradio: function () {
						return {
							album: $('#span_information_album').text(),
							artist: $('#span_information_artist').text(),
							name: $('#span_information_title').text(),
							stopped: $('#player_lowest_controls_wrapper #play').length ? true : false
						};
					},

					amazon: function () {
						return {
							artist: $('#nowPlayingSection .currentSongDetails .title').next().text().substring(3),
							duration: calculateDuration($('#nowPlayingSection .currentSongStatus #currentTime').next().next().text()),
							name: $('#nowPlayingSection .currentSongDetails .title').text(),
							stopped: $('#mp3Player .mp3Player-MasterControl .mp3MasterPlayGroup').hasClass('paused')
						};
					},

					bandcamp: function () {
						var discover, info;

						discover = (window.location.pathname.slice(1) === "discover" ? true : false);
						info = {
							stopped: (!$('.inline_player .playbutton').hasClass('playing'))
						};

						if (!info.stopped) {
							if (discover) {
								info.artist = $("#detail_body_container .itemsubtext a").text();
							} else {
								info.artist = $('span[itemprop="byArtist"]').text();
							}
							info.name = $('.track_info .title').first().text();
							info.duration = calculateDuration($('.inline_player .track_info .time_total').text());
							info.elapsed = calculateDuration($('.inline_player .track_info .time_elapsed').text());

							if (info.name === '') {
								info.name = $('.trackTitle').first().text();
							}
						}
						return info;
					},

					google: function () {
						return {
							artist: $('#playerArtist .fade-out-content').attr('title'),
							duration: calculateDuration($('#duration').text()),
							name: $('#playerSongTitle .fade-out-content').attr('title'),
							stopped: ($('#playPause').attr('title') == 'Play')
						};
					},

					grooveshark: function () {
						return {
							album: $('#playerDetails_nowPlaying .album').attr('title'),
							artist: $('#playerDetails_nowPlaying .artist').attr('title'),
							duration: calculateDuration($('#player #player_duration').text()),
							name: $('#playerDetails_nowPlaying .currentSongLink').attr('title'),
							stopped: $('#player #player_play_pause').hasClass('play')
						};
					},

					jango: function () {
						var artist = $("#player_info #player_current_artist").contents().not($("span")).eq(0).text();

						if (artist.indexOf(String.fromCharCode(8230)) >= 0) {
							artist = document.title.split(":")[0];
						}

						return {
							artist: artist,
							duration: calculateDuration($('#player_info #timer').text().substring(1)),
							name: $('#player_info #current-song').text().replace(/^\s+/, '').replace(/\s+$/, ''),
							stopped: $('#btn-playpause').hasClass('pause')
						};
					},

					pandora: function () {
						function stripChildrensLabel (string) {
							return string.replace(/\s+\(Children's\)$/i, '');
						}
						function stripHolidayLabel (string) {
							return string.replace(/\s+\(Holiday\)$/i, '');
						}
						function cleanseArtist (string) {
							var artist = stripChildrensLabel(string);
							return stripHolidayLabel(artist);
						}
						return {
							album: $('#playerBar .playerBarAlbum').text(),
							artist: cleanseArtist($('#playerBar .playerBarArtist').text()),
							duration: calculateDuration($('#playbackControl .elapsedTime').text(), $('#playbackControl .remainingTime').text()),
							elapsed: calculateDuration($('#playbackControl .elapsedTime').text()),
							name: $('#playerBar .playerBarSong').text(),
							stopped: $('#playerBar .playButton').is(':visible')
						};
					},

					playerfm: function() {

						var elapsedString       = $('.permaplayer .current .play-monitor .time-elapsed').text();
						var timeRemainingString = $('.permaplayer .current .play-monitor .time-remaining').text();

						return {
							artist:   $('.permaplayer .track-wrapper .current-series-link').text(),
							name:     $('.permaplayer .track-wrapper .current-episode-link').text(),
							elapsed:  calculateDuration(elapsedString),
							duration: calculateDuration(elapsedString, timeRemainingString),
							stopped:  $('.container .mainflow .playpause .icon-play').is(':visible')
						};
					},

					rhapsody: function () {
						return {
							artist: $('#player-artist-link').text(),
							duration: calculateDuration($('#player-total-time').text()),
							elapsed: calculateDuration($('#player-current-time').text()),
							name: $('#player-track-link').text(),
							stopped: ($('#player-play').css('display') == 'block')
						};
					},

					songza: function () {
						return {
							artist: $('#player .szi-roll-song .szi-info .szi-artist').text(),
							name: $('#player .szi-roll-song .szi-info .szi-title').text(),
							percent: parseFloat($('#player .szi-progress .szi-bar').width() / $('#player .szi-progress').width()),
							stopped: ($('#player .sz-player-state-pause').length > 0)
						};
					},

					soundcloud: function() {
						var soundcloudNext = $('body > #app').length > 0;

						if (soundcloudNext) {
							var playing = $('.sc-button-play.sc-button-pause'),
									info = {
										stopped: (playing.length == 0)
									};

							if (!info.stopped) {
								var player = playing.parents('.sound');

								info.artist = player.find('.soundTitle__username').text();
								info.duration = calculateDuration(player.find('.timeIndicator__total').text().replace('.', ':'));
								info.elapsed = calculateDuration(player.find('.timeIndicator__current').text().replace('.', ':'));
								info.name = player.find('.soundTitle__title').text();
							}
							return info;
						}
						else {
							var playing = $('.play.playing'),
								info = {
									stopped: (playing.length == 0)
								};

							if (!info.stopped) {
								var player = playing.parents('div.player');

								info.artist = player.find('.user-name').text();
								info.duration = calculateDuration(player.find('.timecodes span:last').text().replace('.', ':'));
								info.elapsed = calculateDuration(player.find('.timecodes span:first').text().replace('.', ':'));
								info.name = player.find('h3 a').text();
							}
							return info;
						}
					},

					thisismyjam: function () {
						var info = {
								stopped: $('#playPause').hasClass('paused')
							};
						if (!info.stopped) {
							info.artist = $('#artist-name').text();
							info.duration = calculateDuration($('#totalTime').text().substring(3));
							info.elapsed = calculateDuration($('#currentTime').text());
							info.name = $('#track-title').text();
						}
						return info;
					},

					turntable: function () {
						var info = {};
						if ($('#songboard_artist').text().length) {
							info.artist = $('#room-info-tab .song:first-child .details div:first-child').text().split(' - ');
							info.duration = calculateDuration(info.artist.pop());
							info.artist = info.artist.join(' - ');
							info.name = $('#room-info-tab .song:first-child .title').text();
							info.score = parseFloat($('#room-info-tab .song:first-child .details div.score').text().replace(/[^0-9]+/g, ''));
						}
						return info;
					},

					twonky: function () {
						if ($('.meta_title').text().length) {
							return {
								album: $('.meta_album').text(),
								artist: $('.meta_artist').text(),
								duration: calculateDuration($('.meta_duration').text()),
								name: $('.meta_title').text(),
								stopped: $('.trackPlayerButtonIcon').hasClass('play')
							};
						}
					},

					we7: function () {
						return {
							artist: $('#track-marquee #track-title a').eq(0).text(),
							name: $('#track-marquee #track-title a').eq(1).text(),
							duration: calculateDuration($('#elapsed').text(), $('#remaining').text()),
							elapsed: calculateDuration($('#elapsed').text())
						};
					}

				};

			return $.extend(currentsong, scrape[host]());

		}

		function getElapsedTime (data) {
			var elapsed = data.elapsed;
			if (elapsed === 0) {
				var now = (new Date()).getTime() / 1000.0;
				elapsed = Math.round(now - song.timestamp) * 1000;
			}
			return elapsed;
		}

		function getHost () {

			var host, hostname;

			host = false;
			hostname = window.location.hostname.toLowerCase();

			if (hostname.indexOf('accuradio') >= 0) {
				host = 'accuradio';
			}
			else if (hostname.indexOf('amazon') >= 0 && window.location.pathname.indexOf('music') >= 0) {
				host = 'amazon';
			}
			else if (hostname.indexOf('bandcamp') >= 0) {
				host = 'bandcamp';
			}
			else if (hostname.indexOf('google') >= 0) {
				host = 'google';
			}
			else if (hostname.indexOf('grooveshark') >= 0) {
				host = 'grooveshark';
			}
			else if (hostname.indexOf('jango') >= 0) {
				host = 'jango';
			}
			else if (hostname.indexOf('pandora') >= 0) {
				host = 'pandora';
			}
			else if (hostname.indexOf('player.fm') >= 0) {
				host = 'playerfm';
			}
			else if (hostname.indexOf('rhapsody') >= 0 || hostname.indexOf('napster') >= 0) {
				if ($('#container').length) {
					host = 'rhapsody';
				}
			}
			else if (hostname.indexOf('songza') >= 0) {
				if ($('#player').length) {
					host = 'songza';
				}
			}
			else if (hostname.indexOf('soundcloud') >= 0) {
				host = 'soundcloud';
			}
			else if (hostname.indexOf('thisismyjam') >= 0) {
				host = 'thisismyjam';
			}
			else if (hostname.indexOf('turntable') >= 0) {
				host = 'turntable';
			}
			else if (hostname.indexOf('twonky') >= 0) {
				if ($('body.musicDashboard').length) {
					host = 'twonky';
				}
			}
			else if (hostname.indexOf('we7') >= 0) {
				if ($('#player-section').length) {
					host = 'we7';
				}
			}
			return host;
		}

		function init () {
			host = getHost();
			if (host === false) {
				return false;
			}
			interval = window.setInterval(pollSongInfo, 5000);
		}

		function pollSongInfo () {
			var currentsong = getCurrentSongInfo(),
				currentsong_update_object = {};

			currentsong.album = $.trim(currentsong.album);
			currentsong.artist = $.trim(currentsong.artist);
			currentsong.name = $.trim(currentsong.name);

			if (currentsong.name != song.name || currentsong.artist != song.artist) {
				song = currentsong;
				sendMessage('nowPlaying', song);
			}
			else if (currentsong.name.length && currentsong.artist.length) {
				if (currentsong.hasOwnProperty('percent') && currentsong.duration === 0) {
					currentsong.duration = Math.round((currentsong.timestamp * 1000 - song.timestamp * 1000) / currentsong.percent);
					currentsong.elapsed = Math.round(currentsong.duration * currentsong.percent);
				}
				if (currentsong.duration > song.duration || song.duration - currentsong.duration > 200000) {
					currentsong_update_object.duration = song.duration = currentsong.duration;
				}
				if (currentsong.score != song.score) {
					currentsong_update_object.score = song.score = currentsong.score;
				}
				currentsong_update_object.elapsed = song.elapsed = getElapsedTime(currentsong);
				sendMessage('updateCurrentSong', currentsong_update_object);
			}
			sendMessage('keepAlive', null);
		}

		function sendMessage (name, message) {
			if (typeof chrome != 'undefined') {
				chrome.extension.sendMessage({
					name: name,
					message: message
				});
			}
			else if (typeof safari != 'undefined') {
				safari.self.tab.dispatchMessage(name, message);
			}
		}

		// Initialize on document ready
		$(function () {
			init();
		});

		return {
			getCurrentSongInfo: getCurrentSongInfo
		};

	}());

}

<|endoftext|>


<commit_before>Router.configure({
  layoutTemplate: 'layout'
});

Router.map(function() {
  this.route('index', {
    path: '/'
   //  onBeforeAction: function(){
   //    if(!Meteor.remote.userId()){
   //      Router.go('authentication');
   //    }
   //    this.next();
   // }
  });
  this.route('authentication', {
    path: '/login',
    waitOn: function() {
      Meteor.remote.subscribe('user');
      Meteor.subscribe('users');
    },
    fastRender: true
  });
  this.route('television', {
    path: '/rede-meionorte',
    /*waitOn: function() {
      Meteor.remote.subscribe('program');
      Meteor.remote.subscribe('category');
      Meteor.remote.subscribe('content');
      Meteor.remote.subscribe('user');
      Meteor.remote.subscribe('answer');
      Meteor.remote.subscribe('poll');
      Meteor.remote.subscribe('polluser');
    },*/
    fastRender: true
  });
  this.route('programation', {path: '/rede-meionorte/programacao'});
  this.route('tabs.timeline', {path: '/rede-meionorte/timeline/:_id', layoutTemplate: 'tabsInteraction'});
  this.route('tabs.polls', {path: '/rede-meionorte/enquete/:_id', layoutTemplate: 'tabsInteraction'});
});

Meteor.startup(function () {

  if (Meteor.isClient) {

    var location = Iron.Location.get();
    if (location.queryObject.platformOverride) {
      Session.set('platformOverride', location.queryObject.platformOverride);
    }
    if ('addEventListener' in document) {
      document.addEventListener('DOMContentLoaded', function() {
          FastClick.attach(document.body);
      }, false);
    }
    var WebFontConfig = {
      google: { families: [ 'Roboto:400,300,500,700:latin' ] }
    };
    (function() {
      var wf = document.createElement('script');
      wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
      '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
      wf.type = 'text/javascript';
      wf.async = 'true';
      var s = document.getElementsByTagName('script')[0];
      s.parentNode.insertBefore(wf, s);
    })();

  }

});
<commit_msg>router<commit_after>Router.configure({
  layoutTemplate: 'layout',
     onBeforeAction: function(){
       if(!Meteor.remote.userId()){
         Router.go('authentication');
       }
       this.next();
    }
});

Router.map(function() {
  this.route('index', {
    path: '/'
  });
  this.route('authentication', {
    path: '/login',
    /*waitOn: function() {
      Meteor.remote.subscribe('user');
      Meteor.subscribe('users');
    },*/
    fastRender: true
  });
  this.route('television', {
    path: '/rede-meionorte',
    /*waitOn: function() {
      Meteor.remote.subscribe('program');
      Meteor.remote.subscribe('category');
      Meteor.remote.subscribe('content');
      Meteor.remote.subscribe('user');
      Meteor.remote.subscribe('answer');
      Meteor.remote.subscribe('poll');
      Meteor.remote.subscribe('polluser');
    },*/
    fastRender: true,
     onBeforeAction: function(){
       if(!Meteor.remote.userId()){
         Router.go('authentication');
       }
       this.next();
    }
  });
  this.route('programation', {path: '/rede-meionorte/programacao'});
  this.route('tabs.timeline', {path: '/rede-meionorte/timeline/:_id', layoutTemplate: 'tabsInteraction'});
  this.route('tabs.polls', {path: '/rede-meionorte/enquete/:_id', layoutTemplate: 'tabsInteraction'});
});

Meteor.startup(function () {

  if (Meteor.isClient) {

    var location = Iron.Location.get();
    if (location.queryObject.platformOverride) {
      Session.set('platformOverride', location.queryObject.platformOverride);
    }
    if ('addEventListener' in document) {
      document.addEventListener('DOMContentLoaded', function() {
          FastClick.attach(document.body);
      }, false);
    }
    var WebFontConfig = {
      google: { families: [ 'Roboto:400,300,500,700:latin' ] }
    };
    (function() {
      var wf = document.createElement('script');
      wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
      '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
      wf.type = 'text/javascript';
      wf.async = 'true';
      var s = document.getElementsByTagName('script')[0];
      s.parentNode.insertBefore(wf, s);
    })();

  }

});
<|endoftext|>


<commit_before>var gulp = require('gulp');
var vulcanize = require('gulp-vulcanize');
var crisper = require('gulp-crisper');
var clean = require('gulp-clean');
var runSequence = require('run-sequence');
var htmlreplace = require('gulp-html-replace');

gulp.task('vulcanize', function() {
  return gulp.src('dist/elements.html')
    .pipe(vulcanize())
    .pipe(crisper())
    .pipe(gulp.dest('dist/files'));
  });

gulp.task('move-webcomponentsjs', function () {
  return gulp.src(['dist/bower_components/webcomponentsjs/webcomponents-lite.min.js']).pipe(gulp.dest('dist/files'));
});

gulp.task('move-font-awesome', function () {
  return gulp.src(['bower_components/font-awesome/css/font-awesome.min.css']).pipe(gulp.dest('dist/files'));
});

gulp.task('clean-elements-html', function () {
  return gulp.src('dist/elements.html')
    .pipe(clean({force: true}));
});

gulp.task('clean-bower-components', function () {
  return gulp.src('dist/bower_components', {read: false})
    .pipe(clean());
});

gulp.task('move-elements', function () {
  return gulp.src(['dist/files/**']).pipe(gulp.dest('dist'));
});

gulp.task('clean-elements', function () {
   return gulp.src('dist/files', {read: false})
    .pipe(clean());
});

gulp.task('copy-polymer-dependencies', function() {
  gulp.src('dist/index.html')
    .pipe(htmlreplace({
        'css': 'font-awesome.min.css',
        'js': 'elements.js',
        'webcomponents': 'webcomponents-lite.min.js'
    }))
    .pipe(gulp.dest('dist/'));
});

gulp.task('default', function(callback) {
  runSequence('vulcanize', ['move-webcomponentsjs', 'move-font-awesome'], ['clean-elements-html', 'clean-bower-components'], 'move-elements', 'clean-elements', 'copy-polymer-dependencies',
              callback);
});<commit_msg>add font-awesome<commit_after>var gulp = require('gulp');
var vulcanize = require('gulp-vulcanize');
var crisper = require('gulp-crisper');
var clean = require('gulp-clean');
var runSequence = require('run-sequence');
var htmlreplace = require('gulp-html-replace');

gulp.task('vulcanize', function() {
  return gulp.src('dist/elements.html')
    .pipe(vulcanize())
    .pipe(crisper())
    .pipe(gulp.dest('dist/files'));
  });

gulp.task('move-webcomponentsjs', function () {
  return gulp.src(['dist/bower_components/webcomponentsjs/webcomponents-lite.min.js']).pipe(gulp.dest('dist/files'));
});

gulp.task('move-font-awesome', function () {
  return gulp.src(['dist/bower_components/font-awesome/css/font-awesome.min.css']).pipe(gulp.dest('dist/files'));
});

gulp.task('clean-elements-html', function () {
  return gulp.src('dist/elements.html')
    .pipe(clean({force: true}));
});

gulp.task('clean-bower-components', function () {
  return gulp.src('dist/bower_components', {read: false})
    .pipe(clean());
});

gulp.task('move-elements', function () {
  return gulp.src(['dist/files/**']).pipe(gulp.dest('dist'));
});

gulp.task('clean-elements', function () {
   return gulp.src('dist/files', {read: false})
    .pipe(clean());
});

gulp.task('copy-polymer-dependencies', function() {
  gulp.src('dist/index.html')
    .pipe(htmlreplace({
        'css': 'font-awesome.min.css',
        'js': 'elements.js',
        'webcomponents': 'webcomponents-lite.min.js'
    }))
    .pipe(gulp.dest('dist/'));
});

gulp.task('default', function(callback) {
  runSequence('vulcanize', ['move-webcomponentsjs', 'move-font-awesome'], ['clean-elements-html', 'clean-bower-components'], 'move-elements', 'clean-elements', 'copy-polymer-dependencies',
              callback);
});<|endoftext|>


<commit_before>var gulp    = require("gulp"),
	jade    = require("gulp-jade"),
	minCSS  = require("gulp-minify-css"),
	minHTML = require("gulp-minify-html"),
	uglify  = require("gulp-uglify");

gulp.task("build:jade", function () {
	gulp.src("src/public/index.jade")
		.pipe(jade())
		.pipe(minHTML())
		.pipe(gulp.dest("dist/public/"));
});

gulp.task("build:jsx", function () {
	gulp.src("src/public/js/**.js")
		.pipe(uglify({ mangle: false }))
		.pipe(gulp.dest("dist/public/js/"));
});

gulp.task("build:css", function () {
	gulp.src("src/public/css/**.css")
		.pipe(minCSS())
		.pipe(gulp.dest("dist/public/css/"));
});

gulp.task("build:serv", function () {
	gulp.src("src/app.js")
		.pipe(uglify({ mangle: false }))
		.pipe(gulp.dest("dist/"));
});

gulp.task("watch", ["build:jade", "build:js", "build:css", "build:serv"], function () {
	gulp.watch("src/public/index.jade", ["build:jade"]);
	gulp.watch("src/public/jsx/**.jsx", ["build:jsx"]);
	gulp.watch("src/public/css/**.css", ["build:css"]);
	gulp.watch("src/app.js", ["build:serv"]);
});<commit_msg>Completely removed JSX things<commit_after>var gulp    = require("gulp"),
	jade    = require("gulp-jade"),
	minCSS  = require("gulp-minify-css"),
	minHTML = require("gulp-minify-html"),
	uglify  = require("gulp-uglify");

gulp.task("build:jade", function () {
	gulp.src("src/public/index.jade")
		.pipe(jade())
		.pipe(minHTML())
		.pipe(gulp.dest("dist/public/"));
});

gulp.task("build:js", function () {
	gulp.src("src/public/js/**.js")
		.pipe(uglify({ mangle: false }))
		.pipe(gulp.dest("dist/public/js/"));
});

gulp.task("build:css", function () {
	gulp.src("src/public/css/**.css")
		.pipe(minCSS())
		.pipe(gulp.dest("dist/public/css/"));
});

gulp.task("build:serv", function () {
	gulp.src("src/app.js")
		.pipe(uglify({ mangle: false }))
		.pipe(gulp.dest("dist/"));
});

gulp.task("watch", ["build:jade", "build:js", "build:css", "build:serv"], function () {
	gulp.watch("src/public/index.jade", ["build:jade"]);
	gulp.watch("src/public/js/**.js", ["build:js"]);
	gulp.watch("src/public/css/**.css", ["build:css"]);
	gulp.watch("src/app.js", ["build:serv"]);
});<|endoftext|>


<commit_before>const path = require('path');
const webpack = require("webpack");
const childProcess = require('child_process')
// As of v3.0.3 GitRevisionPlugin does not work with MiniCssExtractPlugin
// const GitRevisionPlugin = require('git-revision-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyPlugin = require('copy-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// These steps remove the need for a separate plugin to set the githash
const gitHashLength = 8
const gitHash = childProcess.execSync('git rev-parse --short HEAD').toString().substring(0,gitHashLength);

module.exports = {
  entry: {
      main: './src/index.js',
  },
  output: {
    filename: '[name]-bundle.js',
    path: path.resolve(__dirname, 'dist', gitHash),
    publicPath: path.join('/dist', gitHash, '/'),
  },

  optimization: {
    splitChunks: {
      chunks: 'all',
    },
  },
  resolve: {
    alias: {
      marionette: 'backbone.marionette/lib/backbone.marionette.min',

      'jquery.touchswipe': 'jquery-touchswipe',
      'jquery.ui': 'vendor/jquery/jquery-ui.min', // Revert to old version for testing...
      // 'jquery.ui': 'jquery-ui', // Only required for timepicker-addon 1.5.5 apparently!
      'jquery-ui.timepicker': 'jquery-ui-timepicker-addon', // Need to update timepicker css to avoid showing microseconds/milliseconds
      // Jquery-ui-combox is not the official combobox extension from npm
      // Instead it is a collection of extensions: (https://github.com/bseth99/jquery-ui-extensions)
      'jquery-ui.combobox': 'vendor/jquery/jquery-ui.combobox',

      // Jquery.flot provided by NPM package (exact name match)
      // Jquery.flot.resize also from NPM but slightly older version 1.0.0 2012 instead of 2013 (vendor lib)
      'jquery.flot.resize': 'jquery-flot-resize',
      'jquery.flot.pie': 'flot-pie',
      'jquery.flot.time': 'vendor/flot/jquery.flot.time.min',
      'jquery.flot.selection': 'vendor/flot/jquery.flot.selection',
      'jquery.flot.stack': 'vendor/flot/jquery.flot.stack',

       // Jquery flot tooltip is provided ny NPM with exact name match,
       // so not aliased here, was: 'vendor/flot/jquery.flot.tooltip',
      'jquery.flot.tickrotor': 'vendor/flot/jquery.flot.tickrotor',
      'jquery.flot.axislabels': 'flot-axislabels',

      // We can't currently use the magnific-popup from npm e.g.:
      // 'jquery.mp': 'magnific-popup',
      // The vendor library has been modified to append proposal to the request
      // Hence the vendor magnific-popup has a dependency on our utils/xhrimage
      'jquery.mp': 'vendor/jquery/jquery.magnific-popup',

      // jeditable provided by NPM.
      'jquery.editable': 'jquery-jeditable/dist/jquery.jeditable.min',
      'jquery.editable.datepicker': 'jquery-jeditable/dist/jquery.jeditable.datepicker.min',

      // Jquery.color plugin also NPM package
      'jquery.color': 'jquery-color',

      // Caman npm depends on fibers, canvas, fs which we don't want...
      // So use direct downloaded dependency
      caman: 'vendor/caman.min',

      // heatmap in npm has dependency on canvas/node-gyp... so use old one for now
      heatmap: 'vendor/hmap',

      // gunzip is actually the zlib library
      // https://npm.taobao.org/package/zlibjs
      gzip: 'zlibjs/bin/gunzip.min',

      markdown: 'markdown/lib/markdown',

      highmaps: 'highcharts/highmaps',
      'highmaps-world': '@highcharts/map-collection/custom/world',

      // Vue packages from npm (vee-validate requires promise polyfill - also npm)
      vue: 'vue/dist/vue.min',
      veevalidate: 'vee-validate/dist/vee-validate.min',
    },
    modules: [
      path.resolve(__dirname, 'src/js'),
      path.resolve(__dirname, 'src/css'),
      path.resolve(__dirname, 'node_modules'),
    ]
  },
  module: {
    rules: [
      {
        test: /\.html$/,
        use: [
          {
            loader: 'underscore-template-loader',
            options: {
              engine: 'underscore',
            }
          }
        ],
        exclude: [
          path.resolve(__dirname, 'src/js/templates/vue')
        ]
      },
      {
        test: /\.xml$/,
        use: [
          {
            loader: 'raw-loader',
          }
        ]
      },
      // Font loader - url should be relative to entry main.scss file
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: '../../assets/fonts', // output path is relative to main module outputPath
            publicPath: '/assets/fonts'
          }
        }
      },
      // SVG could be images or fonts so use more explicit test here...
      {
        test: /font-awesome\/.+\.(svg)$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: '../../assets/fonts',
            publicPath: '/assets/fonts'
          }
        }
      },
      {
        test: /\.vue$/,
        use: [
          {
            loader: 'vue-loader',
          }
        ]
      },
      {
        test: /vue\/.+\.html$/,
        use: ['html-loader']
      },
      // We need to help Caman load properly
      // Caman adds to the window object within a browser
      // The import loader ensures it it recognised as browser env not NodeJS
      {
        test: /caman\.min\.js$/,
        use: "imports-loader?exports=>undefined,require=>false,this=>window"
      },
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader, // Extract the CSS into separate files
          },
          "css-loader", // translates CSS into CommonJS
          "sass-loader" // compiles Sass to CSS, using Node Sass by default
        ]
      },
      {
        test: /\.(png|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192, // Anything less than 8K is inlined
              name: '[path][name].[ext]',
              outputPath: '../../assets',
              publicPath: '/assets',
              context: 'src',
            }
          }
        ]
      }
    ]
  },

  plugins: [
    new webpack.ProvidePlugin({
       $: "jquery",
        jQuery: "jquery",
        _: "underscore",
        "window.jQuery": "jquery",
        Highcharts: "highmaps"
    }),
    // This generates a short (8 char) git hash used for build paths
    // new GitRevisionPlugin({
    //   commithashCommand: 'rev-parse --short HEAD'
    // }),
    // This builds an index.php file from the src template
    new HtmlWebpackPlugin({
      title: 'SynchWeb Webpack',
      filename: path.resolve(__dirname, 'index.php'),
      template: 'src/index.php',
    }),
    // Copy static assets to the assets folder
    // Anything matching in the from path is copied so images/file.png => assets/images/file.png
    new CopyPlugin([
      // { context: path.resolve(__dirname, 'src/css/stylesheets'),
      //   from: 'images/**',
      //   to: path.resolve(__dirname, 'assets') },
      { context: path.resolve(__dirname, 'src'),
        from: 'images/**',
        to: path.resolve(__dirname, 'assets') }
    ]),
    // Ignore all locale files of moment.js
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    new VueLoaderPlugin(),
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css',
    }),
  ]
}
<commit_msg>Reduced inline image threshold to 4K<commit_after>const path = require('path');
const webpack = require("webpack");
const childProcess = require('child_process')
// As of v3.0.3 GitRevisionPlugin does not work with MiniCssExtractPlugin
// const GitRevisionPlugin = require('git-revision-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyPlugin = require('copy-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// These steps remove the need for a separate plugin to set the githash
const gitHashLength = 8
const gitHash = childProcess.execSync('git rev-parse --short HEAD').toString().substring(0,gitHashLength);

module.exports = {
  entry: {
      main: './src/index.js',
  },
  output: {
    filename: '[name]-bundle.js',
    path: path.resolve(__dirname, 'dist', gitHash),
    publicPath: path.join('/dist', gitHash, '/'),
  },

  optimization: {
    splitChunks: {
      chunks: 'all',
    },
  },
  resolve: {
    alias: {
      marionette: 'backbone.marionette/lib/backbone.marionette.min',

      'jquery.touchswipe': 'jquery-touchswipe',
      'jquery.ui': 'vendor/jquery/jquery-ui.min', // Revert to old version for testing...
      // 'jquery.ui': 'jquery-ui', // Only required for timepicker-addon 1.5.5 apparently!
      'jquery-ui.timepicker': 'jquery-ui-timepicker-addon', // Need to update timepicker css to avoid showing microseconds/milliseconds
      // Jquery-ui-combox is not the official combobox extension from npm
      // Instead it is a collection of extensions: (https://github.com/bseth99/jquery-ui-extensions)
      'jquery-ui.combobox': 'vendor/jquery/jquery-ui.combobox',

      // Jquery.flot provided by NPM package (exact name match)
      // Jquery.flot.resize also from NPM but slightly older version 1.0.0 2012 instead of 2013 (vendor lib)
      'jquery.flot.resize': 'jquery-flot-resize',
      'jquery.flot.pie': 'flot-pie',
      'jquery.flot.time': 'vendor/flot/jquery.flot.time.min',
      'jquery.flot.selection': 'vendor/flot/jquery.flot.selection',
      'jquery.flot.stack': 'vendor/flot/jquery.flot.stack',

       // Jquery flot tooltip is provided ny NPM with exact name match,
       // so not aliased here, was: 'vendor/flot/jquery.flot.tooltip',
      'jquery.flot.tickrotor': 'vendor/flot/jquery.flot.tickrotor',
      'jquery.flot.axislabels': 'flot-axislabels',

      // We can't currently use the magnific-popup from npm e.g.:
      // 'jquery.mp': 'magnific-popup',
      // The vendor library has been modified to append proposal to the request
      // Hence the vendor magnific-popup has a dependency on our utils/xhrimage
      'jquery.mp': 'vendor/jquery/jquery.magnific-popup',

      // jeditable provided by NPM.
      'jquery.editable': 'jquery-jeditable/dist/jquery.jeditable.min',
      'jquery.editable.datepicker': 'jquery-jeditable/dist/jquery.jeditable.datepicker.min',

      // Jquery.color plugin also NPM package
      'jquery.color': 'jquery-color',

      // Caman npm depends on fibers, canvas, fs which we don't want...
      // So use direct downloaded dependency
      caman: 'vendor/caman.min',

      // heatmap in npm has dependency on canvas/node-gyp... so use old one for now
      heatmap: 'vendor/hmap',

      // gunzip is actually the zlib library
      // https://npm.taobao.org/package/zlibjs
      gzip: 'zlibjs/bin/gunzip.min',

      markdown: 'markdown/lib/markdown',

      highmaps: 'highcharts/highmaps',
      'highmaps-world': '@highcharts/map-collection/custom/world',

      // Vue packages from npm (vee-validate requires promise polyfill - also npm)
      vue: 'vue/dist/vue.min',
      veevalidate: 'vee-validate/dist/vee-validate.min',
    },
    modules: [
      path.resolve(__dirname, 'src/js'),
      path.resolve(__dirname, 'src/css'),
      path.resolve(__dirname, 'node_modules'),
    ]
  },
  module: {
    rules: [
      {
        test: /\.html$/,
        use: [
          {
            loader: 'underscore-template-loader',
            options: {
              engine: 'underscore',
            }
          }
        ],
        exclude: [
          path.resolve(__dirname, 'src/js/templates/vue')
        ]
      },
      {
        test: /\.xml$/,
        use: [
          {
            loader: 'raw-loader',
          }
        ]
      },
      // Font loader - url should be relative to entry main.scss file
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: '../../assets/fonts', // output path is relative to main module outputPath
            publicPath: '/assets/fonts'
          }
        }
      },
      // SVG could be images or fonts so use more explicit test here...
      {
        test: /font-awesome\/.+\.(svg)$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: '../../assets/fonts',
            publicPath: '/assets/fonts'
          }
        }
      },
      {
        test: /\.vue$/,
        use: [
          {
            loader: 'vue-loader',
          }
        ]
      },
      {
        test: /vue\/.+\.html$/,
        use: ['html-loader']
      },
      // We need to help Caman load properly
      // Caman adds to the window object within a browser
      // The import loader ensures it it recognised as browser env not NodeJS
      {
        test: /caman\.min\.js$/,
        use: "imports-loader?exports=>undefined,require=>false,this=>window"
      },
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader, // Extract the CSS into separate files
          },
          "css-loader", // translates CSS into CommonJS
          "sass-loader" // compiles Sass to CSS, using Node Sass by default
        ]
      },
      {
        test: /\.(png|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096, // Anything less than this limit is inlined
              name: '[path][name].[ext]',
              outputPath: '../../assets',
              publicPath: '/assets',
              context: 'src',
            }
          }
        ]
      }
    ]
  },

  plugins: [
    new webpack.ProvidePlugin({
       $: "jquery",
        jQuery: "jquery",
        _: "underscore",
        "window.jQuery": "jquery",
        Highcharts: "highmaps"
    }),
    // This generates a short (8 char) git hash used for build paths
    // new GitRevisionPlugin({
    //   commithashCommand: 'rev-parse --short HEAD'
    // }),
    // This builds an index.php file from the src template
    new HtmlWebpackPlugin({
      title: 'SynchWeb Webpack',
      filename: path.resolve(__dirname, 'index.php'),
      template: 'src/index.php',
    }),
    // Copy static assets to the assets folder
    // Anything matching in the from path is copied so images/file.png => assets/images/file.png
    new CopyPlugin([
      // { context: path.resolve(__dirname, 'src/css/stylesheets'),
      //   from: 'images/**',
      //   to: path.resolve(__dirname, 'assets') },
      { context: path.resolve(__dirname, 'src'),
        from: 'images/**',
        to: path.resolve(__dirname, 'assets') }
    ]),
    // Ignore all locale files of moment.js
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    new VueLoaderPlugin(),
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css',
    }),
  ]
}
<|endoftext|>


<commit_before>//Import dependencies
var fs = require('fs');
var gulp = require('gulp');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var header = require('gulp-header');

//Import the package
var pkg = require('./package.json');

//Generate the header
var banner = ['/**',
  ' * <%= pkg.name %> - <%= pkg.description %>',
  ' * @version v<%= pkg.version %>',
  ' * @link <%= pkg.homepage %>',
  ' * @license <%= pkg.license %>',
  ' */',
  '', ''].join('\n');

//Output dir
var output = 'build/';

//Files list
var files = ['src/karyo.js', 'src/build.js', 'src/callback.js', 'src/cursor.js', 'src/foot.js', 'src/get.js',
'src/import.js', 'src/navbar.js', 'src/resize.js', 'src/select.js', 'src/size.js', 'src/use.js', 'src/options.js',
'src/utils.js', 'src/loading.js', 'src/alert.js', 'src/preview.js', 'src/draw/*.js', 'src/events/*.js',
'src/plugins/*.js'];

//Concat all files in build folder
gulp.task('concat', function(){

  //Set the source files
  gulp.src(files)

  //Concat all files in siimple.css
  .pipe(concat('karyo.js'))

  //Add the header
  .pipe(header(banner, { pkg : pkg } ))

  //Save in css/ folder
  .pipe(gulp.dest(output + 'js/'));

});

//Minimify the output file in siimple.min.css
gulp.task('minify', ['concat'], function(){

  //Set the source file
  gulp.src(output + 'js/karyo.js')

  //MinifCss
  .pipe(uglify())

  //Save the minifed file as siimple.min.css
  .pipe(rename('karyo.min.js'))

  //Add the header
  .pipe(header(banner, { pkg : pkg } ))

  //Save in css/ folder
  .pipe(gulp.dest(output + 'js/'));

});

//Copy vendor files
gulp.task('copy-vendor', ['minify'], function(){

  //Select the files and folders to copy
  gulp.src(['vendor/**/*'], {base: './'})

  //Copy to the build folder
  .pipe(gulp.dest(output));

});

//Copy assets files
gulp.task('copy-assets', ['copy-vendor'], function(){

  //Select the files and folders to copy
  gulp.src(['assets/**/*'], {base: './assets'})

  //Copy to the build folder
  .pipe(gulp.dest(output));

});

//Execute the tasks
gulp.task('default', ['copy-assets']);
<commit_msg>Update gulpfile: add table.js<commit_after>//Import dependencies
var fs = require('fs');
var gulp = require('gulp');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var header = require('gulp-header');

//Import the package
var pkg = require('./package.json');

//Generate the header
var banner = ['/**',
  ' * <%= pkg.name %> - <%= pkg.description %>',
  ' * @version v<%= pkg.version %>',
  ' * @link <%= pkg.homepage %>',
  ' * @license <%= pkg.license %>',
  ' */',
  '', ''].join('\n');

//Output dir
var output = 'build/';

//Files list
var files = ['src/karyo.js', 'src/build.js', 'src/callback.js', 'src/cursor.js', 'src/foot.js', 'src/get.js',
'src/import.js', 'src/navbar.js', 'src/resize.js', 'src/select.js', 'src/size.js', 'src/use.js', 'src/options.js',
'src/utils.js', 'src/loading.js', 'src/alert.js', 'src/preview.js', 'src/draw/*.js', 'src/events/*.js',
'src/plugins/*.js', 'src/table.js'];

//Concat all files in build folder
gulp.task('concat', function(){

  //Set the source files
  gulp.src(files)

  //Concat all files in siimple.css
  .pipe(concat('karyo.js'))

  //Add the header
  .pipe(header(banner, { pkg : pkg } ))

  //Save in css/ folder
  .pipe(gulp.dest(output + 'js/'));

});

//Minimify the output file in siimple.min.css
gulp.task('minify', ['concat'], function(){

  //Set the source file
  gulp.src(output + 'js/karyo.js')

  //MinifCss
  .pipe(uglify())

  //Save the minifed file as siimple.min.css
  .pipe(rename('karyo.min.js'))

  //Add the header
  .pipe(header(banner, { pkg : pkg } ))

  //Save in css/ folder
  .pipe(gulp.dest(output + 'js/'));

});

//Copy vendor files
gulp.task('copy-vendor', ['minify'], function(){

  //Select the files and folders to copy
  gulp.src(['vendor/**/*'], {base: './'})

  //Copy to the build folder
  .pipe(gulp.dest(output));

});

//Copy assets files
gulp.task('copy-assets', ['copy-vendor'], function(){

  //Select the files and folders to copy
  gulp.src(['assets/**/*'], {base: './assets'})

  //Copy to the build folder
  .pipe(gulp.dest(output));

});

//Execute the tasks
gulp.task('default', ['copy-assets']);
<|endoftext|>


<commit_before>///<reference path="qunit-1.14.0.js" />

(function () {
    var qUnitGlobalErrorHandler = window.onerror;

    var testTimeout = QUnit.urlParams.testtimeout ? QUnit.urlParams.testtimeout:  15000;
    var hasRun = false;
    var testFailed = false;
    var testError = "";
    var verboseLog = "";
    var log = [];

    QUnit.config.autostart = false;
    QUnit.config.testTimeout = testTimeout;
    QUnit.config.hidepassed = true;
    QUnit.breakOnAssertFail = false;

    var qunitDiv;
    var qunitTestFixtureDiv;
    window.addEventListener("load", function () {
        qunitDiv = document.querySelector("#qunit");
        qunitTestFixtureDiv = document.querySelector("#qunit-fixture");

        function addOptions() {
            var toolBar = document.querySelector("#qunit-testrunner-toolbar");
            if (!toolBar) {
                setTimeout(addOptions);
                return;
            }

            var cb = document.createElement("input");
            cb.id = "breakOnAssertFail";
            cb.type = "checkbox";
            cb.checked = (QUnit.urlParams.breakonassertfail === "true" || QUnit.urlParams.breakonassertfail === true);
            var span = document.createElement("span");
            span.innerHTML = "Break on Assert fail";
            toolBar.appendChild(cb);
            toolBar.appendChild(span);

            cb = document.createElement("input");
            cb.id = "disableTestTimeout";
            cb.type = "checkbox";
            cb.checked = (QUnit.urlParams.disabletesttimeout === "true" || QUnit.urlParams.disabletesttimeout === true);
            var span = document.createElement("span");
            span.innerHTML = "Disable test timeout";
            toolBar.appendChild(cb);
            toolBar.appendChild(span);

            cb = document.createElement("input");
            cb.id = "fastAnimations";
            cb.type = "checkbox";
            cb.checked = (QUnit.urlParams.fastanimations === "true" || QUnit.urlParams.fastanimations === true);
            var span = document.createElement("span");
            span.innerHTML = "Fast Animations";
            toolBar.appendChild(cb);
            toolBar.appendChild(span);

            var btn = document.createElement("button");
            btn.style.borderColor = btn.style.color = "#5E740B";
            btn.style.marginLeft = "4px";
            btn.innerHTML = "Start";
            btn.onclick = function () {
                // Changing the fast animations setting requires a re-load.
                if (!hasRun && (WinJS.Utilities._fastAnimations === document.querySelector("#fastAnimations").checked)) {
                    start();
                } else {
                    var qs = "?autostart=true";
                    qs += "&breakonassertfail=" + document.querySelector("#breakOnAssertFail").checked;
                    qs += "&disabletesttimeout=" + document.querySelector("#disableTestTimeout").checked;
                    qs += "&fastanimations=" + document.querySelector("#fastAnimations").checked;
                    if (QUnit.urlParams.module) {
                        qs += "&module=" + QUnit.urlParams.module;
                    }
                    if (QUnit.urlParams.testNumber) {
                        qs += "&testNumber=" + QUnit.urlParams.testNumber;
                    }
                    window.location = window.location.protocol + "//" + window.location.host + window.location.pathname + qs;
                }
            };
            toolBar.appendChild(btn);

            if (QUnit.urlParams.autostart === "true" || QUnit.urlParams.autostart === true) {
                start();
            }
        }
        addOptions();
    });

    if (QUnit.urlParams.fastanimations === "true" || QUnit.urlParams.fastanimations === true) {
        WinJS.Utilities._fastAnimations = true;
    }

    function start() {
        hasRun = true;
        QUnit.breakOnAssertFail = document.querySelector("#breakOnAssertFail").checked;
        QUnit.config.testTimeout = document.querySelector("#disableTestTimeout").checked ? undefined : testTimeout;
        QUnit.start();
    }

    function completeTest() {
        QUnit.assert.ok(!testFailed, testError);
        QUnit.start();
    }

    function handleGlobalError(testFunc, error) {
        var expectedException = testFunc["LiveUnit.ExpectedException"];
        if (expectedException) {
            if (expectedException.message) {
                expectedException = [expectedException];
            }
            var handled = false;
            for (var i = 0; i < expectedException.length; i++) {
                var message = expectedException[i].message
                // Chrome prefixes with "Uncaught Error". Firefox prefixes with "Error"
                if (message === error || ("Uncaught Error: " + message) === error || ("Error: " + message) === error) {
                    handled = true;
                    break;
                }
            }
            if (!handled) {
                LiveUnit.Assert.fail("Unexpected exception: " + error);
            }
        } else {
            LiveUnit.Assert.fail("Unexpected exception: " + error);
        }
    }

    function hookupGlobalErrorHandler(testFunc) {
        var expectedException = testFunc["LiveUnit.ExpectedException"];
        if (expectedException) {
            if (expectedException.message) {
                expectedException = [expectedException];
            }
            window.onerror = function (e) {
                handleGlobalError(testFunc, e);
            };
        } else {
            window.onerror = qUnitGlobalErrorHandler;
        }
    }

    function cleanUp(testName) {
        testFailed = false;
        testError = "";
        verboseLog = "";

        qunitDiv.style.zIndex = 0;
    }

    QUnit.testStart(function testStart(testDetails) {
        qunitDiv.style.zIndex = -1;
        QUnit.log = function (details) {
            if (!details.result) {
                details.name = testDetails.name;
                log.push(details);
            }
        }
    });

    QUnit.testDone(function testDone(args) {
        if (args.failed) {
            console.log(args.module + ": " + args.name + ", " + args.passed + "/" + args.total + ", " + args.runtime + "ms");
            console.log(verboseLog);
        }
        cleanUp(args.name);
    });

    QUnit.moduleDone(function (args) {
        if (document.body.children.length > 2) {
            for (var i = document.body.children.length - 1; i >= 0; i--) {
                var child = document.body.children[i];
                if (child === qunitDiv || child === qunitTestFixtureDiv) {
                    continue;
                }

                console.log("Test: " + args.name + " - Incomplete cleanup!");
                WinJS.Utilities.disposeSubTree(child);
                document.body.removeChild(child);
            }
        }
    });

    QUnit.done(function (test_results) {
        var tests = log.map(function (details) {
            return {
                name: details.name,
                result: details.result,
                expected: details.expected,
                actual: details.actual,
                source: details.source
            }
        });
        test_results.tests = tests;
        window.global_test_results = test_results;
    });

    function formatString(string) {
        var args = arguments;
        if (args.length > 1) {
            string = string.replace(/({{)|(}})|{(\d+)}|({)|(})/g,
                function (unused, left, right, index, illegalLeft, illegalRight) {
                    if (illegalLeft || illegalRight) {
                        throw new Error(formatString("Malformed string input: {0}", illegalLeft || illegalRight));
                    }
                    return (left && "{") || (right && "}") || args[(index | 0) + 1];
                });
        }
        return string;
    }

    window.LiveUnit = {
        Assert: {
            areEqual: function (expected, actual, message) {
                if (expected !== actual) {
                    if (QUnit.breakOnAssertFail) {
                        debugger;
                    }
                    testError = testError || formatString("areEqual - {0} (expected: {1}, actual: {2})", message || "", expected, actual);
                    testFailed = true;
                }
            },

            areNotEqual: function (left, right, message) {
                if (left === right) {
                    if (QUnit.breakOnAssertFail) {
                        debugger;
                    }
                    testError = testError || formatString("areNotEqual - {0} (both equal: {1})", message || "", left);
                    testFailed = true;
                }
            },

            fail: function (message) {
                if (QUnit.breakOnAssertFail) {
                    debugger;
                }
                testError = testError || formatString("fail - {0}", message || "");
                testFailed = true;
            },

            isFalse: function (falsy, message) {
                if (falsy) {
                    if (QUnit.breakOnAssertFail) {
                        debugger;
                    }
                    testError = testError || formatString("isFalse - {0} (expected: falsy, actual: {1})", message || "", falsy);
                    testFailed = true;
                }
            },

            isTrue: function (truthy, message) {
                if (!truthy) {
                    if (QUnit.breakOnAssertFail) {
                        debugger;
                    }
                    testError = testError || formatString("isTrue - {0} (expected: truthy, actual: {1})", message || "", truthy);
                    testFailed = true;
                }
            },

            isNull: function (obj, message) {
                // LiveUnit's null assert also accepts undefined
                var pass = obj === null || obj === undefined;
                if (!pass) {
                    if (QUnit.breakOnAssertFail) {
                        debugger;
                    }
                    testError = testError || formatString("isNull - {0} (expected: null or undefined, actual: {1})", message || "", obj);
                    testFailed = true;
                }
            },

            isNotNull: function (obj, message) {
                // LiveUnit's null assert also accepts undefined
                var pass = obj !== null && obj !== undefined;
                if (!pass) {
                    if (QUnit.breakOnAssertFail) {
                        debugger;
                    }
                    testError = testError || formatString("isNotNull - {0} (expected: not null and not undefined, actual: {1})", message || "", obj);
                    testFailed = true;
                }
            },
        },

        GetWrappedCallback: function (func) {
            return func;
        },

        LoggingCore: {
            logComment: function (message) {
                verboseLog += "\n" + message;
            }
        },

        registerTestClass: function (moduleName) {
            function runSetupTeardownFunc(func) {
                if (func.length) {
                    QUnit.stop();
                    func(function () {
                        QUnit.start();
                    });
                } else {
                    func();
                }
            }

            var path = moduleName.split(".");
            var module = window;
            path.forEach(function (key) {
                module = module[key];
            });
            var testModule = new module();

            QUnit.module(moduleName, {
                setup: function () {
                    if (!testModule.setUp) {
                        return;
                    }
                    runSetupTeardownFunc(testModule.setUp.bind(testModule));
                },
                teardown: function () {
                    if (!testModule.tearDown) {
                        return;
                    }
                    runSetupTeardownFunc(testModule.tearDown.bind(testModule));
                }
            });

            Object.keys(testModule).forEach(function (key) {
                if (key.indexOf("test") !== 0) {
                    return;
                }

                var testName = key.substr("test".length);
                var testFunc = testModule[key];
                if (testFunc.length) {
                    // Async WebUnit tests take a 'complete' parameter
                    QUnit.asyncTest(testName, function () {
                        hookupGlobalErrorHandler(testFunc);
                        var error = false;
                        try {
                            testFunc.call(testModule, function () {
                                if (!error) {
                                    completeTest();
                                }
                            });
                        } catch (e) {
                            handleGlobalError(testFunc, e.message);
                            completeTest();
                            error = true;
                        }
                    });
                } else {
                    QUnit.asyncTest(testName, function () {
                        hookupGlobalErrorHandler(testFunc);
                        try {
                            testFunc.call(testModule);
                            completeTest();
                        }
                        catch (e) {
                            handleGlobalError(testFunc, e.message);
                            completeTest();
                        }
                    });
                }
            });
        },
    };
})();
<commit_msg>Temporary fix for time reporting on QUnit test pages. Fixes #190.<commit_after>///<reference path="qunit-1.14.0.js" />

(function () {
    var qUnitGlobalErrorHandler = window.onerror;

    var testTimeout = QUnit.urlParams.testtimeout ? QUnit.urlParams.testtimeout:  15000;
    var hasRun = false;
    var testFailed = false;
    var testError = "";
    var verboseLog = "";
    var log = [];

    QUnit.config.autostart = false;
    QUnit.config.testTimeout = testTimeout;
    QUnit.config.hidepassed = true;
    QUnit.breakOnAssertFail = false;

    var qunitDiv;
    var qunitTestFixtureDiv;
    window.addEventListener("load", function () {
        qunitDiv = document.querySelector("#qunit");
        qunitTestFixtureDiv = document.querySelector("#qunit-fixture");

        function addOptions() {
            var toolBar = document.querySelector("#qunit-testrunner-toolbar");
            if (!toolBar) {
                setTimeout(addOptions);
                return;
            }

            var cb = document.createElement("input");
            cb.id = "breakOnAssertFail";
            cb.type = "checkbox";
            cb.checked = (QUnit.urlParams.breakonassertfail === "true" || QUnit.urlParams.breakonassertfail === true);
            var span = document.createElement("span");
            span.innerHTML = "Break on Assert fail";
            toolBar.appendChild(cb);
            toolBar.appendChild(span);

            cb = document.createElement("input");
            cb.id = "disableTestTimeout";
            cb.type = "checkbox";
            cb.checked = (QUnit.urlParams.disabletesttimeout === "true" || QUnit.urlParams.disabletesttimeout === true);
            var span = document.createElement("span");
            span.innerHTML = "Disable test timeout";
            toolBar.appendChild(cb);
            toolBar.appendChild(span);

            cb = document.createElement("input");
            cb.id = "fastAnimations";
            cb.type = "checkbox";
            cb.checked = (QUnit.urlParams.fastanimations === "true" || QUnit.urlParams.fastanimations === true);
            var span = document.createElement("span");
            span.innerHTML = "Fast Animations";
            toolBar.appendChild(cb);
            toolBar.appendChild(span);

            var btn = document.createElement("button");
            btn.style.borderColor = btn.style.color = "#5E740B";
            btn.style.marginLeft = "4px";
            btn.innerHTML = "Start";
            btn.onclick = function () {
                // Changing the fast animations setting requires a re-load.
                if (!hasRun && (WinJS.Utilities._fastAnimations === document.querySelector("#fastAnimations").checked)) {
                    start();
                } else {
                    var qs = "?autostart=true";
                    qs += "&breakonassertfail=" + document.querySelector("#breakOnAssertFail").checked;
                    qs += "&disabletesttimeout=" + document.querySelector("#disableTestTimeout").checked;
                    qs += "&fastanimations=" + document.querySelector("#fastAnimations").checked;
                    if (QUnit.urlParams.module) {
                        qs += "&module=" + QUnit.urlParams.module;
                    }
                    if (QUnit.urlParams.testNumber) {
                        qs += "&testNumber=" + QUnit.urlParams.testNumber;
                    }
                    window.location = window.location.protocol + "//" + window.location.host + window.location.pathname + qs;
                }
            };
            toolBar.appendChild(btn);

            if (QUnit.urlParams.autostart === "true" || QUnit.urlParams.autostart === true) {
                start();
            }
        }
        addOptions();
    });

    if (QUnit.urlParams.fastanimations === "true" || QUnit.urlParams.fastanimations === true) {
        WinJS.Utilities._fastAnimations = true;
    }

    function start() {
        hasRun = true;
        QUnit.breakOnAssertFail = document.querySelector("#breakOnAssertFail").checked;
        QUnit.config.testTimeout = document.querySelector("#disableTestTimeout").checked ? undefined : testTimeout;
        QUnit.config.started = +new Date(); // This is a temporary fix and can be removed when and if jquery/qunit#555 is accepted.
        QUnit.start();
    }

    function completeTest() {
        QUnit.assert.ok(!testFailed, testError);
        QUnit.start();
    }

    function handleGlobalError(testFunc, error) {
        var expectedException = testFunc["LiveUnit.ExpectedException"];
        if (expectedException) {
            if (expectedException.message) {
                expectedException = [expectedException];
            }
            var handled = false;
            for (var i = 0; i < expectedException.length; i++) {
                var message = expectedException[i].message
                // Chrome prefixes with "Uncaught Error". Firefox prefixes with "Error"
                if (message === error || ("Uncaught Error: " + message) === error || ("Error: " + message) === error) {
                    handled = true;
                    break;
                }
            }
            if (!handled) {
                LiveUnit.Assert.fail("Unexpected exception: " + error);
            }
        } else {
            LiveUnit.Assert.fail("Unexpected exception: " + error);
        }
    }

    function hookupGlobalErrorHandler(testFunc) {
        var expectedException = testFunc["LiveUnit.ExpectedException"];
        if (expectedException) {
            if (expectedException.message) {
                expectedException = [expectedException];
            }
            window.onerror = function (e) {
                handleGlobalError(testFunc, e);
            };
        } else {
            window.onerror = qUnitGlobalErrorHandler;
        }
    }

    function cleanUp(testName) {
        testFailed = false;
        testError = "";
        verboseLog = "";

        qunitDiv.style.zIndex = 0;
    }

    QUnit.testStart(function testStart(testDetails) {
        qunitDiv.style.zIndex = -1;
        QUnit.log = function (details) {
            if (!details.result) {
                details.name = testDetails.name;
                log.push(details);
            }
        }
    });

    QUnit.testDone(function testDone(args) {
        if (args.failed) {
            console.log(args.module + ": " + args.name + ", " + args.passed + "/" + args.total + ", " + args.runtime + "ms");
            console.log(verboseLog);
        }
        cleanUp(args.name);
    });

    QUnit.moduleDone(function (args) {
        if (document.body.children.length > 2) {
            for (var i = document.body.children.length - 1; i >= 0; i--) {
                var child = document.body.children[i];
                if (child === qunitDiv || child === qunitTestFixtureDiv) {
                    continue;
                }

                console.log("Test: " + args.name + " - Incomplete cleanup!");
                WinJS.Utilities.disposeSubTree(child);
                document.body.removeChild(child);
            }
        }
    });

    QUnit.done(function (test_results) {
        var tests = log.map(function (details) {
            return {
                name: details.name,
                result: details.result,
                expected: details.expected,
                actual: details.actual,
                source: details.source
            }
        });
        test_results.tests = tests;
        window.global_test_results = test_results;
    });

    function formatString(string) {
        var args = arguments;
        if (args.length > 1) {
            string = string.replace(/({{)|(}})|{(\d+)}|({)|(})/g,
                function (unused, left, right, index, illegalLeft, illegalRight) {
                    if (illegalLeft || illegalRight) {
                        throw new Error(formatString("Malformed string input: {0}", illegalLeft || illegalRight));
                    }
                    return (left && "{") || (right && "}") || args[(index | 0) + 1];
                });
        }
        return string;
    }

    window.LiveUnit = {
        Assert: {
            areEqual: function (expected, actual, message) {
                if (expected !== actual) {
                    if (QUnit.breakOnAssertFail) {
                        debugger;
                    }
                    testError = testError || formatString("areEqual - {0} (expected: {1}, actual: {2})", message || "", expected, actual);
                    testFailed = true;
                }
            },

            areNotEqual: function (left, right, message) {
                if (left === right) {
                    if (QUnit.breakOnAssertFail) {
                        debugger;
                    }
                    testError = testError || formatString("areNotEqual - {0} (both equal: {1})", message || "", left);
                    testFailed = true;
                }
            },

            fail: function (message) {
                if (QUnit.breakOnAssertFail) {
                    debugger;
                }
                testError = testError || formatString("fail - {0}", message || "");
                testFailed = true;
            },

            isFalse: function (falsy, message) {
                if (falsy) {
                    if (QUnit.breakOnAssertFail) {
                        debugger;
                    }
                    testError = testError || formatString("isFalse - {0} (expected: falsy, actual: {1})", message || "", falsy);
                    testFailed = true;
                }
            },

            isTrue: function (truthy, message) {
                if (!truthy) {
                    if (QUnit.breakOnAssertFail) {
                        debugger;
                    }
                    testError = testError || formatString("isTrue - {0} (expected: truthy, actual: {1})", message || "", truthy);
                    testFailed = true;
                }
            },

            isNull: function (obj, message) {
                // LiveUnit's null assert also accepts undefined
                var pass = obj === null || obj === undefined;
                if (!pass) {
                    if (QUnit.breakOnAssertFail) {
                        debugger;
                    }
                    testError = testError || formatString("isNull - {0} (expected: null or undefined, actual: {1})", message || "", obj);
                    testFailed = true;
                }
            },

            isNotNull: function (obj, message) {
                // LiveUnit's null assert also accepts undefined
                var pass = obj !== null && obj !== undefined;
                if (!pass) {
                    if (QUnit.breakOnAssertFail) {
                        debugger;
                    }
                    testError = testError || formatString("isNotNull - {0} (expected: not null and not undefined, actual: {1})", message || "", obj);
                    testFailed = true;
                }
            },
        },

        GetWrappedCallback: function (func) {
            return func;
        },

        LoggingCore: {
            logComment: function (message) {
                verboseLog += "\n" + message;
            }
        },

        registerTestClass: function (moduleName) {
            function runSetupTeardownFunc(func) {
                if (func.length) {
                    QUnit.stop();
                    func(function () {
                        QUnit.start();
                    });
                } else {
                    func();
                }
            }

            var path = moduleName.split(".");
            var module = window;
            path.forEach(function (key) {
                module = module[key];
            });
            var testModule = new module();

            QUnit.module(moduleName, {
                setup: function () {
                    if (!testModule.setUp) {
                        return;
                    }
                    runSetupTeardownFunc(testModule.setUp.bind(testModule));
                },
                teardown: function () {
                    if (!testModule.tearDown) {
                        return;
                    }
                    runSetupTeardownFunc(testModule.tearDown.bind(testModule));
                }
            });

            Object.keys(testModule).forEach(function (key) {
                if (key.indexOf("test") !== 0) {
                    return;
                }

                var testName = key.substr("test".length);
                var testFunc = testModule[key];
                if (testFunc.length) {
                    // Async WebUnit tests take a 'complete' parameter
                    QUnit.asyncTest(testName, function () {
                        hookupGlobalErrorHandler(testFunc);
                        var error = false;
                        try {
                            testFunc.call(testModule, function () {
                                if (!error) {
                                    completeTest();
                                }
                            });
                        } catch (e) {
                            handleGlobalError(testFunc, e.message);
                            completeTest();
                            error = true;
                        }
                    });
                } else {
                    QUnit.asyncTest(testName, function () {
                        hookupGlobalErrorHandler(testFunc);
                        try {
                            testFunc.call(testModule);
                            completeTest();
                        }
                        catch (e) {
                            handleGlobalError(testFunc, e.message);
                            completeTest();
                        }
                    });
                }
            });
        },
    };
})();
<|endoftext|>