<commit_before>/**
	_moon.MarqueeText_ is a basic text control that supports marquee animation.
	When _moon.MarqueeText_ objects are used inside a
	[moon.MarqueeDecorator](#moon.MarqueeDecorator), the decorator synchronizes
	their start times; the user may start a marquee programmatically by calling
	_startMarquee()_.

		enyo.kind({
			name: "moon.Header",
			mixins: ["moon.MarqueeSupport"],
			marqueeSpeed: 100,
			components: [
				{kind: "moon.MarqueeText", content: "longText+longText"},
				{kind: "moon.MarqueeText", content: "longText"}
			],
			rendered: function() {
				this.startMarquee();
			}
		});

	To add the marquee feature to a kind, simply use the MarqueeSupport mixin:

		enyo.kind({
			name: "moon.MarqueeButton",
			kind: "enyo.Button",
			mixins: ["moon.MarqueeSupport"],
			components: [
				{kind:"moon.MarqueeText"}
			],
			contentChanged: function() {
				this.$.marqueeText.setContent(this.content);
			}
		});
*/

enyo.kind({
	name: "moon.MarqueeText",
	mixins: ["moon.MarqueeItem"],
	published: {
		//* Speed of marquee animation, in pixels per second
		marqueeSpeed: 60,
		/**
			Time in milliseconds that the marquee will pause at the end of the
			animation, before resetting to the beginning
		*/
		marqueePause: 1000,
		//* When true, marqueeing will not occur
		disabled: false
	}
});

/**
	@public

	The _moon.MarqueeSupport_ mixin should be used with controls that contain multiple marquees
	whose animation behavior should be synchronized. Calling _this.startMarquee()_ or
	_this.stopMarquee()_ starts/stops all contained marquees.
*/
moon.MarqueeSupport = {
	name: "MarqueeSupport",
	marqueeOnSpotlight: true,
	//* @protected
	handlers: {
		onSpotlightFocus: "_marquee_spotlightFocus",
		onSpotlightBlur: "_marquee_spotlightBlur",
		onMarqueeEnded: "_marquee_marqueeEnded",
		onresize: "_marquee_resize"
	},
	marqueeActive: false,
	//* Initialize marquee timings during _create_
	create: enyo.inherit(function (sup) {
		return function() {
			sup.apply(this, arguments);
			this.marqueeOnSpotlight = (this.marqueeOnSpotlight === undefined) ? true : this.marqueeOnSpotlight;
			this.marqueeSpeed =    (this.marqueeSpeed ===     undefined) ? 60 :    this.marqueeSpeed;
			this.marqueeDelay =    (this.marqueeDelay ===     undefined) ? 1000 :  this.marqueeDelay;
			this.marqueePause =    (this.marqueePause ===     undefined) ? 1000 :  this.marqueePause;
			this.marqueeHold  =    (this.marqueeHold  ===     undefined) ? 2000 :  this.marqueeHold;
			this.marqueeOnRender = (this.marqueeOnRender  === undefined) ? false : this.marqueeOnRender;
		};
	}),
	//* If _this.marqueeOnRender_ is true, kick off marquee animation
	rendered: enyo.inherit(function (sup) {
		return function() {
			sup.apply(this, arguments);
			if (this.marqueeOnRender) {
				this.startMarquee();
			}
		};
	}),
	//* On focus, start child marquees
	_marquee_spotlightFocus: function(inSender, inEvent) {
		if (this.marqueeOnSpotlight) {
			this.startMarquee();
		}
	},
	//* On blur, halt child marquees
	_marquee_spotlightBlur: function(inSender, inEvent) {
		if (this.marqueeOnSpotlight) {
			this.stopMarquee();
		}
	},
	//* When a child marquee animation completes, remove the child from _this.marqueeWaitList_
	_marquee_marqueeEnded: function(inSender, inEvent) {
		if (this.marqueeActive) {
			enyo.remove(inEvent.originator, this.marqueeWaitList);
			if (this.marqueeWaitList.length === 0) {
				this._marquee_startHold();
				this.marqueeActive = false;
			}
		}
		return true;
	},
	_marquee_resize: function(inSender, inEvent) {
		if (this.marqueeOnSpotlight) {
			this._marquee_startHold();
		}
	},

	//* @public

	//* Start timer to waterfall an _onRequestMarqueeStart_ event that kicks off marquee animation on all child marquees
	startMarquee: function() {
		this._marquee_buildWaitList();

		if (this.marqueeWaitList.length === 0) {
			return;
		}

		this.marqueeActive = true;
		this.startJob("marqueeSupportJob", "_marquee_startChildMarquees", this.marqueeDelay);
	},
	//* Waterfall an _onRequestMarqueeStop_ event to halt all running child marquees
	stopMarquee: function() {
		this.stopJob("marqueeSupportJob");
		this.marqueeActive = false;
		this._marquee_stopChildMarquees();
	},
	//* Add _inControl_ to _this.marqueeWaitList_
	addMarqueeItem: function(inControl) {
		this.marqueeWaitList.push(inControl);
	},

	//* @protected

	//* Waterfall request for child animations to build up _this.marqueeWaitList_
	_marquee_buildWaitList: function() {
		this.marqueeWaitList = [];
		this.waterfall("onRequestMarquee", {originator: this, marqueePause: this.marqueePause, marqueeSpeed: this.marqueeSpeed});
	},
	//* Waterfall event to kick off child marquee animations
	_marquee_startChildMarquees: function() {
		this.waterfall("onRequestMarqueeStart");
	},
	//* Waterfall event to halt child marquee animations
	_marquee_stopChildMarquees: function() {
		this.waterfall("onRequestMarqueeStop");
	},
	//* Begin delayed restart of child marquee animations
	_marquee_startHold: function() {
		this.startJob("marqueeSupportJob", "startMarquee", this.marqueeHold);
	}
};

/**
	@public

	The _moon.MarqueeSupport_ mixin is used to add marquee animation functionality
	to a control.
*/
moon.MarqueeItem = {
	events: {
		onMarqueeEnded:""
	},
	//* @protected
	handlers: {
		onRequestMarquee: "_marquee_requestMarquee",
		onRequestMarqueeStart: "_marquee_startAnimation",
		onRequestMarqueeStop: "_marquee_stopAnimation",
		ontransitionend: "_marquee_animationEnded"
	},
	observers: {
		_marquee_contentChanged: ["content"]
	},
	classes: "moon-marquee",
	//* When the content of this control changes, update the content of _this.$.marqueeText_ (if it exists)
	_marquee_contentChanged: function() {
		if (this.$.marqueeText) {
			this.$.marqueeText.setContent(this.content);
		}
	},
	//* If this control needs to marquee, let the event originator know
	_marquee_requestMarquee: function(inSender, inEvent) {
		if (!inEvent || !this._marquee_shouldAnimate()) {
			return;
		}

		inEvent.originator.addMarqueeItem(this);

		this.marqueePause = inEvent.marqueePause || 1000;
		this.marqueeSpeed = inEvent.marqueeSpeed || 60;
	},
	//* Start marquee animation
	_marquee_startAnimation: function() {
		var distance = this._marquee_calcDistance();

		// If there is no need to animate, return early
		if (!this._marquee_shouldAnimate(distance)) {
			return;
		}

		// Lazy creation of _this.$.marqueeText_
		if (!this.$.marqueeText) {
			this._marquee_createMarquee();
		}

		this._marquee_addAnimationStyles(distance);
		return true;
	},
	//* Stop marquee animation
	_marquee_stopAnimation: function(inSender, inEvent) {
		this.stopJob("stopMarquee");
		this._marquee_removeAnimationStyles();
		this.doMarqueeEnded();
	},
	//* When animation ends, start _this.stopMarquee_ job
	_marquee_animationEnded: function(inSender, inEvent) {
		if (inEvent.originator !== this.$.marqueeText) {
			return;
		}

		this.startJob("stopMarquee", "_marquee_stopAnimation", this.marqueePause);
        return true;
	},
	//* Return _true_ if this control has enough content that it needs to animate
	_marquee_shouldAnimate: function(inDistance) {
		inDistance = (inDistance && inDistance >= 0) ? inDistance : this._marquee_calcDistance();
		return (!this.disabled && inDistance > 0);
	},
	//* Determine how far the marquee needs to scroll
	_marquee_calcDistance: function() {
		var node = this._marquee_getMarqueeNode() || this.hasNode();
		return node.scrollWidth - node.clientWidth;
	},
	//* Return duration based on _inDistance_ and _this.marqueeSpeed_
	_marquee_calcDuration: function(inDistance) {
		return inDistance / this.marqueeSpeed;
	},
	//* Return the marquee-able node
	_marquee_getMarqueeNode: function() {
		this.marqueeNode = this.marqueeNode || (this.$.marqueeText ? this.$.marqueeText.hasNode() : null);
		return this.marqueeNode;
	},
	//* Create a marquee-able div inside of _this_
	_marquee_createMarquee: function() {
		this.createComponent({classes: "moon-marquee-text-wrapper", components: [{name: "marqueeText", classes: "moon-marquee-text", allowHtml: this.allowHtml, content: this.content}]});
		this.render();
		return true;
	},
	_marquee_addAnimationStyles: function(inDistance) {
		var duration = this._marquee_calcDuration(inDistance);

		this.$.marqueeText.addClass("animate-marquee");
		this.$.marqueeText.applyStyle("transition-duration", duration + "s");
		this.$.marqueeText.applyStyle("-webkit-transition-duration", duration + "s");

		// Need this timeout for FF!
		setTimeout(enyo.bind(this, function() {
			enyo.dom.transform(this.$.marqueeText, {translateX: (-1 * inDistance) + "px"});
		}), 100);
	},
	_marquee_removeAnimationStyles: function() {
		if (!this.$.marqueeText) {
			return;
		}

		this.$.marqueeText.applyStyle("transition-duration", "0s");
		this.$.marqueeText.applyStyle("-webkit-transition-duration", "0s");

		// Need this timeout for FF!
		setTimeout(enyo.bind(this, function() {
			this.$.marqueeText.removeClass("animate-marquee");
			enyo.dom.transform(this.$.marqueeText, {translateX: null});
		}), 0);
	}
};

//* @public
enyo.kind({
	name: "moon.MarqueeDecorator",
	//* @protected
	mixins: ["moon.MarqueeSupport"],
	style: "overflow: hidden;"
});
<commit_msg>Fix RTL support for marquee.<commit_after>/**
	_moon.MarqueeText_ is a basic text control that supports marquee animation.
	When _moon.MarqueeText_ objects are used inside a
	[moon.MarqueeDecorator](#moon.MarqueeDecorator), the decorator synchronizes
	their start times; the user may start a marquee programmatically by calling
	_startMarquee()_.

		enyo.kind({
			name: "moon.Header",
			mixins: ["moon.MarqueeSupport"],
			marqueeSpeed: 100,
			components: [
				{kind: "moon.MarqueeText", content: "longText+longText"},
				{kind: "moon.MarqueeText", content: "longText"}
			],
			rendered: function() {
				this.startMarquee();
			}
		});

	To add the marquee feature to a kind, simply use the MarqueeSupport mixin:

		enyo.kind({
			name: "moon.MarqueeButton",
			kind: "enyo.Button",
			mixins: ["moon.MarqueeSupport"],
			components: [
				{kind:"moon.MarqueeText"}
			],
			contentChanged: function() {
				this.$.marqueeText.setContent(this.content);
			}
		});
*/

enyo.kind({
	name: "moon.MarqueeText",
	mixins: ["moon.MarqueeItem"],
	published: {
		//* Speed of marquee animation, in pixels per second
		marqueeSpeed: 60,
		/**
			Time in milliseconds that the marquee will pause at the end of the
			animation, before resetting to the beginning
		*/
		marqueePause: 1000,
		//* When true, marqueeing will not occur
		disabled: false
	}
});

