<commit_before>/**
 * Copyright 2015 Alistair Stead
 *
 * 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.
 */
define([], function() {

	var PageController = ['$scope', 'auth', '$stateParams', 'api', '$window', '$rootScope', '$sce', '$timeout', function($scope, auth, $stateParams, api, $window, $rootScope, $sce, $timeout) {
		$scope.isAdminUser = $rootScope.user.role == 'ADMIN';
	    $scope.statistics = null;
	    $scope.setLoading(true);
	    $scope.apiVersion = api.contentVersion.get();
	    $scope.emailTypes = null;

	    $scope.lastContentIDSuccessfullyPreviewed = "";

	    $scope.htmlPreview = "";
	    $scope.plainTextPreview = "";
	    $scope.subjectPreview = "";

	    $scope.emailToSend = {
	    	emailType : -1,
	    	contentObjectId : "",
	    	users: {
		    	ADMIN : false,
		    	EVENT_MANAGER : false,
		    	CONTENT_EDITOR : false,
		    	TEACHER : false,
		    	TESTER : false,
		    	STAFF : false,
		    	STUDENT : false,
			}
	    };

	    $scope.getInitialUserFilterState = function() {
	    	if($stateParams.userIds != null){
	    		$scope.csvuseridlist = $stateParams.userIds;
	    		return('csvuseridlist');
	    	}
	    	return('userfilter');
	    }

	    $scope.queueSize = "?";
	    var checkTimes = 0;

	    var queueSizeChecker = function(){
	    	api.email.getQueueSize({}).$promise.then(function(result){
	    		var d = new Date();
    			$scope.queueSize = "" + result.length + " at " + d.toLocaleTimeString();
				$timeout(queueSizeChecker, 5000);
    		}).catch(function(e){
				$scope.showToast($scope.toastTypes.Failure, "Email Queue Size", "Could not get email queue size (" + e.status + ") " + e.statusText);
				clearInterval(timerId);
			});
    	}

	    queueSizeChecker();

		var getUserIdArrayFromTextArea = function(){
			var userids = $scope.csvuseridlist.split(/[\s,]+/).map(function(e) {return parseInt(e);});;
			return userids;
		}

	    $scope.getTotalUsers = function(){
	    	if($scope.userSelectionType == 'csvuseridlist') {
				var userIdList = getUserIdArrayFromTextArea();
				return userIdList.length;
	    	}

	    	var total = 0;
			if($scope.emailToSend.users.ADMIN) {
	    		total += parseInt($scope.statistics.role.ADMIN);
	    	}

	    	if($scope.emailToSend.users.EVENT_MANAGER) {
	    		total += parseInt($scope.statistics.role.EVENT_MANAGER);
	    	}

	    	if($scope.emailToSend.users.CONTENT_EDITOR) {
	    		total += parseInt($scope.statistics.role.CONTENT_EDITOR);
	    	}

	    	if($scope.emailToSend.users.TEACHER) {
	    		total += parseInt($scope.statistics.role.TEACHER);
	    	}

	    	if($scope.emailToSend.users.TESTER) {
	    		total += parseInt($scope.statistics.role.TESTER);
	    	}

	    	if($scope.emailToSend.users.STAFF) {
	    		total += parseInt($scope.statistics.role.STAFF);
	    	}

	    	if($scope.emailToSend.users.STUDENT) {
	    		total += parseInt($scope.statistics.role.STUDENT);
	    	}
	    	return total;
	    }

	    api.statisticsEndpoint.get().$promise.then(function(result){
	        $scope.statistics = result;
	        $scope.setLoading(false);
	    }).catch(function(e){
			$scope.showToast($scope.toastTypes.Failure, "Statistics load failed", "With error message (" + e.status + ") " + e.statusText);
	    });

	    api.email.getPreferences().$promise.then(function(result){
	    	$scope.emailTypes = result;
	    }).catch(function(e){
			$scope.showToast($scope.toastTypes.Failure, "Preferences load failed", "With error message (" + e.status + ") " + e.statusText);
	    });

	    $scope.loadContentTemplate = function(contentId){
	    	$scope.setLoading(true);
	    	api.email.get({"id" : $scope.emailToSend.contentObjectId}).$promise.then(function(content){
	        	$scope.subjectPreview = content.subject;
	        	$scope.htmlPreview = $sce.trustAsResourceUrl("data:text/html," + encodeURIComponent(content.html));
	        	$scope.plainTextPreview = $sce.trustAsResourceUrl("data:/html," + encodeURIComponent(content.plainText));
	        	$scope.setLoading(false);
	        	$scope.lastContentIDSuccessfullyPreviewed = $scope.emailToSend.contentObjectId;
	    	}).catch(function(e){
    			$scope.showToast($scope.toastTypes.Failure, "Email template failed", "With error message (" + e.status + ") " + e.statusText);
	        	$scope.setLoading(false);
	        	$scope.lastContentIDSuccessfullyPreviewed = "";
	    	});
	    };

        $scope.emailTypeChanged = function(idOfSelectedEmailType){
			$scope.emailToSend.emailType = idOfSelectedEmailType;
		};

	    $scope.validateAndSendEmails = function(){

	    	if(!$scope.emailToSend.emailType || $scope.emailToSend.emailType < 0){
    			$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "You must select a type of email");
				return;
	    	}

	    	if($scope.lastContentIDSuccessfullyPreviewed == "" || $scope.emailToSend.contentObjectId != $scope.lastContentIDSuccessfullyPreviewed){
    			$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "You must preview the email before sending");
				return;
	    	}

			if($scope.userSelectionType == 'userfilter') {
		    	var usersSelected = false;
		    	for(var key in $scope.emailToSend.users) {
	    			if($scope.emailToSend.users[key]){
	    				usersSelected = true;
	    			}
		    	}

		    	if(!usersSelected){
					$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "You must select users to send the email to");
					return;
				}
			}
			else if($scope.userSelectionType == 'csvuseridlist') {
				var numbersAndCommas = /[^,0-9]+/;

				if(numbersAndCommas.test($scope.csvuseridlist)){
					$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "Userids field contains invalid characters");
					return;
				}

				var userids = getUserIdArrayFromTextArea($scope.csvuseridlist);

				// Check for NaNs and invalid characters
				for(var i = 0; i < userids.length; i++){
					if(isNaN(userids[i])){
						$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "One of the userIds given evaluates to NaN");
						return;
					}
				}
			}
			else {
				$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "No user selection type selected");
				return;
			}

        	var confirmation = $window.confirm('You are about to send ' + $scope.getTotalUsers() + ' email(s). Are you sure?');
        	if(confirmation && $scope.userSelectionType == 'userfilter'){
				$scope.setLoading(true);
				api.email.sendEmail({
					contentid : $scope.emailToSend.contentObjectId,
					emailtype: $scope.emailToSend.emailType,
				}, $scope.emailToSend.users).$promise.then(function(){
					$scope.setLoading(false);
	    			$scope.showToast($scope.toastTypes.Success, "Success!", "Email has been sent (and filtered) successfully!");
				}).catch(function(e){
	    			$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "With error message (" + e.status + ") " + e.statusText);
		        	$scope.setLoading(false);
				});
			}
			else if(confirmation && $scope.userSelectionType == 'csvuseridlist'){
				$scope.setLoading(true);
				api.email.sendEmailWithIds({
					contentid : $scope.emailToSend.contentObjectId,
					emailtype: $scope.emailToSend.emailType
				}, getUserIdArrayFromTextArea($scope.csvuseridlist)).$promise.then(function(){
					$scope.setLoading(false);
	    			$scope.showToast($scope.toastTypes.Success, "Success!", "Email has been sent (and filtered) successfully!");
				}).catch(function(e){
	    			$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "With error message (" + e.status + ") " + e.statusText);
		        	$scope.setLoading(false);
				});
			}
	    };

    }]
	return {
		PageController: PageController,
	};
})<commit_msg>Made AdminEmailController slightly more robust.<commit_after>/**
 * Copyright 2015 Alistair Stead
 *
 * 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.
 */
