<commit_before>ChatApp.controller('ChatCtrl', function($scope, $state, $timeout, $interval, $ionicScrollDelegate, $ionicPopover, $ionicModal, $ionicPopup, $ionicNavBarDelegate, chatService){
	$scope.title = 'Chat English';
	$scope.chats = [];
	$scope.reportData = {};

	$scope.inBlockList = false;
	var blocks = [];
	var isBlock = false;

	//$scope.haveStranger = true;
	//$scope.strangerLiked = true;

	//console.log(userData);

	function initChat(){

		var localBlocks = window.localStorage.getItem('blocks');
		if (localBlocks && userData.userID){
			blocks = JSON.parse(localBlocks)[userData.userID];
			if (!blocks){
				blocks = [];
				window.localStorage.removeItem('blocks');
			}
		}

		console.log(blocks);

		chatService.init({
			callbackSendMessage: function(){},
			callbackReceiveMessage: receiveChat,
			callbackConnect: function(){},
			callbackClose: onClose
		});
	};

	function onClose(){
		$scope.$apply(function(){
			$scope.chats.push({
				type: 'system',
				content: 'You has been disconnected, please exit and make new chat.'
			});
			$ionicScrollDelegate.scrollBottom(true);
		});
	}

	var isTyping = false;
	var timer;
	var lastTimeKeyPress = 0;
	var typingEle;

	function receiveChat(data){
		var content;

		if ($scope.chats.length > 0){
			if ($scope.chats[$scope.chats.length - 1].type == 'typing'){
				$scope.chats.pop();
			}
		}

		if (data.type == 'chat'){
			content = {
				type: data.from == 'system' ? 'system' : 'stranger',
				content : data.message
			};

			if (timer){
				isTyping = false;
				$interval.cancel(timer);
			}

		}
		else if (data.type == 'action'){
			if (data.action == 'typing'){
				content = {
					type: 'typing'
				};
			}
			else{

			}
		}

		//Check Like function
		if (data.stranger){
			$scope.haveStranger = true;
			$scope.strangerLiked = data.stranger.isLiked;

			$scope.infoStranger = {
				fullId: data.stranger.id,
				shortId: parseInt(data.stranger.id, 10),
				liked: data.stranger.liked,
				name: data.stranger.name,
				avatar: data.stranger.avatar
			};

			//Check blocklist
			if (data.from == 'system'){
				for (var i = 0; i < blocks.length; i++){
					if (blocks[i] == data.stranger.id){
						isBlock = true;
						$scope.inBlockList = true;
						break;
					}
				}

				if (isBlock){
					$ionicPopup.confirm({
						title: '',
						template: '
Stranger was blocked by you. Do you want to continue to chat with him?
',
						cancelText: 'Yes',
						okText: 'No, I don\'t.'
					}).then(function(res){
						if (!res){
							//Yes
							isBlock = false;
						}
						else {
							//No
							chatService.exit();
							$ionicNavBarDelegate.back();
						}
					});
				}
			}

		}

		if (content){
			if (isBlock && data.from == 'stranger'){

			}
			else{
				$scope.chats.push(content);
			}
		}

		$scope.$apply(function(){
			$ionicScrollDelegate.scrollBottom(true);
		});
	}

	$scope.sendChat = function(){
		var that = this;
		that.newChat = that.newChat.trim().replace(/\s{2,}/g, ' ');
		var newChat = that.newChat;
		if (newChat && newChat !== ''){
			if (timer){
				isTyping = false;
				$interval.cancel(timer);
			}

			chatService.sendMessage({
				type: 'chat',
				message: newChat
			});

			var content = {
				type: 'me',
				content : newChat
			};

			if ($scope.chats.length > 0 && $scope.chats[$scope.chats.length - 1].type == 'typing'){
				$scope.chats.splice($scope.chats.length - 1, 0, content);
			}
			else{
				$scope.chats.push(content);
			}

			$ionicScrollDelegate.scrollBottom(true);

		}

		that.newChat = '';
		$scope.focusInput = true;
	};

	$scope.chatKeyPress = function(e){
		lastTimeKeyPress = e.timeStamp;
		if (isTyping == false){
			isTyping = true;
			chatService.sendMessage({
				type: 'action',
				action: 'typing'
			});
			$interval.cancel(timer);
			timer = $interval(function(){
				if (isTyping && (new Date()).getTime() - lastTimeKeyPress > 4000){
					isTyping = false;
					$interval.cancel(timer);
					chatService.sendMessage({
						type: 'action',
						action: 'stop type'
					});
				}
			}, 1000);
		}
		else{

		}
	}

	$scope.likeStranger = function(){
		if ($scope.strangerLiked){
			return false;
		}
		$scope.strangerLiked = true;

		chatService.sendMessage({
			type: 'action',
			action: 'like'
		});
		$scope.infoStranger.liked++;

		$scope.popoverChat.hide();

		var content = {
			type: 'system',
			content : 'You\'ve just like the stranger. Thank you.'
		};

		$scope.chats.push(content);
		$ionicScrollDelegate.scrollBottom(true);
	};

	$ionicPopover.fromTemplateUrl('templates/popover.html', {
		scope: $scope,
	}).then(function(popover) {
    	$scope.popoverChat = popover;
	});

	$scope.showPopoverChat = function($event){
		$scope.popoverChat.show($event);
	};

	$ionicModal.fromTemplateUrl('templates/report-modal.html', {
		scope: $scope,
		animation: 'slide-in-up'
	}).then(function(modal){
		$scope.reportModal = modal;
	});

	$scope.openReportModal = function(){
		if ($scope.reported){
			return false;
		}
		$scope.reportModal.show();
	};

	$scope.closeReportModal = function(){
		$scope.reportModal.hide();
	};

	$scope.sendReport = function(){
		if ($scope.reported){
			return false;
		}

		if (!$scope.reportData.reason){
			$ionicPopup.alert({
				template: '
Please choose reason
'
			});
		}
		else{
			chatService.sendMessage({
				type: 'report',
				reason: $scope.reportData.reason
			});
			$scope.reported = true;

			$ionicPopup.alert({
				template: '
Your report has been sent. Thank you.
'
			}).then(function(){
				$scope.reportModal.hide();
				$scope.popoverChat.hide();
			});

		}
	};

	$ionicModal.fromTemplateUrl('templates/info-modal.html', {
		scope: $scope,
		animation: 'slide-in-up'
	}).then(function(modal){
		$scope.infoModal = modal;
	});

	$scope.openInfoModal = function(){
		$scope.infoModal.show();
	};

	$scope.closeInfoModal = function(){
		$scope.infoModal.hide();
	};

	$scope.blockStranger = function(){
		var template = '
Do you want block stranger and exit?
';
		if ($scope.inBlockList){
			template = '
Do you want unblock stranger?
';
		}
		$ionicPopup.confirm({
			title: '',
			template: template,
			okText: 'Yes'
		}).then(function(res){
			if (res){
				if ($scope.inBlockList == false){
					blocks.push($scope.infoStranger.fullId);

					var obj = {};
					obj[userData.userID] = blocks;
					window.localStorage.setItem('blocks', JSON.stringify(obj));

					$scope.inBlockList = true;

					$scope.popoverChat.hide();
					chatService.exit();
					$ionicNavBarDelegate.back();
				}
				else{
					for (var i = 0; i < blocks.length; i++){
						if (blocks[i] == $scope.infoStranger.fullId){
							blocks.splice(i, 1);
							break;
						}
					}

					var obj = {};
					obj[userData.userID] = blocks;
					window.localStorage.setItem('blocks', JSON.stringify(obj));

					$scope.inBlockList = false;
					isBlock = false;
					$scope.popoverChat.hide();
				}
			}
			else {

			}
		});

	};

	initChat();
});

