<commit_before>(function () {

    "use strict";

    var elements = document.getElementsByTagName('*'),
        BLACKLISTED = [
                        'donald',
                        'trump',
                        'jtrump',
                        'john',
                        'drumpf',
                        'donaldjtrump'
                      ],
        puppyImgs = [
                        'https://i.imgur.com/fhNroF8.jpg',
                        'https://i.imgur.com/ZGJHIn2.jpg',
                        'https://i.imgur.com/t3vsolX.jpg'
                    ];

   function newSrc () {
        return puppyImgs[randomPick()];
    }

    function randomPick () {
        return Math.floor(Math.random() * (2 - 0 + 1)) + 0;
    }

//Images
    function isBannedImage (element) {
        var searchTerms = new RegExp('(?:)' + BLACKLISTED.join("|") + '(?:)', 'ig'),
            alt = element.getAttribute('alt'),
            src = element.src;

        if (alt && alt.match(searchTerms)) {
            return replaceImage(element);
        }

        if (src.match(searchTerms)) {
            return replaceImage(element);
        }
    }

    function replaceImage (element) {
        var parent = element.parentNode,
            wrapper = document.createElement('div'),
            newImg = document.createElement('img');
        //create new puppy with new url
        newImg.className = "puppyImg";
        newImg.setAttribute('src', newSrc());
        wrapper.className = "puppyContainer";
        //insert puppy img into DOM
        parent.replaceChild(wrapper, element);
        wrapper.insertBefore(newImg, wrapper.firstChild);
    }

//Text
    function replaceText (node) {
        var text = node.nodeValue,
            newText = text.replace(new RegExp('(?:)'+BLACKLISTED.join("|")+'(?:)', 'ig'), ' puppies ' );

        return element.replaceChild(document.createTextNode(newText), node);
    }

    function isBannedText (element) {
        for (var j = 0; j < element.childNodes.length; j++) {
            var node = element.childNodes[j];

            if (node.nodeType === 3) {
                return replaceText(node);
            }
        }
    }

    //find and replace
    for (var i = 0; i < elements.length; i++) {
        var element = elements[i];

        element.tagName === 'IMG' ? checkImage(element) : checkText(element);
    }
})();
<commit_msg>fix discrepancy in function names<commit_after>(function () {

    "use strict";

    var elements = document.getElementsByTagName('*'),
        BLACKLISTED = [
                        'donald',
                        'trump',
                        'jtrump',
                        'john',
                        'drumpf',
                        'donaldjtrump'
                      ],
        puppyImgs = [
                        'https://i.imgur.com/fhNroF8.jpg',
                        'https://i.imgur.com/ZGJHIn2.jpg',
                        'https://i.imgur.com/t3vsolX.jpg'
                    ];

   function newSrc () {
        return puppyImgs[randomPick()];
    }

    function randomPick () {
        return Math.floor(Math.random() * (2 - 0 + 1)) + 0;
    }

//Images
    function checkImage (element) {
        var searchTerms = new RegExp('(?:)' + BLACKLISTED.join("|") + '(?:)', 'ig'),
            alt = element.getAttribute('alt'),
            src = element.src;

        if (alt && alt.match(searchTerms)) {
            return replaceImage(element);
        }

        if (src.match(searchTerms)) {
            return replaceImage(element);
        }
    }

    function replaceImage (element) {
        var parent = element.parentNode,
            wrapper = document.createElement('div'),
            newImg = document.createElement('img');
        //create new puppy with new url
        newImg.className = "puppyImg";
        newImg.setAttribute('src', newSrc());
        wrapper.className = "puppyContainer";
        //insert puppy img into DOM
        parent.replaceChild(wrapper, element);
        wrapper.insertBefore(newImg, wrapper.firstChild);
    }

//Text
    function replaceText (node) {
        var text = node.nodeValue,
            newText = text.replace(new RegExp('(?:)'+BLACKLISTED.join("|")+'(?:)', 'ig'), ' puppies ' );

        return element.replaceChild(document.createTextNode(newText), node);
    }

    function checkText (element) {
        for (var j = 0; j < element.childNodes.length; j++) {
            var node = element.childNodes[j];

            if (node.nodeType === 3) {
                return replaceText(node);
            }
        }
    }

    //find and replace
    for (var i = 0; i < elements.length; i++) {
        var element = elements[i];

        element.tagName === 'IMG' ? checkImage(element) : checkText(element);
    }
})();
<|endoftext|>


<commit_before>function DataManager(tripUrl, stationUrl, weatherUrl, timeDistributionUrl, distanceDistributionUrl, stationAgeUrl, stationFlowUrl) {
	this.tripUrl = tripUrl;
	this.stationUrl = stationUrl;
	this.weatherUrl = weatherUrl;
	this.timeDistributionUrl = timeDistributionUrl;
	this.distanceDistributionUrl = distanceDistributionUrl;
	this.stationAgeUrl = stationAgeUrl;
	this.stationFlowUrl = stationFlowUrl;

	this.selectedStations = [];

	// Filters
	this.date = null;
	this.hour = null;	// format: "hh:mm"

	// Data cache
	this.stations = null;
	this.trips = null;
	this.bikeWeeks = null;
	this.bikeHours = null;
	this.bike = null;
	this.timeDistribution = null;
	this.distanceDistribution = null;

	// Mode
	this.selectionMode = null; 	// MULTIPLE | DOUBLE
}

/*
	Every function expect a callback that will be executed at the end of the loading process
*/
DataManager.prototype.getStations = function(callback) {

	if(this.stations != null)
		callback(this.stations);
	else
		d3.json(this.stationUrl, function(error, json) {
			if(error)
				console.log("can't download file " + this.stationUrl);

			this.stations = json;

			//callback("lol");
			callback(this.stations);
		}.bind(this));
}

/*
	Get the weather of the specified day
*/
DataManager.prototype.getWeather = function(callback) {

	var url = this.weatherUrl;

	if(this.date != null) {
		url += "?";
		url += "from="+this.date;
		url += "&";
		url += "to="+this.date;
	}

	d3.json(url, function(error, json) {
		if(error)
			console.log("can't download file " + this.stationUrl);

		this.stations = json;

		callback(this.stations);
	});
}

DataManager.prototype.getTrips = function(callback) {

	if(this.selectedStations.length == 0) {
		callback([]);
		return;
	}

	if(this.trips != null)
		callback(this.trips);
	else
		d3.json(this.tripUrl, function(error, json) {
			if(error)
				console.log("can't download file " + this.tripUrl);

			this.trips = json;

			callback(json);
		}.bind(this));
}

// Get bikes out per day of the week for the selected stations
DataManager.prototype.getBikesWeek = function(callback) {

	if(this.selectedStations.length == 0) {
		callback([]);
		return;
	}

	var url = this.tripUrl+"?aggregate=DAY_WEEK";

	if(this.date != null) {
		url += "&";
		url += "from="+this.date;
		url += "&";
		url += "to="+this.date;
	}

	if(this.selectedStations.length > 0)
		url +="&stations=";
		for(var s in this.selectedStations) {
			var station = this.selectedStations[s].id;
			if(s == 0)
				url+=station;
			else
				url+=","+station;
		}

	/* NO CACHE FOR NOW
	if(this.bikeWeeks != null)
		callback(this.bikeWeeks);
	else */
	d3.json(url, function(error, json) {
		if(error)
			console.log("can't download file " + this.tripUrl);

		this.bikeWeeks = json;

		callback(json);
	}.bind(this));
}

// Get bikes out per hour of the day for the selected stations
DataManager.prototype.getBikesHourDay = function(callback) {

	if(this.selectedStations.length == 0) {
		callback([]);
		return;
	}

	var url = this.tripUrl+"?aggregate=HOUR_DAY";

	if(this.date != null) {
		url += "&";
		url += "from="+this.date;
		url += "&";
		url += "to="+this.date;
	}

	if(this.selectedStations.length > 0)
		url +="&stations=";
		for(var s in this.selectedStations) {
			var station = this.selectedStations[s].id;
			if(s == 0)
				url+=station;
			else
				url+=","+station;
		}

	/*
	if(this.bikeHours != null)
		callback(this.trips);
	else
		*/
	d3.json(url, function(error, json) {
		if(error)
			console.log("can't download file " + this.tripUrl);

		this.bikeHours = json;

		callback(json);
	}.bind(this));
}

// Get bikes out per day of the year for the selected stations
DataManager.prototype.getBikesDayYear = function(callback) {

	if(this.selectedStations.length == 0) {
		callback([]);
		return;
	}

	var url = this.tripUrl+"?aggregate=DAY_YEAR";

	if(this.selectedStations.length > 0)
		url +="&stations=";
		for(var s in this.selectedStations) {
			var station = this.selectedStations[s].id;
			if(s == 0)
				url+=station;
			else
				url+=","+station;
		}

	/*
	if(this.bikeHours != null)
		callback(this.trips);
	else
		*/
	d3.json(url, function(error, json) {
		if(error)
			console.log("can't download file " + this.tripUrl);

		this.bikeHours = json;

		callback(json);
	}.bind(this));
}

// Get bikes out for the selected stations
DataManager.prototype.getBikes = function(callback) {

	if(this.selectedStations.length == 0) {
		callback([]);
		return;
	}

	var url = this.getTripUrl(true);

	if(this.selectedStations.length > 0)
		url +="&stations=";
		for(var s in this.selectedStations) {
			var station = this.selectedStations[s].id;
			if(s == 0)
				url+=station;
			else
				url+=","+station;
		}

	/*
	if(this.date != null) {
		url += "&";
		url += "from="+this.date;
		url += "&";
		url += "to="+this.date;
	}
	*/
	d3.json(url, function(error, json) {
		if(error)
			console.log("can't download file " + this.tripUrl);

		this.bike = json;

		callback(json);
	}.bind(this));
}

/*
	Get the demographic data for the selected stations
*/
DataManager.prototype.getStationsDemographic = function(callback) {

	if(this.selectedStations.length == 0) {
		callback([]);
		return;
	}

	var url = this.stationUrl;
	url += "?demographic=OUT";

	if(this.date != null) {
		url += "&";
		url += "from="+this.date;
		url += "&";
		url += "to="+this.date;
	}

	// Only selected stations
	if(this.selectedStations.length > 0)
		url +="&stations=";
		for(var s in this.selectedStations) {
			var station = this.selectedStations[s].id;
			if(s == 0)
				url+=station;
			else
				url+=","+station;
		}

	d3.json(url, function(error, json) {
		if(error)
			console.log("can't download file " + this.stationUrl);

		callback(json);
	}.bind(this));
}