define([], function() {

	var PageController = ['$scope', 'auth', '$stateParams', 'api', '$window', '$rootScope', '$sce', '$timeout', function($scope, auth, $stateParams, api, $window, $rootScope, $sce, $timeout) {
		$scope.isAdminUser = $rootScope.user.role == 'ADMIN';
	    $scope.statistics = null;
	    $scope.setLoading(true);
	    $scope.apiVersion = api.contentVersion.get();
	    $scope.emailTypes = null;

	    $scope.lastContentIDSuccessfullyPreviewed = "";

	    $scope.htmlPreview = "";
	    $scope.plainTextPreview = "";
	    $scope.subjectPreview = "";

	    $scope.emailToSend = {
	    	emailType : -1,
	    	contentObjectId : "",
	    	users: {
		    	ADMIN : false,
		    	EVENT_MANAGER : false,
		    	CONTENT_EDITOR : false,
		    	TEACHER : false,
		    	TESTER : false,
		    	STAFF : false,
		    	STUDENT : false,
			}
	    };

	    $scope.getInitialUserFilterState = function() {
	    	debugger
	    	if($stateParams.userIds != ""){
	    		$scope.csvuseridlist = $stateParams.userIds;
	    		return('csvuseridlist');
	    	}
	    	return('userfilter');
	    }

	    $scope.queueSize = "?";
	    var checkTimes = 0;

	    var queueSizeChecker = function(){
	    	api.email.getQueueSize({}).$promise.then(function(result){
	    		var d = new Date();
    			$scope.queueSize = "" + result.length + " at " + d.toLocaleTimeString();
				$timeout(queueSizeChecker, 5000);
    		}).catch(function(e){
				$scope.showToast($scope.toastTypes.Failure, "Email Queue Size", "Could not get email queue size (" + e.status + ") " + e.statusText);
				clearInterval(timerId);
			});
    	}

	    queueSizeChecker();

		var getUserIdArrayFromTextArea = function(){
			var userids = $scope.csvuseridlist.split(/[\s,]+/).map(function(e) {return parseInt(e);});;
			return userids;
		}

	    $scope.getTotalUsers = function(){
	    	if($scope.userSelectionType == 'csvuseridlist') {
				var userIdList = getUserIdArrayFromTextArea();
				return userIdList.length;
	    	}

	    	var total = 0;
			if($scope.emailToSend.users.ADMIN) {
	    		total += parseInt($scope.statistics.role.ADMIN);
	    	}

	    	if($scope.emailToSend.users.EVENT_MANAGER) {
	    		total += parseInt($scope.statistics.role.EVENT_MANAGER);
	    	}

	    	if($scope.emailToSend.users.CONTENT_EDITOR) {
	    		total += parseInt($scope.statistics.role.CONTENT_EDITOR);
	    	}

	    	if($scope.emailToSend.users.TEACHER) {
	    		total += parseInt($scope.statistics.role.TEACHER);
	    	}

	    	if($scope.emailToSend.users.TESTER) {
	    		total += parseInt($scope.statistics.role.TESTER);
	    	}

	    	if($scope.emailToSend.users.STAFF) {
	    		total += parseInt($scope.statistics.role.STAFF);
	    	}

	    	if($scope.emailToSend.users.STUDENT) {
	    		total += parseInt($scope.statistics.role.STUDENT);
	    	}
	    	return total;
	    }

	    api.statisticsEndpoint.get().$promise.then(function(result){
	        $scope.statistics = result;
	        $scope.setLoading(false);
	    }).catch(function(e){
			$scope.showToast($scope.toastTypes.Failure, "Statistics load failed", "With error message (" + e.status + ") " + e.statusText);
	    });

	    api.email.getPreferences().$promise.then(function(result){
	    	$scope.emailTypes = result;
	    }).catch(function(e){
			$scope.showToast($scope.toastTypes.Failure, "Preferences load failed", "With error message (" + e.status + ") " + e.statusText);
	    });

	    $scope.loadContentTemplate = function(contentId){
	    	$scope.setLoading(true);
	    	api.email.get({"id" : $scope.emailToSend.contentObjectId}).$promise.then(function(content){
	        	$scope.subjectPreview = content.subject;
	        	$scope.htmlPreview = $sce.trustAsResourceUrl("data:text/html," + encodeURIComponent(content.html));
	        	$scope.plainTextPreview = $sce.trustAsResourceUrl("data:/html," + encodeURIComponent(content.plainText));
	        	$scope.setLoading(false);
	        	$scope.lastContentIDSuccessfullyPreviewed = $scope.emailToSend.contentObjectId;
	    	}).catch(function(e){
    			$scope.showToast($scope.toastTypes.Failure, "Email template failed", "With error message (" + e.status + ") " + e.statusText);
	        	$scope.setLoading(false);
	        	$scope.lastContentIDSuccessfullyPreviewed = "";
	    	});
	    };

        $scope.emailTypeChanged = function(idOfSelectedEmailType){
			$scope.emailToSend.emailType = idOfSelectedEmailType;
		};

	    $scope.validateAndSendEmails = function(){
	    	//TODO check if loading, if so, disable button

	    	if(!$scope.emailToSend.emailType || $scope.emailToSend.emailType < 0){
	    		$scope.setLoading(false);
    			$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "You must select a type of email");
				return;
	    	}

	    	if($scope.lastContentIDSuccessfullyPreviewed == "" || $scope.emailToSend.contentObjectId != $scope.lastContentIDSuccessfullyPreviewed){
	    		$scope.setLoading(false);
    			$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "You must preview the email before sending");
				return;
	    	}

			if($scope.userSelectionType == 'userfilter') {
		    	var usersSelected = false;
		    	for(var key in $scope.emailToSend.users) {
	    			if($scope.emailToSend.users[key]){
	    				usersSelected = true;
	    			}
		    	}

		    	if(!usersSelected){
		    		$scope.setLoading(false);
					$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "You must select users to send the email to");
					return;
				}
			}
			else if($scope.userSelectionType == 'csvuseridlist') {
				var numbersAndCommas = /[^,0-9]+/;

				if(numbersAndCommas.test($scope.csvuseridlist)){
					$scope.setLoading(false);
					$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "Userids field contains invalid characters");
					return;
				}

				var userids = getUserIdArrayFromTextArea($scope.csvuseridlist);

				// Check for NaNs and invalid characters
				for(var i = 0; i < userids.length; i++){
					if(isNaN(userids[i])){
						$scope.setLoading(false);
						$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "One of the userIds given evaluates to NaN");
						return;
					}
				}
			}
			else {
				$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "No user selection type selected");
				return;
			}

        	var confirmation = $window.confirm('You are about to send ' + $scope.getTotalUsers() + ' email(s). Are you sure?');
        	if(confirmation && $scope.userSelectionType == 'userfilter'){
				$scope.setLoading(true);
				api.email.sendEmail({
					contentid : $scope.emailToSend.contentObjectId,
					emailtype: $scope.emailToSend.emailType,
				}, $scope.emailToSend.users).$promise.then(function(){
					$scope.setLoading(false);
	    			$scope.showToast($scope.toastTypes.Success, "Success!", "Email has been sent (and filtered) successfully!");
		        	return;
				}).catch(function(e){
					$scope.setLoading(false);
	    			$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "With error message (" + e.status + ") " + e.statusText);
		        	return;
				});
			}
			else if(confirmation && $scope.userSelectionType == 'csvuseridlist'){
				$scope.setLoading(true);
				api.email.sendEmailWithIds({
					contentid : $scope.emailToSend.contentObjectId,
					emailtype: $scope.emailToSend.emailType
				}, getUserIdArrayFromTextArea($scope.csvuseridlist)).$promise.then(function(){
					$scope.setLoading(false);
	    			$scope.showToast($scope.toastTypes.Success, "Success!", "Email has been sent (and filtered) successfully!");
	    			return;
				}).catch(function(e){
	    			$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "With error message (" + e.status + ") " + e.statusText);
		        	$scope.setLoading(false);
		        	return;
				});
			}
			else {
    			$scope.showToast($scope.toastTypes.Failure, "Email sending failed", "Could not determine between user filter and id list");
	        	$scope.setLoading(false);
	        	return;
			}

	    };

    }]
	return {
		PageController: PageController,
	};
})<|endoftext|>


<commit_before>( function( mw, $ ) {"use strict";

	mw.PluginManager.add( 'playPauseBtn', mw.KBaseComponent.extend({

		defaultConfig: {
			'parent': 'controlsContainer',
         	'order': 1
		},

		isDisabled: false,

		playIconClass: 'icon-play',
		pauseIconClass: 'icon-pause',

		playTitle: gM( 'mwe-embedplayer-play_clip' ),
		pauseTitle: gM( 'mwe-embedplayer-pause_clip' ),

		setup: function( embedPlayer ) {
			this.addBindings();
		},
		getComponent: function() {
			var _this = this;
			if( !this.$el ) {
				this.$el = $( '<button />' )
							.attr( 'title', this.playTitle )
							.addClass( "btn icon-play" + this.getCssClass() )
							.click( function() {
								_this.togglePlayback();
							});
			}
			return this.$el;
		},
		onEnable: function(){
			this.isDisabled = false;
			this.getComponent().toggleClass('disabled');
		},
		onDisable: function(){
			this.isDisabled = true;
			this.getComponent().toggleClass('disabled');
		},
		addBindings: function() {
			var _this = this;
			this.bind('onplay', function() {
				_this.getComponent()
					.attr( 'title', _this.playTitle )
					.removeClass( _this.playIconClass ).addClass( _this.pauseIconClass );
			});
			this.bind('onpause', function() {
				_this.getComponent()
					.attr( 'title', _this.pauseTitle )
					.removeClass( _this.pauseIconClass ).addClass( _this.playIconClass );
			});
		},
		togglePlayback: function() {
			if( this.isDisabled ) return ;
			var notificationName = ( this.getPlayer().isPlaying() ) ? 'doPause' : 'doPlay';
			this.getPlayer().sendNotification( notificationName );
		}
	})
	);

} )( window.mw, window.jQuery );<commit_msg>add replay icon on end state<commit_after>( function( mw, $ ) {"use strict";

	mw.PluginManager.add( 'playPauseBtn', mw.KBaseComponent.extend({

		defaultConfig: {
			'parent': 'controlsContainer',
         	'order': 1
		},

		isDisabled: false,

		playIconClass: 'icon-play',
		pauseIconClass: 'icon-pause',
		replayIconClass: 'icon-replay',

		playTitle: gM( 'mwe-embedplayer-play_clip' ),
		pauseTitle: gM( 'mwe-embedplayer-pause_clip' ),
		replayTitle: 'Replay',

		setup: function( embedPlayer ) {
			this.addBindings();
		},
		getComponent: function() {
			var _this = this;
			if( !this.$el ) {
				this.$el = $( '<button />' )
							.attr( 'title', this.playTitle )
							.addClass( "btn icon-play" + this.getCssClass() )
							.click( function() {
								_this.togglePlayback();
							});
			}
			return this.$el;
		},
		onEnable: function(){
			this.isDisabled = false;
			this.getComponent().toggleClass('disabled');
		},
		onDisable: function(){
			this.isDisabled = true;
			this.getComponent().toggleClass('disabled');
		},
		addBindings: function() {
			var _this = this;
			this.bind('onPlayerStateChange', function(e, newState ){
				_this.updateUI( newState );
			});
		},
		updateUI: function( newState ){
			var removeIconClasses = this.playIconClass + ' ' + this.pauseIconClass + ' ' + this.replayIconClass;
			var newIconClass = null;
			var title = null;
			var ignoreChange = false;

			switch( newState ) {
				case 'play':
					title = this.pauseTitle;
					newIconClass = this.pauseIconClass;
				break;
				case 'start':
				case 'pause':
					title = this.playTitle;
					newIconClass = this.playIconClass;
				break;
				case 'end':
					title = this.replayTitle;
					newIconClass = this.replayIconClass;
				break;
				default:
					// On other states do nothing
					ignoreChange = true;
				break;
			}

			if( ignoreChange ){
				return;
			} else {
				ignoreChange = false;
				this.getComponent()
					.attr( 'title', title )
					.removeClass( removeIconClasses )
					.addClass( newIconClass );
			}

		},
		togglePlayback: function() {
			if( this.isDisabled ) return ;
			var notificationName = ( this.getPlayer().isPlaying() ) ? 'doPause' : 'doPlay';
			this.getPlayer().sendNotification( notificationName );
		}
	})
	);

} )( window.mw, window.jQuery );<|endoftext|>


<commit_before>/**
 * Test for https://github.com/OOPMan/jquery-plugincreator/issues/1
 */
"use strict";
var test = require("unit.js"),
    assert = test.assert,
    common = require("./common.js");

describe("issue000001", function () {
    var window = common.getWindow(),
        jQuery = common.getjQuery(window),
        unique = jQuery("#unique"),
        nonUnique = jQuery(".non-unique"),
        defaults = {
            testNumber: 1
        },
        members = {
            methodA: function () {
                this.options.testNumber += 1;
            }
        },
        childMembers = {
            methodA: function (optionalParameter, _super) {
                if (typeof optionalParameter != "undefined" && typeof optionalParameter != "function") this.options.testNumber += optionalParameter;
                if (typeof _super == "function") _super();
            }
        };

    describe("Pre-flight checks", function () {
        it("jQuery.addPlugin should be a function", function () {
            test.function(jQuery.addPlugin);
        });

        it("jQuery('#unique') should contain a single item", function () {
            test.number(unique.length).is(1);
        });

        it("jQuery('.non-unique') should contain 4 items", function () {
            test.number(nonUnique.length).is(4);
        });

        it("jQuery.addPlugin('testPlugin', defaults, members) should create jQuery.fn.testPlugin", function () {
            jQuery.addPlugin("testPlugin", defaults, members);
            test.function(jQuery.fn.testPlugin)
                .object(jQuery.fn.testPlugin.defaults)
                    .is(defaults)
                .function(jQuery.fn.testPlugin.updateDefaultsWith)
                .function(jQuery.fn.testPlugin.extendMembersWith)
                .function(jQuery.fn.testPlugin.cloneTo)
                .function(jQuery.fn.testPlugin.extendTo);
        });

        it("jQuery.fn.testPlugin.extendTo('childOfTestPlugin', childMembers) should create jQuery.fn.childOfTestPlugin", function () {
            jQuery.fn.testPlugin.extendTo("childOfTestPlugin", childMembers);
            test.function(jQuery.fn.childOfTestPlugin)
                .object(jQuery.fn.childOfTestPlugin.defaults)
                    .is(defaults)
                .function(jQuery.fn.childOfTestPlugin.updateDefaultsWith)
                .function(jQuery.fn.childOfTestPlugin.extendMembersWith)
                .function(jQuery.fn.childOfTestPlugin.cloneTo)
                .function(jQuery.fn.childOfTestPlugin.extendTo);
        });

    });

    describe("jQuery('#unique').testPlugin()", function () {
        it("should instantiate testPlugin on #unique", function () {
            this.instance = unique.testPlugin();
            test.object(this.instance);
        });
        it("should copy the contents of `defaults` into the `options` member on the testPlugin instance", function () {
            test.object(this.instance.options).is(defaults);
        });

        describe("jQuery('#unique').testPlugin('methodA')", function () {
            it("should call `methodA` on the testPlugin instance, causing the `testNumber` in the `options` member on the testPlugin to be incremened by 1", function () {
                unique.testPlugin("methodA");
                test.number(unique.testPlugin("getInstance").options.testNumber).is(2);
            });
        });
    });

    describe("jQuery('#unique').childOfTestPlugin()", function () {
        it("should instantiate childOfTestPlugin on #unique", function () {
            this.instance = unique.childOfTestPlugin();
            test.object(this.instance);
        });
        it("should copy the contents of `defaults` into the `options` member on the childOfTestPlugin instance", function () {
            test.object(this.instance.options).is(defaults);
        });

        describe("jQuery('#unique').childOfTestPlugin('methodA', 2)", function () {
            it("should call `methodA` on the testPlugin instance, causing the `testNumber` in the `options` member on the testPlugin to be incremented by 1", function () {
                unique.childOfTestPlugin("methodA", 2);
                test.number(unique.childOfTestPlugin("getInstance").options.testNumber).is(3);
            });
        });

        describe("jQuery('#unique').childOfTestPlugin('methodA')", function () {
            it("should call `methodA` on the testPlugin instance, causing the `testNumber` in the `options` member on the testPlugin to be incremented by 1", function () {
                unique.childOfTestPlugin("methodA");
                test.number(unique.childOfTestPlugin("getInstance").options.testNumber).is(4);
            });
        });
    });
});
<commit_msg>Updated test for https://github.com/OOPMan/jquery-plugincreator/issues/1 with new test cases.<commit_after>/**
 * Test for https://github.com/OOPMan/jquery-plugincreator/issues/1
 *
 * _super method injection fails with functions expected to handle variable-length/optional argument lists
 */