/**
	@public

	The _moon.MarqueeSupport_ mixin should be used with controls that contain multiple marquees
	whose animation behavior should be synchronized. Calling _this.startMarquee()_ or
	_this.stopMarquee()_ starts/stops all contained marquees.
*/
moon.MarqueeSupport = {
	name: "MarqueeSupport",
	marqueeOnSpotlight: true,
	//* @protected
	handlers: {
		onSpotlightFocus: "_marquee_spotlightFocus",
		onSpotlightBlur: "_marquee_spotlightBlur",
		onMarqueeEnded: "_marquee_marqueeEnded",
		onresize: "_marquee_resize"
	},
	marqueeActive: false,
	//* Initialize marquee timings during _create_
	create: enyo.inherit(function (sup) {
		return function() {
			sup.apply(this, arguments);
			this.marqueeOnSpotlight = (this.marqueeOnSpotlight === undefined) ? true : this.marqueeOnSpotlight;
			this.marqueeSpeed =    (this.marqueeSpeed ===     undefined) ? 60 :    this.marqueeSpeed;
			this.marqueeDelay =    (this.marqueeDelay ===     undefined) ? 1000 :  this.marqueeDelay;
			this.marqueePause =    (this.marqueePause ===     undefined) ? 1000 :  this.marqueePause;
			this.marqueeHold  =    (this.marqueeHold  ===     undefined) ? 2000 :  this.marqueeHold;
			this.marqueeOnRender = (this.marqueeOnRender  === undefined) ? false : this.marqueeOnRender;
		};
	}),
	//* If _this.marqueeOnRender_ is true, kick off marquee animation
	rendered: enyo.inherit(function (sup) {
		return function() {
			sup.apply(this, arguments);
			if (this.marqueeOnRender) {
				this.startMarquee();
			}
		};
	}),
	//* On focus, start child marquees
	_marquee_spotlightFocus: function(inSender, inEvent) {
		if (this.marqueeOnSpotlight) {
			this.startMarquee();
		}
	},
	//* On blur, halt child marquees
	_marquee_spotlightBlur: function(inSender, inEvent) {
		if (this.marqueeOnSpotlight) {
			this.stopMarquee();
		}
	},
	//* When a child marquee animation completes, remove the child from _this.marqueeWaitList_
	_marquee_marqueeEnded: function(inSender, inEvent) {
		if (this.marqueeActive) {
			enyo.remove(inEvent.originator, this.marqueeWaitList);
			if (this.marqueeWaitList.length === 0) {
				this._marquee_startHold();
				this.marqueeActive = false;
			}
		}
		return true;
	},
	_marquee_resize: function(inSender, inEvent) {
		if (this.marqueeOnSpotlight) {
			this._marquee_startHold();
		}
	},

	//* @public

	//* Start timer to waterfall an _onRequestMarqueeStart_ event that kicks off marquee animation on all child marquees
	startMarquee: function() {
		this._marquee_buildWaitList();

		if (this.marqueeWaitList.length === 0) {
			return;
		}

		this.marqueeActive = true;
		this.startJob("marqueeSupportJob", "_marquee_startChildMarquees", this.marqueeDelay);
	},
	//* Waterfall an _onRequestMarqueeStop_ event to halt all running child marquees
	stopMarquee: function() {
		this.stopJob("marqueeSupportJob");
		this.marqueeActive = false;
		this._marquee_stopChildMarquees();
	},
	//* Add _inControl_ to _this.marqueeWaitList_
	addMarqueeItem: function(inControl) {
		this.marqueeWaitList.push(inControl);
	},

	//* @protected

	//* Waterfall request for child animations to build up _this.marqueeWaitList_
	_marquee_buildWaitList: function() {
		this.marqueeWaitList = [];
		this.waterfall("onRequestMarquee", {originator: this, marqueePause: this.marqueePause, marqueeSpeed: this.marqueeSpeed});
	},
	//* Waterfall event to kick off child marquee animations
	_marquee_startChildMarquees: function() {
		this.waterfall("onRequestMarqueeStart");
	},
	//* Waterfall event to halt child marquee animations
	_marquee_stopChildMarquees: function() {
		this.waterfall("onRequestMarqueeStop");
	},
	//* Begin delayed restart of child marquee animations
	_marquee_startHold: function() {
		this.startJob("marqueeSupportJob", "startMarquee", this.marqueeHold);
	}
};

/**
	@public

	The _moon.MarqueeSupport_ mixin is used to add marquee animation functionality
	to a control.
*/
moon.MarqueeItem = {
	events: {
		onMarqueeEnded:""
	},
	//* @protected
	handlers: {
		onRequestMarquee: "_marquee_requestMarquee",
		onRequestMarqueeStart: "_marquee_startAnimation",
		onRequestMarqueeStop: "_marquee_stopAnimation",
		ontransitionend: "_marquee_animationEnded"
	},
	observers: {
		_marquee_contentChanged: ["content"]
	},
	classes: "moon-marquee",
	//* When the content of this control changes, update the content of _this.$.marqueeText_ (if it exists)
	_marquee_contentChanged: function() {
		if (this.$.marqueeText) {
			this.$.marqueeText.setContent(this.content);
		}
	},
	//* If this control needs to marquee, let the event originator know
	_marquee_requestMarquee: function(inSender, inEvent) {
		if (!inEvent || !this._marquee_shouldAnimate()) {
			return;
		}

		inEvent.originator.addMarqueeItem(this);

		this.marqueePause = inEvent.marqueePause || 1000;
		this.marqueeSpeed = inEvent.marqueeSpeed || 60;
	},
	//* Start marquee animation
	_marquee_startAnimation: function(inSender, inEvent) {
		var distance = this._marquee_calcDistance();

		// If there is no need to animate, return early
		if (!this._marquee_shouldAnimate(distance)) {
			return;
		}

		// Lazy creation of _this.$.marqueeText_
		if (!this.$.marqueeText) {
			this._marquee_createMarquee();
		}

		this._marquee_addAnimationStyles(distance);
		return true;
	},
	//* Stop marquee animation
	_marquee_stopAnimation: function(inSender, inEvent) {
		this.stopJob("stopMarquee");
		this._marquee_removeAnimationStyles();
		this.doMarqueeEnded();
	},
	//* When animation ends, start _this.stopMarquee_ job
	_marquee_animationEnded: function(inSender, inEvent) {
		if (inEvent.originator !== this.$.marqueeText) {
			return;
		}

		this.startJob("stopMarquee", "_marquee_stopAnimation", this.marqueePause);
        return true;
	},
	//* Return _true_ if this control has enough content that it needs to animate
	_marquee_shouldAnimate: function(inDistance) {
		inDistance = (inDistance && inDistance >= 0) ? inDistance : this._marquee_calcDistance();
		return (!this.disabled && inDistance > 0);
	},
	//* Determine how far the marquee needs to scroll
	_marquee_calcDistance: function() {
		var node = this._marquee_getMarqueeNode() || this.hasNode(),
			distance = Math.abs(node.scrollWidth - node.clientWidth);
		return distance;
	},
	//* Return duration based on _inDistance_ and _this.marqueeSpeed_
	_marquee_calcDuration: function(inDistance) {
		return inDistance / this.marqueeSpeed;
	},
	//* Return the marquee-able node
	_marquee_getMarqueeNode: function() {
		this.marqueeNode = this.marqueeNode || (this.$.marqueeText ? this.$.marqueeText.hasNode() : null);
		return this.marqueeNode;
	},
	//* Create a marquee-able div inside of _this_
	_marquee_createMarquee: function() {
		this.createComponent({classes: "moon-marquee-text-wrapper", components: [{name: "marqueeText", classes: "moon-marquee-text", allowHtml: this.allowHtml, content: this.content}]});
		this.render();
		return true;
	},
	_marquee_addAnimationStyles: function(inDistance) {
		var duration = this._marquee_calcDuration(inDistance);

		this.$.marqueeText.addClass("animate-marquee");
		this.$.marqueeText.applyStyle("transition-duration", duration + "s");
		this.$.marqueeText.applyStyle("-webkit-transition-duration", duration + "s");

		// Need this timeout for FF!
		setTimeout(enyo.bind(this, function() {
			enyo.dom.transform(this.$.marqueeText, {translateX: this._marquee_adjustDistanceForRTL(inDistance) + "px"});
		}), 100);
	},
	_marquee_removeAnimationStyles: function() {
		if (!this.$.marqueeText) {
			return;
		}

		this.$.marqueeText.applyStyle("transition-duration", "0s");
		this.$.marqueeText.applyStyle("-webkit-transition-duration", "0s");

		// Need this timeout for FF!
		setTimeout(enyo.bind(this, function() {
			this.$.marqueeText.removeClass("animate-marquee");
			enyo.dom.transform(this.$.marqueeText, {translateX: null});
		}), 0);
	},
	//* Flip distance value for RTL support
	_marquee_adjustDistanceForRTL: function(inDistance) {
		return this.rtl ? inDistance : inDistance * -1;
	}
};

//* @public
enyo.kind({
	name: "moon.MarqueeDecorator",
	//* @protected
	mixins: ["moon.MarqueeSupport"],
	style: "overflow: hidden;"
});
<|endoftext|>


<commit_before>window.urb.seqn_s = 0
window.urb.cabs = {}

window.urb.send = function(params,cb) {
  if(!params)
    throw new Error("You must supply params to urb.send.")
  if(!params.appl)
    throw new Error("You must specify an appl for urb.send.")
  if(!params.data) { params.data = {}; }

  var method, perm, url, $this

  type = params.type ? params.type : "mes"
  perm = this.perms[type]

  params.ship = params.ship ? params.ship : this.ship

  method = "put"
  url = [perm,this.user,this.port,this.seqn_s]
  url = "/"+url.join("/")

  this.seqn_s++

  $this = this
  this.qreq(method,url,params,true,function(err,data) {
    if(err) { $this.seqn_s--; }
    if(cb) { cb.apply(this,arguments); }
  })
}

window.urb.subscribe = function(params,cb) {
  if(!cb)
    throw new Error("You must supply a callback to urb.subscribe.")
  if(!params)
    throw new Error("You must supply params to urb.subscribe.")
  if(!params.appl)
    throw new Error("You must specify an appl for urb.subscribe.")
  if(!params.path)
    throw new Error("You must specify a path for urb.subscribe.")
  params.ship = params.ship ? params.ship : this.ship

  var method, perm, url, $this

  params.type = "sub"

  this.cabs[this.gsig(params)] = cb

  url = [this.perms["sub"],this.user,this.port]
  url = "/"+url.join("/")
  method = "put"

  $this = this
  this.qreq(method,url,params,true,function(err,data) {
    if(cb) { cb.apply(this,[err,{status: data.status, data: data.data}])}
    if(!err && $this.puls == 0) {
      params.type = "pol"
      $this.poll(params)
    }
  })
}

window.urb.unsubscribe = function(params,cb) {
  if(!params)
    throw new Error("You must supply params to urb.unsubscribe.")
  if(!params.appl)
    throw new Error("You must specify an appl for urb.unsubscribe.")
  if(!params.path)
    throw new Error("You must specify a path for urb.unsubscribe.")
  params.ship = params.ship ? params.ship : this.ship

  method = "put"
  type = "uns"
  url = [this.perms[type],this.user,this.port]
  url = "/"+url.join("/")

  var $this = this
  this.req(method,url,params,true,function(err,data) {
    $this.cabs[$this.gsig(params)]('subscription closed')
    delete $this.cabs[$this.gsig(params)]
  })
}
<commit_msg>Made appl optional if set globally on window.urb<commit_after>window.urb.seqn_s = 0
window.urb.cabs = {}

window.urb.send = function(params,cb) {
  if(!params)
    throw new Error("You must supply params to urb.send.")
  if(!params.appl)
    if(!urb.appl)
      throw new Error("You must specify an appl for urb.send.")
    params.appl = urb.appl
  if(!params.data) { params.data = {}; }

  var method, perm, url, $this

  type = params.type ? params.type : "mes"
  perm = this.perms[type]

  params.ship = params.ship ? params.ship : this.ship

  method = "put"
  url = [perm,this.user,this.port,this.seqn_s]
  url = "/"+url.join("/")

  this.seqn_s++

  $this = this
  this.qreq(method,url,params,true,function(err,data) {
    if(err) { $this.seqn_s--; }
    if(cb) { cb.apply(this,arguments); }
  })
}