DataManager.prototype.getStationsAge = function(callback) {

	if(this.selectedStations.length == 0) {
		callback([]);
		return;
	}

	var url = this.stationAgeUrl;
	url += "?demographic=OUT";

	if(this.date != null) {
		url += "&";
		url += "from="+this.date;
		url += "&";
		url += "to="+this.date;
	}

	// Only selected stations
	if(this.selectedStations.length > 0)
		url +="&stations=";
		for(var s in this.selectedStations) {
			var station = this.selectedStations[s].id;
			if(s == 0)
				url+=station;
			else
				url+=","+station;
		}

	d3.json(url, function(error, json) {
		if(error)
			console.log("can't download file " + this.stationUrl);

		callback(json);
	}.bind(this));
}

DataManager.prototype.getTripUrl = function(coordinates) {
	var url = this.tripUrl;

	if(this.date != null ||
	   this.selectedStations != [] ||
	   coordinates == true)
		url += "?";

	if(this.date != null) {
		url += "&";
		url += "from="+this.date;
		url += "&";
		url += "to="+this.date;
	}

	if(coordinates == true) {
		url += "&";
		url += "coordinates=TRUE";
	}
	return url;
}

// Get time distribution of bike trips
DataManager.prototype.getTimeDistribution = function(callback) {

	var url = this.timeDistributionUrl;

	if(this.timeDistribution != null)
		callback(this.timeDistribution);
	else
		d3.json(url, function(error, json) {
			if(error)
				console.log("can't download file " + this.timeDistributionUrl);

			this.timeDistribution = json;

			callback(json);
		}.bind(this));
}

// Get time distribution of bike trips
DataManager.prototype.getDistanceDistribution = function(callback) {

	var url = this.distanceDistributionUrl;

	if(this.distanceDistribution != null)
		callback(this.distanceDistribution);
	else
		d3.json(url, function(error, json) {
			if(error)
				console.log("can't download file " + this.distanceDistributionUrl);

			this.distanceDistribution = json;

			callback(json);
		}.bind(this));
}

/*
	Get the flow for the station
	flow: IN | OUT
*/
DataManager.prototype.getFlow = function(callback, stationId, flow) {

	var url = this.stationFlowUrl;

	url += "?";
	url += "station="+stationId;
	url += "&";
	url += "flow="+flow;

	d3.json(url, function(error, json) {
		if(error)
			console.log("can't download file " + this.stationFlowUrl);

		callback(json);
	}.bind(this));
}<commit_msg>Added date support for flow DB API<commit_after>function DataManager(tripUrl, stationUrl, weatherUrl, timeDistributionUrl, distanceDistributionUrl, stationAgeUrl, stationFlowUrl) {
	this.tripUrl = tripUrl;
	this.stationUrl = stationUrl;
	this.weatherUrl = weatherUrl;
	this.timeDistributionUrl = timeDistributionUrl;
	this.distanceDistributionUrl = distanceDistributionUrl;
	this.stationAgeUrl = stationAgeUrl;
	this.stationFlowUrl = stationFlowUrl;

	this.selectedStations = [];

	// Filters
	this.date = null;
	this.hour = null;	// format: "hh:mm"

	// Data cache
	this.stations = null;
	this.trips = null;
	this.bikeWeeks = null;
	this.bikeHours = null;
	this.bike = null;
	this.timeDistribution = null;
	this.distanceDistribution = null;

	// Mode
	this.selectionMode = null; 	// MULTIPLE | DOUBLE
}

/*
	Every function expect a callback that will be executed at the end of the loading process
*/
DataManager.prototype.getStations = function(callback) {

	if(this.stations != null)
		callback(this.stations);
	else
		d3.json(this.stationUrl, function(error, json) {
			if(error)
				console.log("can't download file " + this.stationUrl);

			this.stations = json;

			//callback("lol");
			callback(this.stations);
		}.bind(this));
}

/*
	Get the weather of the specified day
*/
DataManager.prototype.getWeather = function(callback) {

	var url = this.weatherUrl;

	if(this.date != null) {
		url += "?";
		url += "from="+this.date;
		url += "&";
		url += "to="+this.date;
	}

	d3.json(url, function(error, json) {
		if(error)
			console.log("can't download file " + this.stationUrl);

		this.stations = json;

		callback(this.stations);
	});
}

DataManager.prototype.getTrips = function(callback) {

	if(this.selectedStations.length == 0) {
		callback([]);
		return;
	}

	if(this.trips != null)
		callback(this.trips);
	else
		d3.json(this.tripUrl, function(error, json) {
			if(error)
				console.log("can't download file " + this.tripUrl);

			this.trips = json;

			callback(json);
		}.bind(this));
}

// Get bikes out per day of the week for the selected stations
DataManager.prototype.getBikesWeek = function(callback) {

	if(this.selectedStations.length == 0) {
		callback([]);
		return;
	}

	var url = this.tripUrl+"?aggregate=DAY_WEEK";

	if(this.date != null) {
		url += "&";
		url += "from="+this.date;
		url += "&";
		url += "to="+this.date;
	}

	if(this.selectedStations.length > 0)
		url +="&stations=";
		for(var s in this.selectedStations) {
			var station = this.selectedStations[s].id;
			if(s == 0)
				url+=station;
			else
				url+=","+station;
		}

	/* NO CACHE FOR NOW
	if(this.bikeWeeks != null)
		callback(this.bikeWeeks);
	else */
	d3.json(url, function(error, json) {
		if(error)
			console.log("can't download file " + this.tripUrl);

		this.bikeWeeks = json;

		callback(json);
	}.bind(this));
}

// Get bikes out per hour of the day for the selected stations
DataManager.prototype.getBikesHourDay = function(callback) {

	if(this.selectedStations.length == 0) {
		callback([]);
		return;
	}

	var url = this.tripUrl+"?aggregate=HOUR_DAY";

	if(this.date != null) {
		url += "&";
		url += "from="+this.date;
		url += "&";
		url += "to="+this.date;
	}

	if(this.selectedStations.length > 0)
		url +="&stations=";
		for(var s in this.selectedStations) {
			var station = this.selectedStations[s].id;
			if(s == 0)
				url+=station;
			else
				url+=","+station;
		}

	/*
	if(this.bikeHours != null)
		callback(this.trips);
	else
		*/
	d3.json(url, function(error, json) {
		if(error)
			console.log("can't download file " + this.tripUrl);

		this.bikeHours = json;

		callback(json);
	}.bind(this));
}

// Get bikes out per day of the year for the selected stations
DataManager.prototype.getBikesDayYear = function(callback) {

	if(this.selectedStations.length == 0) {
		callback([]);
		return;
	}

	var url = this.tripUrl+"?aggregate=DAY_YEAR";

	if(this.selectedStations.length > 0)
		url +="&stations=";
		for(var s in this.selectedStations) {
			var station = this.selectedStations[s].id;
			if(s == 0)
				url+=station;
			else
				url+=","+station;
		}

	/*
	if(this.bikeHours != null)
		callback(this.trips);
	else
		*/
	d3.json(url, function(error, json) {
		if(error)
			console.log("can't download file " + this.tripUrl);

		this.bikeHours = json;

		callback(json);
	}.bind(this));
}

// Get bikes out for the selected stations
DataManager.prototype.getBikes = function(callback) {

	if(this.selectedStations.length == 0) {
		callback([]);
		return;
	}

	var url = this.getTripUrl(true);

	if(this.selectedStations.length > 0)
		url +="&stations=";
		for(var s in this.selectedStations) {
			var station = this.selectedStations[s].id;
			if(s == 0)
				url+=station;
			else
				url+=","+station;
		}

	/*
	if(this.date != null) {
		url += "&";
		url += "from="+this.date;
		url += "&";
		url += "to="+this.date;
	}
	*/
	d3.json(url, function(error, json) {
		if(error)
			console.log("can't download file " + this.tripUrl);

		this.bike = json;

		callback(json);
	}.bind(this));
}

/*
	Get the demographic data for the selected stations
*/
DataManager.prototype.getStationsDemographic = function(callback) {

	if(this.selectedStations.length == 0) {
		callback([]);
		return;
	}

	var url = this.stationUrl;
	url += "?demographic=OUT";

	if(this.date != null) {
		url += "&";
		url += "from="+this.date;
		url += "&";
		url += "to="+this.date;
	}

	// Only selected stations
	if(this.selectedStations.length > 0)
		url +="&stations=";
		for(var s in this.selectedStations) {
			var station = this.selectedStations[s].id;
			if(s == 0)
				url+=station;
			else
				url+=","+station;
		}

	d3.json(url, function(error, json) {
		if(error)
			console.log("can't download file " + this.stationUrl);

		callback(json);
	}.bind(this));
}

DataManager.prototype.getStationsAge = function(callback) {

	if(this.selectedStations.length == 0) {
		callback([]);
		return;
	}

	var url = this.stationAgeUrl;
	url += "?demographic=OUT";

	if(this.date != null) {
		url += "&";
		url += "from="+this.date;
		url += "&";
		url += "to="+this.date;
	}

	// Only selected stations
	if(this.selectedStations.length > 0)
		url +="&stations=";
		for(var s in this.selectedStations) {
			var station = this.selectedStations[s].id;
			if(s == 0)
				url+=station;
			else
				url+=","+station;
		}

	d3.json(url, function(error, json) {
		if(error)
			console.log("can't download file " + this.stationUrl);

		callback(json);
	}.bind(this));
}

DataManager.prototype.getTripUrl = function(coordinates) {
	var url = this.tripUrl;

	if(this.date != null ||
	   this.selectedStations != [] ||
	   coordinates == true)
		url += "?";

	if(this.date != null) {
		url += "&";
		url += "from="+this.date;
		url += "&";
		url += "to="+this.date;
	}

	if(coordinates == true) {
		url += "&";
		url += "coordinates=TRUE";
	}
	return url;
}

// Get time distribution of bike trips
DataManager.prototype.getTimeDistribution = function(callback) {

	var url = this.timeDistributionUrl;

	if(this.timeDistribution != null)
		callback(this.timeDistribution);
	else
		d3.json(url, function(error, json) {
			if(error)
				console.log("can't download file " + this.timeDistributionUrl);

			this.timeDistribution = json;

			callback(json);
		}.bind(this));
}

// Get time distribution of bike trips
DataManager.prototype.getDistanceDistribution = function(callback) {

	var url = this.distanceDistributionUrl;

	if(this.distanceDistribution != null)
		callback(this.distanceDistribution);
	else
		d3.json(url, function(error, json) {
			if(error)
				console.log("can't download file " + this.distanceDistributionUrl);

			this.distanceDistribution = json;

			callback(json);
		}.bind(this));
}