"use strict";
var test = require("unit.js"),
    assert = test.assert,
    common = require("./common.js");

describe("issue000001", function () {
    var window = common.getWindow(),
        jQuery = common.getjQuery(window),
        unique = jQuery("#unique"),
        nonUnique = jQuery(".non-unique"),
        defaults = {
            testNumber: 1
        },
        members = {
            methodA: function () {
                this.options.testNumber += 1;
            },
            methodB: function () {
                this.options.testNumber -= 1;
            },
            methodC: function () {
                this.options.testNumber = 100;
            }
        },
        childMembers = {
            /**
             * This function will override the methodA function in members.
             *
             * If the jQuery-PluginCreator inheritance system is working correctly then the function should execute
             * correctly if the optional parameter is omitted. In such an event:
             *
             * optionalParameter will be undefined
             * _super will be a reference to the methodA function in members.
             * *
             * @param {number} [optionalParameter]
             * @param {Function} _super
             */
            methodA: function (optionalParameter, _super) {
                if (typeof optionalParameter != "undefined" && typeof optionalParameter != "function") this.options.testNumber += optionalParameter;
                if (typeof _super == "function") _super();
            },
            /**
             * This function will override the methodB function in members.
             *
             * If the jQuery-PluginCreator inheritance system is working correctly then the function should execute
             * correctly if the optional parameter is omitted. In such an event:
             *
             * optionalParameter will be undefined
             * _super will NOT be injected into the arguments list
             *
             * @param {number} [optionalParameter]
             */
            methodB: function (optionalParameter) {
                if (typeof optionalParameter != "undefined" && typeof optionalParameter != "function") this.options.testNumber -= optionalParameter;
                else if (typeof optionalParameter == "function") this.options.testNumber -= 2;
                else this.options.testNumber -= 1;
            },
            /**
             * This function will override the methodC function in members.
             *
             * If the jQuery-PluginCreator inheritance system is working correctly then the function the _super parameter
             * will be populated.
             *
             * @param _super
             */
            methodC: function (_super) {
                if (typeof _super == "function") this.options.testNumber = -100;
            }
        };

    describe("Pre-flight checks", function () {
        it("jQuery.addPlugin should be a function", function () {
            test.function(jQuery.addPlugin);
        });

        it("jQuery('#unique') should contain a single item", function () {
            test.number(unique.length).is(1);
        });

        it("jQuery('.non-unique') should contain 4 items", function () {
            test.number(nonUnique.length).is(4);
        });

        it("jQuery.addPlugin('testPlugin', defaults, members) should create jQuery.fn.testPlugin", function () {
            jQuery.addPlugin("testPlugin", defaults, members);
            test.function(jQuery.fn.testPlugin)
                .object(jQuery.fn.testPlugin.defaults)
                    .is(defaults)
                .function(jQuery.fn.testPlugin.updateDefaultsWith)
                .function(jQuery.fn.testPlugin.extendMembersWith)
                .function(jQuery.fn.testPlugin.cloneTo)
                .function(jQuery.fn.testPlugin.extendTo);
        });

        it("jQuery.fn.testPlugin.extendTo('childOfTestPlugin', childMembers) should create jQuery.fn.childOfTestPlugin", function () {
            jQuery.fn.testPlugin.extendTo("childOfTestPlugin", childMembers);
            test.function(jQuery.fn.childOfTestPlugin)
                .object(jQuery.fn.childOfTestPlugin.defaults)
                    .is(defaults)
                .function(jQuery.fn.childOfTestPlugin.updateDefaultsWith)
                .function(jQuery.fn.childOfTestPlugin.extendMembersWith)
                .function(jQuery.fn.childOfTestPlugin.cloneTo)
                .function(jQuery.fn.childOfTestPlugin.extendTo);
        });

    });

    describe("jQuery('#unique').testPlugin()", function () {
        it("should instantiate testPlugin on #unique", function () {
            this.instance = unique.testPlugin();
            test.object(this.instance);
        });
        it("should copy the contents of `defaults` into the `options` member on the testPlugin instance", function () {
            test.object(this.instance.options).is(defaults);
        });

        describe("jQuery('#unique').testPlugin('methodA')", function () {
            it("should call `methodA` on the testPlugin instance, causing the `testNumber` in the `options` member on the testPlugin to be incremented by 1", function () {
                unique.testPlugin("methodA");
                test.number(unique.testPlugin("getInstance").options.testNumber).is(2);
            });
        });

        describe("jQuery('#unique').testPlugin('methodB')", function () {
            it("should call `methodB` on the testPlugin instance, causing the `testNumber` in the `options` member on the testPlugin to be decremented by 1", function () {
                unique.testPlugin("methodB");
                test.number(unique.testPlugin("getInstance").options.testNumber).is(1);
            });
        });

        describe("jQuery('#unique').testPlugin('methodC')", function () {
            it("should call `methodC` on the testPlugin instance, causing the `testNumber` in the `options` member on the testPlugin to be set to 100", function () {
                unique.testPlugin("methodC");
                test.number(unique.testPlugin("getInstance").options.testNumber).is(100);
            });
        });
    });

    describe("jQuery('#unique').childOfTestPlugin()", function () {
        it("should instantiate childOfTestPlugin on #unique", function () {
            this.instance = unique.childOfTestPlugin();
            test.object(this.instance);
        });
        it("should copy the contents of `defaults` into the `options` member on the childOfTestPlugin instance", function () {
            test.object(this.instance.options).is(defaults);
        });

        describe("jQuery('#unique').childOfTestPlugin('methodA', 2)", function () {
            it("should call `methodA` on the testPlugin instance, causing the `testNumber` in the `options` member on the testPlugin to be incremented by 3 in total", function () {
                unique.childOfTestPlugin("methodA", 2);
                test.number(unique.childOfTestPlugin("getInstance").options.testNumber).is(4);
            });
        });

        describe("jQuery('#unique').childOfTestPlugin('methodA')", function () {
            it("should call `methodA` on the testPlugin instance, causing the `testNumber` in the `options` member on the testPlugin to be incremented by 1 in total", function () {
                unique.childOfTestPlugin("methodA");
                test.number(unique.childOfTestPlugin("getInstance").options.testNumber).is(5);
            });
        });

        describe("jQuery('#unique').childOfTestPlugin('methodB', 2)", function () {
            it("should call `methodB` on the testPlugin instance, causing the `testNumber` in the `options` member on the testPlugin to be decremented by 2", function () {
                unique.childOfTestPlugin("methodB", 2);
                test.number(unique.childOfTestPlugin("getInstance").options.testNumber).is(3);
            });
        });

        describe("jQuery('#unique').childOfTestPlugin('methodB')", function () {
            it("should call `methodB` on the testPlugin instance, causing the `testNumber` in the `options` member on the testPlugin to be decremented by 1", function () {
                unique.childOfTestPlugin("methodB");
                test.number(unique.childOfTestPlugin("getInstance").options.testNumber).is(2);
            });
        });

        describe("jQuery('#unique').childOfTestPlugin('methodC')", function () {
            it("should call `methodC` on the testPlugin instance, causing the `testNumber` in the `options` member on the testPlugin to be set to -100", function () {
                unique.childOfTestPlugin("methodC");
                test.number(unique.childOfTestPlugin("getInstance").options.testNumber).is(-100);
            });
        });
    });
});
<|endoftext|>