window.urb.subscribe = function(params,cb) {
  if(!cb)
    throw new Error("You must supply a callback to urb.subscribe.")
  if(!params)
    throw new Error("You must supply params to urb.subscribe.")
  if(!params.appl)
    if(!urb.appl)
      throw new Error("You must specify an appl for urb.subscribe.")
    params.appl = urb.appl
  if(!params.path)
    throw new Error("You must specify a path for urb.subscribe.")
  params.ship = params.ship ? params.ship : this.ship

  var method, perm, url, $this

  params.type = "sub"

  this.cabs[this.gsig(params)] = cb

  url = [this.perms["sub"],this.user,this.port]
  url = "/"+url.join("/")
  method = "put"

  $this = this
  this.qreq(method,url,params,true,function(err,data) {
    if(cb) { cb.apply(this,[err,{status: data.status, data: data.data}])}
    if(!err && $this.puls == 0) {
      params.type = "pol"
      $this.poll(params)
    }
  })
}

window.urb.unsubscribe = function(params,cb) {
  if(!params)
    throw new Error("You must supply params to urb.unsubscribe.")
  if(!params.appl)
    if(!urb.appl )
      throw new Error("You must specify an appl for urb.unsubscribe.")
    params.appl = urb.appl
  if(!params.path)
    throw new Error("You must specify a path for urb.unsubscribe.")
  params.ship = params.ship ? params.ship : this.ship

  method = "put"
  type = "uns"
  url = [this.perms[type],this.user,this.port]
  url = "/"+url.join("/")

  var $this = this
  this.req(method,url,params,true,function(err,data) {
    $this.cabs[$this.gsig(params)]('subscription closed')
    delete $this.cabs[$this.gsig(params)]
  })
}
<|endoftext|>


<commit_before>//——————————————————————————————————新窗口浏览主题——————————————————————————————————

    var nwe_window;
    chrome.runtime.sendMessage({get_newWindow_status: 't'}, function(response) {
        if ( response.newWindow_status ){
            $('.item_title a').attr('target', '_blank');
            nwe_window = "target='_blank'";
        }
    });

//——————————————————————————————————新窗口浏览主题——————————————————————————————————