/*
	Get the flow for the station
	flow: IN | OUT
*/
DataManager.prototype.getFlow = function(callback, stationId, flow) {

	var url = this.stationFlowUrl;

	url += "?";
	url += "station="+stationId;
	url += "&";
	url += "flow="+flow;

	if(this.date != null) {
		url += "&";
		url += "from="+this.date;
		url += "&";
		url += "to="+this.date;
	}

	d3.json(url, function(error, json) {
		if(error)
			console.log("can't download file " + this.stationFlowUrl);

		callback(json);
	}.bind(this));
}<|endoftext|>


<commit_before>(function(angular) {

	var module = angular.module('net.enzey.service.css.editor', []);

	module.service('nzCssRuleEditor', function($window, $http, $q) {
		// Create a new style sheet to hold custom styles
		angular.element($window.document.head).append( angular.element('<style></style>') );

		// Get last loaded style sheet (the style sheet just added)
		var styleSheet = $window.document.styleSheets[document.styleSheets.length - 1];

		var cssRuleCode = $window.document.all ? 'rules' : 'cssRules'; //account for IE and FF
		var styleSetter = $window.document.all ? 'value' : 'style'; //account for IE and FF

		var CssRuleEditor = this;
		var cssRuleCache = {};

		var getJsStyleName = function(styleName) {
			var firstCharacterRegex = new RegExp('^.');
			styleName = styleName.split('-');
			for (var i = 1; i < styleName.length; i++) {
				styleName[i] = styleName[i].replace(firstCharacterRegex, styleName[i][0].toUpperCase());
			}

			return styleName.join('');
		};

		var getCssRules = function(styleSheet) {
			var cssRules;
			if (styleSheet['rules']) {
				cssRules = styleSheet['rules'];
			} else {
				cssRules = styleSheet['cssRules'];
			}
			return cssRules;
		};

		var extractStyles = function(styles) {
			var extractedStyles = {};
			for (var i = 0; i < styles.length; i++) {
				var styleName = getJsStyleName(styles[i]);
				extractedStyles[ styleName ] = styles[ styleName ];
			}
			return extractedStyles;
		};

		var parseStyleSheet = function(styleSheet) {
			var cssRules = getCssRules(styleSheet);

			for (var iRule = 0; iRule < cssRules.length; iRule++) {
				var cssRule = cssRules[iRule];
				if (cssRule instanceof CSSStyleRule) {
					var styles;
					if (cssRule['value']) {
						styles = cssRule['value'];
					} else {
						styles = cssRule['style'];
					}
					styles = extractStyles(styles);
					cssRule.selectorText.split(',').forEach(function(selector) {
						selector = selector.replace(new RegExp('^ *'), '');
						selector = selector.replace(new RegExp(' *$'), '');

						if (!allCssRules[selector]) {
							allCssRules[selector] = {};
						}
						angular.extend(allCssRules[selector], styles);
					});
				}
			};
		};

		var cacheStyleSheets = function() {
			var allStyleSheets = $window.document.styleSheets;
			var styleSheetCache = new Array(allStyleSheets.length-1);

			var promises = [];
			for (var i = 0; i < allStyleSheets.length-1; i++) {
				(function () {
					var index = i;
					var currentStyleSheet = allStyleSheets[i];
					var deferred = $q.defer();
					promises.push(deferred.promise);

					try {
						getCssRules(currentStyleSheet);
						styleSheetCache[index] = currentStyleSheet;
						deferred.resolve(currentStyleSheet);
					} catch (e) {
						$http.get(currentStyleSheet.href).success(function(data, status, headers, config) {
							var tempStyle = angular.element("<style></style>");
							tempStyle.html(data);
							angular.element($window.document.head).prepend(tempStyle);

							var allStyleSheets = $window.document.styleSheets;
							var lastStyleSheet = allStyleSheets[0];

							styleSheetCache[index] = lastStyleSheet;

							tempStyle.remove();
							deferred.resolve(lastStyleSheet);
						}).error(function(data, status, headers, config) {
							deferred.reject();
						});
					}
				})()
			}
			var allPromises = $q.all(promises).then(function(foo, bar) {
				return styleSheetCache;
			});

			return allPromises;
		};

		var allCssRules = {};
		var baseStyleSheets = [];

		this.getBaseRules = function() {
			var promise = cacheStyleSheets().then(function(styleSheetCache) {
				baseStyleSheets = styleSheetCache;
				styleSheetCache.forEach(function(styleSheet) {
					parseStyleSheet(styleSheet);
				});
				return angular.extend({}, allCssRules);
			});

			return promise;
		};

		this.getCustomRule = function(ruleName) {
			if (!ruleName) return;

			var cssRule = cssRuleCache[ruleName];
			if (!cssRule) {
				// Rules does not exist
				styleSheet.insertRule(ruleName + ' {}', 0);

				var cssRules;
				if (styleSheet['rules']) {
					cssRules = styleSheet['rules'];
				} else {
					cssRules = styleSheet['cssRules'];
				}
				cssRuleCache[ruleName] = cssRules[0];
				//cssRuleCache[ruleName] = styleSheet[cssRuleCode][0];
				cssRule = cssRuleCache[ruleName];
			}
			var styles;
			if (cssRule['value']) {
				styles = cssRule['value'];
			} else {
				styles = cssRule['style'];
			}
			return styles;
			//return cssRule[styleSetter];
		};

		this.removeCustomRule = function(ruleName) {
			if (!ruleName) return;

			var cssRules = styleSheet[cssRuleCode];
			for (var i = 0; i < cssRules.length; i++) {
				var cssRule = cssRules[i];
				if (cssRule.selectorText.toLowerCase() === ruleName.toLowerCase()) {
					styleSheet.deleteRule(i);
					cssRuleCache[ruleName] = null;
					delete cssRuleCache[ruleName];
				}
			}
		};

		this.getAllCustomRules = function() {
			return angular.extend({}, cssRuleCache);
		};

		this.removeAllCustomRules = function() {
			Object.keys(cssRuleCache).forEach(function (ruleName){
				CssRuleEditor.removeRule(ruleName);
			});
		};

	});

})(angular);<commit_msg>Add function to get all rules associated to a specific element.<commit_after>(function(angular) {

	var module = angular.module('net.enzey.service.css.editor', []);

	module.service('nzCssRuleEditor', function($window, $http, $q) {
		// Create a new style sheet to hold custom styles
		angular.element($window.document.head).append( angular.element('<style></style>') );

		// Get last loaded style sheet (the style sheet just added)
		var styleSheet = $window.document.styleSheets[document.styleSheets.length - 1];

		var cssRuleCode = $window.document.all ? 'rules' : 'cssRules'; //account for IE and FF
		var styleSetter = $window.document.all ? 'value' : 'style'; //account for IE and FF

		var CssRuleEditor = this;
		var cssRuleCache = {};

		var getJsStyleName = function(styleName) {
			var firstCharacterRegex = new RegExp('^.');
			styleName = styleName.split('-');
			for (var i = 1; i < styleName.length; i++) {
				styleName[i] = styleName[i].replace(firstCharacterRegex, styleName[i][0].toUpperCase());
			}

			return styleName.join('');
		};

		var getCssRules = function(styleSheet) {
			var cssRules;
			if (styleSheet['rules']) {
				cssRules = styleSheet['rules'];
			} else {
				cssRules = styleSheet['cssRules'];
			}
			return cssRules;
		};

		var extractStyles = function(styles) {
			var extractedStyles = {};
			for (var i = 0; i < styles.length; i++) {
				var styleName = getJsStyleName(styles[i]);
				extractedStyles[ styleName ] = styles[ styleName ];
			}
			return extractedStyles;
		};

		var parseStyleSheet = function(styleSheet) {
			var cssRules = getCssRules(styleSheet);

			for (var iRule = 0; iRule < cssRules.length; iRule++) {
				var cssRule = cssRules[iRule];
				if (cssRule instanceof CSSStyleRule) {
					var styles;
					if (cssRule['value']) {
						styles = cssRule['value'];
					} else {
						styles = cssRule['style'];
					}
					styles = extractStyles(styles);
					cssRule.selectorText.split(',').forEach(function(selector) {
						selector = selector.replace(new RegExp('^ *'), '');
						selector = selector.replace(new RegExp(' *$'), '');

						if (!allCssRules[selector]) {
							allCssRules[selector] = {};
						}
						angular.extend(allCssRules[selector], styles);
					});
				}
			};
		};

		var cacheStyleSheets = function() {
			var allStyleSheets = $window.document.styleSheets;
			var styleSheetCache = new Array(allStyleSheets.length-1);

			var promises = [];
			for (var i = 0; i < allStyleSheets.length-1; i++) {
				(function () {
					var index = i;
					var currentStyleSheet = allStyleSheets[i];
					var deferred = $q.defer();
					promises.push(deferred.promise);

					try {
						getCssRules(currentStyleSheet);
						styleSheetCache[index] = currentStyleSheet;
						deferred.resolve(currentStyleSheet);
					} catch (e) {
						$http.get(currentStyleSheet.href).success(function(data, status, headers, config) {
							var tempStyle = angular.element("<style></style>");
							tempStyle.html(data);
							angular.element($window.document.head).prepend(tempStyle);

							var allStyleSheets = $window.document.styleSheets;
							var lastStyleSheet = allStyleSheets[0];

							styleSheetCache[index] = lastStyleSheet;

							tempStyle.remove();
							deferred.resolve(lastStyleSheet);
						}).error(function(data, status, headers, config) {
							deferred.reject();
						});
					}
				})()
			}
			var allPromises = $q.all(promises).then(function(foo, bar) {
				return styleSheetCache;
			});

			return allPromises;
		};

		var allCssRules = {};
		var baseStyleSheets = [];

		this.getBaseRules = function() {
			var promise = cacheStyleSheets().then(function(styleSheetCache) {
				baseStyleSheets = styleSheetCache;
				styleSheetCache.forEach(function(styleSheet) {
					parseStyleSheet(styleSheet);
				});
				return angular.extend({}, allCssRules);
			});

			return promise;
		};

		this.getCustomRule = function(ruleName) {
			if (!ruleName) return;

			var cssRule = cssRuleCache[ruleName];
			if (!cssRule) {
				// Rules does not exist
				styleSheet.insertRule(ruleName + ' {}', 0);

				var cssRules;
				if (styleSheet['rules']) {
					cssRules = styleSheet['rules'];
				} else {
					cssRules = styleSheet['cssRules'];
				}
				cssRuleCache[ruleName] = cssRules[0];
				//cssRuleCache[ruleName] = styleSheet[cssRuleCode][0];
				cssRule = cssRuleCache[ruleName];
			}
			var styles;
			if (cssRule['value']) {
				styles = cssRule['value'];
			} else {
				styles = cssRule['style'];
			}
			return styles;
			//return cssRule[styleSetter];
		};

		this.removeCustomRule = function(ruleName) {
			if (!ruleName) return;

			var cssRules = styleSheet[cssRuleCode];
			for (var i = 0; i < cssRules.length; i++) {
				var cssRule = cssRules[i];
				if (cssRule.selectorText.toLowerCase() === ruleName.toLowerCase()) {
					styleSheet.deleteRule(i);
					cssRuleCache[ruleName] = null;
					delete cssRuleCache[ruleName];
				}
			}
		};

		this.getAllCustomRules = function() {
			return angular.extend({}, cssRuleCache);
		};

		this.removeAllCustomRules = function() {
			Object.keys(cssRuleCache).forEach(function (ruleName){
				CssRuleEditor.removeRule(ruleName);
			});
		};

		this.getRules = function(element) {
			var deferred = $q.defer();

			var rulesForElement = [];
			var collectRules = function(rule) {
				var foundElements = $window.document.querySelectorAll(rule);
				for (var i = 0; i < foundElements.length; i++) {
					if (element === foundElements[i]) {
						rulesForElement.push(rule);
						break;
					}
				}
			}
			CssRuleEditor.getBaseRules().then(function(rules) {
				Object.keys(rules).forEach(collectRules);
				Object.keys(CssRuleEditor.getAllCustomRules()).forEach(collectRules);
				deferred.resolve(rulesForElement)
			});

			return deferred.promise;
		}
	});

})(angular);<|endoftext|>