<commit_before>/**
* Copyright (c) Microsoft.  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 _ = require('underscore');
var url = require('url');
var util = require('util');

var constants = require('../constants');

var $ = require('../utils').getLocaleString;

var DEFAULT_ENV_NAME = 'AzureCloud';

function nulls(properties) {
  return properties.reduce(function (acc, prop) { acc[prop] = null; return acc; }, {});
}

function Environment(envData) {
  var self = this;

  self.name = envData.name;
  var values = envData;
  _.defaults(values, nulls(_.pluck(Environment.parameters, 'name')));

  Environment.parameters.forEach(function (param) {
    Object.defineProperty(self, param.name, param.propertyDescriptor(self));
  });

  Object.defineProperties(self, {
    isPublicEnvironment: {
      enumerable: true,
      configurable: false,
      get: function () {
        return _.chain(Environment.publicEnvironments).pluck('name').contains(this.name).value();
      }
    },

    values: {
      enumerable: false,
      configurable: false,
      get: function () { return values; }
    }
  });
}

function EnvironmentParameter(name, environmentVariable, description) {
  this.name = name;
  this.environmentVariable = environmentVariable;
  this.description = $(description);
}

_.extend(EnvironmentParameter.prototype, {
  propertyDescriptor: function (env) {
    var self = this;
    return {
      enumerable: true,
      configurable: false,
      get: function () {
        var val = process.env[self.environmentVariable] || env.values[self.name];
        if (val === null) {
          throw new Error(util.format(
            $('The endpoint field %s is not defined in this environment.' +
              ' Either this feature is not supported or the endpoint needs to be set using \'azure account env set\''),
            self.name));
        }
        return val;
      },
      set: function (value) { this.values[self.name] = value; }
    };
  },
});

Environment.parameters = [
  new EnvironmentParameter('portalUrl', 'AZURE_PORTAL_URL', 'the management portal URL'),
  new EnvironmentParameter('publishingProfileUrl', 'AZURE_PUBLISHINGPROFILE_URL', 'the publish settings file URL'),
  new EnvironmentParameter('managementEndpointUrl', 'AZURE_MANAGEMENTENDPOINT_URL', 'the management service endpoint'),
  new EnvironmentParameter('resourceManagerEndpointUrl', 'AZURE_RESOURCEMANAGERENDPOINT_URL', 'the resource management endpoint'),
  new EnvironmentParameter('sqlManagementEndpointUrl', 'AZURE_SQL_MANAGEMENTENDPOINT_URL', 'the sql server management endpoint for mobile commands'),
  new EnvironmentParameter('sqlServerHostnameSuffix', 'AZURE_SQL_SERVER_HOSTNAME_SUFFIX', 'the dns suffix for sql servers'),
  new EnvironmentParameter('activeDirectoryEndpointUrl', 'AZURE_ACTIVEDIRECTORY_ENDPOINT_URL', 'the Active Directory login endpoint'),
  new EnvironmentParameter('activeDirectoryResourceId', 'AZURE_ACTIVEDIRECTORY_RESOURCE_ID', 'The resource ID to obtain AD tokens for'),
  new EnvironmentParameter('galleryEndpointUrl', 'AZURE_GALLERY_ENDPOINT_URL', 'the template gallery endpoint'),
  new EnvironmentParameter('activeDirectoryGraphResourceId', 'AZURE_ACTIVEDIRECTORY_GRAPH_RESOURCE_ID', 'the Active Directory resource ID'),
  new EnvironmentParameter('activeDirectoryGraphApiVersion', 'AZURE_ACTIVEDIRECTORY_GRAPH_API_VERSION', 'the Active Directory api version'),
  new EnvironmentParameter('storageEndpointSuffix', 'AZURE_STORAGE_ENDPOINT_SUFFIX', 'the endpoint suffix for storage accounts'),
  new EnvironmentParameter('keyVaultDnsSuffix', 'AZURE_KEYVAULT_DNS_SUFFIX', 'the keyvault service dns suffix'),
  new EnvironmentParameter('azureDataLakeStoreFileSystemEndpointSuffix', 'AZURE_DATALAKE_STORE_FILESYSTEM_DNS_SUFFIX', 'the data lake store filesystem service dns suffix'),
  new EnvironmentParameter('azureDataLakeAnalyticsCatalogAndJobEndpointSuffix', 'AZURE_DATALAKE_ANALYTICS_JOB_CATALOG_DNS_SUFFIX', 'the data lake analytics job and catalog service dns suffix')
];

function addRealm(targetUrl, realm) {
  if (realm) {
    var urlObj = url.parse(targetUrl, true);
    delete urlObj.search;
    urlObj.query.whr = realm;
    targetUrl = url.format(urlObj);
  }
  return targetUrl;
}

_.extend(Environment.prototype, {
  getPortalUrl: function (realm) {
    return addRealm(this.portalUrl, realm);
  },

  getPublishingProfileUrl: function (realm) {
    return addRealm(this.publishingProfileUrl, realm);
  },

  toJSON: function () {
    return _.extend({ name: this.name }, this.values);
  },

  getAuthConfig: function (tenantId, resourceId) {
    if (!tenantId) {
      tenantId = constants.AAD_COMMON_TENANT;
    }
    if (!resourceId) {
      resourceId = this.activeDirectoryResourceId;
    }
    return {
      authorityUrl: this.activeDirectoryEndpointUrl,
      tenantId: tenantId,
      resourceId: resourceId,
      clientId: constants.XPLAT_CLI_CLIENT_ID
    };
  },

  isDefaultEnv: function () {
    return this.name === DEFAULT_ENV_NAME;
  }
});

Environment.publicEnvironments = [
  new Environment({
    name: DEFAULT_ENV_NAME,
    portalUrl: 'http://go.microsoft.com/fwlink/?LinkId=254433',
    publishingProfileUrl: 'http://go.microsoft.com/fwlink/?LinkId=254432',
    managementEndpointUrl: 'https://management.core.windows.net',
    resourceManagerEndpointUrl: 'https://management.azure.com/',
    sqlManagementEndpointUrl: 'https://management.core.windows.net:8443/',
    sqlServerHostnameSuffix: '.database.windows.net',
    galleryEndpointUrl: 'https://gallery.azure.com/',
    activeDirectoryEndpointUrl: 'https://login.microsoftonline.com',
    activeDirectoryResourceId: 'https://management.core.windows.net/',
    activeDirectoryGraphResourceId: 'https://graph.windows.net/',
    activeDirectoryGraphApiVersion: '2013-04-05',
    storageEndpointSuffix: '.core.windows.net',
    keyVaultDnsSuffix: '.vault.azure.net',
    azureDataLakeStoreFileSystemEndpointSuffix: 'azuredatalakestore.net',
    azureDataLakeAnalyticsCatalogAndJobEndpointSuffix: 'azuredatalakeanalytics.net'
  }),
  new Environment({
    name: 'AzureChinaCloud',
    portalUrl: 'http://go.microsoft.com/fwlink/?LinkId=301902',
    publishingProfileUrl: 'http://go.microsoft.com/fwlink/?LinkID=301774',
    managementEndpointUrl: 'https://management.core.chinacloudapi.cn',
    resourceManagerEndpointUrl: 'https://management.chinacloudapi.cn',
    sqlManagementEndpointUrl: 'https://management.core.chinacloudapi.cn:8443/',
    sqlServerHostnameSuffix: '.database.chinacloudapi.cn',
    galleryEndpointUrl: 'https://gallery.chinacloudapi.cn/',
    activeDirectoryEndpointUrl: 'https://login.chinacloudapi.cn',
    activeDirectoryResourceId: 'https://management.core.chinacloudapi.cn/',
    activeDirectoryGraphResourceId: 'https://graph.chinacloudapi.cn/',
    activeDirectoryGraphApiVersion: '2013-04-05',
    storageEndpointSuffix: '.core.chinacloudapi.cn',
    keyVaultDnsSuffix: '.vault.azure.cn',
    // TODO: add dns suffixes for the china cloud for datalake store and datalake analytics once they are defined.
    azureDataLakeStoreFileSystemEndpointSuffix: 'N/A',
    azureDataLakeAnalyticsCatalogAndJobEndpointSuffix: 'N/A'
  }),
  new Environment({
    name: 'AzureUSGovernment',
    portalUrl: 'https://manage.windowsazure.us',
    publishingProfileUrl: 'https://manage.windowsazure.us/publishsettings/index',
    managementEndpointUrl: 'https://management.core.usgovcloudapi.net',
    resourceManagerEndpointUrl: 'https://management.usgovcloudapi.net',
    sqlManagementEndpointUrl: 'https://management.core.usgovcloudapi.net:8443/',
    sqlServerHostnameSuffix: '.database.usgovcloudapi.net',
    galleryEndpointUrl: 'https://gallery.usgovcloudapi.net/',
    activeDirectoryEndpointUrl: 'https://login.microsoftonline.com',
    activeDirectoryResourceId: 'https://management.core.usgovcloudapi.net/',
    activeDirectoryGraphResourceId: 'https://graph.windows.net/',
    activeDirectoryGraphApiVersion: '2013-04-05',
    storageEndpointSuffix: '.core.usgovcloudapi.net',
    keyVaultDnsSuffix: '.vault.usgovcloudapi.net',
    // TODO: add dns suffixes for the US government for datalake store and datalake analytics once they are defined.
    azureDataLakeStoreFileSystemEndpointSuffix: 'N/A',
    azureDataLakeAnalyticsCatalogAndJobEndpointSuffix: 'N/A'
  }),
  new Environment({
    name: 'AzureGermanCloud',
    portalUrl: 'http://portal.microsoftazure.de/',
    publishingProfileUrl: 'https://manage.microsoftazure.de/publishsettings/index',
    managementEndpointUrl: 'https://management.core.cloudapi.de/',
    resourceManagerEndpointUrl: 'https://management.microsoftazure.de/',
    sqlManagementEndpointUrl: 'https://management.core.cloudapi.de:8443/',
    sqlServerHostnameSuffix: '.database.cloudapi.de',
    galleryEndpointUrl: 'https://gallery.cloudapi.de/',
    activeDirectoryEndpointUrl: 'https://login.microsoftonline.de',
    activeDirectoryResourceId: 'https://management.core.cloudapi.de/',
    activeDirectoryGraphResourceId: 'https://graph.cloudapi.de/',
    activeDirectoryGraphApiVersion: '2013-04-05',
    storageEndpointSuffix: '.core.cloudapi.de',
    keyVaultDnsSuffix: '.vault.microsoftazure.de',
    // TODO: add dns suffixes for the US government for datalake store and datalake analytics once they are defined.
    azureDataLakeStoreFileSystemEndpointSuffix: 'N/A',
    azureDataLakeAnalyticsCatalogAndJobEndpointSuffix: 'N/A'
  })
];

module.exports = Environment;
<commit_msg>Updating AzureGermanCloud endpoints<commit_after>/**
* Copyright (c) Microsoft.  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 _ = require('underscore');
var url = require('url');
var util = require('util');

var constants = require('../constants');

var $ = require('../utils').getLocaleString;

var DEFAULT_ENV_NAME = 'AzureCloud';

function nulls(properties) {
  return properties.reduce(function (acc, prop) { acc[prop] = null; return acc; }, {});
}

function Environment(envData) {
  var self = this;

  self.name = envData.name;
  var values = envData;
  _.defaults(values, nulls(_.pluck(Environment.parameters, 'name')));

  Environment.parameters.forEach(function (param) {
    Object.defineProperty(self, param.name, param.propertyDescriptor(self));
  });

  Object.defineProperties(self, {
    isPublicEnvironment: {
      enumerable: true,
      configurable: false,
      get: function () {
        return _.chain(Environment.publicEnvironments).pluck('name').contains(this.name).value();
      }
    },

    values: {
      enumerable: false,
      configurable: false,
      get: function () { return values; }
    }
  });
}

function EnvironmentParameter(name, environmentVariable, description) {
  this.name = name;
  this.environmentVariable = environmentVariable;
  this.description = $(description);
}

_.extend(EnvironmentParameter.prototype, {
  propertyDescriptor: function (env) {
    var self = this;
    return {
      enumerable: true,
      configurable: false,
      get: function () {
        var val = process.env[self.environmentVariable] || env.values[self.name];
        if (val === null) {
          throw new Error(util.format(
            $('The endpoint field %s is not defined in this environment.' +
              ' Either this feature is not supported or the endpoint needs to be set using \'azure account env set\''),
            self.name));
        }
        return val;
      },
      set: function (value) { this.values[self.name] = value; }
    };
  },
});

Environment.parameters = [
  new EnvironmentParameter('portalUrl', 'AZURE_PORTAL_URL', 'the management portal URL'),
  new EnvironmentParameter('publishingProfileUrl', 'AZURE_PUBLISHINGPROFILE_URL', 'the publish settings file URL'),
  new EnvironmentParameter('managementEndpointUrl', 'AZURE_MANAGEMENTENDPOINT_URL', 'the management service endpoint'),
  new EnvironmentParameter('resourceManagerEndpointUrl', 'AZURE_RESOURCEMANAGERENDPOINT_URL', 'the resource management endpoint'),
  new EnvironmentParameter('sqlManagementEndpointUrl', 'AZURE_SQL_MANAGEMENTENDPOINT_URL', 'the sql server management endpoint for mobile commands'),
  new EnvironmentParameter('sqlServerHostnameSuffix', 'AZURE_SQL_SERVER_HOSTNAME_SUFFIX', 'the dns suffix for sql servers'),
  new EnvironmentParameter('activeDirectoryEndpointUrl', 'AZURE_ACTIVEDIRECTORY_ENDPOINT_URL', 'the Active Directory login endpoint'),
  new EnvironmentParameter('activeDirectoryResourceId', 'AZURE_ACTIVEDIRECTORY_RESOURCE_ID', 'The resource ID to obtain AD tokens for'),
  new EnvironmentParameter('galleryEndpointUrl', 'AZURE_GALLERY_ENDPOINT_URL', 'the template gallery endpoint'),
  new EnvironmentParameter('activeDirectoryGraphResourceId', 'AZURE_ACTIVEDIRECTORY_GRAPH_RESOURCE_ID', 'the Active Directory resource ID'),
  new EnvironmentParameter('activeDirectoryGraphApiVersion', 'AZURE_ACTIVEDIRECTORY_GRAPH_API_VERSION', 'the Active Directory api version'),
  new EnvironmentParameter('storageEndpointSuffix', 'AZURE_STORAGE_ENDPOINT_SUFFIX', 'the endpoint suffix for storage accounts'),
  new EnvironmentParameter('keyVaultDnsSuffix', 'AZURE_KEYVAULT_DNS_SUFFIX', 'the keyvault service dns suffix'),
  new EnvironmentParameter('azureDataLakeStoreFileSystemEndpointSuffix', 'AZURE_DATALAKE_STORE_FILESYSTEM_DNS_SUFFIX', 'the data lake store filesystem service dns suffix'),
  new EnvironmentParameter('azureDataLakeAnalyticsCatalogAndJobEndpointSuffix', 'AZURE_DATALAKE_ANALYTICS_JOB_CATALOG_DNS_SUFFIX', 'the data lake analytics job and catalog service dns suffix')
];

function addRealm(targetUrl, realm) {
  if (realm) {
    var urlObj = url.parse(targetUrl, true);
    delete urlObj.search;
    urlObj.query.whr = realm;
    targetUrl = url.format(urlObj);
  }
  return targetUrl;
}

_.extend(Environment.prototype, {
  getPortalUrl: function (realm) {
    return addRealm(this.portalUrl, realm);
  },

  getPublishingProfileUrl: function (realm) {
    return addRealm(this.publishingProfileUrl, realm);
  },

  toJSON: function () {
    return _.extend({ name: this.name }, this.values);
  },

  getAuthConfig: function (tenantId, resourceId) {
    if (!tenantId) {
      tenantId = constants.AAD_COMMON_TENANT;
    }
    if (!resourceId) {
      resourceId = this.activeDirectoryResourceId;
    }
    return {
      authorityUrl: this.activeDirectoryEndpointUrl,
      tenantId: tenantId,
      resourceId: resourceId,
      clientId: constants.XPLAT_CLI_CLIENT_ID
    };
  },

  isDefaultEnv: function () {
    return this.name === DEFAULT_ENV_NAME;
  }
});

Environment.publicEnvironments = [
  new Environment({
    name: DEFAULT_ENV_NAME,
    portalUrl: 'http://go.microsoft.com/fwlink/?LinkId=254433',
    publishingProfileUrl: 'http://go.microsoft.com/fwlink/?LinkId=254432',
    managementEndpointUrl: 'https://management.core.windows.net',
    resourceManagerEndpointUrl: 'https://management.azure.com/',
    sqlManagementEndpointUrl: 'https://management.core.windows.net:8443/',
    sqlServerHostnameSuffix: '.database.windows.net',
    galleryEndpointUrl: 'https://gallery.azure.com/',
    activeDirectoryEndpointUrl: 'https://login.microsoftonline.com',
    activeDirectoryResourceId: 'https://management.core.windows.net/',
    activeDirectoryGraphResourceId: 'https://graph.windows.net/',
    activeDirectoryGraphApiVersion: '2013-04-05',
    storageEndpointSuffix: '.core.windows.net',
    keyVaultDnsSuffix: '.vault.azure.net',
    azureDataLakeStoreFileSystemEndpointSuffix: 'azuredatalakestore.net',
    azureDataLakeAnalyticsCatalogAndJobEndpointSuffix: 'azuredatalakeanalytics.net'
  }),
  new Environment({
    name: 'AzureChinaCloud',
    portalUrl: 'http://go.microsoft.com/fwlink/?LinkId=301902',
    publishingProfileUrl: 'http://go.microsoft.com/fwlink/?LinkID=301774',
    managementEndpointUrl: 'https://management.core.chinacloudapi.cn',
    resourceManagerEndpointUrl: 'https://management.chinacloudapi.cn',
    sqlManagementEndpointUrl: 'https://management.core.chinacloudapi.cn:8443/',
    sqlServerHostnameSuffix: '.database.chinacloudapi.cn',
    galleryEndpointUrl: 'https://gallery.chinacloudapi.cn/',
    activeDirectoryEndpointUrl: 'https://login.chinacloudapi.cn',
    activeDirectoryResourceId: 'https://management.core.chinacloudapi.cn/',
    activeDirectoryGraphResourceId: 'https://graph.chinacloudapi.cn/',
    activeDirectoryGraphApiVersion: '2013-04-05',
    storageEndpointSuffix: '.core.chinacloudapi.cn',
    keyVaultDnsSuffix: '.vault.azure.cn',
    // TODO: add dns suffixes for the china cloud for datalake store and datalake analytics once they are defined.
    azureDataLakeStoreFileSystemEndpointSuffix: 'N/A',
    azureDataLakeAnalyticsCatalogAndJobEndpointSuffix: 'N/A'
  }),
  new Environment({
    name: 'AzureUSGovernment',
    portalUrl: 'https://manage.windowsazure.us',
    publishingProfileUrl: 'https://manage.windowsazure.us/publishsettings/index',
    managementEndpointUrl: 'https://management.core.usgovcloudapi.net',
    resourceManagerEndpointUrl: 'https://management.usgovcloudapi.net',
    sqlManagementEndpointUrl: 'https://management.core.usgovcloudapi.net:8443/',
    sqlServerHostnameSuffix: '.database.usgovcloudapi.net',
    galleryEndpointUrl: 'https://gallery.usgovcloudapi.net/',
    activeDirectoryEndpointUrl: 'https://login.microsoftonline.com',
    activeDirectoryResourceId: 'https://management.core.usgovcloudapi.net/',
    activeDirectoryGraphResourceId: 'https://graph.windows.net/',
    activeDirectoryGraphApiVersion: '2013-04-05',
    storageEndpointSuffix: '.core.usgovcloudapi.net',
    keyVaultDnsSuffix: '.vault.usgovcloudapi.net',
    // TODO: add dns suffixes for the US government for datalake store and datalake analytics once they are defined.
    azureDataLakeStoreFileSystemEndpointSuffix: 'N/A',
    azureDataLakeAnalyticsCatalogAndJobEndpointSuffix: 'N/A'
  }),
  new Environment({
    name: 'AzureGermanCloud',
    portalUrl: 'http://portal.microsoftazure.de/',
    publishingProfileUrl: 'https://manage.microsoftazure.de/publishsettings/index',
    managementEndpointUrl: 'https://management.core.cloudapi.de',
    resourceManagerEndpointUrl: 'https://management.microsoftazure.de',
    sqlManagementEndpointUrl: 'https://management.core.cloudapi.de:8443/',
    sqlServerHostnameSuffix: '.database.cloudapi.de',
    galleryEndpointUrl: 'https://gallery.cloudapi.de/',
    activeDirectoryEndpointUrl: 'https://login.microsoftonline.de',
    activeDirectoryResourceId: 'https://management.core.cloudapi.de/',
    activeDirectoryGraphResourceId: 'https://graph.cloudapi.de/',
    activeDirectoryGraphApiVersion: '2013-04-05',
    storageEndpointSuffix: '.core.cloudapi.de',
    keyVaultDnsSuffix: '.vault.microsoftazure.de',
    // TODO: add dns suffixes for the US government for datalake store and datalake analytics once they are defined.
    azureDataLakeStoreFileSystemEndpointSuffix: 'N/A',
    azureDataLakeAnalyticsCatalogAndJobEndpointSuffix: 'N/A'
  })
];

module.exports = Environment;
<|endoftext|>


<commit_before>import path from 'path';

export default {
    colors: true,
    basePath: path.resolve('./'),
    files: [
        'lib/*.js'
    ],
    preprocessors: {
        'lib/*.js': 'webpack'
    },
    frameworks: [ 'mocha' ],
    webpack: {
        cache: true,
        resolve: {
            root: path.resolve('./')
        },
        module: {
            preLoaders: [
                {
                    test: /\.js$/,
                    exclude: [
                        path.resolve('lib/'),
                        path.resolve('node_modules/')
                    ],
                    loader: 'babel'
                },
                {
                    test: /\.js$/,
                    include: path.resolve('lib/'),
                    loader: 'isparta'
                }
            ]
        }
    },
    webpackMiddleware: {
        noInfo: true,
        quiet: true
    },
    coverageReporter: {
        dir: '../coverage',
        reporters: [
            { type: 'lcovonly', subdir: '.' }
        ]
    },
    browserNoActivityTimeout: 60 * 1000, // default 10 * 1000
    browserDisconnectTimeout: 10 * 1000, // default 2 * 1000
    browserDisconnectTolerance: 2, // default 0
    captureTimeout: 2 * 60 * 1000 // default 1 * 60 * 1000
};
<commit_msg>Revert ":space_invader: attempt to fix travis tests run"<commit_after>import path from 'path';

export default {
    colors: true,
    files: [
        'lib/*.js'
    ],
    preprocessors: {
        'lib/*.js': 'webpack'
    },
    frameworks: [ 'mocha' ],
    webpack: {
        cache: true,
        resolve: {
            root: path.resolve('./')
        },
        module: {
            preLoaders: [
                {
                    test: /\.js$/,
                    exclude: [
                        path.resolve('lib/'),
                        path.resolve('node_modules/')
                    ],
                    loader: 'babel'
                },
                {
                    test: /\.js$/,
                    include: path.resolve('lib/'),
                    loader: 'isparta'
                }
            ]
        }
    },
    webpackMiddleware: {
        noInfo: true,
        quiet: true
    },
    coverageReporter: {
        dir: '../coverage',
        reporters: [
            { type: 'lcovonly', subdir: '.' }
        ]
    },
    browserNoActivityTimeout: 60 * 1000, // default 10 * 1000
    browserDisconnectTimeout: 10 * 1000, // default 2 * 1000
    browserDisconnectTolerance: 2, // default 0
    captureTimeout: 2 * 60 * 1000 // default 1 * 60 * 1000
};
<|endoftext|>


<commit_before>/**
 *
 * # Fastbinder
 *
 * Fast and worry-free dynamic event binding.
 *
 * https://github.com/andrewchilds/fastbinder
 *
 * ## Supported Attributes
 *
 * - data-on-blur
 * - data-on-click
 * - data-on-change
 * - data-on-focus
 * - data-on-hover
 * - data-on-keydown
 * - data-on-keyup
 * - data-on-mousedown
 * - data-on-mouseup
 * - data-on-scroll
 * - data-on-submit
 *
 * ## Scope to Controller
 *
 * - data-controller
 *
 * ## Usage
 *
 * jQuery.fastbinder();
 * jQuery.fastbinder({ hoverDelay: 250 });
 * jQuery.fastbinder.setOptions({ forceExternalLinks: false });
 * jQuery.fastbinder.destroy();
 *
 * ## Attribute Examples
 *
 * <input type="text" data-on-change="MyLibrary.myFunction" />
 * Execute myFunction on click
 *
 */