ChatApp.controller('navBarCtrl', function($scope, $state, $ionicNavBarDelegate, chatService){
	$scope.exit = function(){
		//console.log('User exit!!');
		chatService.exit();

		$ionicNavBarDelegate.back();
	}
});<commit_msg>close info layer<commit_after>ChatApp.controller('ChatCtrl', function($scope, $state, $timeout, $interval, $ionicScrollDelegate, $ionicPopover, $ionicModal, $ionicPopup, $ionicNavBarDelegate, chatService){
	$scope.title = 'Chat English';
	$scope.chats = [];
	$scope.reportData = {};

	$scope.inBlockList = false;
	var blocks = [];
	var isBlock = false;

	//$scope.haveStranger = true;
	//$scope.strangerLiked = true;

	//console.log(userData);

	function initChat(){

		var localBlocks = window.localStorage.getItem('blocks');
		if (localBlocks && userData.userID){
			blocks = JSON.parse(localBlocks)[userData.userID];
			if (!blocks){
				blocks = [];
				window.localStorage.removeItem('blocks');
			}
		}

		console.log(blocks);

		chatService.init({
			callbackSendMessage: function(){},
			callbackReceiveMessage: receiveChat,
			callbackConnect: function(){},
			callbackClose: onClose
		});
	};

	function onClose(){
		$scope.$apply(function(){
			$scope.chats.push({
				type: 'system',
				content: 'You has been disconnected, please exit and make new chat.'
			});
			$ionicScrollDelegate.scrollBottom(true);
		});
	}

	var isTyping = false;
	var timer;
	var lastTimeKeyPress = 0;
	var typingEle;

	function receiveChat(data){
		var content;

		if ($scope.chats.length > 0){
			if ($scope.chats[$scope.chats.length - 1].type == 'typing'){
				$scope.chats.pop();
			}
		}

		if (data.type == 'chat'){
			content = {
				type: data.from == 'system' ? 'system' : 'stranger',
				content : data.message
			};

			if (timer){
				isTyping = false;
				$interval.cancel(timer);
			}

		}
		else if (data.type == 'action'){
			if (data.action == 'typing'){
				content = {
					type: 'typing'
				};
			}
			else{

			}
		}

		//Check Like function
		if (data.stranger){
			$scope.haveStranger = true;
			$scope.strangerLiked = data.stranger.isLiked;

			$scope.infoStranger = {
				fullId: data.stranger.id,
				shortId: parseInt(data.stranger.id, 10),
				liked: data.stranger.liked,
				name: data.stranger.name,
				avatar: data.stranger.avatar
			};

			//Check blocklist
			if (data.from == 'system'){
				for (var i = 0; i < blocks.length; i++){
					if (blocks[i] == data.stranger.id){
						isBlock = true;
						$scope.inBlockList = true;
						break;
					}
				}

				if (isBlock){
					$ionicPopup.confirm({
						title: '',
						template: '
Stranger was blocked by you. Do you want to continue to chat with him?
',
						cancelText: 'Yes',
						okText: 'No, I don\'t.'
					}).then(function(res){
						if (!res){
							//Yes
							isBlock = false;
						}
						else {
							//No
							chatService.exit();
							$ionicNavBarDelegate.back();
						}
					});
				}
			}

		}

		if (content){
			if (isBlock && data.from == 'stranger'){

			}
			else{
				$scope.chats.push(content);
			}
		}

		$scope.$apply(function(){
			$ionicScrollDelegate.scrollBottom(true);
		});
	}

	$scope.sendChat = function(){
		var that = this;
		that.newChat = that.newChat.trim().replace(/\s{2,}/g, ' ');
		var newChat = that.newChat;
		if (newChat && newChat !== ''){
			if (timer){
				isTyping = false;
				$interval.cancel(timer);
			}

			chatService.sendMessage({
				type: 'chat',
				message: newChat
			});

			var content = {
				type: 'me',
				content : newChat
			};

			if ($scope.chats.length > 0 && $scope.chats[$scope.chats.length - 1].type == 'typing'){
				$scope.chats.splice($scope.chats.length - 1, 0, content);
			}
			else{
				$scope.chats.push(content);
			}

			$ionicScrollDelegate.scrollBottom(true);

		}

		that.newChat = '';
		$scope.focusInput = true;
	};

	$scope.chatKeyPress = function(e){
		lastTimeKeyPress = e.timeStamp;
		if (isTyping == false){
			isTyping = true;
			chatService.sendMessage({
				type: 'action',
				action: 'typing'
			});
			$interval.cancel(timer);
			timer = $interval(function(){
				if (isTyping && (new Date()).getTime() - lastTimeKeyPress > 4000){
					isTyping = false;
					$interval.cancel(timer);
					chatService.sendMessage({
						type: 'action',
						action: 'stop type'
					});
				}
			}, 1000);
		}
		else{

		}
	}

	$scope.likeStranger = function(){
		if ($scope.strangerLiked){
			return false;
		}
		$scope.strangerLiked = true;

		chatService.sendMessage({
			type: 'action',
			action: 'like'
		});
		$scope.infoStranger.liked++;

		$scope.popoverChat.hide();

		var content = {
			type: 'system',
			content : 'You\'ve just like the stranger. Thank you.'
		};

		$scope.chats.push(content);
		$ionicScrollDelegate.scrollBottom(true);
	};

	$ionicPopover.fromTemplateUrl('templates/popover.html', {
		scope: $scope,
	}).then(function(popover) {
    	$scope.popoverChat = popover;
	});

	$scope.showPopoverChat = function($event){
		$scope.popoverChat.show($event);
	};

	$ionicModal.fromTemplateUrl('templates/report-modal.html', {
		scope: $scope,
		animation: 'slide-in-up'
	}).then(function(modal){
		$scope.reportModal = modal;
	});

	$scope.openReportModal = function(){
		if ($scope.reported){
			return false;
		}
		$scope.reportModal.show();
	};

	$scope.closeReportModal = function(){
		$scope.reportModal.hide();
	};

	$scope.sendReport = function(){
		if ($scope.reported){
			return false;
		}

		if (!$scope.reportData.reason){
			$ionicPopup.alert({
				template: '
Please choose reason
'
			});
		}
		else{
			chatService.sendMessage({
				type: 'report',
				reason: $scope.reportData.reason
			});
			$scope.reported = true;

			$ionicPopup.alert({
				template: '
Your report has been sent. Thank you.
'
			}).then(function(){
				$scope.reportModal.hide();
				$scope.popoverChat.hide();
			});

		}
	};

	$ionicModal.fromTemplateUrl('templates/info-modal.html', {
		scope: $scope,
		animation: 'slide-in-up'
	}).then(function(modal){
		$scope.infoModal = modal;
	});

	$scope.openInfoModal = function(){
		$scope.infoModal.show();
	};

	$scope.closeInfoModal = function(){
		$scope.infoModal.hide();
		$scope.popoverChat.hide();
	};

	$scope.blockStranger = function(){
		var template = '
Do you want block stranger and exit?
';
		if ($scope.inBlockList){
			template = '
Do you want unblock stranger?
';
		}
		$ionicPopup.confirm({
			title: '',
			template: template,
			okText: 'Yes'
		}).then(function(res){
			if (res){
				if ($scope.inBlockList == false){
					blocks.push($scope.infoStranger.fullId);

					var obj = {};
					obj[userData.userID] = blocks;
					window.localStorage.setItem('blocks', JSON.stringify(obj));

					$scope.inBlockList = true;

					$scope.popoverChat.hide();
					chatService.exit();
					$ionicNavBarDelegate.back();
				}
				else{
					for (var i = 0; i < blocks.length; i++){
						if (blocks[i] == $scope.infoStranger.fullId){
							blocks.splice(i, 1);
							break;
						}
					}

					var obj = {};
					obj[userData.userID] = blocks;
					window.localStorage.setItem('blocks', JSON.stringify(obj));

					$scope.inBlockList = false;
					isBlock = false;
					$scope.popoverChat.hide();
				}
			}
			else {

			}
		});

	};

	initChat();
});

ChatApp.controller('navBarCtrl', function($scope, $state, $ionicNavBarDelegate, chatService){
	$scope.exit = function(){
		//console.log('User exit!!');
		chatService.exit();

		$ionicNavBarDelegate.back();
	}
});<|endoftext|>


<commit_before>var SvgObject   = require(__dirname + '/svgobject'),
    Matrix      = require(__dirname + '/../matrix/extends'),
    _           = require('underscore'),
    utils       = require(__dirname + '/../matrix/utils'),
    async       = require('async'),
    nUtil       = require('util');

var Circle = function() {
    if (!(this instanceof Circle))
        throw 'this function in a constructor. Use new to call it';

    SvgObject.call(this);
    this.type   = 'circle';
    this.cx     = 0;
    this.cy     = 0;
    this.r      = 0;
};

nUtil.inherits(Circle, SvgObject);

/**
 * Get Center x value
 * @returns {number}
 */
Circle.prototype.getCx = function getCx() {
    return this.cx;
};

/**
 * Get Center y value
 * @returns {number}
 */
Circle.prototype.getCy = function getCy() {
    return this.cy;
};

/**
 * Get circle's radius
 * @return {number}
 */
Circle.prototype.getRadius = function getRadius() {
    return this.r;
};

/**
 * Set Cx coordinate
 * @param {number}      cx      cx coordinate
 */
Circle.prototype.setCx = function setCx(cx) {
    this.cx = cx;
};

/**
 * Set Cy coordinate
 * @param {number}      cy      cy coordinate
 */
Circle.prototype.setCy = function setCy(cy) {
    this.cy = cy;
};

/**
 * Set Radius
 * @param {number}      r      radius
 */
Circle.prototype.setRadius = function setRadius(r) {
    this.r = r;
};

/**
 * Return JSON from object
 * @param   {boolean}    [matrix]       return transform attribute if false.
 * @returns {object}                    JSON Object
 */
Circle.prototype.toJSON = function(matrix){
    var parentJSON = SvgObject.prototype.toJSON.call(this, matrix);

    parentJSON.cx   = this.cx;
    parentJSON.cy   = this.cy;
    parentJSON.r    = this.r;

    return parentJSON;
};

/**
 * Return XML from object
 * @param   {boolean}    [matrix]       return transform attribute if false.
 * @returns {xmlBuilder}                XML Object
 */
Circle.prototype.toXml = function toXml(matrix) {
    var xml = SvgObject.prototype.toXml.call(this, matrix);

    xml.att('cx', this.cx);
    xml.att('cy', this.cy);
    xml.att('r', this.r);

    return xml;
};

/**
 * Get the element Bounding Box
 * @param {function} callback           Callback Function
 */
Circle.prototype.getBBox = function getBBox(callback) {
    this.bbox = utils.bbox(this.cx - this.r, this.cy - this.r, this.r*2, this.r*2);
    callback(this.bbox);
};

module.exports = Circle;

/**
 * Create Circle from SVG image node
 *
 * @param   {object}    node            xml2js node from SVG file
 * @returns {Circle}                    the Circle object
 */
module.exports.fromNode = function fromNode(node) {
    var circle = new Circle();

    if (typeof node != 'undefined' && typeof node.$ != 'undefined') {
        SvgObject.fromNode(circle, node);

        if (typeof node.$.cx != 'undefined') {
            circle.cx = parseFloat(node.$.cx);
        }
        if (typeof node.$.cy != 'undefined') {
            circle.cy = parseFloat(node.$.cy);
        }
        if (typeof node.$.r != 'undefined') {
            circle.r = parseFloat(node.$.r);
        }
    }
    return circle;
};

/**
 * Create Circle from JSON element
 *
 * @param   {object}    json        json element
 * @returns {Circle}                the Circle object
 */