<commit_before>/* Meta.js
KC3改 Meta Data

Provides access to data on built-in JSON files
*/
(function(){
	"use strict";

	window.KC3Meta = {
		_cache:{},
		_icons:{},
		_exp:{},
		_gauges:{},
		_ship:{},
		_defeq:{},
		_slotitem:{},
		_quests:{},
		_ranks:{},
		_stype:{},
		_servers:{},
		_battle:{},
		_terms:{
			troll:{},
			lang:{},
		},
		_edges:{},
		_defaultIcon:"",

		/* Initialization
		-------------------------------------------------------*/
		init :function( repo ){
			/* to remove deprecated warning
				http://stackoverflow.com/questions/22090764/alternative-to-async-false-ajax
			*/
			// Load Common Meta
			this._icons		= JSON.parse( $.ajax(repo+'icons.json', { async: false }).responseText );
			this._exp		= JSON.parse( $.ajax(repo+'experience.json', { async: false }).responseText );
			this._gauges	= JSON.parse( $.ajax(repo+'gauges.json', { async: false }).responseText );
			this._defeq		= JSON.parse( $.ajax(repo+'defeq.json', { async: false }).responseText );
			this._edges		= JSON.parse( $.ajax(repo+'edges.json', { async: false }).responseText );

			// Load Translations
			this._ship 		= KC3Translation.getJSON(repo, 'ships', true);
			this._slotitem	= KC3Translation.getJSON(repo, 'items', true);
			this._quests	= KC3Translation.getJSON(repo, 'quests', true);
			this._ranks		= KC3Translation.getJSON(repo, 'ranks', true);
			this._stype		= KC3Translation.getJSON(repo, 'stype', true);
			this._servers	= KC3Translation.getJSON(repo, 'servers', true);
			this._battle	= KC3Translation.getJSON(repo, 'battle', true);
			// troll language always loaded
			this._terms.troll		= JSON.parse( $.ajax(repo+'lang/data/troll/terms.json', { async: false }).responseText );
			// other language loaded here
			this._terms.lang		= KC3Translation.getJSON(repo, 'terms');
		},

		/* Data Access
		-------------------------------------------------------*/
		defaultIcon :function(iconSrc){
			this._defaultIcon = iconSrc;
		},

		shipIcon :function(id, empty){
			if(typeof this._icons[id] !== "undefined"){
				return "http://i708.photobucket.com/albums/ww87/dragonjet25/KC3%20Ship%20Icons/"+this._icons[id];
			}
			if(typeof empty == "undefined"){
				return this._defaultIcon;
			}
			return empty;
		},

		abyssIcon :function(id, empty){
			if(typeof this._icons[id] !== "undefined"){
				return "http://i708.photobucket.com/albums/ww87/dragonjet25/KC3%20Abyss%20Icons/"+this._icons[id];
			}
			if(typeof empty == "undefined"){
				return this._defaultIcon;
			}
			return empty;
		},

		formationIcon :function(formationId){
			return "../../../../assets/img/formation2/" + formationId + ".png";
		},

		formationText :function(formationId){
			return [
				"",
				"Line Ahead",
				"Double Line",
				"Diamond",
				"Echelon",
				"Line Abreast",
				"","","","","",
				"Cruising Formation 1 (anti-sub)",
				"Cruising Formation 2 (forward)",
				"Cruising Formation 1 (anti-sub)",
				"Cruising Formation 1 (anti-sub)",
				"","","","","","",
				"Cruising Formation 1 (anti-sub)",
				"Cruising Formation 2 (forward)",
				"Cruising Formation 1 (anti-sub)",
				"Cruising Formation 1 (anti-sub)"
			][formationId];
		},

		shipName :function( jp_name ){
			if(typeof this._cache[jp_name] !== "undefined"){ return this._cache[jp_name]; }
			if(typeof this._ship[jp_name] !== "undefined"){
				this._cache[jp_name] = this._ship[jp_name];
				return this._cache[jp_name];
			}
			if( jp_name.substr(jp_name.length-1, 1) == "改" ){
				var bare1 = jp_name.substr(0, jp_name.length-1);
				if(typeof this._ship[bare1] !== "undefined"){
					this._cache[jp_name] = this._ship[bare1] + " " + this._ship._Kai;
					return this._cache[jp_name];
				}
			}
			if( jp_name.substr(jp_name.length-2, 2) == "改二" ){
				var bare2 = jp_name.substr(0, jp_name.length-2);
				if(typeof this._ship[bare2] !== "undefined"){
					this._cache[jp_name] = this._ship[bare2] + " " + this._ship._KaiNi;
					return this._cache[jp_name];
				}
			}
			if( jp_name.substr(jp_name.length-1, 1) == "甲" ){
				var bare3 = jp_name.substr(0, jp_name.length-1);
				if(typeof this._ship[bare3] !== "undefined"){
					this._cache[jp_name] = this._ship[bare3] + this._ship._A;
					return this._cache[jp_name];
				}
			}
			if( jp_name.substr(jp_name.length-3, 3) == "改二甲" ){
				var bare4 = jp_name.substr(0, jp_name.length-3);
				if(typeof this._ship[bare4] !== "undefined"){
					this._cache[jp_name] = this._ship[bare4] + " " + this._ship._KaiNiA;
					return this._cache[jp_name];
				}
			}
			return jp_name;
		},

		gearName :function( jp_name ){
			if(typeof this._slotitem[ jp_name ] !== "undefined"){
				return this._slotitem[ jp_name ];
			}
			return jp_name;
		},

		exp :function(level){
			return this._exp[level] || [0,0];
		},

		quest :function(id){
			return this._quests[id] || false;
		},

		rank :function(id){
			return this._ranks[id] || "Unknown Rank";
		},

		stype :function(id){
			return this._stype[id] || "??";
		},

		server :function(ip){
			return this._servers[ip] || {name:"Unknown Server", num:0, ip:ip };
		},

		serverByNum :function(num){
			var ctr;
			for(ctr in this._servers){
				if(this._servers[ctr].num==num){
					return this._servers[ctr];
				}
			}
			return {name:"Unknown Server", num:num, ip:"0.0.0.0" };
		},

		gauge :function(map_id){
			return this._gauges["m"+map_id] || false;
		},

		defaultEquip :function(id){
			if (typeof this._defeq["s" + id] == "undefined") {
				console.log("No ship has master id " + id + " in defeq.json");
			}
			return this._defeq["s" + id] || 0;
		},

		detection :function(index){
			return this._battle.detection[index] || ["",""];
		},

		airbattle :function(index){
			return this._battle.airbattle[index] || ["",""];
		},

		engagement :function(index){
			return this._battle.engagement[index] || ["",""];
		},

		term: function(key) {
			return (ConfigManager.info_troll && this._terms.troll[key]) || this._terms.lang[key] || key;
		},

		nodeLetter : function(worldId, mapId, edgeId) {
			var map = this._edges["World " + worldId + "-" + mapId];
			if (typeof map !== "undefined") {
				var edge = map[edgeId];
				if (typeof edge !== "undefined") {
					return edge[1];	// return destination
				}
			}
			return edgeId;
		}
	};

})();
<commit_msg>Reisen U. cosplays Shoukaku<commit_after>/* Meta.js
KC3改 Meta Data

Provides access to data on built-in JSON files
*/
(function(){
	"use strict";

	window.KC3Meta = {
		_cache:{},
		_icons:{},
		_exp:{},
		_gauges:{},
		_ship:{},
		_defeq:{},
		_slotitem:{},
		_quests:{},
		_ranks:{},
		_stype:{},
		_servers:{},
		_battle:{},
		_terms:{
			troll:{},
			lang:{},
		},
		_edges:{},
		_defaultIcon:"",

		/* Initialization
		-------------------------------------------------------*/
		init :function( repo ){
			/* to remove deprecated warning
				http://stackoverflow.com/questions/22090764/alternative-to-async-false-ajax
			*/
			// Load Common Meta
			this._icons		= JSON.parse( $.ajax(repo+'icons.json', { async: false }).responseText );
			this._exp		= JSON.parse( $.ajax(repo+'experience.json', { async: false }).responseText );
			this._gauges	= JSON.parse( $.ajax(repo+'gauges.json', { async: false }).responseText );
			this._defeq		= JSON.parse( $.ajax(repo+'defeq.json', { async: false }).responseText );
			this._edges		= JSON.parse( $.ajax(repo+'edges.json', { async: false }).responseText );

			// Load Translations
			this._ship 		= KC3Translation.getJSON(repo, 'ships', true);
			this._slotitem	= KC3Translation.getJSON(repo, 'items', true);
			this._quests	= KC3Translation.getJSON(repo, 'quests', true);
			this._ranks		= KC3Translation.getJSON(repo, 'ranks', true);
			this._stype		= KC3Translation.getJSON(repo, 'stype', true);
			this._servers	= KC3Translation.getJSON(repo, 'servers', true);
			this._battle	= KC3Translation.getJSON(repo, 'battle', true);
			// troll language always loaded
			this._terms.troll		= JSON.parse( $.ajax(repo+'lang/data/troll/terms.json', { async: false }).responseText );
			// other language loaded here
			this._terms.lang		= KC3Translation.getJSON(repo, 'terms');
		},

		/* Data Access
		-------------------------------------------------------*/
		defaultIcon :function(iconSrc){
			this._defaultIcon = iconSrc;
		},

		shipIcon :function(id, empty){
			if(typeof this._icons[id] !== "undefined"){
				return "http://i708.photobucket.com/albums/ww87/dragonjet25/KC3%20Ship%20Icons/"+this._icons[id];
			}
			if(typeof empty == "undefined"){
				return this._defaultIcon;
			}
			return empty;
		},

		abyssIcon :function(id, empty){
			if(typeof this._icons[id] !== "undefined"){
				return "http://i708.photobucket.com/albums/ww87/dragonjet25/KC3%20Abyss%20Icons/"+this._icons[id];
			}
			if(typeof empty == "undefined"){
				return this._defaultIcon;
			}
			return empty;
		},

		formationIcon :function(formationId){
			return "../../../../assets/img/formation2/" + formationId + ".png";
		},

		formationText :function(formationId){
			return [
				"",
				"Line Ahead",
				"Double Line",
				"Diamond",
				"Echelon",
				"Line Abreast",
				"","","","","",
				"Cruising Formation 1 (anti-sub)",
				"Cruising Formation 2 (forward)",
				"Cruising Formation 1 (anti-sub)",
				"Cruising Formation 1 (anti-sub)",
				"","","","","","",
				"Cruising Formation 1 (anti-sub)",
				"Cruising Formation 2 (forward)",
				"Cruising Formation 1 (anti-sub)",
				"Cruising Formation 1 (anti-sub)"
			][formationId];
		},

		shipName :function( jp_name ){
			if(typeof this._cache[jp_name] !== "undefined"){ return this._cache[jp_name]; }
			if(typeof this._ship[jp_name] !== "undefined"){
				this._cache[jp_name] = this._ship[jp_name];
				return this._cache[jp_name];
			}
			var
				bare = jp_name,
				combin = [],
				repTab = {
					"甲"   : '_A',
					"改二" : '_KaiNi',
					"改"   : '_Kai',
				},
				repRes = null,
				replaced = false;
			// in here, the regular expression will read which one comes first (which mean, to be in the end of the name
			// and then, the bare string will be chopped by how long the pattern match...
			// the matched one, added to the combination stack (which is FILO order)
			// removing from the replacement table in order to prevent infinite loop ^^;
			// if there's no match, it'll instantly stop and return the actual value
			while( repRes = (new RegExp(".+("+(Object.keys(repTab).join("|"))+")$",'gi')).exec(bare) ){
				bare = bare.substr(0, bare.length-repRes[1].length);
				combin.unshift(this._ship[repTab[repRes[1]]]);
				delete repTab[repRes[1]];
				replaced = true;
			}
			console.log("Remaining",bare,"with combination",combin.join(" "));
			if(replaced) {
				combin.unshift("");
				if(typeof this._ship[bare] !== "undefined"){
					this._cache[jp_name] = this._ship[bare] + (combin.length > 0 ? combin.join(" ") : "");
				}
				return this._cache[jp_name];
			}
			return jp_name;
		},

		gearName :function( jp_name ){
			if(typeof this._slotitem[ jp_name ] !== "undefined"){
				return this._slotitem[ jp_name ];
			}
			return jp_name;
		},

		exp :function(level){
			return this._exp[level] || [0,0];
		},

		quest :function(id){
			return this._quests[id] || false;
		},

		rank :function(id){
			return this._ranks[id] || "Unknown Rank";
		},

		stype :function(id){
			return this._stype[id] || "??";
		},

		server :function(ip){
			return this._servers[ip] || {name:"Unknown Server", num:0, ip:ip };
		},

		serverByNum :function(num){
			var ctr;
			for(ctr in this._servers){
				if(this._servers[ctr].num==num){
					return this._servers[ctr];
				}
			}
			return {name:"Unknown Server", num:num, ip:"0.0.0.0" };
		},

		gauge :function(map_id){
			return this._gauges["m"+map_id] || false;
		},

		defaultEquip :function(id){
			if (typeof this._defeq["s" + id] == "undefined") {
				console.log("No ship has master id " + id + " in defeq.json");
			}
			return this._defeq["s" + id] || 0;
		},

		detection :function(index){
			return this._battle.detection[index] || ["",""];
		},

		airbattle :function(index){
			return this._battle.airbattle[index] || ["",""];
		},

		engagement :function(index){
			return this._battle.engagement[index] || ["",""];
		},

		term: function(key) {
			return (ConfigManager.info_troll && this._terms.troll[key]) || this._terms.lang[key] || key;
		},

		nodeLetter : function(worldId, mapId, edgeId) {
			var map = this._edges["World " + worldId + "-" + mapId];
			if (typeof map !== "undefined") {
				var edge = map[edgeId];
				if (typeof edge !== "undefined") {
					return edge[1];	// return destination
				}
			}
			return edgeId;
		}
	};

})();
<|endoftext|>