(function ($) {

  // Utils

  // Faster than jQuery.data
  function data(el, name, val) {
    return attr(el, 'data-' + name, val);
  }

  function attr(el, name, val) {
    if (el && el.jquery) {
      el = el[0];
    }
    if (el && el.getAttribute) {
      if (typeof val !== 'undefined') {
        el.setAttribute(name, val);
      } else {
        var elAttr = el.getAttribute(name);
        return convertNumber(elAttr);
      }
    }
  }

  function convertNumber(str) {
    return (str === '' || isNaN(str)) ? str : parseFloat(str);
  }

  function strToFunction(functionName, context) {
    context = context || window;
    var namespaces = functionName.split('.');
    var func = namespaces.pop();
    for (var i = 0; i < namespaces.length; i++) {
      if (!context[namespaces[i]]) {
        return false;
      }
      context = context[namespaces[i]];
    }
    return context[func];
  }

  function getController(target) {
    var controller = '';
    var controllerElement = target.closest('[data-controller]');
    if (controllerElement.length > 0) {
      controller = $.fastbinder.options.controllerPrefix + data(controllerElement, 'controller');
    }
    return controller;
  }

  function isEnterKey(e) {
    return e && e.which === 13;
  }

  // Handlers

  function fireEventHandler(target, eventType, e) {
    if (target.length > 0) {
      var handler = data(target, eventType);
      if (handler) {
        var controller = getController(target);
        var controllerHandlerFn = strToFunction(controller + '.' + handler);
        var handlerFn = strToFunction(handler);
        var beforeFn = $.fastbinder.options.beforeEventHandlerFn;

        if (typeof controllerHandlerFn === 'function') {
          if (typeof beforeFn === 'function') {
            beforeFn({
              controller: controller,
              handler: handler,
              eventType: eventType,
              targetElement: target[0]
            });
          }

          return controllerHandlerFn.call(target[0], e);
        }

        if (typeof handlerFn === 'function') {
          if (typeof beforeFn === 'function') {
            beforeFn({
              handler: handler,
              eventType: eventType,
              targetElement: target[0]
            });
          }

          return handlerFn.call(target[0], e);
        }
      }
    }
  }

  function genericBinder(options) {
    options = $.extend({
      attribute: 'on-click',
      beforeTrigger: null,
      context: document.body,
      delay: 0,
      deferLookup: false,
      name: 'click'
    }, options);

    var names = options.name.split(' ');
    $.each(names, function (key, val) {
      names[key] = val + '.' + $.fastbinder.options.namespace;
    });

    var timeout;
    $(options.context).on(names.join(' '), function (e) {
      var target = $(e.target).closest('[data-' + options.attribute + ']');

      if (options.beforeTrigger && !options.beforeTrigger(e)) {
        return;
      }
      if (target.length || options.deferLookup) {
        var fn = function () {
          if (options.deferLookup) {
            target = $(e.target).closest('[data-' + options.attribute + ']');
            if (target.length === 0) {
              return;
            }
          }
          return fireEventHandler(target, options.attribute, e);
        };
        var delay = (options.delay && $.isFunction(options.delay)) ? options.delay(target) : options.delay;
        if (delay) {
          clearTimeout(timeout);
          timeout = setTimeout(fn, delay);
        } else {
          return fn();
        }
      }
    });
  }

  function initKeyupHandler() {
    var timeoutID;
    $(window).on('keydown.' + $.fastbinder.options.namespace, function (e) {
      var target = $(document.activeElement);
      if (target.is('input, textarea')) {
        var fn = function () {
          fireEventHandler(target, 'on-keydown', e);
        };
        if ($.fastbinder.options.keydownDelay > 0) {
          clearTimeout(timeoutID);
          timeoutID = setTimeout(fn, $.fastbinder.options.keydownDelay);
        } else {
          fn();
        }
      }
    }).on('keyup.' + $.fastbinder.options.namespace, function (e) {
      var target = $(document.activeElement);
      if (target.is('input, textarea')) {
        if (isEnterKey(e)) {
          fireEventHandler(target, 'on-submit', e);
        } else {
          var fn = function () {
            fireEventHandler(target, 'on-keyup', e);
          };
          if ($.fastbinder.options.keyupDelay > 0) {
            clearTimeout(timeoutID);
            timeoutID = setTimeout(fn, $.fastbinder.options.keyupDelay);
          } else {
            fn();
          }
        }
      }
    });
  }

  function handleExternalLinks(e) {
    // Handle proper links
    var target = $(e.target);
    if (target.is('a') && target.attr('href') &&
      target.attr('href') !== '#' && !data(target, 'on-click')) {
      if ($.fastbinder.options.forceExternalLinks && !target.attr('target') &&
        target.attr('href').toLowerCase().indexOf('http') === 0) {
        target.attr('target', '_blank');
      }
      return false;
    }
    return true;
  }

  // Public API

  $.fastbinder = function (options) {
    $.fastbinder.setOptions(options);
    $.fastbinder.destroy();
    $.fastbinder.init();
  };

  $.fastbinder.on = genericBinder;
  $.fastbinder.strToFunction = strToFunction;
  $.fastbinder.getController = getController;
  $.fastbinder.fireEventHandler = fireEventHandler;

  $.fastbinder.defaults = {
    namespace: 'fastbinder',
    controllerPrefix: '',
    hoverDelay: 50,
    keydownDelay: 0,
    keyupDelay: 50,
    scrollDelay: 50,
    forceExternalLinks: true,
    beforeEventHandlerFn: null
  };

  $.fastbinder.setOptions = function (options) {
    $.fastbinder.options = $.extend($.fastbinder.options || $.fastbinder.defaults, options);
  };

  $.fastbinder.destroy = function () {
    $(document.body).off('.' + $.fastbinder.options.namespace);
    $(window).off('.' + $.fastbinder.options.namespace);
  };

  $.fastbinder.off = function (eventName) {
    $(document.body).off(eventName + '.' + $.fastbinder.options.namespace);
    $(window).off(eventName + '.' + $.fastbinder.options.namespace);
  };

  $.fastbinder.init = function () {
    $.fastbinder.on({ name: 'click', attribute: 'on-click', beforeTrigger: handleExternalLinks });
    $.fastbinder.on({ name: 'mousedown', attribute: 'on-mousedown' });
    $.fastbinder.on({ name: 'mouseup', attribute: 'on-mouseup' });
    $.fastbinder.on({ name: 'submit', attribute: 'on-submit', context: window });
    $.fastbinder.on({ name: 'change', attribute: 'on-change', context: window });
    $.fastbinder.on({ name: 'focusin', attribute: 'on-focus' });
    $.fastbinder.on({ name: 'focusout', attribute: 'on-blur' });

    $.fastbinder.on({
      name: 'scroll',
      attribute: 'on-scroll',
      context: window,
      delay: function () {
        return $.fastbinder.options.scrollDelay;
      },
      deferLookup: true
    });
    $.fastbinder.on({
      name: 'mousemove',
      attribute: 'on-hover',
      delay: function (target) {
        return data(target, 'hover-delay') || $.fastbinder.options.hoverDelay;
      },
      deferLookup: true
    });

    initKeyupHandler();
  };

}(window.jQuery));
<commit_msg>Guard against empty namespace segment<commit_after>/**
 *
 * # Fastbinder
 *
 * Fast and worry-free dynamic event binding.
 *
 * https://github.com/andrewchilds/fastbinder
 *
 * ## Supported Attributes
 *
 * - data-on-blur
 * - data-on-click
 * - data-on-change
 * - data-on-focus
 * - data-on-hover
 * - data-on-keydown
 * - data-on-keyup
 * - data-on-mousedown
 * - data-on-mouseup
 * - data-on-scroll
 * - data-on-submit
 *
 * ## Scope to Controller
 *
 * - data-controller
 *
 * ## Usage
 *
 * jQuery.fastbinder();
 * jQuery.fastbinder({ hoverDelay: 250 });
 * jQuery.fastbinder.setOptions({ forceExternalLinks: false });
 * jQuery.fastbinder.destroy();
 *
 * ## Attribute Examples
 *
 * <input type="text" data-on-change="MyLibrary.myFunction" />
 * Execute myFunction on click
 *
 */