module.exports.fromJson = function fromJson(json){
    var circle = new Circle();

    if (typeof json != 'undefined') {
        SvgObject.fromJson(circle, json);

        if (typeof json.cx != 'undefined') {
            circle.cx = json.cx;
        }
        if (typeof json.cy != 'undefined') {
            circle.cy = json.cy;
        }
        if (typeof json.r != 'undefined') {
            circle.r = json.r;
        }
    }
    return circle;
};<commit_msg>add circle innerBox<commit_after>var SvgObject   = require(__dirname + '/svgobject'),
    Matrix      = require(__dirname + '/../matrix/extends'),
    _           = require('underscore'),
    utils       = require(__dirname + '/../matrix/utils'),
    async       = require('async'),
    nUtil       = require('util');

var Circle = function() {
    if (!(this instanceof Circle))
        throw 'this function in a constructor. Use new to call it';

    SvgObject.call(this);
    this.type   = 'circle';
    this.cx     = 0;
    this.cy     = 0;
    this.r      = 0;
};

nUtil.inherits(Circle, SvgObject);

/**
 * Get Center x value
 * @returns {number}
 */
Circle.prototype.getCx = function getCx() {
    return this.cx;
};

/**
 * Get Center y value
 * @returns {number}
 */
Circle.prototype.getCy = function getCy() {
    return this.cy;
};

/**
 * Get circle's radius
 * @return {number}
 */
Circle.prototype.getRadius = function getRadius() {
    return this.r;
};

/**
 * Set Cx coordinate
 * @param {number}      cx      cx coordinate
 */
Circle.prototype.setCx = function setCx(cx) {
    this.cx = cx;
};

/**
 * Set Cy coordinate
 * @param {number}      cy      cy coordinate
 */
Circle.prototype.setCy = function setCy(cy) {
    this.cy = cy;
};

/**
 * Set Radius
 * @param {number}      r      radius
 */
Circle.prototype.setRadius = function setRadius(r) {
    this.r = r;
};

/**
 * Return JSON from object
 * @param   {boolean}    [matrix]       return transform attribute if false.
 * @returns {object}                    JSON Object
 */
Circle.prototype.toJSON = function(matrix){
    var parentJSON = SvgObject.prototype.toJSON.call(this, matrix);

    parentJSON.cx   = this.cx;
    parentJSON.cy   = this.cy;
    parentJSON.r    = this.r;

    return parentJSON;
};

/**
 * Return XML from object
 * @param   {boolean}    [matrix]       return transform attribute if false.
 * @returns {xmlBuilder}                XML Object
 */
Circle.prototype.toXml = function toXml(matrix) {
    var xml = SvgObject.prototype.toXml.call(this, matrix);

    xml.att('cx', this.cx);
    xml.att('cy', this.cy);
    xml.att('r', this.r);

    return xml;
};

/**
 * Get the element Bounding Box
 * @param {function} callback           Callback Function
 */
Circle.prototype.getBBox = function getBBox(callback) {
    this.bbox = utils.bbox(this.cx - this.r, this.cy - this.r, this.r*2, this.r*2);
    callback(this.bbox);
};

/**
 * Get the element innerBox
 * @param {function} callback               Callback function
 */
Circle.prototype.getInnerBox = function getInnerBox(callback) {
    // @todo verify calcul
    var diff = this.r*2 - Math.sqrt(2)*this.r;

    callback({
        x       : this.cx - diff,
        y       : this.cy - diff,
        width   : this.r-diff,
        height  : this.r - diff
    });
};

module.exports = Circle;

/**
 * Create Circle from SVG image node
 *
 * @param   {object}    node            xml2js node from SVG file
 * @returns {Circle}                    the Circle object
 */
module.exports.fromNode = function fromNode(node) {
    var circle = new Circle();

    if (typeof node != 'undefined' && typeof node.$ != 'undefined') {
        SvgObject.fromNode(circle, node);

        if (typeof node.$.cx != 'undefined') {
            circle.cx = parseFloat(node.$.cx);
        }
        if (typeof node.$.cy != 'undefined') {
            circle.cy = parseFloat(node.$.cy);
        }
        if (typeof node.$.r != 'undefined') {
            circle.r = parseFloat(node.$.r);
        }
    }
    return circle;
};

/**
 * Create Circle from JSON element
 *
 * @param   {object}    json        json element
 * @returns {Circle}                the Circle object
 */