<commit_before>import React from 'react';
import {mount} from 'enzyme';
import {CompositeDisposable} from 'event-kit';

import {cloneRepository, deferSetState} from '../helpers';
import IssueishPaneItem from '../../lib/items/issueish-pane-item';
import PaneItem from '../../lib/atom/pane-item';
import WorkdirContextPool from '../../lib/models/workdir-context-pool';
import {issueishPaneItemProps} from '../fixtures/props/issueish-pane-props';

describe('IssueishPaneItem', function() {
  let atomEnv, subs;

  beforeEach(function() {
    atomEnv = global.buildAtomEnvironment();
    subs = new CompositeDisposable();
  });

  afterEach(function() {
    subs.dispose();
    atomEnv.destroy();
  });

  function buildApp(overrideProps = {}) {
    const props = issueishPaneItemProps(overrideProps);

    return (
      <PaneItem workspace={atomEnv.workspace} uriPattern={IssueishPaneItem.uriPattern}>
        {({itemHolder, params}) => (
          <IssueishPaneItem
            ref={itemHolder.setter}
            {...params}
            issueishNumber={parseInt(params.issueishNumber, 10)}
            {...props}
          />
        )}
      </PaneItem>
    );
  }

  it('renders within the workspace center', async function() {
    const wrapper = mount(buildApp({}));

    const uri = IssueishPaneItem.buildURI('one.com', 'me', 'code', 400, __dirname);
    const item = await atomEnv.workspace.open(uri);

    assert.lengthOf(wrapper.update().find('IssueishPaneItem'), 1);

    const centerPaneItems = atomEnv.workspace.getCenter().getPaneItems();
    assert.include(centerPaneItems.map(i => i.getURI()), uri);

    assert.strictEqual(item.getURI(), uri);
    assert.strictEqual(item.getTitle(), 'me/code#400');
  });

  describe('issueish switching', function() {
    let workdirContextPool, atomGithubRepo, atomAtomRepo;

    beforeEach(async function() {
      workdirContextPool = new WorkdirContextPool();

      const atomGithubWorkdir = await cloneRepository();
      atomGithubRepo = workdirContextPool.add(atomGithubWorkdir).getRepository();
      await atomGithubRepo.getLoadPromise();
      await atomGithubRepo.addRemote('upstream', 'git@github.com:atom/github.git');

      const atomAtomWorkdir = await cloneRepository();
      atomAtomRepo = workdirContextPool.add(atomAtomWorkdir).getRepository();
      await atomAtomRepo.getLoadPromise();
      await atomAtomRepo.addRemote('upstream', 'https://github.com/atom/atom.git');
    });

    it('switches to a different issueish', async function() {
      const wrapper = mount(buildApp({workdirContextPool}));
      await atomEnv.workspace.open(IssueishPaneItem.buildURI('host.com', 'me', 'original', 1, __dirname));

      const before = wrapper.update().find('IssueishDetailContainer');
      assert.strictEqual(before.prop('host'), 'host.com');
      assert.strictEqual(before.prop('owner'), 'me');
      assert.strictEqual(before.prop('repo'), 'original');
      assert.strictEqual(before.prop('issueishNumber'), 1);

      await wrapper.find('IssueishDetailContainer').prop('switchToIssueish')('you', 'switched', 2);

      const after = wrapper.update().find('IssueishDetailContainer');
      assert.strictEqual(after.prop('host'), 'host.com');
      assert.strictEqual(after.prop('owner'), 'you');
      assert.strictEqual(after.prop('repo'), 'switched');
      assert.strictEqual(after.prop('issueishNumber'), 2);
    });

    it('changes the active repository when its issueish changes', async function() {
      const wrapper = mount(buildApp({workdirContextPool}));
      await atomEnv.workspace.open(IssueishPaneItem.buildURI('host.com', 'me', 'original', 1, __dirname));

      wrapper.update();
      assert.isTrue(wrapper.find('IssueishDetailContainer').prop('repository').isLoading());

      await wrapper.find('IssueishDetailContainer').prop('switchToIssueish')('atom', 'github', 2);
      wrapper.update();
      assert.strictEqual(wrapper.find('IssueishDetailContainer').prop('repository'), atomGithubRepo);

      await wrapper.find('IssueishDetailContainer').prop('switchToIssueish')('atom', 'atom', 100);
      wrapper.update();
      assert.strictEqual(wrapper.find('IssueishDetailContainer').prop('repository'), atomAtomRepo);
    });

    it('reverts to an absent repository when no matching repository is found', async function() {
      const workdir = atomAtomRepo.getWorkingDirectoryPath();
      const wrapper = mount(buildApp({workdirContextPool}));
      await atomEnv.workspace.open(IssueishPaneItem.buildURI('github.com', 'atom', 'atom', 5, workdir));

      wrapper.update();
      assert.strictEqual(wrapper.find('IssueishDetailContainer').prop('repository'), atomAtomRepo);

      await wrapper.find('IssueishDetailContainer').prop('switchToIssueish')('another', 'repo', 100);
      wrapper.update();
      assert.isTrue(wrapper.find('IssueishDetailContainer').prop('repository').isAbsent());
    });

    it('aborts a repository swap when pre-empted', async function() {
      const wrapper = mount(buildApp({workdirContextPool}));
      const item = await atomEnv.workspace.open(IssueishPaneItem.buildURI('github.com', 'another', 'repo', 5, __dirname));

      wrapper.update();
      assert.isTrue(wrapper.find('IssueishDetailContainer').prop('repository').isLoading());

      const {resolve: resolve0, started: started0} = deferSetState(item.getRealItem());
      const swap0 = wrapper.find('IssueishDetailContainer').prop('switchToIssueish')('atom', 'github', 100);
      await started0;

      const {resolve: resolve1} = deferSetState(item.getRealItem());
      const swap1 = wrapper.find('IssueishDetailContainer').prop('switchToIssueish')('atom', 'atom', 200);

      resolve1();
      await swap1;
      resolve0();
      await swap0;

      wrapper.update();
      assert.strictEqual(wrapper.find('IssueishDetailContainer').prop('repository'), atomAtomRepo);
    });

    it('reverts to an absent repository when multiple potential repositories are found', async function() {
      const workdir = await cloneRepository();
      const repo = workdirContextPool.add(workdir).getRepository();
      await repo.getLoadPromise();
      await repo.addRemote('upstream', 'https://github.com/atom/atom.git');

      const wrapper = mount(buildApp({workdirContextPool}));
      await atomEnv.workspace.open(IssueishPaneItem.buildURI('host.com', 'me', 'original', 1, __dirname));
      wrapper.update();

      await wrapper.find('IssueishDetailContainer').prop('switchToIssueish')('atom', 'atom', 100);
      wrapper.update();

      assert.strictEqual(wrapper.find('IssueishDetailContainer').prop('owner'), 'atom');
      assert.strictEqual(wrapper.find('IssueishDetailContainer').prop('repo'), 'atom');
      assert.strictEqual(wrapper.find('IssueishDetailContainer').prop('issueishNumber'), 100);
      assert.isTrue(wrapper.find('IssueishDetailContainer').prop('repository').isAbsent());
    });
  });

  it('reconstitutes its original URI', async function() {
    const wrapper = mount(buildApp({}));

    const uri = IssueishPaneItem.buildURI('host.com', 'me', 'original', 1, __dirname);
    const item = await atomEnv.workspace.open(uri);
    assert.strictEqual(item.getURI(), uri);
    assert.strictEqual(item.serialize().uri, uri);

    wrapper.update().find('IssueishDetailContainer').prop('switchToIssueish')('you', 'switched', 2);

    assert.strictEqual(item.getURI(), uri);
    assert.strictEqual(item.serialize().uri, uri);
  });

  it('broadcasts title changes', async function() {
    const wrapper = mount(buildApp({}));
    const item = await atomEnv.workspace.open(IssueishPaneItem.buildURI('host.com', 'user', 'repo', 1, __dirname));
    assert.strictEqual(item.getTitle(), 'user/repo#1');

    const handler = sinon.stub();
    subs.add(item.onDidChangeTitle(handler));

    wrapper.update().find('IssueishDetailContainer').prop('onTitleChange')('SUP');
    assert.strictEqual(handler.callCount, 1);
    assert.strictEqual(item.getTitle(), 'SUP');

    wrapper.update().find('IssueishDetailContainer').prop('onTitleChange')('SUP');
    assert.strictEqual(handler.callCount, 1);
  });

  it('tracks pending state termination', async function() {
    mount(buildApp({}));
    const item = await atomEnv.workspace.open(IssueishPaneItem.buildURI('host.com', 'user', 'repo', 1, __dirname));

    const handler = sinon.stub();
    subs.add(item.onDidTerminatePendingState(handler));

    item.terminatePendingState();
    assert.strictEqual(handler.callCount, 1);

    item.terminatePendingState();
    assert.strictEqual(handler.callCount, 1);
  });
});
<commit_msg>Remove flaky assertions<commit_after>import React from 'react';
import {mount} from 'enzyme';
import {CompositeDisposable} from 'event-kit';