(function ($) {

  // Utils

  // Faster than jQuery.data
  function data(el, name, val) {
    return attr(el, 'data-' + name, val);
  }

  function attr(el, name, val) {
    if (el && el.jquery) {
      el = el[0];
    }
    if (el && el.getAttribute) {
      if (typeof val !== 'undefined') {
        el.setAttribute(name, val);
      } else {
        var elAttr = el.getAttribute(name);
        return convertNumber(elAttr);
      }
    }
  }

  function convertNumber(str) {
    return (str === '' || isNaN(str)) ? str : parseFloat(str);
  }

  function strToFunction(functionName, context) {
    context = context || window;
    var namespaces = functionName.split('.');
    var func = namespaces.pop();
    for (var i = 0; i < namespaces.length; i++) {
      if (namespaces[i]) {
        if (!context[namespaces[i]]) {
          return false;
        }
        context = context[namespaces[i]];
      }
    }
    return context[func];
  }

  function getController(target) {
    var controller = '';
    var controllerElement = target.closest('[data-controller]');
    if (controllerElement.length > 0) {
      controller = $.fastbinder.options.controllerPrefix + data(controllerElement, 'controller');
    }
    return controller;
  }

  function isEnterKey(e) {
    return e && e.which === 13;
  }

  // Handlers

  function fireEventHandler(target, eventType, e) {
    if (target.length > 0) {
      var handler = data(target, eventType);
      if (handler) {
        var controller = getController(target);
        var controllerHandlerFn = strToFunction(controller + '.' + handler);
        var handlerFn = strToFunction(handler);
        var beforeFn = $.fastbinder.options.beforeEventHandlerFn;

        if (typeof controllerHandlerFn === 'function') {
          if (typeof beforeFn === 'function') {
            beforeFn({
              controller: controller,
              handler: handler,
              eventType: eventType,
              targetElement: target[0]
            });
          }

          return controllerHandlerFn.call(target[0], e);
        }

        if (typeof handlerFn === 'function') {
          if (typeof beforeFn === 'function') {
            beforeFn({
              handler: handler,
              eventType: eventType,
              targetElement: target[0]
            });
          }

          return handlerFn.call(target[0], e);
        }
      }
    }
  }

  function genericBinder(options) {
    options = $.extend({
      attribute: 'on-click',
      beforeTrigger: null,
      context: document.body,
      delay: 0,
      deferLookup: false,
      name: 'click'
    }, options);

    var names = options.name.split(' ');
    $.each(names, function (key, val) {
      names[key] = val + '.' + $.fastbinder.options.namespace;
    });

    var timeout;
    $(options.context).on(names.join(' '), function (e) {
      var target = $(e.target).closest('[data-' + options.attribute + ']');

      if (options.beforeTrigger && !options.beforeTrigger(e)) {
        return;
      }
      if (target.length || options.deferLookup) {
        var fn = function () {
          if (options.deferLookup) {
            target = $(e.target).closest('[data-' + options.attribute + ']');
            if (target.length === 0) {
              return;
            }
          }
          return fireEventHandler(target, options.attribute, e);
        };
        var delay = (options.delay && $.isFunction(options.delay)) ? options.delay(target) : options.delay;
        if (delay) {
          clearTimeout(timeout);
          timeout = setTimeout(fn, delay);
        } else {
          return fn();
        }
      }
    });
  }

  function initKeyupHandler() {
    var timeoutID;
    $(window).on('keydown.' + $.fastbinder.options.namespace, function (e) {
      var target = $(document.activeElement);
      if (target.is('input, textarea')) {
        var fn = function () {
          fireEventHandler(target, 'on-keydown', e);
        };
        if ($.fastbinder.options.keydownDelay > 0) {
          clearTimeout(timeoutID);
          timeoutID = setTimeout(fn, $.fastbinder.options.keydownDelay);
        } else {
          fn();
        }
      }
    }).on('keyup.' + $.fastbinder.options.namespace, function (e) {
      var target = $(document.activeElement);
      if (target.is('input, textarea')) {
        if (isEnterKey(e)) {
          fireEventHandler(target, 'on-submit', e);
        } else {
          var fn = function () {
            fireEventHandler(target, 'on-keyup', e);
          };
          if ($.fastbinder.options.keyupDelay > 0) {
            clearTimeout(timeoutID);
            timeoutID = setTimeout(fn, $.fastbinder.options.keyupDelay);
          } else {
            fn();
          }
        }
      }
    });
  }

  function handleExternalLinks(e) {
    // Handle proper links
    var target = $(e.target);
    if (target.is('a') && target.attr('href') &&
      target.attr('href') !== '#' && !data(target, 'on-click')) {
      if ($.fastbinder.options.forceExternalLinks && !target.attr('target') &&
        target.attr('href').toLowerCase().indexOf('http') === 0) {
        target.attr('target', '_blank');
      }
      return false;
    }
    return true;
  }

  // Public API

  $.fastbinder = function (options) {
    $.fastbinder.setOptions(options);
    $.fastbinder.destroy();
    $.fastbinder.init();
  };

  $.fastbinder.on = genericBinder;
  $.fastbinder.strToFunction = strToFunction;
  $.fastbinder.getController = getController;
  $.fastbinder.fireEventHandler = fireEventHandler;

  $.fastbinder.defaults = {
    namespace: 'fastbinder',
    controllerPrefix: '',
    hoverDelay: 50,
    keydownDelay: 0,
    keyupDelay: 50,
    scrollDelay: 50,
    forceExternalLinks: true,
    beforeEventHandlerFn: null
  };

  $.fastbinder.setOptions = function (options) {
    $.fastbinder.options = $.extend($.fastbinder.options || $.fastbinder.defaults, options);
  };

  $.fastbinder.destroy = function () {
    $(document.body).off('.' + $.fastbinder.options.namespace);
    $(window).off('.' + $.fastbinder.options.namespace);
  };

  $.fastbinder.off = function (eventName) {
    $(document.body).off(eventName + '.' + $.fastbinder.options.namespace);
    $(window).off(eventName + '.' + $.fastbinder.options.namespace);
  };

  $.fastbinder.init = function () {
    $.fastbinder.on({ name: 'click', attribute: 'on-click', beforeTrigger: handleExternalLinks });
    $.fastbinder.on({ name: 'mousedown', attribute: 'on-mousedown' });
    $.fastbinder.on({ name: 'mouseup', attribute: 'on-mouseup' });
    $.fastbinder.on({ name: 'submit', attribute: 'on-submit', context: window });
    $.fastbinder.on({ name: 'change', attribute: 'on-change', context: window });
    $.fastbinder.on({ name: 'focusin', attribute: 'on-focus' });
    $.fastbinder.on({ name: 'focusout', attribute: 'on-blur' });

    $.fastbinder.on({
      name: 'scroll',
      attribute: 'on-scroll',
      context: window,
      delay: function () {
        return $.fastbinder.options.scrollDelay;
      },
      deferLookup: true
    });
    $.fastbinder.on({
      name: 'mousemove',
      attribute: 'on-hover',
      delay: function (target) {
        return data(target, 'hover-delay') || $.fastbinder.options.hoverDelay;
      },
      deferLookup: true
    });

    initKeyupHandler();
  };

}(window.jQuery));
<|endoftext|>