//——————————————————————————————————预览功能——————————————————————————————————

    chrome.runtime.sendMessage({get_preview_status: 't'}, function(response) {
        if ( !response.preview_status ){
            $('div#Main > div:nth-of-type(2) .cell').each(function(){
                if($(this).find('.fade').text().indexOf('...')!=-1){
                    return ;
                }
                $(this).find('.fade').append("  •  预览");
            });
        }

        var btn_id = 0;
        $('.preview').click(function(){
            var _this = $(this);
            var _cell = _this.parents(".cell");
            if (_this.text() == '预览'){
                _this.text('加载中...');
                _cell.after("

");
                var _href = _cell.find('.item_title a').attr('href');
                $.get(_href, function(data){
                    var _previewWindow = _cell.next('.previewWindow');
                    data = data.substr(data.indexOf("header")+8);
                    //当匹配不到topic_conten时返回-1 substring 按0处理，既显示整个标题头部
                    data = data.substring(data.indexOf("
"), data.indexOf("
"));
                    data = data.replace('hljs.initHighlightingOnLoad();', '');
                    _this.addClass('btn_id'+btn_id);
                    _previewWindow.html(data+"
\
                                                详细\
                                                收起\
                                                \

");
                    var _next_cell = _previewWindow.next();
                    _next_cell.css('borderTop', _next_cell.css('borderBottom'));
                    _this.text('收起');
                    _previewWindow.slideDown(800);

                });
            }else{
                _this.text('预览');
                var _previewWindow = _cell.next('.previewWindow');
                setTimeout(function(){
                    _previewWindow.next().css('borderTop', 'none');
                    _previewWindow.remove();
                },800);
                _previewWindow.slideUp(800);
            }
        });

    });

//——————————————————————————————————预览功能——————————————————————————————————

//——————————————————————————————————一键领取登陆奖励——————————————————————————————————

    var _mission_btn = $('div#Rightbar > div:nth-of-type(4) a');
    if ( _mission_btn.text() == '领取今日的登录奖励' ){
        _mission_btn.attr('href', "/mission/daily/redeem" + RegExp("/signout(\\?once=[0-9]+)").exec($('div#Top').html())[1]);
        _mission_btn.html('一键领取今日的登录奖励 by vPlus
Take your passion and make it come true. ')
    }

//——————————————————————————————————一键领取登陆奖励——————————————————————————————————<commit_msg>Gift ClickOnce<commit_after>//——————————————————————————————————新窗口浏览主题——————————————————————————————————

    var nwe_window;
    chrome.runtime.sendMessage({get_newWindow_status: 't'}, function(response) {
        if ( response.newWindow_status ){
            $('.item_title a').attr('target', '_blank');
            nwe_window = "target='_blank'";
        }
    });

//——————————————————————————————————新窗口浏览主题——————————————————————————————————

//——————————————————————————————————预览功能——————————————————————————————————

    chrome.runtime.sendMessage({get_preview_status: 't'}, function(response) {
        if ( !response.preview_status ){
            $('div#Main > div:nth-of-type(2) .cell').each(function(){
                if($(this).find('.fade').text().indexOf('...')!=-1){
                    return ;
                }
                $(this).find('.fade').append("  •  预览");
            });
        }

        var btn_id = 0;
        $('.preview').click(function(){
            var _this = $(this);
            var _cell = _this.parents(".cell");
            if (_this.text() == '预览'){
                _this.text('加载中...');
                _cell.after("

");
                var _href = _cell.find('.item_title a').attr('href');
                $.get(_href, function(data){
                    var _previewWindow = _cell.next('.previewWindow');
                    data = data.substr(data.indexOf("header")+8);
                    //当匹配不到topic_conten时返回-1 substring 按0处理，既显示整个标题头部
                    data = data.substring(data.indexOf("
"), data.indexOf("
"));
                    data = data.replace('hljs.initHighlightingOnLoad();', '');
                    _this.addClass('btn_id'+btn_id);
                    _previewWindow.html(data+"
\
                                                详细\
                                                收起\
                                                \

");
                    var _next_cell = _previewWindow.next();
                    _next_cell.css('borderTop', _next_cell.css('borderBottom'));
                    _this.text('收起');
                    _previewWindow.slideDown(800);

                });
            }else{
                _this.text('预览');
                var _previewWindow = _cell.next('.previewWindow');
                setTimeout(function(){
                    _previewWindow.next().css('borderTop', 'none');
                    _previewWindow.remove();
                },800);
                _previewWindow.slideUp(800);
            }
        });

    });

//——————————————————————————————————预览功能——————————————————————————————————

//——————————————————————————————————一键领取登陆奖励——————————————————————————————————

    var _mission_btn = $('div#Rightbar > div:nth-of-type(4) a');
    if ( _mission_btn.text() == '领取今日的登录奖励' ){
        // _mission_btn.attr('href', "/mission/daily/redeem" + RegExp("/signout(\\?once=[0-9]+)").exec($('div#Top').html())[1]);
        _mission_btn.html('一键领取今日的登录奖励 by vPlus
Take your passion and make it come true. ')
    }

    //Enable Gift ClickOnce Feature
    //From v2excellent.js
    $('a[href="/mission/daily"]')
    .attr('id', 'gift_v2excellent')
    .attr('href', '#')
    .click(function() {
        $('#gift_v2excellent').text('正在领取......');
        giftLink = ("/mission/daily/redeem" + RegExp("/signout(\\?once=[0-9]+)").exec($('div#Top').html())[1]);
        $.get(giftLink, function(checkResult) {
            var okSign = $('<output>')
            .append($.parseHTML(checkResult))
            .find('li.fa.fa-ok-sign');
            if (okSign.length > 0) {
            $.get('/balance', function(result) {
                var amount = $('<output>')
                .append($.parseHTML(result))
                .find('table>tbody>tr:contains("每日登录"):first>td:nth(2)')
                .text();
                $('#gift_v2excellent').html(
                '已领取 ' + amount + ' 铜币。'
                );
                setTimeout(function() {
                $('#Rightbar>.sep20:nth(1)').remove();
                $('#Rightbar>.box:nth(1)').remove();
                }, 2000);
            });
            }
        });
        return false;
    });
//——————————————————————————————————一键领取登陆奖励——————————————————————————————————<|endoftext|>


<commit_before>(function () {
  'use strict';

  function debug() {
    //console.log(arguments);
  }

  function skip() {}

  var states = {
    PENDING: 0,
    FULFILLED: 1,
    REJECTED: 2
  };
  var nextValue = {};
  var vPromise = function (fn) {
    this._state = states.PENDING;
    this.value = null;
    this._resolveChain = [];
    this.nextValue = null;
    var that = this;

    var onFulfilled = function (resolve, val) {
      if (typeof resolve !== 'function') { // 2.2.1
        return;
      }

      if (that._state !== states.PENDING) {
        that._state = states.FULFILLED;
        that.nextValue = resolve(val);
      }
    };

    var onReject = function (reject, reason) {
      if (typeof reject !== 'function') { // 2.2.1
        return;
      }
      if (that._state !== states.PENDING && that._state !== states.FULFILLED) {
        that._state = states.REJECTED;
        reject(reason);
      }
    };

    var handle = function (resolve, reject) {
      if (that._state === states.PENDING) {
        return;
      }

      var val = that.value;
      setTimeout(function () {
          try {
            fn(onFulfilled(resolve,val), onReject(reject, that.reason));
          } catch (e) {
            debug(e);
          }
      }, 1);
    };

    if (fn !== skip) {
      fn(function (value) {
        that.value = value;
        setTimeout(function () {
          if (that._state !== states.PENDING) {
            return;
          }
          var ii;
          var chainLength = that._resolveChain.length;
          for (ii = 0; ii < chainLength; ii++) {
            try {
              that._resolveChain[ii](value);
            } catch (e) {}
          }
          that._resolve(value);
          that._state = states.FULFILLED;
         }, 1);
      },
      function (reason) {
        that.reason = reason;
        setTimeout(function () {
          if (that._state !== states.PENDING) {
            return;
          }
          that._reject(reason);
          that._state = states.REJECTED;
         }, 1);
      });
    }

    this.then = function (resolve, reject) {
      if (that._state === states.PENDING) {
        if (typeof that._resolve == "function") {
          that._resolveChain.push(that._resolve);
        }
        that._resolve = resolve;
        that._reject = reject;
        return;
      }

      var next = new vPromise(fn);
      handle(resolve, reject);
      next._state = -1; // placeholder
      return next;
    };

    this.catch = function (fn) {
    };

    return this;
  };

  vPromise.resolve = function (value) {
    var skipped = new vPromise(skip);
    return doResolve(skipped, value);
  };

  function doResolve(skipped, value) {
    skipped._state = states.FULFILLED;
    skipped.value = value;
    return skipped;
  }

  vPromise.reject = function (reason) {
    var skipped = new vPromise(skip);
    return doReject(skipped, reason);
  };

  function doReject(skipped, reason) {
    skipped._state = states.REJECTED;
    skipped.reason = reason;
    return skipped;
  }

  if (typeof module != 'undefined') {
    module.exports = vPromise;
  }

}());
<commit_msg>Cleanup to last most working condition before refactoring.<commit_after>(function () {
  'use strict';

  function debug() {
    console.log(arguments);
  }

  function skip() {}

  var states = {
    PENDING: 0,
    FULFILLED: 1,
    REJECTED: 2
  };

  function asap(cb) {
    setTimeout(cb, 1);
  }

  var vPromise = function (fn) {
    this._state = states.PENDING;
    this.value = null;
    this._resolveChain = [];

    var that = this;

    var onFulfilled = function (resolve, val) {
      if (typeof resolve !== 'function') { // 2.2.1
        return;
      }
      var ii;
      var chainLength = that._resolveChain.length;
      for (ii = 0; ii < chainLength; ii++) {
        try {
          that._resolveChain[ii](val);
        } catch (e) {}
      }
      resolve(val);
      if (that._state !== states.PENDING) {
        that._state = states.FULFILLED;
      }
    };

    var onReject = function (reject, reason) {
      if (typeof reject !== 'function') { // 2.2.1
        return;
      }
      if (that._state !== states.PENDING && that._state !== states.FULFILLED) {
        that._state = states.REJECTED;
        reject(reason);
      }
    };

    var handle = function (resolve, reject) {
      if (that._state === states.PENDING) {
        return;
      }

      var val = that.value;
      asap(function () {
          try {
            fn(onFulfilled(resolve,val), onReject(reject, that.reason));
          } catch (e) {
            debug(e);
          }
      });
    };

    if (fn !== skip) {
      fn(function (value) {
        that.value = value;
        asap(function () {
          if (that._state !== states.PENDING) {
            return;
          }
          var ii;
          var chainLength = that._resolveChain.length;
          for (ii = 0; ii < chainLength; ii++) {
            try {
              that._resolveChain[ii](value);
            } catch (e) {}
          }
          that._resolve(value);
          that._state = states.FULFILLED;
         });
      },
      function (reason) {
        that.reason = reason;
        asap(function () {
          if (that._state !== states.PENDING) {
            return;
          }
          that._reject(reason);
          that._state = states.REJECTED;
         });
      });
    }

    this.then = function (resolve, reject) {
      if (that._state === states.PENDING) {
        if (typeof that._resolve == "function") {
          that._resolveChain.push(that._resolve);
        }
        that._resolve = resolve;
        that._reject = reject;
        return;
      }

      var next = new vPromise(fn);
      handle(resolve, reject);
      next._state = -1; // placeholder
      return next;
    };

    return this;
  };

  vPromise.resolve = function (value) {
    var skipped = new vPromise(skip);
    return doResolve(skipped, value);
  };

  function doResolve(skipped, value) {
    skipped._state = states.FULFILLED;
    skipped.value = value;
    return skipped;
  }

  vPromise.reject = function (reason) {
    var skipped = new vPromise(skip);
    return doReject(skipped, reason);
  };

  function doReject(skipped, reason) {
    skipped._state = states.REJECTED;
    skipped.reason = reason;
    return skipped;
  }

  if (typeof module != 'undefined') {
    module.exports = vPromise;
  }

}());
<|endoftext|>


<commit_before>/*
   Copyright 2014-2015 CLEARWAVE DESIGNS, LLC

      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.

   Author:        Adam Carson
   Website:       http://clearwavedesigns.com
   Dependencies:  None.

   Name(s):       FlagstoneJS (flagstone.js)
   Version:       2.1.20151017
   Slogan:        "Responsive tiling."
   Description:   Responsively tiles HTML elements left or right, top to bottom, and where there's the most room.
 */

function FLAGSTONE(settings) {

  var _ = function(s) { var a = [], nl = document.querySelectorAll(s); for (var i = 0, l = nl.length; i < l; i++) { a[i] = nl[i]; } return a.length > 1 ? a : a[0]; };

  var o = settings || {};
  // AREA (CONTAINER)
  var areaStr = o.area || '[flagstones]';
  var area = _(areaStr);
  var areaMargin = o.margin || o.margin === 0 ? o.margin : o.areaMargin || o.areaMargin === 0 ? o.areaMargin : 10;
  var areaWidth = 0;
  var areaHeight = 0;
  // MIN WIDTH
  var minWidth = o.minWidth || 280;
  // COLUMNS
  var maxColumns = o.maxColumns || 1920;
  var calcColumns = 0;
  var columns = 0;
  // FLAGSTONES
  var flagstonesStr = o.flagstones || '[flagstone]';
  var flagstones = _(flagstonesStr);
  var flagstonesMargin = o.margin || o.margin === 0 ? o.margin : o.flagstonesMargin || o.flagstonesMargin === 0 ? o.flagstonesMargin : 10;
  var flagstoneWidth = (areaWidth / columns) - ((flagstonesMargin * (columns + 1)) / columns);
  var flagstoneHeights = [];
  // DIRECTION
  var direction = o.direction ? o.direction.toLowerCase() : 'left';
  // RANDOM POSITIONS
  var random = o.random ? (flagstones.sort(function(){ return 0.5-Math.random(); }), true) : false;
  // RANDOM SPACE FREQUENCY
  var spaceFrequency = o.spaceFrequency || 0.4;
  // RANDOM SPACE GENERATOR
  var spaceGenerator = function() {
    for (var i = 0, l = flagstones.length; i < l; i++) {
      if (Math.random() < spaceFrequency) {
        flagstones.splice(i, 0, false); // Inject an element with the boolean "false"
      }
    }
  };
  // RANDOM SPACE
  var space = o.space ? (spaceGenerator(), true) : false;
  // ANIMATION
  var duration = o.duration / 1000 || 0;
  // RESIZE/RESET DELAY
  var resizeDelay = o.resizeDelay || o.resizeDelay === 0 ? o.resizeDelay : 250;
  // SQUARE
  var square = o.square || false;
  // HIDE (for Developers as well when then are injecting new content onto their page, so they can hide the flagstones before they get a change to re-calculate);
  this.hide = function() {
    area.className = area.className + ' flagstones-hidden';
  };
  // CUSTOM
  var custom = o.custom || function() { return false; };

  // RUN
  var run = function() {
    var columnHeights = [columns];
    for (var i = 0, l = flagstoneHeights.length; i < l; i++) {
      if (i < columns) {
        // First "row"
        if (flagstones[i]) {
          var width = flagstones[i].style.cssText.replace(/.*width\:\s?(\d+).+/, '$1');
          flagstones[i].style = '';
          flagstones[i].style.cssText = 'width:' + width + 'px;' + (square ? 'height:' + width + 'px;': '') + 'top:' + areaMargin + 'px;' + direction + ':' + (flagstoneWidth * i + (i ? flagstonesMargin * i + areaMargin : areaMargin)) + 'px;';
          columnHeights[i] = flagstoneHeights[i] + areaMargin;
          custom(i, flagstones[i]);
        } else {
          if (columns > 1) {
            columnHeights[i] = flagstoneWidth + areaMargin;
          }
        }
      } else {
        // Every other "row"
        var smallestColumnHeight = Math.min.apply(null, columnHeights);
        var smallestColumn = columnHeights.indexOf(smallestColumnHeight);
        if (flagstones[i]) {
          var width = flagstones[i].style.cssText.replace(/.*width\:\s?(\d+).+/, '$1');
          flagstones[i].style = '';
          flagstones[i].style.cssText = 'width:' + width + 'px;' + (square ? 'height:' + width + 'px;': '') + 'top:' + (smallestColumnHeight + flagstonesMargin) + 'px;' + direction + ':' + (flagstoneWidth * smallestColumn + (smallestColumn ? flagstonesMargin * smallestColumn + areaMargin : areaMargin)) + 'px;';
          columnHeights[smallestColumn] += flagstoneHeights[i] + flagstonesMargin;
          custom(i, flagstones[i]);
        } else {
          if (columns > 1) {
            columnHeights[smallestColumn] += flagstoneWidth + flagstonesMargin;
          }
        }
      }
      area.style.height = (Math.max.apply(null, columnHeights) || flagstoneHeights[0] + areaMargin) + areaMargin + 'px';
    }
    setTimeout(function() {
      area.className = area.className.replace(/\s?flagstones\-hidden/, '');
    }.bind(this), 0);
  }; // end run()
  // RESIZE AND RESET
  var resetDelay1;
  var resetDelay2;
  var resetDelay3;
  this.reset = function() {
    // Set area
    areaWidth = area.outerWidth || area.offsetWidth;
    if (areaWidth < minWidth + (areaMargin ? areaMargin * 2 : 0)) {
      areaWidth = minWidth;
    }
    // Set widths
    calcColumns = Math.floor(areaWidth / minWidth);
    columns = calcColumns > maxColumns ? maxColumns : calcColumns;
    flagstoneWidth = (areaWidth / columns) - ((flagstonesMargin * (columns - 1) + (areaMargin * 2)) / columns);
    // Set heights
    flagstoneHeights = [];
    for (var i = 0, l = flagstones.length; i < l; i++) {
      if (flagstones[i]) {
        flagstones[i].style.width = flagstoneWidth + 'px';
      }
      flagstoneHeights.push(square || !flagstones[i] ? flagstoneWidth : flagstones[i].outerHeight || flagstones[i].offsetHeight);
    }
    run();
  }.bind(this);
  // DYNAMIC CONTENT RESET / HARD RESET
  this.hardReset = function() {
    this.hide();
    setTimeout(function() {
      flagstones = _(flagstonesStr);
      if (random) { flagstones.sort(function(){return 0.5-Math.random();}); }
      if (space) { spaceGenerator(); }
      this.reset();
    }.bind(this), 0);
  }.bind(this);
  // RESETS (ADDRESSES ISSUES WITH POSITIONING WHEN CSS ANIMATIONS ARE USED, THAT'S WHY THERE ARE 3 RESETS)
  var resets = function() {
      clearTimeout(resetDelay1);
      clearTimeout(resetDelay2);
      clearTimeout(resetDelay3);
      resetDelay1 = setTimeout(this.reset.bind(this), resizeDelay);
      resetDelay2 = setTimeout(this.reset.bind(this), (duration * 1000) + resizeDelay);
      resetDelay3 = setTimeout(this.reset.bind(this), (duration * 2000) + resizeDelay);
  }.bind(this);
  // INITIALIZE
  (function() {
    this.hide;
    // Setup styles
    var styles = areaStr + '{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:relative;min-width:' + (minWidth + (flagstonesMargin * 2)) + 'px;}' + flagstonesStr + '{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;top:0px;' + direction + ':0px;}' + areaStr + '.flagstones-hidden{visibility:hidden;}</style>' + areaStr + '{-webkit-transition-duration:' + duration + 's;-moz-transition-duration:' + duration + 's;-ms-transition-duration:' + duration + 's;-o-transition-duration:' + duration + 's;transition-duration:' + duration + 's;}' + flagstonesStr + '{-webkit-transition-duration:' + duration + 's;-moz-transition-duration:' + duration + 's;-ms-transition-duration:' + duration + 's;-o-transition-duration:' + duration + 's;transition-duration:' + duration + 's;}';
    var style = document.createElement('style');
    style.type = 'text/css';
    style.appendChild(document.createTextNode(styles));
    _('head').appendChild(style);
    // Run reset to calculate and run flagstone!
    setTimeout(this.reset, 0);
    // Reset immediately after resources have loaded to get correct heights
    window.addEventListener('load', resets.bind(this));
    // Resize listener
    window.addEventListener('resize', resets.bind(this));
  }.bind(this))()
} // end FLAGSTONEJS
<commit_msg>Support strict mode<commit_after>/*
   Copyright 2014-2015 CLEARWAVE DESIGNS, LLC

      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.

   Author:        Adam Carson
   Website:       http://clearwavedesigns.com
   Dependencies:  None.

   Name(s):       FlagstoneJS (flagstone.js)
   Version:       2.1.20151017
   Slogan:        "Responsive tiling."
   Description:   Responsively tiles HTML elements left or right, top to bottom, and where there's the most room.
 */

function FLAGSTONE(settings) {

  var _ = function(s) { var a = [], nl = document.querySelectorAll(s); for (var i = 0, l = nl.length; i < l; i++) { a[i] = nl[i]; } return a.length > 1 ? a : a[0]; };

  var o = settings || {};
  // AREA (CONTAINER)
  var areaStr = o.area || '[flagstones]';
  var area = _(areaStr);
  var areaMargin = o.margin || o.margin === 0 ? o.margin : o.areaMargin || o.areaMargin === 0 ? o.areaMargin : 10;
  var areaWidth = 0;
  var areaHeight = 0;
  // MIN WIDTH
  var minWidth = o.minWidth || 280;
  // COLUMNS
  var maxColumns = o.maxColumns || 1920;
  var calcColumns = 0;
  var columns = 0;
  // FLAGSTONES
  var flagstonesStr = o.flagstones || '[flagstone]';
  var flagstones = _(flagstonesStr);
  var flagstonesMargin = o.margin || o.margin === 0 ? o.margin : o.flagstonesMargin || o.flagstonesMargin === 0 ? o.flagstonesMargin : 10;
  var flagstoneWidth = (areaWidth / columns) - ((flagstonesMargin * (columns + 1)) / columns);
  var flagstoneHeights = [];
  // DIRECTION
  var direction = o.direction ? o.direction.toLowerCase() : 'left';
  // RANDOM POSITIONS
  var random = o.random ? (flagstones.sort(function(){ return 0.5-Math.random(); }), true) : false;
  // RANDOM SPACE FREQUENCY
  var spaceFrequency = o.spaceFrequency || 0.4;
  // RANDOM SPACE GENERATOR
  var spaceGenerator = function() {
    for (var i = 0, l = flagstones.length; i < l; i++) {
      if (Math.random() < spaceFrequency) {
        flagstones.splice(i, 0, false); // Inject an element with the boolean "false"
      }
    }
  };
  // RANDOM SPACE
  var space = o.space ? (spaceGenerator(), true) : false;
  // ANIMATION
  var duration = o.duration / 1000 || 0;
  // RESIZE/RESET DELAY
  var resizeDelay = o.resizeDelay || o.resizeDelay === 0 ? o.resizeDelay : 250;
  // SQUARE
  var square = o.square || false;
  // HIDE (for Developers as well when then are injecting new content onto their page, so they can hide the flagstones before they get a change to re-calculate);
  this.hide = function() {
    area.className = area.className + ' flagstones-hidden';
  };
  // CUSTOM
  var custom = o.custom || function() { return false; };

  // RUN
  var run = function() {
    var columnHeights = [columns];
    for (var i = 0, l = flagstoneHeights.length; i < l; i++) {
      if (i < columns) {
        // First "row"
        if (flagstones[i]) {
          var width = flagstones[i].style.cssText.replace(/.*width\:\s?(\d+).+/, '$1');
          flagstones[i].style.cssText = 'width:' + width + 'px;' + (square ? 'height:' + width + 'px;': '') + 'top:' + areaMargin + 'px;' + direction + ':' + (flagstoneWidth * i + (i ? flagstonesMargin * i + areaMargin : areaMargin)) + 'px;';
          columnHeights[i] = flagstoneHeights[i] + areaMargin;
          custom(i, flagstones[i]);
        } else {
          if (columns > 1) {
            columnHeights[i] = flagstoneWidth + areaMargin;
          }
        }
      } else {
        // Every other "row"
        var smallestColumnHeight = Math.min.apply(null, columnHeights);
        var smallestColumn = columnHeights.indexOf(smallestColumnHeight);
        if (flagstones[i]) {
          var width = flagstones[i].style.cssText.replace(/.*width\:\s?(\d+).+/, '$1');
          flagstones[i].style.cssText = 'width:' + width + 'px;' + (square ? 'height:' + width + 'px;': '') + 'top:' + (smallestColumnHeight + flagstonesMargin) + 'px;' + direction + ':' + (flagstoneWidth * smallestColumn + (smallestColumn ? flagstonesMargin * smallestColumn + areaMargin : areaMargin)) + 'px;';
          columnHeights[smallestColumn] += flagstoneHeights[i] + flagstonesMargin;
          custom(i, flagstones[i]);
        } else {
          if (columns > 1) {
            columnHeights[smallestColumn] += flagstoneWidth + flagstonesMargin;
          }
        }
      }
      area.style.height = (Math.max.apply(null, columnHeights) || flagstoneHeights[0] + areaMargin) + areaMargin + 'px';
    }
    setTimeout(function() {
      area.className = area.className.replace(/\s?flagstones\-hidden/, '');
    }.bind(this), 0);
  }; // end run()
  // RESIZE AND RESET
  var resetDelay1;
  var resetDelay2;
  var resetDelay3;
  this.reset = function() {
    // Set area
    areaWidth = area.outerWidth || area.offsetWidth;
    if (areaWidth < minWidth + (areaMargin ? areaMargin * 2 : 0)) {
      areaWidth = minWidth;
    }
    // Set widths
    calcColumns = Math.floor(areaWidth / minWidth);
    columns = calcColumns > maxColumns ? maxColumns : calcColumns;
    flagstoneWidth = (areaWidth / columns) - ((flagstonesMargin * (columns - 1) + (areaMargin * 2)) / columns);
    // Set heights
    flagstoneHeights = [];
    for (var i = 0, l = flagstones.length; i < l; i++) {
      if (flagstones[i]) {
        flagstones[i].style.width = flagstoneWidth + 'px';
      }
      flagstoneHeights.push(square || !flagstones[i] ? flagstoneWidth : flagstones[i].outerHeight || flagstones[i].offsetHeight);
    }
    run();
  }.bind(this);
  // DYNAMIC CONTENT RESET / HARD RESET
  this.hardReset = function() {
    this.hide();
    setTimeout(function() {
      flagstones = _(flagstonesStr);
      if (random) { flagstones.sort(function(){return 0.5-Math.random();}); }
      if (space) { spaceGenerator(); }
      this.reset();
    }.bind(this), 0);
  }.bind(this);
  // RESETS (ADDRESSES ISSUES WITH POSITIONING WHEN CSS ANIMATIONS ARE USED, THAT'S WHY THERE ARE 3 RESETS)
  var resets = function() {
      clearTimeout(resetDelay1);
      clearTimeout(resetDelay2);
      clearTimeout(resetDelay3);
      resetDelay1 = setTimeout(this.reset.bind(this), resizeDelay);
      resetDelay2 = setTimeout(this.reset.bind(this), (duration * 1000) + resizeDelay);
      resetDelay3 = setTimeout(this.reset.bind(this), (duration * 2000) + resizeDelay);
  }.bind(this);
  // INITIALIZE
  (function() {
    this.hide;
    // Setup styles
    var styles = areaStr + '{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:relative;min-width:' + (minWidth + (flagstonesMargin * 2)) + 'px;}' + flagstonesStr + '{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;top:0px;' + direction + ':0px;}' + areaStr + '.flagstones-hidden{visibility:hidden;}</style>' + areaStr + '{-webkit-transition-duration:' + duration + 's;-moz-transition-duration:' + duration + 's;-ms-transition-duration:' + duration + 's;-o-transition-duration:' + duration + 's;transition-duration:' + duration + 's;}' + flagstonesStr + '{-webkit-transition-duration:' + duration + 's;-moz-transition-duration:' + duration + 's;-ms-transition-duration:' + duration + 's;-o-transition-duration:' + duration + 's;transition-duration:' + duration + 's;}';
    var style = document.createElement('style');
    style.type = 'text/css';
    style.appendChild(document.createTextNode(styles));
    _('head').appendChild(style);
    // Run reset to calculate and run flagstone!
    setTimeout(this.reset, 0);
    // Reset immediately after resources have loaded to get correct heights
    addEventListener('load', resets.bind(this));
    // Resize listener
    addEventListener('resize', resets.bind(this));
  }.bind(this))()
} // end FLAGSTONEJS
<|endoftext|>


<commit_before>dojo.provide("dijit.form.ValidationTextbox");

dojo.require("dojo.i18n");
dojo.require("dijit.util.wai");

dojo.require("dijit.form.Textbox");
dojo.require("dijit.Tooltip");

dojo.requireLocalization("dijit.form", "validate");

dojo.declare(
	"dijit.form.ValidationTextbox",
	dijit.form.Textbox,
	{
		// summary:
		//		A subclass of Textbox.
		//		Over-ride isValid in subclasses to perform specific kinds of validation.

		// default values for new subclass properties
		// required: Boolean
		//		Can be true or false, default is false.
		required: false,
		// promptMessage: String
		//		Hint string
		promptMessage: "",
		// invalidMessage: String
		// 		The message to display if value is invalid.
		invalidMessage: "",
		// missingMessage: String
		//		The message to display if value is missing or missing.
		missingMessage: "",
		// listenOnKeyPress: Boolean
		//		Updates messages on each key press.  Default is true.
		listenOnKeyPress: true,
		// constraints: Object
		//		user-defined object needed to pass parameters to the validator functions
		constraints: {},
		// regExp: String
		//		regular expression string used to validate the input
		//		Do not specify both regExp and regExpGen
		regExp: ".*",
		// regExpGen: Function
		//		user replaceable function used to generate regExp when dependent on constraints
		//		Do not specify both regExp and regExpGen
		regExpGen: function(constraints){ return this.regExp; },

		setValue: function(value){
			dijit.form.ValidationTextbox.superclass.setValue.call(this, value);
			this.validate(false);
		},

		validator: function(value,constraints){
			// summary: user replaceable function used to validate the text input against the regular expression.
			return (new RegExp("^(" + this.regExpGen(constraints) + ")$")).test(value);
		},

		isValid: function(/* Boolean*/ isFocused){
			// summary: Need to over-ride with your own validation code in subclasses
			return this.validator(this.textbox.value, this.constraints);
		},

		isEmpty: function() {
			// summary: Checks for whitespace
			return /^\s*$/.test(this.textbox.value); // Boolean
		},

		isMissing: function(/* Boolean*/ isFocused){
			// summary: Checks to see if value is required and is whitespace
			return this.required && this.isEmpty(); // Boolean
		},

		getErrorMessage: function(/* Boolean*/ isFocused){
			// summary: return an error message to show if appropriate
			if(this.isMissing(isFocused)){
				return (this.promptMessage == "" || !isFocused) ? this.missingMessage : this.promptMessage;
			}else if(( this.required || !this.isEmpty() ) && !this.isValid(isFocused)){ return this.invalidMessage; }
		},

		getWarningMessage: function(/* Boolean*/ isFocused){
			// summary: return a warning message to show if appropriate
			if(this.isMissing(false) || (( this.required || !this.isEmpty() ) && !this.isValid(false))){
				return this.promptMessage;
			}
		},

		getValidMessage: function(/* Boolean*/ isFocused){
			if(this.isEmpty()){ return this.promptMessage; }
		},

		validate: function(/* Boolean*/ isFocused){
			// summary:
			//		Called by oninit, onblur, and onkeypress.
			// description:
			//		Show missing or invalid messages if appropriate, and highlight textbox field.

			var _class;
			var message = this.getErrorMessage(isFocused);
			if (typeof message == "string"){
				_class = "Error";
			}else{
				message = this.getWarningMessage(isFocused);
				if (typeof message == "string"){
					_class = "Warning";
				}else{
					_class = "Normal";
					message = this.getValidMessage(isFocused);
					if (typeof message != "string"){ message = ""; }
				}
			}
			this._displayMessage(message);
			this.updateClass(_class);
		},

		// currently displayed message
		_message: "",

		_displayMessage: function(/*String*/ message){
			if(this._message == message){ return; }
			this._message = message;
			if(message){
				dijit.MasterTooltip.show(message, this.domNode);
			}else{
				dijit.MasterTooltip.hide();
			}
		},

		updateClass: function(className){
			// summary: used to ensure that only 1 validation class is set at a time
			var _this = this;
			dojo.forEach(["Normal", "Warning", "Error"], function(label){
				_this._removeClass(_this.nodeWithBorder, "dojoInputFieldValidation"+label); });
			this._addClass(this.nodeWithBorder, "dojoInputFieldValidation"+className);
		},

		onfocus: function(evt){
			dijit.form.ValidationTextbox.superclass.onfocus.apply(this, arguments);
			if (this.listenOnKeyPress){
				this.validate(true);
			}else{
				this.updateClass("Warning");
			}
		},

		onkeyup: function(evt){
			this.onfocus(evt);
		},

		postMixInProperties: function(){
			if(this.constraints == dijit.form.ValidationTextbox.prototype.constraints){
				this.constraints = {};
			}
			dijit.form.ValidationTextbox.superclass.postMixInProperties.apply(this, arguments);
			this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
			dojo.forEach(["invalidMessage", "missingMessage"], function(prop){
				if(!this[prop]){ this[prop] = this.messages[prop]; }
			}, this);
			var p = this.regExpGen(this.constraints);
			this.regExp = p;
			// make value a string for all types so that form reset works well
			this.value = (this.value == null || this.value == "") ? "" : this.format(this.value, this.constraints);
		},

		postCreate: function(){
			dijit.form.ValidationTextbox.superclass.postCreate.apply(this);

			// Attach isMissing and isValid methods to the textbox.
			// We may use them later in connection with a submit button widget.
			// TODO: this is unorthodox; it seems better to do it another way -- Bill
			this.textbox.isValid = function(){ this.isValid.call(this); };
			this.textbox.isMissing = function(){ this.isMissing.call(this); };
			// setting the value here is needed since value="" in the template causes "undefined" on form reset
			this.textbox.setAttribute("value", this.value);
			this.validate(false);
		}
	}
);

dojo.declare(
	"dijit.form.SerializableTextbox",
	dijit.form.ValidationTextbox,
	{
		// summary:
		//		A subclass of ValidationTextbox.
		//		Provides a hidden input field and a serialize method to override

		serialize: function(val){
			// summary: user replaceable function used to convert the getValue() result to a String
			return val.toString();
		},

		toString: function(){
			// summary: display the widget as a printable string using the widget's value
			var val = this.getValue();
			return val ? ((typeof val == "string") ? val : this.serialize(val)) : "";
		},

		validate: function(){
			this.valueNode.value = this.toString();
			dijit.form.SerializableTextbox.superclass.validate.apply(this, arguments);
		},

		postCreate: function(){
			var textbox = this.textbox;
			var valueNode = (this.valueNode = document.createElement("input"));
			valueNode.setAttribute("type", textbox.type);
			valueNode.setAttribute("value", this.toString());
			dojo.style(valueNode, "display", "none");
			valueNode.name = this.textbox.name;
			textbox.name = "";

			dojo.place(valueNode, textbox, "after");

			dijit.form.SerializableTextbox.superclass.postCreate.apply(this, arguments);
		}
	}
);

dojo.declare(
	"dijit.form.RangeBoundTextbox",
	dijit.form.SerializableTextbox,
	{
		// summary:
		//		A subclass of SerializableTextbox.
		//		Tests for a value out-of-range
		/*===== contraints object:
		// min: Number
		//		Minimum signed value.  Default is -Infinity
		min: undefined,
		// max: Number
		//		Maximum signed value.  Default is +Infinity
		max: undefined,
		=====*/

		// rangeMessage: String
		//              The message to display if value is out-of-range
		rangeMessage: "",

		compare: function(val1, val2){
			// summary: compare 2 values
			return val1 - val2;
		},

		rangeCheck: function(/* Number */ primitive, /* Object */ constraints){
			// summary: user replaceable function used to validate the range of the numeric input value
			var isMin = (typeof constraints.min != "undefined");
			var isMax = (typeof constraints.max != "undefined");
			if (isMin || isMax){
				return (!isMin || this.compare(primitive,constraints.min) >= 0) &&
					(!isMax || this.compare(primitive,constraints.max) <= 0);
			}else{ return true; }
		},

		isInRange: function(/* Boolean*/ isFocused){
			// summary: Need to over-ride with your own validation code in subclasses
			return this.rangeCheck(this.getValue(), this.constraints);
		},

		getErrorMessage: function(/* Boolean*/ isFocused){
			var msg = dijit.form.RangeBoundTextbox.superclass.getErrorMessage.apply(this, arguments);
			if(typeof msg != "string"){
				if(this.isValid(false) && !this.isInRange(isFocused)){ return this.rangeMessage; }
			}else{ return msg; }
		},

		postMixInProperties: function(){
			dijit.form.RangeBoundTextbox.superclass.postMixInProperties.apply(this, arguments);
			if(!this.rangeMessage){
				this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
				this.rangeMessage = this.messages.rangeMessage;
			}
		},

		postCreate: function(){
			dijit.form.RangeBoundTextbox.superclass.postCreate.apply(this, arguments);
			if(typeof this.constraints.min != "undefined"){
				dijit.util.wai.setAttr(this.domNode, "waiState", "valuemin", this.constraints.min);
			}
			if(typeof this.constraints.max != "undefined"){
				dijit.util.wai.setAttr(this.domNode, "waiState", "valuemax", this.constraints.max);
			}
		}
	}
);
<commit_msg>Only show popup validation errors when you are focused on a node; remove missingMessage (since it was only being used when you blurrred a node) Refs #2743.<commit_after>dojo.provide("dijit.form.ValidationTextbox");

dojo.require("dojo.i18n");
dojo.require("dijit.util.wai");

dojo.require("dijit.form.Textbox");
dojo.require("dijit.Tooltip");

dojo.requireLocalization("dijit.form", "validate");

dojo.declare(
	"dijit.form.ValidationTextbox",
	dijit.form.Textbox,
	{
		// summary:
		//		A subclass of Textbox.
		//		Over-ride isValid in subclasses to perform specific kinds of validation.

		// default values for new subclass properties
		// required: Boolean
		//		Can be true or false, default is false.
		required: false,
		// promptMessage: String
		//		Hint string
		promptMessage: "",
		// invalidMessage: String
		// 		The message to display if value is invalid.
		invalidMessage: "",
		// listenOnKeyPress: Boolean
		//		Updates messages on each key press.  Default is true.
		listenOnKeyPress: true,
		// constraints: Object
		//		user-defined object needed to pass parameters to the validator functions
		constraints: {},
		// regExp: String
		//		regular expression string used to validate the input
		//		Do not specify both regExp and regExpGen
		regExp: ".*",
		// regExpGen: Function
		//		user replaceable function used to generate regExp when dependent on constraints
		//		Do not specify both regExp and regExpGen
		regExpGen: function(constraints){ return this.regExp; },

		setValue: function(value){
			dijit.form.ValidationTextbox.superclass.setValue.call(this, value);
			this.validate(false);
		},

		validator: function(value,constraints){
			// summary: user replaceable function used to validate the text input against the regular expression.
			return (new RegExp("^(" + this.regExpGen(constraints) + ")$")).test(value);
		},

		isValid: function(/* Boolean*/ isFocused){
			// summary: Need to over-ride with your own validation code in subclasses
			return this.validator(this.textbox.value, this.constraints);
		},

		isEmpty: function() {
			// summary: Checks for whitespace
			return /^\s*$/.test(this.textbox.value); // Boolean
		},

		isMissing: function(/* Boolean*/ isFocused){
			// summary: Checks to see if value is required and is whitespace
			return this.required && this.isEmpty(); // Boolean
		},

		getErrorMessage: function(/* Boolean*/ isFocused){
			// summary: return an error message to show if appropriate
			return this.invalidMessage;
		},

		getPromptMessage: function(/* Boolean*/ isFocused){
			// summary: return a hint to show if appropriate
			return this.promptMessage;
		},

		validate: function(/* Boolean*/ isFocused){
			// summary:
			//		Called by oninit, onblur, and onkeypress.
			// description:
			//		Show missing or invalid messages if appropriate, and highlight textbox field.

			var message;
			if (!this.isValid()){
				this.updateClass("Error");
				message = this.getErrorMessage(isFocused);
			}else{
				this.updateClass(this.isMissing() ? "Warning" : "Normal");
				message = this.getPromptMessage(isFocused);
			}
			this._displayMessage(isFocused ? message : "");
		},

		// currently displayed message
		_message: "",

		_displayMessage: function(/*String*/ message){
			if(this._message == message){ return; }
			this._message = message;
			if(message){
				dijit.MasterTooltip.show(message, this.domNode);
			}else{
				dijit.MasterTooltip.hide();
			}
		},

		updateClass: function(className){
			// summary: used to ensure that only 1 validation class is set at a time
			var _this = this;
			dojo.forEach(["Normal", "Warning", "Error"], function(label){
				_this._removeClass(_this.nodeWithBorder, "dojoInputFieldValidation"+label); });
			this._addClass(this.nodeWithBorder, "dojoInputFieldValidation"+className);
		},

		onfocus: function(evt){
			dijit.form.ValidationTextbox.superclass.onfocus.apply(this, arguments);
			if (this.listenOnKeyPress){
				this.validate(true);
			}else{
				this.updateClass("Warning");
			}
		},

		onkeyup: function(evt){
			this.onfocus(evt);
		},

		postMixInProperties: function(){
			if(this.constraints == dijit.form.ValidationTextbox.prototype.constraints){
				this.constraints = {};
			}
			dijit.form.ValidationTextbox.superclass.postMixInProperties.apply(this, arguments);
			this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
			dojo.forEach(["invalidMessage", "missingMessage"], function(prop){
				if(!this[prop]){ this[prop] = this.messages[prop]; }
			}, this);
			var p = this.regExpGen(this.constraints);
			this.regExp = p;
			// make value a string for all types so that form reset works well
			this.value = (this.value == null || this.value == "") ? "" : this.format(this.value, this.constraints);
		},

		postCreate: function(){
			dijit.form.ValidationTextbox.superclass.postCreate.apply(this);

			// Attach isMissing and isValid methods to the textbox.
			// We may use them later in connection with a submit button widget.
			// TODO: this is unorthodox; it seems better to do it another way -- Bill
			this.textbox.isValid = function(){ this.isValid.call(this); };
			this.textbox.isMissing = function(){ this.isMissing.call(this); };
			// setting the value here is needed since value="" in the template causes "undefined" on form reset
			this.textbox.setAttribute("value", this.value);
			this.validate(false);
		}
	}
);

dojo.declare(
	"dijit.form.SerializableTextbox",
	dijit.form.ValidationTextbox,
	{
		// summary:
		//		A subclass of ValidationTextbox.
		//		Provides a hidden input field and a serialize method to override

		serialize: function(val){
			// summary: user replaceable function used to convert the getValue() result to a String
			return val.toString();
		},

		toString: function(){
			// summary: display the widget as a printable string using the widget's value
			var val = this.getValue();
			return val ? ((typeof val == "string") ? val : this.serialize(val)) : "";
		},

		validate: function(){
			this.valueNode.value = this.toString();
			dijit.form.SerializableTextbox.superclass.validate.apply(this, arguments);
		},

		postCreate: function(){
			var textbox = this.textbox;
			var valueNode = (this.valueNode = document.createElement("input"));
			valueNode.setAttribute("type", textbox.type);
			valueNode.setAttribute("value", this.toString());
			dojo.style(valueNode, "display", "none");
			valueNode.name = this.textbox.name;
			textbox.name = "";

			dojo.place(valueNode, textbox, "after");

			dijit.form.SerializableTextbox.superclass.postCreate.apply(this, arguments);
		}
	}
);

dojo.declare(
	"dijit.form.RangeBoundTextbox",
	dijit.form.SerializableTextbox,
	{
		// summary:
		//		A subclass of SerializableTextbox.
		//		Tests for a value out-of-range
		/*===== contraints object:
		// min: Number
		//		Minimum signed value.  Default is -Infinity
		min: undefined,
		// max: Number
		//		Maximum signed value.  Default is +Infinity
		max: undefined,
		=====*/

		// rangeMessage: String
		//              The message to display if value is out-of-range
		rangeMessage: "",

		compare: function(val1, val2){
			// summary: compare 2 values
			return val1 - val2;
		},

		rangeCheck: function(/* Number */ primitive, /* Object */ constraints){
			// summary: user replaceable function used to validate the range of the numeric input value
			var isMin = (typeof constraints.min != "undefined");
			var isMax = (typeof constraints.max != "undefined");
			if (isMin || isMax){
				return (!isMin || this.compare(primitive,constraints.min) >= 0) &&
					(!isMax || this.compare(primitive,constraints.max) <= 0);
			}else{ return true; }
		},

		isInRange: function(/* Boolean*/ isFocused){
			// summary: Need to over-ride with your own validation code in subclasses
			return this.rangeCheck(this.getValue(), this.constraints);
		},

		getErrorMessage: function(/* Boolean*/ isFocused){
			var msg = dijit.form.RangeBoundTextbox.superclass.getErrorMessage.apply(this, arguments);
			if(typeof msg != "string"){
				if(this.isValid(false) && !this.isInRange(isFocused)){ return this.rangeMessage; }
			}else{ return msg; }
		},

		postMixInProperties: function(){
			dijit.form.RangeBoundTextbox.superclass.postMixInProperties.apply(this, arguments);
			if(!this.rangeMessage){
				this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
				this.rangeMessage = this.messages.rangeMessage;
			}
		},

		postCreate: function(){
			dijit.form.RangeBoundTextbox.superclass.postCreate.apply(this, arguments);
			if(typeof this.constraints.min != "undefined"){
				dijit.util.wai.setAttr(this.domNode, "waiState", "valuemin", this.constraints.min);
			}
			if(typeof this.constraints.max != "undefined"){
				dijit.util.wai.setAttr(this.domNode, "waiState", "valuemax", this.constraints.max);
			}
		}
	}
);
<|endoftext|>


<commit_before>// ==UserScript==
// @name        FPL Iwon scroller
// @namespace   mikemanger
// @grant       none
// @include     https://fplcomps.iwn.io/*/*
// @updateURL   https://raw.githubusercontent.com/mikemanger/userscripts/master/fpl-iwon-scroller.user.js
// @downloadURL https://raw.githubusercontent.com/mikemanger/userscripts/master/fpl-iwon-scroller.user.js
// @version     1.0.0
// ==/UserScript==

function auto_scrolling() {
	window.scrollTo(0, document.body.scrollHeight);
}
setInterval(auto_scrolling, 500);
<commit_msg>Add clicker to fpl script<commit_after>// ==UserScript==
// @name        FPL Iwon scroller
// @namespace   mikemanger
// @grant       none
// @include     https://fplcomps.iwn.io/*/*
// @updateURL   https://raw.githubusercontent.com/mikemanger/userscripts/master/fpl-iwon-scroller.user.js
// @downloadURL https://raw.githubusercontent.com/mikemanger/userscripts/master/fpl-iwon-scroller.user.js
// @version     1.0.1
// ==/UserScript==

function auto_scrolling() {
	window.scrollTo(0, document.body.scrollHeight);
}
setInterval(auto_scrolling, 500);

jQuery(document).ready(function(){
	jQuery('.submitButton').click();
});
<|endoftext|>


<commit_before>/**
	The MIT License (MIT)

	Copyright (c) 2014 MyChannel-Apps.de

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.

	@author		Christoph Kühl <djchrisnet>, Adrian Preuß <Bizarrus>
	@docs		http://www.mychannel-apps.de/documentation/tools/number
*/

/*
	@docs	TODO
*/
if(!Number.prototype.fix) {
	Object.defineProperty(Number.prototype, 'fix', {
		enumerable:		false,
		configurable:	false,
		writable:		false,
		value: function(count) {
			return parseFloat(this.toFixed(parseInt(count) || 2));
		}
	});
}

/*
	@docs	TODO
*/
if(!Number.prototype.format) {
	Object.defineProperty(Number.prototype, 'format', {
		enumerable:		false,
		configurable:	false,
		writable:		false,
		value: function(n, x) {
			return this.toFixed(Math.max(0, ~~n)).replace(new RegExp('\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\.' : '$') + ')', 'g'), '$&,');
		}
	});
}<commit_msg>Zero fill for numbers<commit_after>/**
	The MIT License (MIT)

	Copyright (c) 2014 MyChannel-Apps.de

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.

	@author		Christoph Kühl <djchrisnet>, Adrian Preuß <Bizarrus>
	@docs		http://www.mychannel-apps.de/documentation/tools/number
*/

/*
	@docs	TODO
*/
if(!Number.prototype.fix) {
	Object.defineProperty(Number.prototype, 'fix', {
		enumerable:		false,
		configurable:	false,
		writable:		false,
		value: function(count) {
			return parseFloat(this.toFixed(parseInt(count) || 2));
		}
	});
}

/*
	@docs	TODO
*/
if(!Number.prototype.format) {
	Object.defineProperty(Number.prototype, 'format', {
		enumerable:		false,
		configurable:	false,
		writable:		false,
		value: function(n, x) {
			return this.toFixed(Math.max(0, ~~n)).replace(new RegExp('\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\.' : '$') + ')', 'g'), '$&,');
		}
	});
}

/*
	@docs	TODO
*/
if(!Number.prototype.zero) {
  Object.defineProperty(Number.prototype, 'zero', {
    enumerable: false,
    configurable: false,
    writable: false,
    value: function() {
		return (this>10) ? ''+this : '0'+this;
    }
  });
}<|endoftext|>


<commit_before>$(function() {
  var notification = new exercism.models.Notification(),
  notificationList = new exercism.collections.NotificationList({
    model: notification
  });
  $('.dropdown-toggle').dropdown();
  exercism.collections.notificationsList = new exercism.collections.NotificationList({
    model: notification
  });
  exercism.views.toggleNotifications = new exercism.views.ToggleNotifications({
    el: $("#toggle-notifications"),
    collection: notificationList
  });

  // Only initialize the javascript for the filters if there are filter
  //   assets on the page.
  if ($('#submission-filters').length !== 0) {
    exercism.models.selectFilter = new exercism.models.SelectFilter();
    exercism.views.selectFilter = new exercism.views.SelectFilter({ model: exercism.models.selectFilter });
  }
});

//TODO move all variable declaration to the tops of functions.
$(function() {
  $(".pending-submission, .work").each(function(index,element) {
    var elem = $(element);

    var language = elem.data('language');
    $(".language",elem).tooltip({ title: language });

    var nitCount = elem.data('nits');
    $(".nits",elem).tooltip({ title: nitCount + " Nits by Others" });

    $(".opinions",elem).tooltip({ title: "More Opinions Desired" });

    var versionCount = elem.data('versions');
    $(".versions",elem).tooltip({ title: "Iteration " + versionCount });
  });

  $(".code a[data-action='enlarge']").on("click",function() {
    var codeDiv = $(this).parents(".code");
    codeDiv.removeClass("span6");
    codeDiv.addClass("span12");
    $(this).hide();
    $("a[data-action='shrink']",codeDiv).show();
  });

  $(".code a[data-action='shrink']").on("click",function() {
    var codeDiv = $(this).parents(".code");
    codeDiv.removeClass("span12");
    codeDiv.addClass("span6");
    $(this).hide();
    $("a[data-action='enlarge']",codeDiv).show();
  });

  $("#code-timeline").on("click",function(event) {
    var revisionId = $(event.target).data("revision");
    $(event.target).toggleClass("selected");
    $('#revision-' + revisionId).toggle();
  });

  $('form input[type=submit], form button[type=submit]').on('click', function() {
    var $this = $(this);
    window.setTimeout(function() { $this.attr('disabled', true); }, 1);
  });

  $('form').ready(function () {
      var unsaved = false;
      $(":input").change(function() {
          unsaved = true;
      });
      function unloadPage() {
          if(unsaved){
              return "You have unsaved changes on this page"
          }
      }
      window.onbeforeunload = unloadPage;
  });

  $('.work-slug').popover({
    trigger: 'hover',
    placement: 'right',
    html: true,
    delay: {
      show: 600,
      hide: 100
    },
    content: 'use the command exercism fetch to add this assignment to your exercism directory'
  });

  $(".mute").each(function(index, element) {
    var elem = $(element);

    $(".mute-btn",elem).tooltip({ placement: "bottom", title: "Mute this submission until there is further activity." });
    $(".unmute-btn",elem).tooltip({ placement: "bottom", title: "Unmute this sumission." });
  });
});
<commit_msg>Travis Build Failed, Missing Semicolon<commit_after>$(function() {
  var notification = new exercism.models.Notification(),
  notificationList = new exercism.collections.NotificationList({
    model: notification
  });
  $('.dropdown-toggle').dropdown();
  exercism.collections.notificationsList = new exercism.collections.NotificationList({
    model: notification
  });
  exercism.views.toggleNotifications = new exercism.views.ToggleNotifications({
    el: $("#toggle-notifications"),
    collection: notificationList
  });

  // Only initialize the javascript for the filters if there are filter
  //   assets on the page.
  if ($('#submission-filters').length !== 0) {
    exercism.models.selectFilter = new exercism.models.SelectFilter();
    exercism.views.selectFilter = new exercism.views.SelectFilter({ model: exercism.models.selectFilter });
  }
});

//TODO move all variable declaration to the tops of functions.
$(function() {
  $(".pending-submission, .work").each(function(index,element) {
    var elem = $(element);

    var language = elem.data('language');
    $(".language",elem).tooltip({ title: language });

    var nitCount = elem.data('nits');
    $(".nits",elem).tooltip({ title: nitCount + " Nits by Others" });

    $(".opinions",elem).tooltip({ title: "More Opinions Desired" });

    var versionCount = elem.data('versions');
    $(".versions",elem).tooltip({ title: "Iteration " + versionCount });
  });

  $(".code a[data-action='enlarge']").on("click",function() {
    var codeDiv = $(this).parents(".code");
    codeDiv.removeClass("span6");
    codeDiv.addClass("span12");
    $(this).hide();
    $("a[data-action='shrink']",codeDiv).show();
  });

  $(".code a[data-action='shrink']").on("click",function() {
    var codeDiv = $(this).parents(".code");
    codeDiv.removeClass("span12");
    codeDiv.addClass("span6");
    $(this).hide();
    $("a[data-action='enlarge']",codeDiv).show();
  });

  $("#code-timeline").on("click",function(event) {
    var revisionId = $(event.target).data("revision");
    $(event.target).toggleClass("selected");
    $('#revision-' + revisionId).toggle();
  });

  $('form input[type=submit], form button[type=submit]').on('click', function() {
    var $this = $(this);
    window.setTimeout(function() { $this.attr('disabled', true); }, 1);
  });

  $('form').ready(function () {
      var unsaved = false;
      $(":input").change(function() {
          unsaved = true;
      });
      function unloadPage() {
          if(unsaved){
              return "You have unsaved changes on this page";
          }
      }
      window.onbeforeunload = unloadPage;
  });

  $('.work-slug').popover({
    trigger: 'hover',
    placement: 'right',
    html: true,
    delay: {
      show: 600,
      hide: 100
    },
    content: 'use the command exercism fetch to add this assignment to your exercism directory'
  });

  $(".mute").each(function(index, element) {
    var elem = $(element);

    $(".mute-btn",elem).tooltip({ placement: "bottom", title: "Mute this submission until there is further activity." });
    $(".unmute-btn",elem).tooltip({ placement: "bottom", title: "Unmute this sumission." });
  });
});
<|endoftext|>


<commit_before>var $ = require("jquery"),
    _ = require("underscore"),
    Marionette = require("backbone.marionette"),
    d3 = require("d3"),
    topojson = require("topojson"),
    // This isn't a proper module, so don't use the geoZoom directly
    // as if it were. Instead, requiring the file will add the
    // d3.geo.zoom function to the existing d3 object
    geoZoom = require("../utils/d3.geo.zoom");

var MapView = Marionette.ItemView.extend({
    template: false,
    tagName: "svg",

    margin: {
        top: 20,
        right: 20,
        bottom: 20,
        left: 20
    },

    zoomMin: 0.7,
    zoomMax: 10,
    scale: 250,
    clipAngle: 90,
    precision: 0.1,
    circleRadius: 5,

    initialize: function(options) {
        options = options || {};
        this.margin = options.margin || this.margin;
        this.selector = options.selector || ".map";
        this.world = options.worldData;
        this.routers = options.routersData;
        this.links = options.linksData;

        this.setDimensions();
        this.replaceElement();
        this.initializeVisualisation();

        this.resizeMap = _.debounce(this.resizeMap, 250);
        _.bindAll(this, "zoomRedraw", "resizeMap", "appendRouter",
                  "appendLink", "getRouterFill");

        this.listenTo(this.world, "sync", this.drawMap);
        this.listenTo(this.routers, "sync", this.handleSync);
        this.listenTo(this.links, "sync", this.handleSync);
        d3.select(window).on("resize", this.resizeMap);
    },

    onRender: function() {
        this.initMap();
    },

    handleSync: function() {
        if(this.routers.data && this.links.data) {
            this.drawLinks();
            this.drawRouters();
        }
    },

    initializeVisualisation: function() {
        if(!this.projection) {
            this.projection = d3.geo.orthographic()
                .scale(this.scale)
                .translate([this.width / 2, this.height / 2])
                .clipAngle(this.clipAngle)
                .precision(this.precision);
        } else {
            this.projection.translate([this.width / 2, this.height / 2]);
        }

        this.geoZoomFunction = d3.geo.zoom()
            .projection(this.projection)
            .scaleExtent([this.projection.scale() * this.zoomMin,
                          this.projection.scale() * this.zoomMax])
            .on("zoom.redraw", _.bind(this.zoomRedraw, this));

        this.path = d3.geo.path()
            .projection(this.projection);

        this.graticule = d3.geo.graticule();
    },

    initMap: function() {
        this.svg = d3.select(this.el)
            .append("g")
            .attr("transform", "translate(" + this.margin.left +
                  "," + this.margin.top + ")");

        this.svg.append("defs").append("path")
            .datum({type: "Sphere"})
            .attr("id", "sphere")
            .attr("class", "globe")
            .attr("d", this.path)
            .on("mousedown.grab", this.onMouseGrab);

        this.svg.append("use")
            .attr("class", "stroke grabbable")
            .attr("xlink:href", "#sphere")
            .on("mousedown.grab", this.onMouseGrab);

        this.svg.append("use")
            .attr("class", "fill grabbable")
            .attr("xlink:href", "#sphere")
            .on("mousedown.grab", this.onMouseGrab);

        this.svg.append("path")
            .datum(this.graticule)
            .attr("class", "graticule grabbable")
            .attr("d", this.path)
            .on("mousedown.grab", this.onMouseGrab);
    },

    drawMap: function() {
        this.svg.insert("path", ".graticule")
            .datum(topojson.feature(this.world.data,
                                    this.world.data.objects.land))
            .attr("class", "land  grabbable")
            .attr("d", this.path)
            .on("mousedown.grab", this.onMouseGrab);

        this.svg.insert("path", ".graticule")
            .datum(topojson.mesh(this.world.data,
                                 this.world.data.objects.countries,
                                 function(a, b) {
                                     return a !== b;
                                 }
                                )
                  )
            .attr("class", "boundary  grabbable")
            .attr("d", this.path)
            .on("mousedown.grab", this.onMouseGrab);

        // Allow zoom and rotation of map
        this.svg.selectAll("path")
            .call(this.geoZoomFunction);
    },

    drawRouters: function() {
        this.routers.data.forEach(this.appendRouter);
    },

    drawLinks: function() {
        this.links.data.forEach(this.appendLink);
    },

    appendRouter: function(d) {
        this.svg.append("path")
            .datum({type: "Point", coordinates: [d.lng, d.lat], data: d})
            .attr("class", "router grabbable")
            .attr("d", this.path.pointRadius(this.circleRadius))
            .attr("fill", this.getRouterFill)
            .call(this.geoZoomFunction);
    },

    appendLink: function(d) {
        var leftPos = this.routers.coordinatesByLxcName[d.left];
        var rightPos = this.routers.coordinatesByLxcName[d.right];

        if(!leftPos || !rightPos) {
            // Invalid/unknown LXC name, no coordinates returned
            return;
        }

        var link = {
            type: "LineString",
            coordinates: [[leftPos.lng, leftPos.lat],
                          [rightPos.lng, rightPos.lat]]
        };

        this.svg.append("path")
            .datum(link)
            .attr("d", this.path)
            .attr("class", "link grabbable")
            .call(this.geoZoomFunction);
    },

    zoomRedraw: function() {
        if (d3.event.sourceEvent.preventDefault) {
            d3.event.sourceEvent.preventDefault();
        }

        this.svg.selectAll("path").attr("d", this.path);
    },

    resizeMap: function() {
        if(!this.svgWidth || !this.world.data) return;

        this.svg.remove();

        this.setDimensions();

        this.$el.attr("width", this.svgWidth);
        this.$el.attr("height", this.svgHeight);

        this.initializeVisualisation();
        this.initMap();
        this.drawMap();
        this.drawRouters();
    },

    onMouseGrab: function() {
        var path = d3.select(this).classed("grabbed", true);
        var w = d3.select(window)
            .on("mouseup.grab." + this.classList,
                function() {
                    path.classed("grabbed", false);
                    w.on("mouseup.grab", null);
                });
    },

    setDimensions: function() {
        this.svgWidth = this.getWidth();
        this.svgHeight = this.getHeight();

        this.width = this.svgWidth - this.margin.left - this.margin.right;
        this.height = this.svgHeight - this.margin.top - this.margin.bottom;
    },

    // This function replaces the view's el in order to have the right svg
    // namespace for the d3 visualisations
    replaceElement: function() {
        this.setElement(d3.select(this.selector)
                        .append("svg")
                        .attr("width", this.svgWidth)
                        .attr("height", this.svgHeight)
                        [0]);
    },

    getWidth: function() {
        return parseInt(d3.select(this.selector).style("width"));
    },

    getHeight: function() {
        return parseInt(d3.select(this.selector).style("height"));
    },

    getRouterFill: function(d) {
        tier = d.data.tier
        if(tier === 0) return "chartreuse";
        if(tier === 1) return "red";
        if(tier === 2) return "orange";
        if(tier === 3) return "yellow";
        console.error("Invalid router tier:" + tier);
    }
});

module.exports = MapView;
<commit_msg>Fix: redraw links on window resize<commit_after>var $ = require("jquery"),
    _ = require("underscore"),
    Marionette = require("backbone.marionette"),
    d3 = require("d3"),
    topojson = require("topojson"),
    // This isn't a proper module, so don't use the geoZoom directly
    // as if it were. Instead, requiring the file will add the
    // d3.geo.zoom function to the existing d3 object
    geoZoom = require("../utils/d3.geo.zoom");

var MapView = Marionette.ItemView.extend({
    template: false,
    tagName: "svg",

    margin: {
        top: 20,
        right: 20,
        bottom: 20,
        left: 20
    },

    zoomMin: 0.7,
    zoomMax: 10,
    scale: 250,
    clipAngle: 90,
    precision: 0.1,
    circleRadius: 5,

    initialize: function(options) {
        options = options || {};
        this.margin = options.margin || this.margin;
        this.selector = options.selector || ".map";
        this.world = options.worldData;
        this.routers = options.routersData;
        this.links = options.linksData;

        this.setDimensions();
        this.replaceElement();
        this.initializeVisualisation();

        this.resizeMap = _.debounce(this.resizeMap, 250);
        _.bindAll(this, "zoomRedraw", "resizeMap", "appendRouter",
                  "appendLink", "getRouterFill");

        this.listenTo(this.world, "sync", this.drawMap);
        this.listenTo(this.routers, "sync", this.handleSync);
        this.listenTo(this.links, "sync", this.handleSync);
        d3.select(window).on("resize", this.resizeMap);
    },

    onRender: function() {
        this.initMap();
    },

    handleSync: function() {
        if(this.routers.data && this.links.data) {
            this.drawLinks();
            this.drawRouters();
        }
    },

    initializeVisualisation: function() {
        if(!this.projection) {
            this.projection = d3.geo.orthographic()
                .scale(this.scale)
                .translate([this.width / 2, this.height / 2])
                .clipAngle(this.clipAngle)
                .precision(this.precision);
        } else {
            this.projection.translate([this.width / 2, this.height / 2]);
        }

        this.geoZoomFunction = d3.geo.zoom()
            .projection(this.projection)
            .scaleExtent([this.projection.scale() * this.zoomMin,
                          this.projection.scale() * this.zoomMax])
            .on("zoom.redraw", _.bind(this.zoomRedraw, this));

        this.path = d3.geo.path()
            .projection(this.projection);

        this.graticule = d3.geo.graticule();
    },

    initMap: function() {
        this.svg = d3.select(this.el)
            .append("g")
            .attr("transform", "translate(" + this.margin.left +
                  "," + this.margin.top + ")");

        this.svg.append("defs").append("path")
            .datum({type: "Sphere"})
            .attr("id", "sphere")
            .attr("class", "globe")
            .attr("d", this.path)
            .on("mousedown.grab", this.onMouseGrab);

        this.svg.append("use")
            .attr("class", "stroke grabbable")
            .attr("xlink:href", "#sphere")
            .on("mousedown.grab", this.onMouseGrab);

        this.svg.append("use")
            .attr("class", "fill grabbable")
            .attr("xlink:href", "#sphere")
            .on("mousedown.grab", this.onMouseGrab);

        this.svg.append("path")
            .datum(this.graticule)
            .attr("class", "graticule grabbable")
            .attr("d", this.path)
            .on("mousedown.grab", this.onMouseGrab);
    },

    drawMap: function() {
        this.svg.insert("path", ".graticule")
            .datum(topojson.feature(this.world.data,
                                    this.world.data.objects.land))
            .attr("class", "land  grabbable")
            .attr("d", this.path)
            .on("mousedown.grab", this.onMouseGrab);

        this.svg.insert("path", ".graticule")
            .datum(topojson.mesh(this.world.data,
                                 this.world.data.objects.countries,
                                 function(a, b) {
                                     return a !== b;
                                 }
                                )
                  )
            .attr("class", "boundary  grabbable")
            .attr("d", this.path)
            .on("mousedown.grab", this.onMouseGrab);

        // Allow zoom and rotation of map
        this.svg.selectAll("path")
            .call(this.geoZoomFunction);
    },

    drawRouters: function() {
        this.routers.data.forEach(this.appendRouter);
    },

    drawLinks: function() {
        this.links.data.forEach(this.appendLink);
    },

    appendRouter: function(d) {
        this.svg.append("path")
            .datum({type: "Point", coordinates: [d.lng, d.lat], data: d})
            .attr("class", "router grabbable")
            .attr("d", this.path.pointRadius(this.circleRadius))
            .attr("fill", this.getRouterFill)
            .call(this.geoZoomFunction);
    },

    appendLink: function(d) {
        var leftPos = this.routers.coordinatesByLxcName[d.left];
        var rightPos = this.routers.coordinatesByLxcName[d.right];

        if(!leftPos || !rightPos) {
            // Invalid/unknown LXC name, no coordinates returned
            return;
        }

        var link = {
            type: "LineString",
            coordinates: [[leftPos.lng, leftPos.lat],
                          [rightPos.lng, rightPos.lat]]
        };

        this.svg.append("path")
            .datum(link)
            .attr("d", this.path)
            .attr("class", "link grabbable")
            .call(this.geoZoomFunction);
    },

    zoomRedraw: function() {
        if (d3.event.sourceEvent.preventDefault) {
            d3.event.sourceEvent.preventDefault();
        }

        this.svg.selectAll("path").attr("d", this.path);
    },

    resizeMap: function() {
        if(!this.svgWidth || !this.world.data) return;

        this.svg.remove();

        this.setDimensions();

        this.$el.attr("width", this.svgWidth);
        this.$el.attr("height", this.svgHeight);

        this.initializeVisualisation();
        this.initMap();
        this.drawMap();
        this.drawRouters();
        this.drawLinks();
    },

    onMouseGrab: function() {
        var path = d3.select(this).classed("grabbed", true);
        var w = d3.select(window)
            .on("mouseup.grab." + this.classList,
                function() {
                    path.classed("grabbed", false);
                    w.on("mouseup.grab", null);
                });
    },

    setDimensions: function() {
        this.svgWidth = this.getWidth();
        this.svgHeight = this.getHeight();

        this.width = this.svgWidth - this.margin.left - this.margin.right;
        this.height = this.svgHeight - this.margin.top - this.margin.bottom;
    },

    // This function replaces the view's el in order to have the right svg
    // namespace for the d3 visualisations
    replaceElement: function() {
        this.setElement(d3.select(this.selector)
                        .append("svg")
                        .attr("width", this.svgWidth)
                        .attr("height", this.svgHeight)
                        [0]);
    },

    getWidth: function() {
        return parseInt(d3.select(this.selector).style("width"));
    },

    getHeight: function() {
        return parseInt(d3.select(this.selector).style("height"));
    },

    getRouterFill: function(d) {
        tier = d.data.tier
        if(tier === 0) return "chartreuse";
        if(tier === 1) return "red";
        if(tier === 2) return "orange";
        if(tier === 3) return "yellow";
        console.error("Invalid router tier:" + tier);
    }
});

module.exports = MapView;
<|endoftext|>