import {cloneRepository, deferSetState} from '../helpers';
import IssueishPaneItem from '../../lib/items/issueish-pane-item';
import PaneItem from '../../lib/atom/pane-item';
import WorkdirContextPool from '../../lib/models/workdir-context-pool';
import {issueishPaneItemProps} from '../fixtures/props/issueish-pane-props';

describe('IssueishPaneItem', function() {
  let atomEnv, subs;

  beforeEach(function() {
    atomEnv = global.buildAtomEnvironment();
    subs = new CompositeDisposable();
  });

  afterEach(function() {
    subs.dispose();
    atomEnv.destroy();
  });

  function buildApp(overrideProps = {}) {
    const props = issueishPaneItemProps(overrideProps);

    return (
      <PaneItem workspace={atomEnv.workspace} uriPattern={IssueishPaneItem.uriPattern}>
        {({itemHolder, params}) => (
          <IssueishPaneItem
            ref={itemHolder.setter}
            {...params}
            issueishNumber={parseInt(params.issueishNumber, 10)}
            {...props}
          />
        )}
      </PaneItem>
    );
  }

  it('renders within the workspace center', async function() {
    const wrapper = mount(buildApp({}));

    const uri = IssueishPaneItem.buildURI('one.com', 'me', 'code', 400, __dirname);
    const item = await atomEnv.workspace.open(uri);

    assert.lengthOf(wrapper.update().find('IssueishPaneItem'), 1);

    const centerPaneItems = atomEnv.workspace.getCenter().getPaneItems();
    assert.include(centerPaneItems.map(i => i.getURI()), uri);

    assert.strictEqual(item.getURI(), uri);
    assert.strictEqual(item.getTitle(), 'me/code#400');
  });

  describe('issueish switching', function() {
    let workdirContextPool, atomGithubRepo, atomAtomRepo;

    beforeEach(async function() {
      workdirContextPool = new WorkdirContextPool();

      const atomGithubWorkdir = await cloneRepository();
      atomGithubRepo = workdirContextPool.add(atomGithubWorkdir).getRepository();
      await atomGithubRepo.getLoadPromise();
      await atomGithubRepo.addRemote('upstream', 'git@github.com:atom/github.git');

      const atomAtomWorkdir = await cloneRepository();
      atomAtomRepo = workdirContextPool.add(atomAtomWorkdir).getRepository();
      await atomAtomRepo.getLoadPromise();
      await atomAtomRepo.addRemote('upstream', 'https://github.com/atom/atom.git');
    });

    it('switches to a different issueish', async function() {
      const wrapper = mount(buildApp({workdirContextPool}));
      await atomEnv.workspace.open(IssueishPaneItem.buildURI('host.com', 'me', 'original', 1, __dirname));

      const before = wrapper.update().find('IssueishDetailContainer');
      assert.strictEqual(before.prop('host'), 'host.com');
      assert.strictEqual(before.prop('owner'), 'me');
      assert.strictEqual(before.prop('repo'), 'original');
      assert.strictEqual(before.prop('issueishNumber'), 1);

      await wrapper.find('IssueishDetailContainer').prop('switchToIssueish')('you', 'switched', 2);

      const after = wrapper.update().find('IssueishDetailContainer');
      assert.strictEqual(after.prop('host'), 'host.com');
      assert.strictEqual(after.prop('owner'), 'you');
      assert.strictEqual(after.prop('repo'), 'switched');
      assert.strictEqual(after.prop('issueishNumber'), 2);
    });

    it('changes the active repository when its issueish changes', async function() {
      const wrapper = mount(buildApp({workdirContextPool}));
      await atomEnv.workspace.open(IssueishPaneItem.buildURI('host.com', 'me', 'original', 1, __dirname));

      wrapper.update();

      await wrapper.find('IssueishDetailContainer').prop('switchToIssueish')('atom', 'github', 2);
      wrapper.update();
      assert.strictEqual(wrapper.find('IssueishDetailContainer').prop('repository'), atomGithubRepo);

      await wrapper.find('IssueishDetailContainer').prop('switchToIssueish')('atom', 'atom', 100);
      wrapper.update();
      assert.strictEqual(wrapper.find('IssueishDetailContainer').prop('repository'), atomAtomRepo);
    });

    it('reverts to an absent repository when no matching repository is found', async function() {
      const workdir = atomAtomRepo.getWorkingDirectoryPath();
      const wrapper = mount(buildApp({workdirContextPool}));
      await atomEnv.workspace.open(IssueishPaneItem.buildURI('github.com', 'atom', 'atom', 5, workdir));

      wrapper.update();
      assert.strictEqual(wrapper.find('IssueishDetailContainer').prop('repository'), atomAtomRepo);

      await wrapper.find('IssueishDetailContainer').prop('switchToIssueish')('another', 'repo', 100);
      wrapper.update();
      assert.isTrue(wrapper.find('IssueishDetailContainer').prop('repository').isAbsent());
    });

    it('aborts a repository swap when pre-empted', async function() {
      const wrapper = mount(buildApp({workdirContextPool}));
      const item = await atomEnv.workspace.open(IssueishPaneItem.buildURI('github.com', 'another', 'repo', 5, __dirname));

      wrapper.update();

      const {resolve: resolve0, started: started0} = deferSetState(item.getRealItem());
      const swap0 = wrapper.find('IssueishDetailContainer').prop('switchToIssueish')('atom', 'github', 100);
      await started0;

      const {resolve: resolve1} = deferSetState(item.getRealItem());
      const swap1 = wrapper.find('IssueishDetailContainer').prop('switchToIssueish')('atom', 'atom', 200);

      resolve1();
      await swap1;
      resolve0();
      await swap0;

      wrapper.update();
      assert.strictEqual(wrapper.find('IssueishDetailContainer').prop('repository'), atomAtomRepo);
    });

    it('reverts to an absent repository when multiple potential repositories are found', async function() {
      const workdir = await cloneRepository();
      const repo = workdirContextPool.add(workdir).getRepository();
      await repo.getLoadPromise();
      await repo.addRemote('upstream', 'https://github.com/atom/atom.git');

      const wrapper = mount(buildApp({workdirContextPool}));
      await atomEnv.workspace.open(IssueishPaneItem.buildURI('host.com', 'me', 'original', 1, __dirname));
      wrapper.update();

      await wrapper.find('IssueishDetailContainer').prop('switchToIssueish')('atom', 'atom', 100);
      wrapper.update();

      assert.strictEqual(wrapper.find('IssueishDetailContainer').prop('owner'), 'atom');
      assert.strictEqual(wrapper.find('IssueishDetailContainer').prop('repo'), 'atom');
      assert.strictEqual(wrapper.find('IssueishDetailContainer').prop('issueishNumber'), 100);
      assert.isTrue(wrapper.find('IssueishDetailContainer').prop('repository').isAbsent());
    });
  });

  it('reconstitutes its original URI', async function() {
    const wrapper = mount(buildApp({}));

    const uri = IssueishPaneItem.buildURI('host.com', 'me', 'original', 1, __dirname);
    const item = await atomEnv.workspace.open(uri);
    assert.strictEqual(item.getURI(), uri);
    assert.strictEqual(item.serialize().uri, uri);

    wrapper.update().find('IssueishDetailContainer').prop('switchToIssueish')('you', 'switched', 2);

    assert.strictEqual(item.getURI(), uri);
    assert.strictEqual(item.serialize().uri, uri);
  });

  it('broadcasts title changes', async function() {
    const wrapper = mount(buildApp({}));
    const item = await atomEnv.workspace.open(IssueishPaneItem.buildURI('host.com', 'user', 'repo', 1, __dirname));
    assert.strictEqual(item.getTitle(), 'user/repo#1');

    const handler = sinon.stub();
    subs.add(item.onDidChangeTitle(handler));

    wrapper.update().find('IssueishDetailContainer').prop('onTitleChange')('SUP');
    assert.strictEqual(handler.callCount, 1);
    assert.strictEqual(item.getTitle(), 'SUP');

    wrapper.update().find('IssueishDetailContainer').prop('onTitleChange')('SUP');
    assert.strictEqual(handler.callCount, 1);
  });

  it('tracks pending state termination', async function() {
    mount(buildApp({}));
    const item = await atomEnv.workspace.open(IssueishPaneItem.buildURI('host.com', 'user', 'repo', 1, __dirname));

    const handler = sinon.stub();
    subs.add(item.onDidTerminatePendingState(handler));

    item.terminatePendingState();
    assert.strictEqual(handler.callCount, 1);

    item.terminatePendingState();
    assert.strictEqual(handler.callCount, 1);
  });
});
<|endoftext|>