<commit_before>// Karma configuration
// Generated on Wed Jul 15 2015 09:44:02 GMT+0200 (Romance Daylight Time)

module.exports = function(config) {
  'use strict';
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '../',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'www/build/js/angular2-polyfills.js',
      'node_modules/traceur/bin/traceur-runtime.js', // Required by PhantomJS2, otherwise it shouts ReferenceError: Can't find variable: require
      {pattern: 'www/build/test/test.bundle.js', included: true},
      {pattern: 'www/build/test/test.bundle.js.map', included: false},
      {pattern: 'www/build/**/*.html', included: false},
    ],

    // list of files to exclude
    exclude: [
      'node_modules/angular2/**/*_spec.js',
      'node_modules/ionic-angular/**/*spec*',
      'node_modules/ionic-angular/decorators/app.js'
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'www/build/test/test.bundle.js': 'coverage'
    },

    // options on how to report coverage:
    coverageReporter: {
      reporters: [
        {type: 'json', dir: 'coverage', subdir: 'istanbul-remap'}
      ]
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['mocha','coverage'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // GOTCHA -- Karma proxies _everything_ through base first..
    //           Also any files you want to serve need to be in the files array above with serverd: true
    proxies: {
      // allows us to keep test code separate from app code and still have the references work
      '/base/node_modules/ionic-angular/decorators/app.js': '/base/www/build/test/app.stub.js', // stub out Ionic's @App decorator
      '/base/ionic-angular.js': '/base/test/ionic-angular.js'
    },

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: [
      'PhantomJS',
    ],

    customLaunchers: {
      Chrome_travis_ci: {
        base: 'Chrome',
        flags: ['--no-sandbox']
      }
    },
  });

  if (process.env.APPVEYOR) {
    config.browsers = ['IE'];
    config.singleRun = true;
    config.browserNoActivityTimeout = 90000; // Note: default value (10000) is not enough
  }

  if (process.env.TRAVIS || process.env.CIRCLECI) {
    config.browsers = ['Chrome_travis_ci'];
    config.singleRun = true;
  }
};
<commit_msg>Proxy html<commit_after>// Karma configuration
// Generated on Wed Jul 15 2015 09:44:02 GMT+0200 (Romance Daylight Time)

module.exports = function(config) {
  'use strict';
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '../',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'www/build/js/angular2-polyfills.js',
      'node_modules/traceur/bin/traceur-runtime.js', // Required by PhantomJS2, otherwise it shouts ReferenceError: Can't find variable: require
      {pattern: 'www/build/test/test.bundle.js', included: true},
      {pattern: 'www/build/test/test.bundle.js.map', included: false},
      {pattern: 'www/build/**/*.html', included: false},
    ],

    // list of files to exclude
    exclude: [
      'node_modules/angular2/**/*_spec.js',
      'node_modules/ionic-angular/**/*spec*',
      'node_modules/ionic-angular/decorators/app.js'
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'www/build/test/test.bundle.js': 'coverage'
    },

    // options on how to report coverage:
    coverageReporter: {
      reporters: [
        {type: 'json', dir: 'coverage', subdir: 'istanbul-remap'}
      ]
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['mocha','coverage'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // GOTCHA -- Karma proxies _everything_ through base first..
    //           Also any files you want to serve need to be in the files array above with serverd: true
    proxies: {
      // allows us to keep test code separate from app code and still have the references work
      '/base/node_modules/ionic-angular/decorators/app.js': '/base/www/build/test/app.stub.js', // stub out Ionic's @App decorator
      '/base/ionic-angular.js': '/base/test/ionic-angular.js',
      '/build': '/base/www/build'
    },

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: [
      'PhantomJS',
    ],

    customLaunchers: {
      Chrome_travis_ci: {
        base: 'Chrome',
        flags: ['--no-sandbox']
      }
    },
  });

  if (process.env.APPVEYOR) {
    config.browsers = ['IE'];
    config.singleRun = true;
    config.browserNoActivityTimeout = 90000; // Note: default value (10000) is not enough
  }

  if (process.env.TRAVIS || process.env.CIRCLECI) {
    config.browsers = ['Chrome_travis_ci'];
    config.singleRun = true;
  }
};
<|endoftext|>