module.exports.fromJson = function fromJson(json){
    var circle = new Circle();

    if (typeof json != 'undefined') {
        SvgObject.fromJson(circle, json);

        if (typeof json.cx != 'undefined') {
            circle.cx = json.cx;
        }
        if (typeof json.cy != 'undefined') {
            circle.cy = json.cy;
        }
        if (typeof json.r != 'undefined') {
            circle.r = json.r;
        }
    }
    return circle;
};<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint max-lines: off*/
(function(){
	"use strict";
	var settingsDisplay = [
		{
			name: "general",
			sections: [
				{
					name: "",
					settings: [
						{
							"name": "displayAdvancedSettings"
						},
						{
							"name": "blockMode"
						},
					]
				},
				{
					name: "asking",
					settings: [
						{
							"name": "askOnlyOnce",
							"displayDependencies": {
								"blockMode": ["ask"]
							}
						},
						{
							"name": "askDenyMode",
							"displayDependencies": {
								"blockMode": ["ask"],
								"displayAdvancedSettings": [true]
							}
						},
						{
							"name": "showCanvasWhileAsking",
							"displayDependencies": {
								"blockMode": ["ask"],
								"displayAdvancedSettings": [true]
							}
						},
					]
				},
				{
					name: "faking",
					settings: [
						{
							"name": "rng",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "storePersistentRnd",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"rng": ["persistent"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"rng": ["persistent"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "persistentRndClearInterval",
							"inputs": ["persistentRndClearIntervalValue", "persistentRndClearIntervalUnit"],
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"rng": ["persistent"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"rng": ["persistent"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "clearPersistentRnd",
							"actions": ["clearPersistentRnd", "clearPersistentRndForContainer"],
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"rng": ["persistent"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"rng": ["persistent"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "sharePersistentRndBetweenDomains",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"rng": ["persistent"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"rng": ["persistent"],
									"displayAdvancedSettings": [true]
								}
							]
						},
					]
				},
				{
					name: "notifications",
					settings: [
						{
							"name": "showNotifications"
						},
						{
							"name": "highlightPageAction",
							"displayDependencies": [
								{
									"showNotifications": [true]
								}
							]
						},
						{
							"name": "displayBadge"
						},
						{
							"name": "highlightBrowserAction"
						},
						{
							"name": "storeNotificationData",
							"displayDependencies": [
								{
									"showNotifications": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "ignoreList",
							"multiline": true,
							"displayDependencies": [
								{
									"showNotifications": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"displayBadge": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"highlightBrowserAction": ["color", "blink"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "ignoredAPIs",
							"displayDependencies": [
								{
									"showNotifications": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"displayBadge": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"highlightBrowserAction": ["color", "blink"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "showCallingFile",
							"displayDependencies": {
								"blockMode": ["ask"],
								"displayAdvancedSettings": [true]
							}
						},
						{
							"name": "showCompleteCallingStack",
							"displayDependencies": [
								{
									"displayAdvancedSettings": [true]
								}
							]
						},
					]
				},
				{
					name: "lists",
					settings: [
						{
							"name": "enableStackList",
							"displayDependencies": {
								"blockMode": ["fake", "block", "ask"],
								"displayAdvancedSettings": [true]
							}
						},
						{
							"name": "stackList",
							"multiline": true,
							"displayDependencies": {
								"enableStackList": [true],
								"displayAdvancedSettings": [true]
							}

						},
						{
							"name": "whiteList",
							"multiline": true,
							"displayDependencies": {
								"blockMode": ["fake", "block", "ask"],
								"displayAdvancedSettings": [true]
							}
						},
						{
							"name": "sessionWhiteList",
							"multiline": true,
							"displayDependencies": {
								"blockMode": ["fake", "block", "ask"],
								"displayAdvancedSettings": [true]
							}
						},
						{
							"name": "blackList",
							"multiline": true,
							"displayDependencies": {
								"blockMode": ["block", "fake", "ask", "allow"],
								"displayAdvancedSettings": [true]
							}
						},
					]
				},
				{
					name: "settings",
					settings: [
						{
							"name": "displayDescriptions"
						},
						{
							"name": "openSettingSanitation"
						},
						{
							"name": "exportSettings",
							"actions": ["inspectSettings", "inspectWhitelist", "saveSettings", "loadSettings"]
						},
						{
							"name": "resetSettings"
						}
					]
				},
			]
		},
		{
			name: "APIs",
			sections: [
				{
					name: "Canvas-API",
					settings: [
						{
							"name": "protectedCanvasPart"
						},
						{
							"name": "protectedAPIFeatures",
							"displayedSection": "Canvas-API",
							"displayDependencies": [
								{
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "minFakeSize",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "maxFakeSize",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "ignoreFrequentColors",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"protectedCanvasPart": ["readout", "everything"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "minColors",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"protectedCanvasPart": ["readout", "everything"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "fakeAlphaChannel",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"protectedCanvasPart": ["readout", "everything"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "useCanvasCache",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"protectedCanvasPart": ["readout", "everything"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "storeImageForInspection",
							"displayDependencies": [
								{
									"showNotifications": [true],
									"storeNotificationData": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
					]
				},
				{
					name: "Audio-API",
					settings: [
						{
							"name": "protectAudio"
						},
						{
							"name": "protectedAPIFeatures",
							"displayedSection": "Audio-API",
							"displayDependencies": [
								{
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "audioFakeRate",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "audioNoiseLevel",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "useAudioCache",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "audioUseFixedIndices",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "audioFixedIndices",
							"displayDependencies": [
								{
									"audioUseFixedIndices": [true],
									"blockMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"audioUseFixedIndices": [true],
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
					]
				},
				{
					name: "History-API",
					settings: [
						{
							"name": "protectedAPIFeatures",
							"displayedSection": "History-API",
							"displayDependencies": [
								{
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "historyLengthThreshold",
							"displayDependencies": {
								"displayAdvancedSettings": [true]
							}
						},
					]
				},
				{
					name: "Window-API",
					settings: [
						{
							"name": "protectWindow"
						},
						{
							"name": "protectedAPIFeatures",
							"displayedSection": "Window-API",
							"displayDependencies": [
								{
									"protectWindow": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
					]
				},
				{
					name: "DOMRect-API",
					settings: [
						{
							"name": "protectDOMRect"
						},
						{
							"name": "protectedAPIFeatures",
							"displayedSection": "DOMRect-API",
							"displayDependencies": [
								{
									"protectDOMRect": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "domRectIntegerFactor",
							"displayDependencies": {
								"protectDOMRect": [true],
								"displayAdvancedSettings": [true]
							}
						},
					]
				},
				{
					name: "Navigator-API",
					settings: [
						{
							"name": "protectNavigator"
						},
						{
							"name": "protectedAPIFeatures",
							"displayedSection": "Navigator-API",
							"displayDependencies": [
								{
									"protectNavigator": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "openNavigatorSettings",
							"displayDependencies": [
								{
									"protectNavigator": [true]
								}
							]
						},
					]
				},
			]
		},
		{
			name: "misc",
			sections: [
				{
					name: "misc",
					settings: [
						{
							"name": "theme"
						},
						{
							"name": "blockDataURLs",
							"displayDependencies": {
								"displayAdvancedSettings": [true]
							}
						},
						{
							"name": "showReleaseNotes"
						},
						{
							"name": "logLevel",
							"displayDependencies": {
								"displayAdvancedSettings": [true]
							}
						},
					]
				},
			]
		}
	];
	settingsDisplay.displayHidden = "displayHiddenSettings";

	if ((typeof module) !== "undefined"){
		module.exports = settingsDisplay;
	}
	else {
		require.register("./settingsDisplay", settingsDisplay);
	}
}());<commit_msg>Only show "Clear container" if they are available<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint max-lines: off*/
(function(){
	"use strict";
	var settingsDisplay = [
		{
			name: "general",
			sections: [
				{
					name: "",
					settings: [
						{
							"name": "displayAdvancedSettings"
						},
						{
							"name": "blockMode"
						},
					]
				},
				{
					name: "asking",
					settings: [
						{
							"name": "askOnlyOnce",
							"displayDependencies": {
								"blockMode": ["ask"]
							}
						},
						{
							"name": "askDenyMode",
							"displayDependencies": {
								"blockMode": ["ask"],
								"displayAdvancedSettings": [true]
							}
						},
						{
							"name": "showCanvasWhileAsking",
							"displayDependencies": {
								"blockMode": ["ask"],
								"displayAdvancedSettings": [true]
							}
						},
					]
				},
				{
					name: "faking",
					settings: [
						{
							"name": "rng",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "storePersistentRnd",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"rng": ["persistent"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"rng": ["persistent"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "persistentRndClearInterval",
							"inputs": ["persistentRndClearIntervalValue", "persistentRndClearIntervalUnit"],
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"rng": ["persistent"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"rng": ["persistent"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "clearPersistentRnd",
							"actions": [
								"clearPersistentRnd",
								browser.contextualIdentities? "clearPersistentRndForContainer": false
							],
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"rng": ["persistent"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"rng": ["persistent"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "sharePersistentRndBetweenDomains",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"rng": ["persistent"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"rng": ["persistent"],
									"displayAdvancedSettings": [true]
								}
							]
						},
					]
				},
				{
					name: "notifications",
					settings: [
						{
							"name": "showNotifications"
						},
						{
							"name": "highlightPageAction",
							"displayDependencies": [
								{
									"showNotifications": [true]
								}
							]
						},
						{
							"name": "displayBadge"
						},
						{
							"name": "highlightBrowserAction"
						},
						{
							"name": "storeNotificationData",
							"displayDependencies": [
								{
									"showNotifications": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "ignoreList",
							"multiline": true,
							"displayDependencies": [
								{
									"showNotifications": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"displayBadge": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"highlightBrowserAction": ["color", "blink"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "ignoredAPIs",
							"displayDependencies": [
								{
									"showNotifications": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"displayBadge": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"highlightBrowserAction": ["color", "blink"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "showCallingFile",
							"displayDependencies": {
								"blockMode": ["ask"],
								"displayAdvancedSettings": [true]
							}
						},
						{
							"name": "showCompleteCallingStack",
							"displayDependencies": [
								{
									"displayAdvancedSettings": [true]
								}
							]
						},
					]
				},
				{
					name: "lists",
					settings: [
						{
							"name": "enableStackList",
							"displayDependencies": {
								"blockMode": ["fake", "block", "ask"],
								"displayAdvancedSettings": [true]
							}
						},
						{
							"name": "stackList",
							"multiline": true,
							"displayDependencies": {
								"enableStackList": [true],
								"displayAdvancedSettings": [true]
							}

						},
						{
							"name": "whiteList",
							"multiline": true,
							"displayDependencies": {
								"blockMode": ["fake", "block", "ask"],
								"displayAdvancedSettings": [true]
							}
						},
						{
							"name": "sessionWhiteList",
							"multiline": true,
							"displayDependencies": {
								"blockMode": ["fake", "block", "ask"],
								"displayAdvancedSettings": [true]
							}
						},
						{
							"name": "blackList",
							"multiline": true,
							"displayDependencies": {
								"blockMode": ["block", "fake", "ask", "allow"],
								"displayAdvancedSettings": [true]
							}
						},
					]
				},
				{
					name: "settings",
					settings: [
						{
							"name": "displayDescriptions"
						},
						{
							"name": "openSettingSanitation"
						},
						{
							"name": "exportSettings",
							"actions": ["inspectSettings", "inspectWhitelist", "saveSettings", "loadSettings"]
						},
						{
							"name": "resetSettings"
						}
					]
				},
			]
		},
		{
			name: "APIs",
			sections: [
				{
					name: "Canvas-API",
					settings: [
						{
							"name": "protectedCanvasPart"
						},
						{
							"name": "protectedAPIFeatures",
							"displayedSection": "Canvas-API",
							"displayDependencies": [
								{
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "minFakeSize",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "maxFakeSize",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "ignoreFrequentColors",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"protectedCanvasPart": ["readout", "everything"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "minColors",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"protectedCanvasPart": ["readout", "everything"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "fakeAlphaChannel",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"protectedCanvasPart": ["readout", "everything"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "useCanvasCache",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"protectedCanvasPart": ["readout", "everything"],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "storeImageForInspection",
							"displayDependencies": [
								{
									"showNotifications": [true],
									"storeNotificationData": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
					]
				},
				{
					name: "Audio-API",
					settings: [
						{
							"name": "protectAudio"
						},
						{
							"name": "protectedAPIFeatures",
							"displayedSection": "Audio-API",
							"displayDependencies": [
								{
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "audioFakeRate",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "audioNoiseLevel",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "useAudioCache",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "audioUseFixedIndices",
							"displayDependencies": [
								{
									"blockMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "audioFixedIndices",
							"displayDependencies": [
								{
									"audioUseFixedIndices": [true],
									"blockMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								},
								{
									"audioUseFixedIndices": [true],
									"blockMode": ["ask"],
									"askDenyMode": ["fake"],
									"protectAudio": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
					]
				},
				{
					name: "History-API",
					settings: [
						{
							"name": "protectedAPIFeatures",
							"displayedSection": "History-API",
							"displayDependencies": [
								{
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "historyLengthThreshold",
							"displayDependencies": {
								"displayAdvancedSettings": [true]
							}
						},
					]
				},
				{
					name: "Window-API",
					settings: [
						{
							"name": "protectWindow"
						},
						{
							"name": "protectedAPIFeatures",
							"displayedSection": "Window-API",
							"displayDependencies": [
								{
									"protectWindow": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
					]
				},
				{
					name: "DOMRect-API",
					settings: [
						{
							"name": "protectDOMRect"
						},
						{
							"name": "protectedAPIFeatures",
							"displayedSection": "DOMRect-API",
							"displayDependencies": [
								{
									"protectDOMRect": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "domRectIntegerFactor",
							"displayDependencies": {
								"protectDOMRect": [true],
								"displayAdvancedSettings": [true]
							}
						},
					]
				},
				{
					name: "Navigator-API",
					settings: [
						{
							"name": "protectNavigator"
						},
						{
							"name": "protectedAPIFeatures",
							"displayedSection": "Navigator-API",
							"displayDependencies": [
								{
									"protectNavigator": [true],
									"displayAdvancedSettings": [true]
								}
							]
						},
						{
							"name": "openNavigatorSettings",
							"displayDependencies": [
								{
									"protectNavigator": [true]
								}
							]
						},
					]
				},
			]
		},
		{
			name: "misc",
			sections: [
				{
					name: "misc",
					settings: [
						{
							"name": "theme"
						},
						{
							"name": "blockDataURLs",
							"displayDependencies": {
								"displayAdvancedSettings": [true]
							}
						},
						{
							"name": "showReleaseNotes"
						},
						{
							"name": "logLevel",
							"displayDependencies": {
								"displayAdvancedSettings": [true]
							}
						},
					]
				},
			]
		}
	];
	settingsDisplay.displayHidden = "displayHiddenSettings";

	if ((typeof module) !== "undefined"){
		module.exports = settingsDisplay;
	}
	else {
		require.register("./settingsDisplay", settingsDisplay);
	}
}());<|endoftext|>


<commit_before>var http = require('http'),
    Vow = require('vow'),
    form = new require('formidable').IncomingForm(),
    PORT = process.env.ASKER_TEST_PORT || 10080;

/**
 * @constructor
 * @class TestServer
 * @param {Number} port
 * @param {String} [host=localhost]
 * @param {Array} testDispatchers array of functions used as dispatchers for request
 */
function TestServer(port, host, testDispatchers) {
    if (Array.isArray(host) && typeof testDispatchers === 'undefined') {
        this.tests = host;
    } else {
        this.tests = testDispatchers ? [].concat(testDispatchers) : [];
    }

    this.port = port;
    this.host = (typeof host === 'string') ? host : 'localhost';

    this.servant = http.createServer(this.dispatcher.bind(this));
}

/**
 * @param {Function} callback
 */
TestServer.prototype.listen = function(callback) {
    return this.servant.listen(this.port, this.host, callback);
};

/**
 * @param {http.IncomingMessage} req
 * @param {http.ServerResponse} res
 */
TestServer.prototype.dispatcher = function(req, res) {
    var d = this.tests.shift();

    if ( ! d || (typeof d !== 'function')) {
        res.statusCode = 500;
        res.end(this.buildResponse(false, ( ! d) ? 'test dispatcher not found' : 'test dispatcher is not a function'));
    } else {
        // Use formidable parser when getting typed content (urlencoded, json, multipart)
        if (/(urlencoded|json|multipart)/.test(req.headers['content-type'])) {
            form.parse(req, function(err, fields, files) {
                if (err) {
                    res.statusCode = 500;
                    res.end('formidable error: ' + err);
                } else {
                    req.body = fields;
                    req.files = files;
                    d(req, res);
                }
            });
        } else {
            req.body = '';
            req.on('data', function(d) {
                req.body += d;
            });
            req.on('end', function() {
                d(req, res);
            });
        }
    }
};

/**
 * add test dispatcher to tests pool
 * @param {Function} testDispatcher
 */
TestServer.prototype.addTest = function(testDispatcher) {
    this.tests.push(testDispatcher);
};

/**
 * build JSON response
 * @param {Boolean} isDone
 * @param {String} message
 * @returns {String} stringified object { done : isDone, message : message }
 */
TestServer.prototype.buildResponse = function(isDone, message) {
    return JSON.stringify({
        done : isDone,
        message : message
    });
};

/**
 * proxy to http.Server.close method
 * @param {Function} callback
 */
TestServer.prototype.close = function(callback) {
    this.servant.on('close', callback);
    return this.servant.close();
};

/**
 * Promisify all http tests, flawlessly create/close servers
 * @param {Function} testFn test function
 * @returns {Function}
 */
function httpTest(testFn) {
    /**
     * @param {Function} mochaDone test done callback
     */
    return function(mochaDone) {
        var server;

        (function() {
            var promise = Vow.promise();

            server = new TestServer(PORT++);
            server.listen(function() {
                promise.fulfill(server);
            });

            return promise;
        })()
        .then(function(server) {
            var promise = Vow.promise();

            testFn(function() {
                promise.fulfill(server);
            }, server);

            return promise;
        })
        .then(function(server) {
            server.close(mochaDone);
        });
    };
}

module.exports = httpTest;
<commit_msg>fix httpTest utility for node 0.8<commit_after>var http = require('http'),
    Vow = require('vow'),
    Form = require('formidable').IncomingForm,
    form = new Form(),
    PORT = process.env.ASKER_TEST_PORT || 10080;

/**
 * @constructor
 * @class TestServer
 * @param {Number} port
 * @param {String} [host=localhost]
 * @param {Array} testDispatchers array of functions used as dispatchers for request
 */
function TestServer(port, host, testDispatchers) {
    if (Array.isArray(host) && typeof testDispatchers === 'undefined') {
        this.tests = host;
    } else {
        this.tests = testDispatchers ? [].concat(testDispatchers) : [];
    }

    this.port = port;
    this.host = (typeof host === 'string') ? host : 'localhost';

    this.servant = http.createServer(this.dispatcher.bind(this));
}

/**
 * @param {Function} callback
 */
TestServer.prototype.listen = function(callback) {
    return this.servant.listen(this.port, this.host, callback);
};

/**
 * @param {http.IncomingMessage} req
 * @param {http.ServerResponse} res
 */
TestServer.prototype.dispatcher = function(req, res) {
    var d = this.tests.shift();

    if ( ! d || (typeof d !== 'function')) {
        res.statusCode = 500;
        res.end(this.buildResponse(false, ( ! d) ? 'test dispatcher not found' : 'test dispatcher is not a function'));
    } else {
        // Use formidable parser when getting typed content (urlencoded, json, multipart)
        if (/(urlencoded|json|multipart)/.test(req.headers['content-type'])) {
            form.parse(req, function(err, fields, files) {
                if (err) {
                    res.statusCode = 500;
                    res.end('formidable error: ' + err);
                } else {
                    req.body = fields;
                    req.files = files;
                    d(req, res);
                }
            });
        } else {
            req.body = '';

            req.on('data', function(d) {
                req.body += d;
            });

            req.on('end', function() {
                d(req, res);
            });
        }
    }
};

/**
 * add test dispatcher to tests pool
 * @param {Function} testDispatcher
 */
TestServer.prototype.addTest = function(testDispatcher) {
    this.tests.push(testDispatcher);
};

/**
 * build JSON response
 * @param {Boolean} isDone
 * @param {String} message
 * @returns {String} stringified object { done : isDone, message : message }
 */
TestServer.prototype.buildResponse = function(isDone, message) {
    return JSON.stringify({
        done : isDone,
        message : message
    });
};

/**
 * proxy to http.Server.close method
 * @param {Function} callback
 */
TestServer.prototype.close = function(callback) {
    this.servant.on('close', callback);
    return this.servant.close();
};

/**
 * Promisify all http tests, flawlessly create/close servers
 * @param {Function} testFn test function
 * @returns {Function}
 */
function httpTest(testFn) {
    /**
     * @param {Function} mochaDone test done callback
     */
    return function(mochaDone) {
        var server;

        (function() {
            var promise = Vow.promise();

            server = new TestServer(PORT++);
            server.listen(function() {
                promise.fulfill(server);
            });

            return promise;
        })()
        .then(function(server) {
            var promise = Vow.promise();

            testFn(function() {
                server.close(mochaDone);
            }, server);

            return promise;
        })
        .done();
    };
}

module.exports = httpTest;
<|endoftext|>


<commit_before>(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define("Servable", [], factory);
	else if(typeof exports === 'object')
		exports["Servable"] = factory();
	else
		root["Servable"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId]) {
/******/ 			return installedModules[moduleId].exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ 		// Flag the module as loaded
/******/ 		module.l = true;
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/******/
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;
/******/
/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;
/******/
/******/ 	// identity function for calling harmony imports with the correct context
/******/ 	__webpack_require__.i = function(value) { return value; };
/******/
/******/ 	// define getter function for harmony exports
/******/ 	__webpack_require__.d = function(exports, name, getter) {
/******/ 		if(!__webpack_require__.o(exports, name)) {
/******/ 			Object.defineProperty(exports, name, {
/******/ 				configurable: false,
/******/ 				enumerable: true,
/******/ 				get: getter
/******/ 			});
/******/ 		}
/******/ 	};
/******/
/******/ 	// getDefaultExport function for compatibility with non-harmony modules
/******/ 	__webpack_require__.n = function(module) {
/******/ 		var getter = module && module.__esModule ?
/******/ 			function getDefault() { return module['default']; } :
/******/ 			function getModuleExports() { return module; };
/******/ 		__webpack_require__.d(getter, 'a', getter);
/******/ 		return getter;
/******/ 	};
/******/
/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";
/******/
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(__webpack_require__.s = 1);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return Subscription; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return Observable; });
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var noop = function noop() {};

var Subscription = function () {
  function Subscription(callback, observer) {
    _classCallCheck(this, Subscription);

    this.isComplete = false;
    this.dispose = noop;

    this.observer = this.wrapObserver(observer);

    this.callWithObserver(callback);
  }

  Subscription.prototype.unsubscribe = function unsubscribe() {
    var _this = this;

    this.catchErrors(function () {
      _this.dispose();

      _this.isComplete = true;
      _this.observer.next = noop;
      _this.observer.error = noop;
      _this.observer.complete = noop;
    })();
  };

  Subscription.prototype.catchErrors = function catchErrors(callback) {
    var _this2 = this;

    return function () {
      try {
        callback.apply(undefined, arguments);
      } catch (errors) {
        _this2.observer.error(errors);
      }
    };
  };

  Subscription.prototype.wrapObserver = function wrapObserver(observer) {
    var _this3 = this;

    var _observer$next = observer.next,
        next = _observer$next === undefined ? noop : _observer$next,
        _observer$error = observer.error,
        error = _observer$error === undefined ? noop : _observer$error,
        _observer$complete = observer.complete,
        complete = _observer$complete === undefined ? noop : _observer$complete;

    // assumes that an object was passed as first value to subscription

    if (next.next || next.error || next.complete) {
      return this.wrapObserver(next);
    }

    var returnObserver = {};

    returnObserver.next = this.catchErrors(function () {
      if (!_this3.isComplete) {
        next.apply(undefined, arguments);
      } else {
        // overwrite the next so it cannot run again if complete
        next = noop;
      }
    });

    returnObserver.error = this.catchErrors(function () {
      if (!_this3.isComplete) {
        error.apply(undefined, arguments);
      } else {
        // overwrite the error so it cannot run again if complete
        error = noop;
      }
    });

    returnObserver.complete = this.catchErrors(function () {
      if (!_this3.isComplete) {
        _this3.unsubscribe();
        complete();
      }

      // overwrite the complete so it doesnt run again
      complete = noop;
      _this3.isComplete = true;
    });

    return returnObserver;
  };

  Subscription.prototype.callWithObserver = function callWithObserver(callback) {
    var _this4 = this;

    this.catchErrors(function () {
      var response = callback(_this4.observer);

      if (typeof response === 'function') {
        _this4.dispose = response;
      }
    })();
  };

  return Subscription;
}();

var Observable = function () {
  function Observable(observerCallback) {
    _classCallCheck(this, Observable);

    this.observerCallback = observerCallback;
  }

  Observable.prototype.subscribe = function subscribe() {
    var next = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : noop;
    var error = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop;
    var complete = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : noop;

    return new Subscription(this.observerCallback, { next: next, error: error, complete: complete });
  };

  return Observable;
}();

/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__servable__ = __webpack_require__(0);
/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Subscription", function() { return __WEBPACK_IMPORTED_MODULE_0__servable__["a"]; });
/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Observable", function() { return __WEBPACK_IMPORTED_MODULE_0__servable__["b"]; });

/***/ })
/******/ ]);
});<commit_msg>cleanup repository after release<commit_after><|endoftext|>


<commit_before>/**
 * @license
 * Copyright The Closure Library Authors.
 * SPDX-License-Identifier: Apache-2.0
 */

goog.module('goog.cssomTest');
goog.setTestOnly();

const CssRuleType = goog.require('goog.cssom.CssRuleType');
const cssom = goog.require('goog.cssom');
const googArray = goog.require('goog.array');
const testSuite = goog.require('goog.testing.testSuite');
const userAgent = goog.require('goog.userAgent');

// Since sheet cssom_test1.css's first line is to import
// cssom_test2.css, we should get 2 before one in the string.
let cssText = '.css-link-1 { display: block; } ' +
    '.css-import-2 { display: block; } ' +
    '.css-import-1 { display: block; } ' +
    '.css-style-1 { display: block; } ' +
    '.css-style-2 { display: block; } ' +
    '.css-style-3 { display: block; }';

const replacementCssText = '.css-repl-1 { display: block; }';

const isIe7 =
    userAgent.IE && (userAgent.compare(userAgent.VERSION, '7.0') == 0);

// We're going to toLowerCase cssText before testing, because IE returns
// CSS property names in UPPERCASE, and the function shouldn't
// "fix" the text as it would be expensive and rarely of use.
// Same goes for the trailing whitespace in IE.
// Same goes for fixing the optimized removal of trailing ; in rules.
// Also needed for Opera.
function fixCssTextForIe(cssText) {
  cssText = cssText.toLowerCase().replace(/\s*$/, '');
  if (cssText.match(/[^;] \}/)) {
    cssText = cssText.replace(/([^;]) \}/g, '$1; }');
  }
  return cssText;
}

// Tests the scenario where we have a known stylesheet and index.

testSuite({
  testGetFileNameFromStyleSheet() {
    let styleSheet = {'href': 'http://foo.com/something/filename.css'};
    assertEquals('filename.css', cssom.getFileNameFromStyleSheet(styleSheet));

    styleSheet = {'href': 'https://foo.com:123/something/filename.css'};
    assertEquals('filename.css', cssom.getFileNameFromStyleSheet(styleSheet));

    styleSheet = {'href': 'http://foo.com/something/filename.css?bar=bas'};
    assertEquals('filename.css', cssom.getFileNameFromStyleSheet(styleSheet));

    styleSheet = {'href': 'filename.css?bar=bas'};
    assertEquals('filename.css', cssom.getFileNameFromStyleSheet(styleSheet));

    styleSheet = {'href': 'filename.css'};
    assertEquals('filename.css', cssom.getFileNameFromStyleSheet(styleSheet));
  },

  testGetAllCssStyleSheets() {
    const styleSheets = cssom.getAllCssStyleSheets();
    assertEquals(4, styleSheets.length);
    // Makes sure they're in the right cascade order.
    assertEquals(
        'cssom_test_link_1.css',
        cssom.getFileNameFromStyleSheet(styleSheets[0]));
    assertEquals(
        'cssom_test_import_2.css',
        cssom.getFileNameFromStyleSheet(styleSheets[1]));
    assertEquals(
        'cssom_test_import_1.css',
        cssom.getFileNameFromStyleSheet(styleSheets[2]));
    // Not an external styleSheet
    assertNull(cssom.getFileNameFromStyleSheet(styleSheets[3]));
  },

  testGetAllCssText() {
    const allCssText = cssom.getAllCssText();
    // In IE7, a CSSRule object gets included twice and replaces another
    // existing CSSRule object. We aren't using
    // goog.testing.ExpectedFailures since it brings in additional CSS
    // which breaks a lot of our expectations about the number of rules
    // present in a style sheet.
    if (!isIe7) {
      assertEquals(cssText, fixCssTextForIe(allCssText));
    }
  },

  testGetAllCssStyleRules() {
    const allCssRules = cssom.getAllCssStyleRules();
    assertEquals(6, allCssRules.length);
  },

  testAddCssText() {
    const newCssText = '.css-add-1 { display: block; }';
    const newCssNode = cssom.addCssText(newCssText);

    assertEquals(document.styleSheets.length, 3);

    const allCssText = cssom.getAllCssText();

    // In IE7, a CSSRule object gets included twice and replaces another
    // existing CSSRule object. We aren't using
    // goog.testing.ExpectedFailures since it brings in additional CSS
    // which breaks a lot of our expectations about the number of rules
    // present in a style sheet.
    if (!isIe7) {
      // Opera inserts the CSSRule to the first position. And fixCssText
      // is also needed to clean up whitespace.
      if (userAgent.OPERA) {
        assertEquals(`${newCssText} ${cssText}`, fixCssTextForIe(allCssText));
      } else {
        assertEquals(`${cssText} ${newCssText}`, fixCssTextForIe(allCssText));
      }
    }

    let cssRules = cssom.getAllCssStyleRules();
    assertEquals(7, cssRules.length);

    // Remove the new stylesheet now so it doesn't interfere with other
    // tests.
    newCssNode.parentNode.removeChild(newCssNode);
    // Sanity check.
    cssRules = cssom.getAllCssStyleRules();
    assertEquals(6, cssRules.length);
  },

  testAddCssRule() {
    // test that addCssRule correctly adds the rule to the style
    // sheet.
    const styleSheets = cssom.getAllCssStyleSheets();
    const styleSheet = styleSheets[3];
    const newCssRule = '.css-addCssRule { display: block; }';
    let rules = styleSheet.rules || styleSheet.cssRules;
    const origNumberOfRules = rules.length;

    cssom.addCssRule(styleSheet, newCssRule, 1);

    rules = styleSheet.rules || styleSheet.cssRules;
    const newNumberOfRules = rules.length;
    assertEquals(newNumberOfRules, origNumberOfRules + 1);

    // Remove the added rule so we don't mess up other tests.
    cssom.removeCssRule(styleSheet, 1);
  },

  testAddCssRuleAtPos() {
    // test that addCssRule correctly adds the rule to the style
    // sheet at the specified position.
    const styleSheets = cssom.getAllCssStyleSheets();
    const styleSheet = styleSheets[3];
    const newCssRule = '.css-addCssRulePos { display: block; }';
    let rules = cssom.getCssRulesFromStyleSheet(styleSheet);
    const origNumberOfRules = rules.length;

    // Firefox croaks if we try to insert a CSSRule at an index that
    // contains a CSSImport Rule. Since we deal only with CSSStyleRule
    // objects, we find the first CSSStyleRule and return its index.
    //
    // NOTE(user): We could have unified the code block below for all
    // browsers but IE6 horribly mangled up the stylesheet by creating
    // duplicate instances of a rule when removeCssRule was invoked
    // just after addCssRule with the looping construct in. This is
    // perfectly fine since IE's styleSheet.rules does not contain
    // references to anything but CSSStyleRules.
    let pos = 0;
    if (styleSheet.cssRules) {
      pos =
          googArray.findIndex(rules, (rule) => rule.type == CssRuleType.STYLE);
    }
    cssom.addCssRule(styleSheet, newCssRule, pos);

    rules = cssom.getCssRulesFromStyleSheet(styleSheet);
    const newNumberOfRules = rules.length;
    assertEquals(newNumberOfRules, origNumberOfRules + 1);

    // Remove the added rule so we don't mess up other tests.
    cssom.removeCssRule(styleSheet, pos);

    rules = cssom.getCssRulesFromStyleSheet(styleSheet);
    assertEquals(origNumberOfRules, rules.length);
  },

  testAddCssRuleNoIndex() {
    // How well do we handle cases where the optional index is
    //  not passed in?
    const styleSheets = cssom.getAllCssStyleSheets();
    const styleSheet = styleSheets[3];
    let rules = cssom.getCssRulesFromStyleSheet(styleSheet);
    const origNumberOfRules = rules.length;
    const newCssRule = '.css-addCssRuleNoIndex { display: block; }';

    // Try inserting the rule without specifying an index.
    // Make sure we don't throw an exception, and that we added
    // the entry.
    cssom.addCssRule(styleSheet, newCssRule);

    rules = cssom.getCssRulesFromStyleSheet(styleSheet);
    const newNumberOfRules = rules.length;
    assertEquals(newNumberOfRules, origNumberOfRules + 1);

    // Remove the added rule so we don't mess up the other tests.
    cssom.removeCssRule(styleSheet, newNumberOfRules - 1);

    rules = cssom.getCssRulesFromStyleSheet(styleSheet);
    assertEquals(origNumberOfRules, rules.length);
  },

  testGetParentStyleSheetAfterGetAllCssStyleRules() {
    const cssRules = cssom.getAllCssStyleRules();
    const cssRule = cssRules[4];
    const parentStyleSheet = cssom.getParentStyleSheet(cssRule);
    const styleSheets = cssom.getAllCssStyleSheets();
    const styleSheet = styleSheets[3];
    assertEquals(styleSheet, parentStyleSheet);
  },

  testGetCssRuleIndexInParentStyleSheetAfterGetAllCssStyleRules() {
    const cssRules = cssom.getAllCssStyleRules();
    const cssRule = cssRules[4];
    // Note here that this is correct - IE's styleSheet.rules does not
    // contain references to anything but CSSStyleRules while FF and others
    // include anything that inherits from the CSSRule interface.
    // See http://dev.w3.org/csswg/cssom/#cssrule.
    const parentStyleSheet = cssom.getParentStyleSheet(cssRule);
    const ruleIndex = (parentStyleSheet.cssRules != null) ? 2 : 1;
    assertEquals(ruleIndex, cssom.getCssRuleIndexInParentStyleSheet(cssRule));
  },

  testGetCssRuleIndexInParentStyleSheetNonStyleRule() {
    // IE's styleSheet.rules only contain CSSStyleRules.
    if (!userAgent.IE) {
      const styleSheets = cssom.getAllCssStyleSheets();
      const styleSheet = styleSheets[3];
      const newCssRule = '@media print { .css-nonStyle { display: block; } }';
      cssom.addCssRule(styleSheet, newCssRule);
      const rules = styleSheet.rules || styleSheet.cssRules;
      const cssRule = rules[rules.length - 1];
      assertEquals(CssRuleType.MEDIA, cssRule.type);
      // Make sure we don't throw an exception.
      cssom.getCssRuleIndexInParentStyleSheet(cssRule, styleSheet);
      // Remove the added rule.
      cssom.removeCssRule(styleSheet, rules.length - 1);
    }
  },

  testReplaceCssRuleWithStyleSheetAndIndex() {
    const styleSheets = cssom.getAllCssStyleSheets();
    const styleSheet = styleSheets[3];
    const rules = cssom.getCssRulesFromStyleSheet(styleSheet);
    const index = 2;
    const origCssRule = rules[index];
    const origCssText =
        fixCssTextForIe(cssom.getCssTextFromCssRule(origCssRule));

    cssom.replaceCssRule(origCssRule, replacementCssText, styleSheet, index);

    const newRules = cssom.getCssRulesFromStyleSheet(styleSheet);
    const newCssRule = newRules[index];
    const newCssText = cssom.getCssTextFromCssRule(newCssRule);
    assertEquals(replacementCssText, fixCssTextForIe(newCssText));

    // Now we need to re-replace our rule, to preserve parity for the other
    // tests.
    cssom.replaceCssRule(newCssRule, origCssText, styleSheet, index);
    const nowRules = cssom.getCssRulesFromStyleSheet(styleSheet);
    const nowCssRule = nowRules[index];
    const nowCssText = cssom.getCssTextFromCssRule(nowCssRule);
    assertEquals(origCssText, fixCssTextForIe(nowCssText));
  },

  testReplaceCssRuleUsingGetAllCssStyleRules() {
    const cssRules = cssom.getAllCssStyleRules();
    const origCssRule = cssRules[4];
    const origCssText =
        fixCssTextForIe(cssom.getCssTextFromCssRule(origCssRule));
    // notice we don't pass in the stylesheet or index.
    cssom.replaceCssRule(origCssRule, replacementCssText);

    const styleSheets = cssom.getAllCssStyleSheets();
    const styleSheet = styleSheets[3];
    const rules = cssom.getCssRulesFromStyleSheet(styleSheet);
    const index = (styleSheet.cssRules != null) ? 2 : 1;
    const cssRule = rules[index];
    const cssText = fixCssTextForIe(cssom.getCssTextFromCssRule(cssRule));
    assertEquals(replacementCssText, cssText);

    // try getting it the other way around too.
    const newCssRules = cssom.getAllCssStyleRules();
    const newCssRule = newCssRules[4];
    const newCssText = fixCssTextForIe(cssom.getCssTextFromCssRule(newCssRule));
    assertEquals(replacementCssText, newCssText);

    // Now we need to re-replace our rule, to preserve parity for the other
    // tests.
    cssom.replaceCssRule(newCssRule, origCssText);
    const nowCssRules = cssom.getAllCssStyleRules();
    const nowCssRule = nowCssRules[4];
    const nowCssText = fixCssTextForIe(cssom.getCssTextFromCssRule(nowCssRule));
    assertEquals(origCssText, nowCssText);
  },
});
<commit_msg>Changes so that the cssom package unit tests type checks RELNOTES: n/a<commit_after>/**
 * @license
 * Copyright The Closure Library Authors.
 * SPDX-License-Identifier: Apache-2.0
 */

goog.module('goog.cssomTest');
goog.setTestOnly();

const CssRuleType = goog.require('goog.cssom.CssRuleType');
const cssom = goog.require('goog.cssom');
const googArray = goog.require('goog.array');
const testSuite = goog.require('goog.testing.testSuite');
const userAgent = goog.require('goog.userAgent');

// Since sheet cssom_test1.css's first line is to import
// cssom_test2.css, we should get 2 before one in the string.
let cssText = '.css-link-1 { display: block; } ' +
    '.css-import-2 { display: block; } ' +
    '.css-import-1 { display: block; } ' +
    '.css-style-1 { display: block; } ' +
    '.css-style-2 { display: block; } ' +
    '.css-style-3 { display: block; }';

const replacementCssText = '.css-repl-1 { display: block; }';

const isIe7 =
    userAgent.IE && (userAgent.compare(userAgent.VERSION, '7.0') == 0);

// We're going to toLowerCase cssText before testing, because IE returns
// CSS property names in UPPERCASE, and the function shouldn't
// "fix" the text as it would be expensive and rarely of use.
// Same goes for the trailing whitespace in IE.
// Same goes for fixing the optimized removal of trailing ; in rules.
// Also needed for Opera.
function fixCssTextForIe(cssText) {
  cssText = cssText.toLowerCase().replace(/\s*$/, '');
  if (cssText.match(/[^;] \}/)) {
    cssText = cssText.replace(/([^;]) \}/g, '$1; }');
  }
  return cssText;
}

// Tests the scenario where we have a known stylesheet and index.

testSuite({
  testGetFileNameFromStyleSheet() {
    // cast to create mock object.
    let styleSheet =
        /** @type {?} */ ({'href': 'http://foo.com/something/filename.css'});
    assertEquals('filename.css', cssom.getFileNameFromStyleSheet(styleSheet));

    styleSheet = /** @type {?} */ (
        {'href': 'https://foo.com:123/something/filename.css'});
    assertEquals('filename.css', cssom.getFileNameFromStyleSheet(styleSheet));

    styleSheet = /** @type {?} */ (
        {'href': 'http://foo.com/something/filename.css?bar=bas'});
    assertEquals('filename.css', cssom.getFileNameFromStyleSheet(styleSheet));

    styleSheet = /** @type {?} */ ({'href': 'filename.css?bar=bas'});
    assertEquals('filename.css', cssom.getFileNameFromStyleSheet(styleSheet));

    styleSheet = /** @type {?} */ ({'href': 'filename.css'});
    assertEquals('filename.css', cssom.getFileNameFromStyleSheet(styleSheet));
  },

  testGetAllCssStyleSheets() {
    // NOTE: getAllCssStyleSheets return type is wrong, it should be
    // !Array<!Stylesheet> rather than nullable array entries
    const styleSheets = /** @type {?} */ (cssom.getAllCssStyleSheets());
    assertEquals(4, styleSheets.length);
    // Makes sure they're in the right cascade order.
    assertEquals(
        'cssom_test_link_1.css',
        cssom.getFileNameFromStyleSheet(styleSheets[0]));
    assertEquals(
        'cssom_test_import_2.css',
        cssom.getFileNameFromStyleSheet(styleSheets[1]));
    assertEquals(
        'cssom_test_import_1.css',
        cssom.getFileNameFromStyleSheet(styleSheets[2]));
    // Not an external styleSheet
    assertNull(cssom.getFileNameFromStyleSheet(styleSheets[3]));
  },

  testGetAllCssText() {
    const allCssText = cssom.getAllCssText();
    // In IE7, a CSSRule object gets included twice and replaces another
    // existing CSSRule object. We aren't using
    // goog.testing.ExpectedFailures since it brings in additional CSS
    // which breaks a lot of our expectations about the number of rules
    // present in a style sheet.
    if (!isIe7) {
      assertEquals(cssText, fixCssTextForIe(allCssText));
    }
  },

  testGetAllCssStyleRules() {
    const allCssRules = cssom.getAllCssStyleRules();
    assertEquals(6, allCssRules.length);
  },

  testAddCssText() {
    const newCssText = '.css-add-1 { display: block; }';
    const newCssNode = cssom.addCssText(newCssText);

    assertEquals(document.styleSheets.length, 3);

    const allCssText = cssom.getAllCssText();

    // In IE7, a CSSRule object gets included twice and replaces another
    // existing CSSRule object. We aren't using
    // goog.testing.ExpectedFailures since it brings in additional CSS
    // which breaks a lot of our expectations about the number of rules
    // present in a style sheet.
    if (!isIe7) {
      // Opera inserts the CSSRule to the first position. And fixCssText
      // is also needed to clean up whitespace.
      if (userAgent.OPERA) {
        assertEquals(`${newCssText} ${cssText}`, fixCssTextForIe(allCssText));
      } else {
        assertEquals(`${cssText} ${newCssText}`, fixCssTextForIe(allCssText));
      }
    }

    let cssRules = cssom.getAllCssStyleRules();
    assertEquals(7, cssRules.length);

    // Remove the new stylesheet now so it doesn't interfere with other
    // tests.
    newCssNode.parentNode.removeChild(newCssNode);
    // Sanity check.
    cssRules = cssom.getAllCssStyleRules();
    assertEquals(6, cssRules.length);
  },

  /** @suppress {missingProperties} cssRules not defined on StyleSheet */
  testAddCssRule() {
    // test that addCssRule correctly adds the rule to the style
    // sheet.
    const styleSheets = cssom.getAllCssStyleSheets();
    const styleSheet = styleSheets[3];
    const newCssRule = '.css-addCssRule { display: block; }';
    let rules = styleSheet.rules || styleSheet.cssRules;
    const origNumberOfRules = rules.length;

    cssom.addCssRule(styleSheet, newCssRule, 1);

    rules = styleSheet.rules || styleSheet.cssRules;
    const newNumberOfRules = rules.length;
    assertEquals(newNumberOfRules, origNumberOfRules + 1);

    // Remove the added rule so we don't mess up other tests.
    cssom.removeCssRule(styleSheet, 1);
  },

  /** @suppress {missingProperties} cssRules not defined on StyleSheet */
  testAddCssRuleAtPos() {
    // test that addCssRule correctly adds the rule to the style
    // sheet at the specified position.
    const styleSheets = cssom.getAllCssStyleSheets();
    const styleSheet = styleSheets[3];
    const newCssRule = '.css-addCssRulePos { display: block; }';
    let rules = cssom.getCssRulesFromStyleSheet(styleSheet);
    const origNumberOfRules = rules.length;

    // Firefox croaks if we try to insert a CSSRule at an index that
    // contains a CSSImport Rule. Since we deal only with CSSStyleRule
    // objects, we find the first CSSStyleRule and return its index.
    //
    // NOTE(user): We could have unified the code block below for all
    // browsers but IE6 horribly mangled up the stylesheet by creating
    // duplicate instances of a rule when removeCssRule was invoked
    // just after addCssRule with the looping construct in. This is
    // perfectly fine since IE's styleSheet.rules does not contain
    // references to anything but CSSStyleRules.
    let pos = 0;
    if (styleSheet.cssRules) {
      pos =
          googArray.findIndex(rules, (rule) => rule.type == CssRuleType.STYLE);
    }
    cssom.addCssRule(styleSheet, newCssRule, pos);

    rules = cssom.getCssRulesFromStyleSheet(styleSheet);
    const newNumberOfRules = rules.length;
    assertEquals(newNumberOfRules, origNumberOfRules + 1);

    // Remove the added rule so we don't mess up other tests.
    cssom.removeCssRule(styleSheet, pos);

    rules = cssom.getCssRulesFromStyleSheet(styleSheet);
    assertEquals(origNumberOfRules, rules.length);
  },

  testAddCssRuleNoIndex() {
    // How well do we handle cases where the optional index is
    //  not passed in?
    const styleSheets = cssom.getAllCssStyleSheets();
    const styleSheet = styleSheets[3];
    let rules = cssom.getCssRulesFromStyleSheet(styleSheet);
    const origNumberOfRules = rules.length;
    const newCssRule = '.css-addCssRuleNoIndex { display: block; }';

    // Try inserting the rule without specifying an index.
    // Make sure we don't throw an exception, and that we added
    // the entry.
    cssom.addCssRule(styleSheet, newCssRule);

    rules = cssom.getCssRulesFromStyleSheet(styleSheet);
    const newNumberOfRules = rules.length;
    assertEquals(newNumberOfRules, origNumberOfRules + 1);

    // Remove the added rule so we don't mess up the other tests.
    cssom.removeCssRule(styleSheet, newNumberOfRules - 1);

    rules = cssom.getCssRulesFromStyleSheet(styleSheet);
    assertEquals(origNumberOfRules, rules.length);
  },

  testGetParentStyleSheetAfterGetAllCssStyleRules() {
    const cssRules = cssom.getAllCssStyleRules();
    const cssRule = cssRules[4];
    const parentStyleSheet = cssom.getParentStyleSheet(cssRule);
    const styleSheets = cssom.getAllCssStyleSheets();
    const styleSheet = styleSheets[3];
    assertEquals(styleSheet, parentStyleSheet);
  },

  /** @suppress {missingProperties} cssRules not defined on StyleSheet */
  testGetCssRuleIndexInParentStyleSheetAfterGetAllCssStyleRules() {
    const cssRules = cssom.getAllCssStyleRules();
    const cssRule = cssRules[4];
    // Note here that this is correct - IE's styleSheet.rules does not
    // contain references to anything but CSSStyleRules while FF and others
    // include anything that inherits from the CSSRule interface.
    // See http://dev.w3.org/csswg/cssom/#cssrule.
    const parentStyleSheet = cssom.getParentStyleSheet(cssRule);
    const ruleIndex = (parentStyleSheet.cssRules != null) ? 2 : 1;
    assertEquals(ruleIndex, cssom.getCssRuleIndexInParentStyleSheet(cssRule));
  },

  /** @suppress {missingProperties} cssRules not defined on StyleSheet */
  testGetCssRuleIndexInParentStyleSheetNonStyleRule() {
    // IE's styleSheet.rules only contain CSSStyleRules.
    if (!userAgent.IE) {
      const styleSheets = cssom.getAllCssStyleSheets();
      const styleSheet = styleSheets[3];
      const newCssRule = '@media print { .css-nonStyle { display: block; } }';
      cssom.addCssRule(styleSheet, newCssRule);
      const rules = styleSheet.rules || styleSheet.cssRules;
      const cssRule = rules[rules.length - 1];
      assertEquals(CssRuleType.MEDIA, cssRule.type);
      // Make sure we don't throw an exception.
      cssom.getCssRuleIndexInParentStyleSheet(cssRule, styleSheet);
      // Remove the added rule.
      cssom.removeCssRule(styleSheet, rules.length - 1);
    }
  },

  testReplaceCssRuleWithStyleSheetAndIndex() {
    const styleSheets = cssom.getAllCssStyleSheets();
    const styleSheet = styleSheets[3];
    const rules = cssom.getCssRulesFromStyleSheet(styleSheet);
    const index = 2;
    const origCssRule = rules[index];
    const origCssText =
        fixCssTextForIe(cssom.getCssTextFromCssRule(origCssRule));

    cssom.replaceCssRule(origCssRule, replacementCssText, styleSheet, index);

    const newRules = cssom.getCssRulesFromStyleSheet(styleSheet);
    const newCssRule = newRules[index];
    const newCssText = cssom.getCssTextFromCssRule(newCssRule);
    assertEquals(replacementCssText, fixCssTextForIe(newCssText));

    // Now we need to re-replace our rule, to preserve parity for the other
    // tests.
    cssom.replaceCssRule(newCssRule, origCssText, styleSheet, index);
    const nowRules = cssom.getCssRulesFromStyleSheet(styleSheet);
    const nowCssRule = nowRules[index];
    const nowCssText = cssom.getCssTextFromCssRule(nowCssRule);
    assertEquals(origCssText, fixCssTextForIe(nowCssText));
  },

  /** @suppress {missingProperties} cssRules not defined on StyleSheet */
  testReplaceCssRuleUsingGetAllCssStyleRules() {
    const cssRules = cssom.getAllCssStyleRules();
    const origCssRule = cssRules[4];
    const origCssText =
        fixCssTextForIe(cssom.getCssTextFromCssRule(origCssRule));
    // notice we don't pass in the stylesheet or index.
    cssom.replaceCssRule(origCssRule, replacementCssText);

    const styleSheets = cssom.getAllCssStyleSheets();
    const styleSheet = styleSheets[3];
    const rules = cssom.getCssRulesFromStyleSheet(styleSheet);
    const index = (styleSheet.cssRules != null) ? 2 : 1;
    const cssRule = rules[index];
    const cssText = fixCssTextForIe(cssom.getCssTextFromCssRule(cssRule));
    assertEquals(replacementCssText, cssText);

    // try getting it the other way around too.
    const newCssRules = cssom.getAllCssStyleRules();
    const newCssRule = newCssRules[4];
    const newCssText = fixCssTextForIe(cssom.getCssTextFromCssRule(newCssRule));
    assertEquals(replacementCssText, newCssText);

    // Now we need to re-replace our rule, to preserve parity for the other
    // tests.
    cssom.replaceCssRule(newCssRule, origCssText);
    const nowCssRules = cssom.getAllCssStyleRules();
    const nowCssRule = nowCssRules[4];
    const nowCssText = fixCssTextForIe(cssom.getCssTextFromCssRule(nowCssRule));
    assertEquals(origCssText, nowCssText);
  },
});
<|endoftext|>


<commit_before>import React, {PropTypes} from "react";
import {Link} from "react-router";
import {VisibleToUser} from "../../accessors/accessors";
import LoadingDots from './LoadingDots';
import {AuthedLink} from './AuthedLink';

const Header = ({loading, coursesCount, authorsCount, onLogout}) => {
  return (

      <AuthedLink to="/" label={`Home`} useSeparator={true}/>
      <AuthedLink to="/authors" label={`Authors (${authorsCount})`} useSeparator={true}/>
      <AuthedLink to="/courses" label={`Courses (${coursesCount})`} useSeparator={true}/>
      <AuthedLink to="/about" label={`About`} useSeparator={true}/>
      <AuthedLink to="/" label="Logout" onClick={onLogout}/>
      {loading && <LoadingDots interval={100} dots={20}/>}

  );
};

Header.propTypes = {
  loading: PropTypes.bool.isRequired,
  coursesCount: PropTypes.number.isRequired,
  authorsCount: PropTypes.number.isRequired,
  onLogout: React.PropTypes.func.isRequired
};

export default Header;
<commit_msg>remove enneeded import<commit_after>import React, {PropTypes} from "react";
import {Link} from "react-router";
import LoadingDots from './LoadingDots';
import {AuthedLink} from './AuthedLink';

const Header = ({loading, coursesCount, authorsCount, onLogout}) => {
  return (

      <AuthedLink to="/" label={`Home`} useSeparator={true}/>
      <AuthedLink to="/authors" label={`Authors (${authorsCount})`} useSeparator={true}/>
      <AuthedLink to="/courses" label={`Courses (${coursesCount})`} useSeparator={true}/>
      <AuthedLink to="/about" label={`About`} useSeparator={true}/>
      <AuthedLink to="/" label="Logout" onClick={onLogout}/>
      {loading && <LoadingDots interval={100} dots={20}/>}

  );
};

Header.propTypes = {
  loading: PropTypes.bool.isRequired,
  coursesCount: PropTypes.number.isRequired,
  authorsCount: PropTypes.number.isRequired,
  onLogout: React.PropTypes.func.isRequired
};

export default Header;
<|endoftext|>