<commit_before>/**
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

var cls = require('../../cls.js');
var shimmer = require('shimmer');
var semver = require('semver');
var SpanData = require('../../span-data.js');
var findIndex = require('lodash.findindex');

var agent;

var SUPPORTED_VERSIONS = '0.13 - 0.15';

function makeClientMethod(method, name) {
  return function clientMethodTrace() {
    var root = cls.getRootContext();
    if (!root) {
      agent.logger.debug('Untraced gRPC call: ', method.path);
      return method.apply(this, arguments);
    } else if (root === SpanData.nullSpan) {
      return method.apply(this, arguments);
    }
    // The span name will be of form "grpc:/[Service]/[MethodName]".
    var span = agent.startSpan('grpc:' + method.path);
    // Check if the response is through a stream or a callback.
    if (!method.responseStream) {
      // We need to wrap the callback with the context, to propagate it.
      // The callback is always required. It should be the only function in the
      // arguments, since we cannot send a function as an argument through gRPC.
      var cbIndex = findIndex(arguments, function(arg) {
        return typeof arg === 'function';
      });
      if (cbIndex !== -1) {
        arguments[cbIndex] = wrapCallback(span, arguments[cbIndex]);
      }
    }
    var call = method.apply(this, arguments);
    // Add extra data only when call successfully goes through. At this point
    // we know that the arguments are correct.
    if (agent.config_.enhancedDatabaseReporting) {
      // This finds an instance of Metadata among the arguments.
      // A possible issue that could occur is if the 'options' parameter from
      // the user contains an '_internal_repr' as well as a 'getMap' function,
      // but this is an extremely rare case.
      var metaIndex = findIndex(arguments, function(arg) {
        return arg && typeof arg === 'object' && arg._internal_repr &&
            typeof arg.getMap === 'function';
      });
      if (metaIndex !== -1) {
        var metadata = arguments[metaIndex];
        span.addLabel('metadata', JSON.stringify(metadata.getMap()));
      }
      if (!method.requestStream) {
        span.addLabel('argument', JSON.stringify(arguments[0]));
      }
    }
    // The user might need the current context in listeners to this stream.
    cls.getNamespace().bindEmitter(call);
    if (method.responseStream) {
      // It is possible that gRPC emits simply 'error', or simply 'status',
      // or both 'status' and 'error'. We need to make sure we do not end
      // the span twice in the last case.
      var spanEnded = false;
      call.on('error', function(err) {
        if (!spanEnded) {
          if (agent.config_.enhancedDatabaseReporting) {
            span.addLabel('error', err);
          }
          agent.endSpan(span);
          spanEnded = true;
        }
      });
      call.on('status', function(status) {
        if (!spanEnded) {
          if (agent.config_.enhancedDatabaseReporting) {
            span.addLabel('status', JSON.stringify(status));
          }
          agent.endSpan(span);
          spanEnded = true;
        }
      });
    }
    return call;
  };
}

/**
 * Wraps a callback so that the current span for this trace is also ended when
 * the callback is invoked.
 * @param {SpanData} span - The span that should end after this callback.
 * @param {function(?Error, value=)} done - The callback to be wrapped.
 */
function wrapCallback(span, done) {
  var fn = function(err, res) {
    if (agent.config_.enhancedDatabaseReporting) {
      if (err) {
        span.addLabel('error', err);
      }
      if (res) {
        span.addLabel('result', JSON.stringify(res));
      }
    }
    agent.endSpan(span);
    done(err, res);
  };
  return cls.getNamespace().bind(fn);
}

function makeClientConstructorWrap(makeClientConstructor) {
  return function makeClientConstructorTrace(methods) {
    var Client = makeClientConstructor.apply(this, arguments);
    shimmer.massWrap(Client.prototype, Object.keys(methods), makeClientMethod);
    return Client;
  };
}