<commit_before>/*! Featherbox 0.2 | github.com/adamaveray/featherbox | Adam Averay | MIT */
(function($){
	var $window	= $(window),
		$body	= $('body');

	var Featherbox	= function(element, options){
		this.options	= $.extend({}, Featherbox.defaults, options);
		this.element	= element;
		this.$element	= $(element);

		this.create();
		if(this.options.autoShow){
			this.show();
		}
	};

	Featherbox.defaults	= {
		// Operation
		autoShow:	true,

		// Animation
		transitionOpenClass:	'__transitioning',
		transitionCloseClass:	'__transitioning',

		// Templating
		extraClass:		null,
		templateModal:	'

',
		templateClose:	'<button class="modal__close" type="button">Close</button>',
		selectorInsertContent:	'.modal',
		selectorInsertClose:	'.modal',

		// Operation
		selectorLoadElements:	'img,iframe'
	};

	$.extend(Featherbox.prototype, {
		options:	null,
		element:	null,

		$element:	null,
		$modal:		null,
		$close:		null,
		$templateModal:	null,
		$templateClose:	null,

		handlerClick:	null,
		handlerKeydown:	null,

		create:	function(){
			var _this	= this;

			if(this.$modal){
				// Clean up existing
				this.close();
			}

			if(!this.$template){
				var $generator	= $(document.createElement('div'));
				this.$templateModal	= $generator.html(this.options.templateModal).children();
				this.$templateClose	= $generator.html(this.options.templateClose).children();
				$generator = null;

				if(this.options.extraClass !== null){
					this.$templateModal.addClass(this.options.extraClass);
				}
			}

			// Create modal
			this.$modal	= this.$templateModal.clone();
			this.$close	= this.$templateClose.clone();
			this.$modal.find(this.options.selectorInsertClose).append(this.$close);

			// Insert content
			this.$modal.find(this.options.selectorInsertContent).append(this.$element);

			// Monitor loading
			this._waitForLoad(this.$modal, this.options.selectorLoadElements, function(){
				window.setTimeout(function(){
				_this._trigger('Load');
				}, 1000);
			});

			// Monitor close events
			window.setTimeout(function(){
				_this._closeOnClick();
				_this._closeOnEscape();
			}, 0);
		},

		show:	function(animate){
			(animate === undefined) && (animate = true);

			if(!this.$modal){
				// Nothing to show
				return;
			}

			var $modal	= this.$modal;
			var _this	= this;

			// Insert into page
			$modal
				.hide()
				.appendTo($body);

			var show	= function(){
				$modal.show();
				_this._trigger('OpenFinish');
			};
			this._trigger('Open');

			if(animate){
				// Animate in
				var className	= this.options.transitionOpenClass;

				$modal
					.addClass(className)
					.show();
				window.setTimeout(function(){
					$modal.removeClass(className);
					show();
				}, 0);
			} else {
				show();
			}
		},

		close:	function(animate){
			(animate === undefined) && (animate = true);

			this._clearCloseOnClick();
			this._clearCloseOnEscape();

			if(!this.$modal){
				// Nothing to close
				return;
			}

			var $modal	= this.$modal;
			var _this	= this;

			this.$modal	= null;
			this.$close	= null;

			var remove	= function(){
				$modal.remove();
				_this._trigger('Close');
			};
			_this._trigger('CloseStart');

			if(animate){
				// Animate out
				var className	= this.options.transitionCloseClass;

				$modal.addClass(className);
				this._onTransitionEnd($modal, remove);
				// window.setTimeout(remove, 500);
			} else {
				remove();
			}
		},

		destroy:	function(){
			this._clearCloseOnClick();
			this._clearCloseOnEscape();

			this.$templateModal && this.$templateModal.remove();
			this.$templateClose && this.$templateClose.remove();

			this.$templateModal	= null;
			this.$templateClose	= null;

			this.$modal && this.$modal.remove();
			this.$modal	= null;
			this.$close	= null;

			this.element	= null;
			this.$element	= null;
		},

		_onTransitionEnd:		function($modal, fn){
			var event	= this._getTransitionEvent($modal[0]);
			if(!event){
				// No transition support
				fn();
				return;
			}

			$modal.one(event, function(){
				fn();
			});
		},
		_getTransitionEvent:	function(element){
			var transitions = {
				'transition':		'transitionend',
				'OTransition':		'oTransitionEnd',
				'MozTransition':	'transitionend',
				'WebkitTransition':	'webkitTransitionEnd'
			};

			for(t in transitions){	if(!transitions.hasOwnProperty(t)){ continue; }
				if(element.style[t] !== undefined){
					return transitions[t];
				}
			}
		},

		_trigger:	function(event, params){
			event	= 'featherbox'+event;
			params	= params || [];

			params.unshift(this);

			this.$element.trigger(event, params);
		},

		_waitForLoad:		function($element, selector, callback){
			// Locate loadable elements
			var $loadable	= this.$modal.find(selector)
										 .add(this.$modal.filter(selector));	// Include container if loadable

			var total		= $loadable.length,
				progress	= 0;

			if(total === 0){
				// Nothing to load - trigger immediately
				window.setTimeout(function(){
					callback();
				}, 0);
			}

			$loadable.on('load', function(){
				progress++;

				if(progress >= total){
					// Loaded
					callback();
				}
			});
		},
		_closeOnClick:		function(){
			var _this	= this;

			this._clearCloseOnClick();

			var handler	= function(e){
				if(!_this.$modal){
					// Nothing to show
					return;
				}

				if($.contains(_this.$modal[0], e.target)){
					// Clicking on modal
					if(e.target !== _this.$modal[0] && e.target !== _this.$close[0]){
						// Not clicking on background or close button - clicking on modal content - ignore click
						return;
					}
				}

				e.preventDefault();
				e.stopPropagation();

				_this.close();
			};
			this.handlerClick	= handler;

			$body.on('click', handler);
		},
		_clearCloseOnClick:	function(){
			if(!this.handlerClick){
				// Nothing to clear
				return;
			}

			var handler	= this.handlerClick;

			this.handlerClick	= null;

			$body.off('click', handler);
		},
		_closeOnEscape:			function(){
			var keyCode	= 27;	// Escape key

			// Clear any existing handlers
			this._clearCloseOnEscape();

			var _this	= this;
			var handler	= function(e){
				if(e.keyCode === keyCode){
					_this.close();
				}
			};

			this.handlerKeydown	= handler;

			$window.on('keydown', handler);
		},
		_clearCloseOnEscape:	function(){
			if(!this.handlerKeydown){
				// Nothing to clear
				return;
			}

			var handler	= this.handlerKeydown;

			this.handlerKeydown	= null;

			$window.off('keydown', handler);
		}
	});

	$.featherbox		= Featherbox;
	$.fn.featherbox	= function(options){
		var modal	= new Featherbox(this, options);
		return $(this).data('featherbox', modal);
	};
}(jQuery));
<commit_msg>Fixed loading HTML templates<commit_after>/*! Featherbox 0.2 | github.com/adamaveray/featherbox | Adam Averay | MIT */
(function($){
	var $window	= $(window),
		$body	= $('body');

	var Featherbox	= function(element, options){
		this.options	= $.extend({}, Featherbox.defaults, options);
		this.element	= element;
		this.$element	= $(element);

		this.create();
		if(this.options.autoShow){
			this.show();
		}
	};

	Featherbox.defaults	= {
		// Operation
		autoShow:	true,

		// Animation
		transitionOpenClass:	'__transitioning',
		transitionCloseClass:	'__transitioning',

		// Templating
		extraClass:		null,
		templateModal:	'

',
		templateClose:	'<button class="modal__close" type="button">Close</button>',
		selectorInsertContent:	'.modal',
		selectorInsertClose:	'.modal',

		// Operation
		selectorLoadElements:	'img,iframe'
	};

	$.extend(Featherbox.prototype, {
		options:	null,
		element:	null,

		$element:	null,
		$modal:		null,
		$close:		null,
		$templateModal:	null,
		$templateClose:	null,

		handlerClick:	null,
		handlerKeydown:	null,

		create:	function(){
			var _this	= this;

			if(this.$modal){
				// Clean up existing
				this.close();
			}

			if(!this.$templateModal){
				this.$templateModal	= $($.parseHTML(this.options.templateModal));
				this.$templateClose	= $($.parseHTML(this.options.templateClose));

				if(this.options.extraClass !== null){
					this.$templateModal.addClass(this.options.extraClass);
				}
			}

			// Create modal
			this.$modal	= this.$templateModal.clone();
			this.$close	= this.$templateClose.clone();
			this.$modal.find(this.options.selectorInsertClose).append(this.$close);

			// Insert content
			this.$modal.find(this.options.selectorInsertContent).append(this.$element);

			// Monitor loading
			this._waitForLoad(this.$modal, this.options.selectorLoadElements, function(){
				window.setTimeout(function(){
				_this._trigger('Load');
				}, 1000);
			});

			// Monitor close events
			window.setTimeout(function(){
				_this._closeOnClick();
				_this._closeOnEscape();
			}, 0);
		},

		show:	function(animate){
			(animate === undefined) && (animate = true);

			if(!this.$modal){
				// Nothing to show
				return;
			}

			var $modal	= this.$modal;
			var _this	= this;

			// Insert into page
			$modal
				.hide()
				.appendTo($body);

			var show	= function(){
				$modal.show();
				_this._trigger('OpenFinish');
			};
			this._trigger('Open');

			if(animate){
				// Animate in
				var className	= this.options.transitionOpenClass;

				$modal
					.addClass(className)
					.show();
				window.setTimeout(function(){
					$modal.removeClass(className);
					show();
				}, 0);
			} else {
				show();
			}
		},

		close:	function(animate){
			(animate === undefined) && (animate = true);

			this._clearCloseOnClick();
			this._clearCloseOnEscape();

			if(!this.$modal){
				// Nothing to close
				return;
			}

			var $modal	= this.$modal;
			var _this	= this;

			this.$modal	= null;
			this.$close	= null;

			var remove	= function(){
				$modal.remove();
				_this._trigger('Close');
			};
			_this._trigger('CloseStart');

			if(animate){
				// Animate out
				var className	= this.options.transitionCloseClass;

				$modal.addClass(className);
				this._onTransitionEnd($modal, remove);
				// window.setTimeout(remove, 500);
			} else {
				remove();
			}
		},

		destroy:	function(){
			this._clearCloseOnClick();
			this._clearCloseOnEscape();

			this.$templateModal && this.$templateModal.remove();
			this.$templateClose && this.$templateClose.remove();

			this.$templateModal	= null;
			this.$templateClose	= null;

			this.$modal && this.$modal.remove();
			this.$modal	= null;
			this.$close	= null;

			this.element	= null;
			this.$element	= null;
		},

		_onTransitionEnd:		function($modal, fn){
			var event	= this._getTransitionEvent($modal[0]);
			if(!event){
				// No transition support
				fn();
				return;
			}

			$modal.one(event, function(){
				fn();
			});
		},
		_getTransitionEvent:	function(element){
			var transitions = {
				'transition':		'transitionend',
				'OTransition':		'oTransitionEnd',
				'MozTransition':	'transitionend',
				'WebkitTransition':	'webkitTransitionEnd'
			};

			for(t in transitions){	if(!transitions.hasOwnProperty(t)){ continue; }
				if(element.style[t] !== undefined){
					return transitions[t];
				}
			}
		},

		_trigger:	function(event, params){
			event	= 'featherbox'+event;
			params	= params || [];

			params.unshift(this);

			this.$element.trigger(event, params);
		},

		_waitForLoad:		function($element, selector, callback){
			// Locate loadable elements
			var $loadable	= this.$modal.find(selector)
										 .add(this.$modal.filter(selector));	// Include container if loadable

			var total		= $loadable.length,
				progress	= 0;

			if(total === 0){
				// Nothing to load - trigger immediately
				window.setTimeout(function(){
					callback();
				}, 0);
			}

			$loadable.on('load', function(){
				progress++;

				if(progress >= total){
					// Loaded
					callback();
				}
			});
		},
		_closeOnClick:		function(){
			var _this	= this;

			this._clearCloseOnClick();

			var handler	= function(e){
				if(!_this.$modal){
					// Nothing to show
					return;
				}

				if($.contains(_this.$modal[0], e.target)){
					// Clicking on modal
					if(e.target !== _this.$modal[0] && e.target !== _this.$close[0]){
						// Not clicking on background or close button - clicking on modal content - ignore click
						return;
					}
				}

				e.preventDefault();
				e.stopPropagation();

				_this.close();
			};
			this.handlerClick	= handler;

			$body.on('click', handler);
		},
		_clearCloseOnClick:	function(){
			if(!this.handlerClick){
				// Nothing to clear
				return;
			}

			var handler	= this.handlerClick;

			this.handlerClick	= null;

			$body.off('click', handler);
		},
		_closeOnEscape:			function(){
			var keyCode	= 27;	// Escape key

			// Clear any existing handlers
			this._clearCloseOnEscape();

			var _this	= this;
			var handler	= function(e){
				if(e.keyCode === keyCode){
					_this.close();
				}
			};

			this.handlerKeydown	= handler;

			$window.on('keydown', handler);
		},
		_clearCloseOnEscape:	function(){
			if(!this.handlerKeydown){
				// Nothing to clear
				return;
			}

			var handler	= this.handlerKeydown;

			this.handlerKeydown	= null;

			$window.off('keydown', handler);
		}
	});

	$.featherbox		= Featherbox;
	$.fn.featherbox	= function(options){
		var modal	= new Featherbox(this, options);
		return $(this).data('featherbox', modal);
	};
}(jQuery));
<|endoftext|>


<commit_before>var gulp = require('gulp'),
  chai = require('chai'),
  expect = chai.expect,
  fs = require('fs'),
  multiline = require('multiline'),
  kssSplitter = require('../lib/modules/kss-splitter');

describe('KSS divider', function() {

  it('should parse single KSS block', function() {
    var str = multiline(function() {
      /*
// Comment
// Styleguide 1.0

.a { b: c }
      */
    }),
    result = [
      [
        'block',
        [
          'kss',
          '// Comment\n// Styleguide 1.0\n'
        ],
        [
          'code',
          '.a { b: c }'
        ]
      ]
    ],
    kssBlocks = kssSplitter.getAst(str);
    expect(kssBlocks).eql(result);
  });

});
<commit_msg>Test to be space agnostic<commit_after>var gulp = require('gulp'),
  chai = require('chai'),
  expect = chai.expect,
  fs = require('fs'),
  multiline = require('multiline'),
  kssSplitter = require('../lib/modules/kss-splitter');

describe('KSS divider', function() {

  it('should parse single KSS block', function() {
    var str = multiline(function() {
      /*
// Comment
// Styleguide 1.0

.a { b: c }
      */
    }),
    result = [
      [
        'block',
        [
          'kss',
          '// Comment\n// Styleguide 1.0\n'
        ],
        [
          'code',
          '.a { b: c }'
        ]
      ]
    ],
    kssBlocks = kssSplitter.getAst(str);
    expect(kssBlocks).eql(result);
  });

  it('should be agnostic to spaces in reference declaration', function(){
    var str = multiline(function() {
      /*
// Comment
//Styleguide 1.0

.a { b: c }
      */
    }),
    result = [
      [
        'block',
        [
          'kss',
          '// Comment\n//Styleguide 1.0 \n'
        ],
        [
          'code',
          '.a { b: c }'
        ]
      ]
    ],
    kssBlocks = kssSplitter.getAst(str);
    expect(kssBlocks).eql(result);
  });

});
<|endoftext|>