module.exports = function(version_, agent_) {
  if (!semver.satisfies(version_, SUPPORTED_VERSIONS)) {
    agent_.logger.info('grpc: unsupported version ' + version_ + ' loaded');
    return {};
  }
  return {
    'src/node/src/client.js': {
      patch: function(client) {
        agent = agent_;
        shimmer.wrap(client, 'makeClientConstructor',
            makeClientConstructorWrap);
      },
      unpatch: function(client) {
        // Only the Client constructor is unwrapped, so that future grpc.load's
        // will not wrap Client methods with tracing. However, existing Client
        // objects with wrapped prototype methods will continue tracing.
        shimmer.unwrap(client, 'makeClientConstructor');
        agent_.logger.info('gRPC makeClientConstructor: unpatched');
      }
    }
  };
};
<commit_msg>Add support for pre-release grpc v1.1.0 (#281)<commit_after>/**
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

var cls = require('../../cls.js');
var shimmer = require('shimmer');
var semver = require('semver');
var SpanData = require('../../span-data.js');
var findIndex = require('lodash.findindex');

var agent;

var SUPPORTED_VERSIONS = '0.13 - 1';

function makeClientMethod(method, name) {
  return function clientMethodTrace() {
    var root = cls.getRootContext();
    if (!root) {
      agent.logger.debug('Untraced gRPC call: ', method.path);
      return method.apply(this, arguments);
    } else if (root === SpanData.nullSpan) {
      return method.apply(this, arguments);
    }
    // The span name will be of form "grpc:/[Service]/[MethodName]".
    var span = agent.startSpan('grpc:' + method.path);
    // Check if the response is through a stream or a callback.
    if (!method.responseStream) {
      // We need to wrap the callback with the context, to propagate it.
      // The callback is always required. It should be the only function in the
      // arguments, since we cannot send a function as an argument through gRPC.
      var cbIndex = findIndex(arguments, function(arg) {
        return typeof arg === 'function';
      });
      if (cbIndex !== -1) {
        arguments[cbIndex] = wrapCallback(span, arguments[cbIndex]);
      }
    }
    var call = method.apply(this, arguments);
    // Add extra data only when call successfully goes through. At this point
    // we know that the arguments are correct.
    if (agent.config_.enhancedDatabaseReporting) {
      // This finds an instance of Metadata among the arguments.
      // A possible issue that could occur is if the 'options' parameter from
      // the user contains an '_internal_repr' as well as a 'getMap' function,
      // but this is an extremely rare case.
      var metaIndex = findIndex(arguments, function(arg) {
        return arg && typeof arg === 'object' && arg._internal_repr &&
            typeof arg.getMap === 'function';
      });
      if (metaIndex !== -1) {
        var metadata = arguments[metaIndex];
        span.addLabel('metadata', JSON.stringify(metadata.getMap()));
      }
      if (!method.requestStream) {
        span.addLabel('argument', JSON.stringify(arguments[0]));
      }
    }
    // The user might need the current context in listeners to this stream.
    cls.getNamespace().bindEmitter(call);
    if (method.responseStream) {
      // It is possible that gRPC emits simply 'error', or simply 'status',
      // or both 'status' and 'error'. We need to make sure we do not end
      // the span twice in the last case.
      var spanEnded = false;
      call.on('error', function(err) {
        if (!spanEnded) {
          if (agent.config_.enhancedDatabaseReporting) {
            span.addLabel('error', err);
          }
          agent.endSpan(span);
          spanEnded = true;
        }
      });
      call.on('status', function(status) {
        if (!spanEnded) {
          if (agent.config_.enhancedDatabaseReporting) {
            span.addLabel('status', JSON.stringify(status));
          }
          agent.endSpan(span);
          spanEnded = true;
        }
      });
    }
    return call;
  };
}

/**
 * Wraps a callback so that the current span for this trace is also ended when
 * the callback is invoked.
 * @param {SpanData} span - The span that should end after this callback.
 * @param {function(?Error, value=)} done - The callback to be wrapped.
 */
function wrapCallback(span, done) {
  var fn = function(err, res) {
    if (agent.config_.enhancedDatabaseReporting) {
      if (err) {
        span.addLabel('error', err);
      }
      if (res) {
        span.addLabel('result', JSON.stringify(res));
      }
    }
    agent.endSpan(span);
    done(err, res);
  };
  return cls.getNamespace().bind(fn);
}

function makeClientConstructorWrap(makeClientConstructor) {
  return function makeClientConstructorTrace(methods) {
    var Client = makeClientConstructor.apply(this, arguments);
    shimmer.massWrap(Client.prototype, Object.keys(methods), makeClientMethod);
    return Client;
  };
}

module.exports = function(version_, agent_) {
  if (!semver.satisfies(version_, SUPPORTED_VERSIONS)) {
    agent_.logger.info('grpc: unsupported version ' + version_ + ' loaded');
    return {};
  }
  return {
    'src/node/src/client.js': {
      patch: function(client) {
        agent = agent_;
        shimmer.wrap(client, 'makeClientConstructor',
            makeClientConstructorWrap);
      },
      unpatch: function(client) {
        // Only the Client constructor is unwrapped, so that future grpc.load's
        // will not wrap Client methods with tracing. However, existing Client
        // objects with wrapped prototype methods will continue tracing.
        shimmer.unwrap(client, 'makeClientConstructor');
        agent_.logger.info('gRPC makeClientConstructor: unpatched');
      }
    }
  };
};
<|endoftext|>


<commit_before>/*global define*/
(function (root, factory) {
  if (typeof exports === 'object') {
    module.exports = factory(require('chance'))
  } else if (typeof define === 'function' && define.amd) {
    define(['chance'], factory)
  } else {
    root.weknowhow = root.weknowhow || {}
    root.weknowhow.chanceGenerators = factory(root.chance)
  }
})(this, function (Chance) {
  // Fix that pick provided a count of zero or one does not return an array
  var originalPick = Chance.prototype.pick
  Chance.prototype.pick = function (array, count) {
    if (count === 0) {
      return []
    }

    if (count === 1) {
      return [originalPick.call(this, array, count)]
    }

    return originalPick.call(this, array, count)
  }

  function ExtendedChance (seed) {
    if (!(this instanceof ExtendedChance)) {
      return new ExtendedChance(seed)
    }

    var that = this
    var chance = typeof seed === 'undefined'
        ? new Chance()
        : new Chance(seed)

    function unwrap (v) {
      if (Array.isArray(v)) {
        return v.map(unwrap)
      } else if (v && typeof v === 'object') {
        return Object.keys(v).reduce(function (result, key) {
          result[key] = unwrap(v[key])
          return result
        }, {})
      } else {
        return v && v.isGenerator ? v() : v
      }
    }

    function generatorFunction (name, args, f) {
      f.isGenerator = true
      f.generatorName = name
      f.args = args
      f.toString = function () {
        return name
      }
      return f
    }

    var overrides = {
      n: function (generator, count) {
        return createGenerator('n', [generator, count], [generator])
      },
      unique: function (generator, count, options) {
        return createGenerator('unique', [generator, count], [generator])
      }
    }

    function minMaxShrinker (generator, data) {
      var currentLimits = generator.args[0] || {}
      var limits
      if (data < 0) {
        limits = {
          min: data,
          max: Math.min(0, currentLimits.max || 0)
        }
      } else {
        limits = {
          min: Math.max(0, currentLimits.min || 0),
          max: data
        }
      }

      return createGenerator(generator.generatorName, [limits])
    }

    var shrinkers = {
      n: function (generator, data) {
        if (data.length === 0) {
          return that.identity(data)
        }

        var count = generator.args[1]
        if (count && count.shrink) {
          count = count.shrink(data.length)
        } else {
          count = data.length
        }

        return createGenerator('pick', [data, count])
      },
      pick: function (generator, data) {
        if (data.length === 0) {
          return that.identity(data)
        }

        var count = generator.args[1]
        if (count && count.shrink) {
          count = count.shrink(data.length)
        } else if (typeof count !== 'number') {
          count = that.integer({ min: 0, max: data.length })
        }

        return createGenerator('pick', [data, count])
      },
      unique: function (generator, data) {
        var count = generator.args[1]
        if (count && count.shrink) {
          count = count.shrink(data.length)
        } else {
          count = data.length
        }

        return createGenerator('pick', [data, count])
      },
      integer: minMaxShrinker,
      natural: minMaxShrinker,
      floating: minMaxShrinker
    }

    function createGenerator (name, args, omitUnwap) {
      var omitUnwrapIndex = {}

      omitUnwap && args.forEach(function (arg, i) {
        if (omitUnwap.indexOf(arg) !== -1) {
          omitUnwrapIndex[i] = true
        }
      })

      var g = generatorFunction(name, args, function () {
        if (arguments.length === 0) {
          return chance[name].apply(chance, args.map(function (arg, i) {
            return omitUnwrapIndex[i] ? arg : unwrap(arg)
          }))
        } else {
          return createGenerator(
            name,
            Array.prototype.slice.call(arguments)
          )
        }
      })

      var shrinker = shrinkers[name]
      if (shrinker) {
        g.shrink = function (data) {
          return shrinker(g, data)
        }
      }

      return g
    }

    Object.keys(Chance.prototype).forEach(function (key) {
      var property = chance[key]
      if (typeof property === 'function') {
        if (overrides[key]) {
          that[key] = generatorFunction(key, [], overrides[key])
        } else {
          that[key] = createGenerator(key, [])
        }
      } else {
        that[key] = property
      }
    })

    that.identity = generatorFunction('identity', [], function (data) {
      return generatorFunction('identity', [data], function () {
        return data
      })
    })
  }

  return ExtendedChance
})
<commit_msg>Introduced shriking for more generators, fixed some edge cases<commit_after>/*global define*/
(function (root, factory) {
  if (typeof exports === 'object') {
    module.exports = factory(require('chance'))
  } else if (typeof define === 'function' && define.amd) {
    define(['chance'], factory)
  } else {
    root.weknowhow = root.weknowhow || {}
    root.weknowhow.chanceGenerators = factory(root.chance)
  }
})(this, function (Chance) {
  // Fix that pick provided a count of zero or one does not return an array
  var originalPick = Chance.prototype.pick
  Chance.prototype.pick = function (array, count) {
    if (count === 0) {
      return []
    }

    if (count === 1) {
      return [originalPick.call(this, array, count)]
    }

    return originalPick.call(this, array, count)
  }

  function copy (source) {
    var result = {}
    Object.keys(source).forEach(function (key) {
      result[key] = source[key]
    })
    return result
  }

  function ExtendedChance (seed) {
    if (!(this instanceof ExtendedChance)) {
      return new ExtendedChance(seed)
    }

    var that = this
    var chance = typeof seed === 'undefined'
        ? new Chance()
        : new Chance(seed)

    function unwrap (v) {
      if (Array.isArray(v)) {
        return v.map(unwrap)
      } else if (v && typeof v === 'object') {
        return Object.keys(v).reduce(function (result, key) {
          result[key] = unwrap(v[key])
          return result
        }, {})
      } else {
        return v && v.isGenerator ? v() : v
      }
    }

    function generatorFunction (name, args, f) {
      f.isGenerator = true
      f.generatorName = name
      f.args = args
      f.toString = function () {
        return name
      }
      return f
    }

    var overrides = {
      n: function (generator, count) {
        return createGenerator('n', [generator, count], [generator])
      },
      unique: function (generator, count, options) {
        return createGenerator('unique', [generator, count], [generator])
      }
    }

    function minMaxShrinker (generator, data) {
      var currentLimits = generator.args[0] || {}
      var limits = copy(currentLimits)

      if (data < 0) {
        var max = currentLimits.max || 0
        limits = {
          min: data,
          max: Math.min(0, max)
        }
      } else {
        var min = currentLimits.min || 0
        limits = {
          min: Math.max(0, min),
          max: data
        }
      }

      return createGenerator(generator.generatorName, [limits])
    }

    var shrinkers = {
      n: function (generator, data) {
        if (data.length === 0) {
          return that.identity(data)
        }

        var count = generator.args[1]
        if (count && count.shrink) {
          count = count.shrink(data.length)
        } else {
          count = data.length
        }

        return createGenerator('pick', [data, count])
      },
      pick: function (generator, data) {
        if (data.length === 0) {
          return that.identity(data)
        }

        var count = generator.args[1]
        if (count && count.shrink) {
          count = count.shrink(data.length)
        } else if (typeof count !== 'number') {
          count = that.integer({ min: 0, max: data.length })
        }

        return createGenerator('pick', [data, count])
      },
      unique: function (generator, data) {
        var count = generator.args[1]
        if (count && count.shrink) {
          count = count.shrink(data.length)
        } else {
          count = data.length
        }

        return createGenerator('pick', [data, count])
      },
      string: function (generator, data) {
        if (data.length === 0) {
          return that.identity(data)
        }

        var currentLimits = generator.args[0] || {}
        var limits = copy(currentLimits)
        if (typeof limits.length === 'undefined') {
          limits.length = that.integer({ min: 0, max: data.length })
        } else if (limits.length && limits.length.shrink) {
          limits.length = limits.length.shrink(data.length)
        }

        return createGenerator('string', [limits])
      },
      integer: minMaxShrinker,
      natural: minMaxShrinker,
      floating: minMaxShrinker,
      year: minMaxShrinker,
      altitude: minMaxShrinker,
      depth: minMaxShrinker,
      latitude: minMaxShrinker,
      longitude: minMaxShrinker,
      dollar: minMaxShrinker
    }

    function createGenerator (name, args, omitUnwap) {
      var omitUnwrapIndex = {}

      omitUnwap && args.forEach(function (arg, i) {
        if (omitUnwap.indexOf(arg) !== -1) {
          omitUnwrapIndex[i] = true
        }
      })

      var g = generatorFunction(name, args, function () {
        if (arguments.length === 0) {
          return chance[name].apply(chance, args.map(function (arg, i) {
            return omitUnwrapIndex[i] ? arg : unwrap(arg)
          }))
        } else {
          return createGenerator(
            name,
            Array.prototype.slice.call(arguments)
          )
        }
      })

      var shrinker = shrinkers[name]
      if (shrinker) {
        g.shrink = function (data) {
          return shrinker(g, data)
        }
      } else {
        g.shrink = function (data) {
          return that.identity(data)
        }
      }

      return g
    }

    Object.keys(Chance.prototype).forEach(function (key) {
      var property = chance[key]
      if (typeof property === 'function') {
        if (overrides[key]) {
          that[key] = generatorFunction(key, [], overrides[key])
        } else {
          that[key] = createGenerator(key, [])
        }
      } else {
        that[key] = property
      }
    })

    that.identity = generatorFunction('identity', [], function (data) {
      return generatorFunction('identity', [data], function () {
        return data
      })
    })
  }

  return ExtendedChance
})
<|endoftext|>


<commit_before>$(document).ready(function() {
  // This is called after the document has loaded in its entirety
  // This guarantees that any elements we bind to will exist on the page
  // when we try to bind to them

  // See: http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
  $('#content').on('submit', 'form.delete_form', function (event) {
    event.preventDefault();
    var $target = $(event.target);
    $.ajax({
      url: $target.attr('action'),
      type: 'DELETE'
    }).done(function(response) {
      $target.closest('.task').remove();
    });
  });

  $('#content').on('submit', 'form.toggle_form', function (event) {

    event.preventDefault();

    var $target = $(event.target);
    var $complete_btn = $target.children('input[type=submit]');

    $complete_btn.attr("disabled", true);

    $.ajax({
      //url: '/task/' + task_id + '/toggle_complete'
      url: $target.attr('action'),
      type: 'PUT'
    }).done(function (response) {
      $target.closest('.task').replaceWith(response);
      // $target.closest('.task').find('p.description').first().toggleClass('strikethrough');

      // // Deal with the button
      // var text = $complete_btn.val() == "Complete" ? "Uncomplete" : "Complete";
      // $complete_btn.val(text);
      // $complete_btn.attr("disabled", false);
    })
  })
});
<commit_msg>Make edit link show form.<commit_after>$(document).ready(function() {
  // Delete
  $('#content').on('submit', 'form.delete_form', function (event) {
    event.preventDefault();
    var $target = $(event.target);
    $.ajax({
      url: $target.attr('action'),
      type: 'DELETE'
    }).done(function(response) {
      $target.closest('.task').remove();
    });
  });
  // Toggle
  $('#content').on('submit', 'form.toggle_form', function (event) {

    event.preventDefault();

    var $target = $(event.target);
    var $complete_btn = $target.children('input[type=submit]');

    $complete_btn.attr("disabled", true);

    $.ajax({
      url: $target.attr('action'),
      type: 'PUT'
    }).done(function (response) {
      $target.closest('.task').replaceWith(response);
    })
  })
  // Edit link
  $('#content').on('click', 'a.edit_link', function(event) {
    event.preventDefault();

    var $target = $(event.target);

    $target.closest('.task').children('.edit_wrapper').show();
  });
});
<|endoftext|>