<commit_before>/**
 Enyo supports a cross-platform set of drag events. These events are provide to allow a single set of event handlers to be
 written for all supports platforms, desktop and mobile alike. The following events are provided:

 * "dragstart", "dragfinish" - sent for pointer moves that exceed a certain threshhold
 * "drag", "drop" - sent to the original target of the pointer move to inform it about the item being moved over or released over another element
 * "dragover", "dragout" - sent in addition to over and out when there is an active drag

 * "hold" - generated when the pointer is held down without moving for a short period (about 200ms).
 * "release" - generated when the pointer is released after being held down, or the pointer is moved off of the node while still held down. The target is the same as the hold event.
 * "holdpulse" - generated when the pointer is held down without moving for a short period and periodically thereafter about every 200ms.
 Use this event to trigger an action after an arbitrary period of time. The holdTime property provides the elapsed time.
 * "flick" - generated when the user flicks the pointer quickly. This event provides flick velocity data: xVelocity is the velocity in the horizontal and
 yVelocity is the vertical velocity.

 * Note: on Android, touchmove event must be prevented via inEvent.preventDefault() or will not fire more than once and enyo dragging system
 * will not function correctly.
 */

//* @protected
enyo.dispatcher.features.push(
	function(e) {
		// NOTE: beware of properties in enyo.gesture inadvertently mapped to event types
		if (enyo.gesture.drag[e.type]) {
			return enyo.gesture.drag[e.type](e);
		}
	}
);

//* @public
enyo.gesture.drag = {
	//* @protected
	hysteresisSquared: 16,
	holdPulseDelay: 200,
	trackCount: 5,
	minFlick: 0.1,
	minTrack: 8,
	down: function(e) {
		// tracking if the mouse is down
		//console.log("tracking ON");
		// Note: 'tracking' flag indicates interest in mousemove, it's turned off
		// on mouseup
		// make sure to stop dragging in case the up event was not received.
		this.stopDragging(e);
		this.cancelHold();
		this.target = e.target;
		this.startTracking(e);
		this.beginHold(e);
	},
	move: function(e) {
		if (this.tracking) {
			this.track(e);
			// If the mouse is not down and we're tracking a drag, abort.
			// this error condition can occur on IE/Webkit after interaction with a scrollbar.
			if (!e.which) {
				this.stopDragging(e);
				this.tracking = false;
				console.log("enyo.gesture.drag: mouse must be down to drag.");
				return;
			}
			if (this.dragEvent) {
				this.sendDrag(e);
			} else if (this.dy*this.dy + this.dx*this.dx >= this.hysteresisSquared) {
				this.sendDragStart(e);
				this.cancelHold();
			}
		}
	},
	up: function(e) {
		this.endTracking(e);
		this.stopDragging(e);
		this.cancelHold();
	},
	leave: function(e) {
		if (this.dragEvent) {
			this.sendDragOut(e);
		}
	},
	stopDragging: function(e) {
		if (this.dragEvent) {
			this.sendDrop(e);
			var handled = this.sendDragFinish(e);
			this.dragEvent = null;
			return handled;
		}
	},
	makeDragEvent: function(inType, inTarget, inEvent, inInfo) {
		var adx = Math.abs(this.dx), ady = Math.abs(this.dy);
		var h = adx > ady;
		// suggest locking if off-axis < 22.5 degrees
		var l = (h ? ady/adx : adx/ady) < 0.414;
		var e = {
			type: inType,
			dx: this.dx,
			dy: this.dy,
			pageX: inEvent.pageX,
			pageY: inEvent.pageY,
			clientX: inEvent.clientX,
			clientY: inEvent.clientY,
			horizontal: h,
			vertical: !h,
			lockable: l,
			target: inTarget,
			dragInfo: inInfo,
			ctrlKey: inEvent.ctrlKey,
			altKey: inEvent.altKey,
			metaKey: inEvent.metaKey,
			shiftKey: inEvent.shiftKey,
			srcEvent: inEvent.srcEvent
		};
		e.preventDefault = enyo.gesture.preventDefault;
		e.disablePrevention = enyo.gesture.disablePrevention;
		return e;
	},
	sendDragStart: function(e) {
		//console.log("dragstart");
		this.dragEvent = this.makeDragEvent("dragstart", this.target, e);
		enyo.dispatch(this.dragEvent);
	},
	sendDrag: function(e) {
		//console.log("sendDrag to " + this.dragEvent.target.id + ", over to " + e.target.id);
		// send dragOver event to the standard event target
		var synth = this.makeDragEvent("dragover", e.target, e, this.dragEvent.dragInfo);
		enyo.dispatch(synth);
		// send drag event to the drag source
		synth.type = "drag";
		synth.target = this.dragEvent.target;
		enyo.dispatch(synth);
	},
	sendDragFinish: function(e) {
		//console.log("dragfinish");
		var synth = this.makeDragEvent("dragfinish", this.dragEvent.target, e, this.dragEvent.dragInfo);
		synth.preventTap = function() {
			e.preventTap && e.preventTap();
		};
		enyo.dispatch(synth);
	},
	sendDragOut: function(e) {
		var synth = this.makeDragEvent("dragout", e.target, e, this.dragEvent.dragInfo);
		enyo.dispatch(synth);
	},
	sendDrop: function(e) {
		var synth = this.makeDragEvent("drop", e.target, e, this.dragEvent.dragInfo);
		synth.preventTap = function() {
			e.preventTap && e.preventTap();
		};
		enyo.dispatch(synth);
	},
	startTracking: function(e) {
		this.tracking = true;
		// note: use clientX/Y to be compatible with ie8
		this.px0 = e.clientX;
		this.py0 = e.clientY;
		this.flickInfo = {startEvent: e, moves: []};
		this.track(e);
	},
	track: function(e) {
		this.dx = e.clientX - this.px0;
		this.dy = e.clientY - this.py0;
		//
		var ti = this.flickInfo;
		ti.moves.push({
			x: e.clientX,
			y: e.clientY,
			t: enyo.now()
		});
		// track specified # of points
		if (ti.moves.length > this.trackCount) {
			ti.moves.shift();
		}
	},
	endTracking: function(e) {
		this.tracking = false;
		var ti = this.flickInfo;
		var moves = ti && ti.moves;
		if (moves && moves.length > 1) {
			// note: important to use up time to reduce flick
			// velocity based on time between move and up.
			var l = moves[moves.length-1];
			var n = enyo.now();
			// take the greatest of flick between each tracked move and last move
			for (var i=moves.length-2, dt=0, x1=0, y1=0, x=0, y=0, sx=0, sy=0, m; m=moves[i]; i--) {
				// this flick (this move - last move) / (this time - last time)
				dt = n - m.t;
				x1 = (l.x - m.x) / dt;
				y1 = (l.y - m.y) / dt;
				// establish flick direction
				sx = sx || (x1 < 0 ? -1 : (x1 > 0 ? 1 : 0));
				sy = sy || (y1 < 0 ? -1 : (y1 > 0 ? 1 : 0));
				// if either axis is a greater flick than previously recorded use this one
				if ((x1 * sx > x * sx) || (y1 * sy > y * sy)) {
					x = x1;
					y = y1;
				}
			}
			var v = Math.sqrt(x*x + y*y);
			if (v > this.minFlick) {
				// generate the flick using the start event so it has those coordinates
				this.sendFlick(ti.startEvent, x, y, v);
			}
		}
		this.flickInfo = null;
	},
	beginHold: function(e) {
		this.holdStart = enyo.now();
		this.holdJob = setInterval(enyo.bind(this, "sendHoldPulse", e), this.holdPulseDelay);
	},
	cancelHold: function() {
		clearInterval(this.holdJob);
		this.holdJob = null;
		if (this.sentHold) {
			this.sentHold = false;
			this.sendRelease(this.holdEvent);
		}
	},
	sendHoldPulse: function(inEvent) {
		if (!this.sentHold) {
			this.sentHold = true;
			this.sendHold(inEvent);
		}
		var e = enyo.gesture.makeEvent("holdpulse", inEvent);
		e.holdTime = enyo.now() - this.holdStart;
		enyo.dispatch(e);
	},
	sendHold: function(inEvent) {
		this.holdEvent = inEvent;
		var e = enyo.gesture.makeEvent("hold", inEvent);
		enyo.dispatch(e);
	},
	sendRelease: function(inEvent) {
		var e = enyo.gesture.makeEvent("release", inEvent);
		enyo.dispatch(e);
	},
	sendFlick: function(inEvent, inX, inY, inV) {
		var e = enyo.gesture.makeEvent("flick", inEvent);
		e.xVelocity = inX;
		e.yVelocity = inY;
		e.velocity = inV;
		enyo.dispatch(e);
	}
};
<commit_msg>* drag: add x/yDirection to drag events. reports the direction of the drag, +1 means right, down, -1 means left, up.<commit_after>/**
 Enyo supports a cross-platform set of drag events. These events are provide to allow a single set of event handlers to be
 written for all supports platforms, desktop and mobile alike. The following events are provided:

 * "dragstart", "dragfinish" - sent for pointer moves that exceed a certain threshhold
 * "drag", "drop" - sent to the original target of the pointer move to inform it about the item being moved over or released over another element
 * "dragover", "dragout" - sent in addition to over and out when there is an active drag

 * "hold" - generated when the pointer is held down without moving for a short period (about 200ms).
 * "release" - generated when the pointer is released after being held down, or the pointer is moved off of the node while still held down. The target is the same as the hold event.
 * "holdpulse" - generated when the pointer is held down without moving for a short period and periodically thereafter about every 200ms.
 Use this event to trigger an action after an arbitrary period of time. The holdTime property provides the elapsed time.
 * "flick" - generated when the user flicks the pointer quickly. This event provides flick velocity data: xVelocity is the velocity in the horizontal and
 yVelocity is the vertical velocity.

 * Note: on Android, touchmove event must be prevented via inEvent.preventDefault() or will not fire more than once and enyo dragging system
 * will not function correctly.
 */

//* @protected
enyo.dispatcher.features.push(
	function(e) {
		// NOTE: beware of properties in enyo.gesture inadvertently mapped to event types
		if (enyo.gesture.drag[e.type]) {
			return enyo.gesture.drag[e.type](e);
		}
	}
);

//* @public
enyo.gesture.drag = {
	//* @protected
	hysteresisSquared: 16,
	holdPulseDelay: 200,
	trackCount: 5,
	minFlick: 0.1,
	minTrack: 8,
	down: function(e) {
		// tracking if the mouse is down
		//console.log("tracking ON");
		// Note: 'tracking' flag indicates interest in mousemove, it's turned off
		// on mouseup
		// make sure to stop dragging in case the up event was not received.
		this.stopDragging(e);
		this.cancelHold();
		this.target = e.target;
		this.startTracking(e);
		this.beginHold(e);
	},
	move: function(e) {
		if (this.tracking) {
			this.track(e);
			// If the mouse is not down and we're tracking a drag, abort.
			// this error condition can occur on IE/Webkit after interaction with a scrollbar.
			if (!e.which) {
				this.stopDragging(e);
				this.tracking = false;
				console.log("enyo.gesture.drag: mouse must be down to drag.");
				return;
			}
			if (this.dragEvent) {
				this.sendDrag(e);
			} else if (this.dy*this.dy + this.dx*this.dx >= this.hysteresisSquared) {
				this.sendDragStart(e);
				this.cancelHold();
			}
		}
	},
	up: function(e) {
		this.endTracking(e);
		this.stopDragging(e);
		this.cancelHold();
	},
	leave: function(e) {
		if (this.dragEvent) {
			this.sendDragOut(e);
		}
	},
	stopDragging: function(e) {
		if (this.dragEvent) {
			this.sendDrop(e);
			var handled = this.sendDragFinish(e);
			this.dragEvent = null;
			return handled;
		}
	},
	makeDragEvent: function(inType, inTarget, inEvent, inInfo) {
		var adx = Math.abs(this.dx), ady = Math.abs(this.dy);
		var h = adx > ady;
		// suggest locking if off-axis < 22.5 degrees
		var l = (h ? ady/adx : adx/ady) < 0.414;
		var e = {
			type: inType,
			dx: this.dx,
			dy: this.dy,
			xDirection: this.xDirection,
			yDirection: this.yDirection,
			pageX: inEvent.pageX,
			pageY: inEvent.pageY,
			clientX: inEvent.clientX,
			clientY: inEvent.clientY,
			horizontal: h,
			vertical: !h,
			lockable: l,
			target: inTarget,
			dragInfo: inInfo,
			ctrlKey: inEvent.ctrlKey,
			altKey: inEvent.altKey,
			metaKey: inEvent.metaKey,
			shiftKey: inEvent.shiftKey,
			srcEvent: inEvent.srcEvent
		};
		e.preventDefault = enyo.gesture.preventDefault;
		e.disablePrevention = enyo.gesture.disablePrevention;
		return e;
	},
	sendDragStart: function(e) {
		//console.log("dragstart");
		this.dragEvent = this.makeDragEvent("dragstart", this.target, e);
		enyo.dispatch(this.dragEvent);
	},
	sendDrag: function(e) {
		//console.log("sendDrag to " + this.dragEvent.target.id + ", over to " + e.target.id);
		// send dragOver event to the standard event target
		var synth = this.makeDragEvent("dragover", e.target, e, this.dragEvent.dragInfo);
		enyo.dispatch(synth);
		// send drag event to the drag source
		synth.type = "drag";
		synth.target = this.dragEvent.target;
		enyo.dispatch(synth);
	},
	sendDragFinish: function(e) {
		//console.log("dragfinish");
		var synth = this.makeDragEvent("dragfinish", this.dragEvent.target, e, this.dragEvent.dragInfo);
		synth.preventTap = function() {
			e.preventTap && e.preventTap();
		};
		enyo.dispatch(synth);
	},
	sendDragOut: function(e) {
		var synth = this.makeDragEvent("dragout", e.target, e, this.dragEvent.dragInfo);
		enyo.dispatch(synth);
	},
	sendDrop: function(e) {
		var synth = this.makeDragEvent("drop", e.target, e, this.dragEvent.dragInfo);
		synth.preventTap = function() {
			e.preventTap && e.preventTap();
		};
		enyo.dispatch(synth);
	},
	startTracking: function(e) {
		this.tracking = true;
		// note: use clientX/Y to be compatible with ie8
		this.px0 = e.clientX;
		this.py0 = e.clientY;
		this.flickInfo = {startEvent: e, moves: []};
		this.track(e);
	},
	track: function(e) {
		this.lastDx = this.dx;
		this.lastDy = this.dy;
		this.dx = e.clientX - this.px0;
		this.dy = e.clientY - this.py0;
		this.xDirection = this.calcDirection(this.dx - this.lastDx);
		this.yDirection = this.calcDirection(this.dy - this.lastDy);
		//
		var ti = this.flickInfo;
		ti.moves.push({
			x: e.clientX,
			y: e.clientY,
			t: enyo.now()
		});
		// track specified # of points
		if (ti.moves.length > this.trackCount) {
			ti.moves.shift();
		}
	},
	endTracking: function(e) {
		this.tracking = false;
		var ti = this.flickInfo;
		var moves = ti && ti.moves;
		if (moves && moves.length > 1) {
			// note: important to use up time to reduce flick
			// velocity based on time between move and up.
			var l = moves[moves.length-1];
			var n = enyo.now();
			// take the greatest of flick between each tracked move and last move
			for (var i=moves.length-2, dt=0, x1=0, y1=0, x=0, y=0, sx=0, sy=0, m; m=moves[i]; i--) {
				// this flick (this move - last move) / (this time - last time)
				dt = n - m.t;
				x1 = (l.x - m.x) / dt;
				y1 = (l.y - m.y) / dt;
				// establish flick direction
				sx = sx || (x1 < 0 ? -1 : (x1 > 0 ? 1 : 0));
				sy = sy || (y1 < 0 ? -1 : (y1 > 0 ? 1 : 0));
				// if either axis is a greater flick than previously recorded use this one
				if ((x1 * sx > x * sx) || (y1 * sy > y * sy)) {
					x = x1;
					y = y1;
				}
			}
			var v = Math.sqrt(x*x + y*y);
			if (v > this.minFlick) {
				// generate the flick using the start event so it has those coordinates
				this.sendFlick(ti.startEvent, x, y, v);
			}
		}
		this.flickInfo = null;
	},
	calcDirection: function(inNum, inDefault) {
		return inNum > 0 ? 1 : (inNum < 0 ? -1 : inDefault);
	},
	beginHold: function(e) {
		this.holdStart = enyo.now();
		this.holdJob = setInterval(enyo.bind(this, "sendHoldPulse", e), this.holdPulseDelay);
	},
	cancelHold: function() {
		clearInterval(this.holdJob);
		this.holdJob = null;
		if (this.sentHold) {
			this.sentHold = false;
			this.sendRelease(this.holdEvent);
		}
	},
	sendHoldPulse: function(inEvent) {
		if (!this.sentHold) {
			this.sentHold = true;
			this.sendHold(inEvent);
		}
		var e = enyo.gesture.makeEvent("holdpulse", inEvent);
		e.holdTime = enyo.now() - this.holdStart;
		enyo.dispatch(e);
	},
	sendHold: function(inEvent) {
		this.holdEvent = inEvent;
		var e = enyo.gesture.makeEvent("hold", inEvent);
		enyo.dispatch(e);
	},
	sendRelease: function(inEvent) {
		var e = enyo.gesture.makeEvent("release", inEvent);
		enyo.dispatch(e);
	},
	sendFlick: function(inEvent, inX, inY, inV) {
		var e = enyo.gesture.makeEvent("flick", inEvent);
		e.xVelocity = inX;
		e.yVelocity = inY;
		e.velocity = inV;
		enyo.dispatch(e);
	}
};
<|endoftext|>


<commit_before>/*!
 * scrolling.js
 *
 * Copyright © 2016 Jorge M. Peláez | MIT license
 * http://j-pel.github.io/dynamize
 *
 */

(function() {

  'use strict';

  var elements = document.getElementsByClassName('scrollable');
  for (var i = 0; i < elements.length; i++) {
    var table = elements[i];
    var thead = elements[i].tHead;
    var page = table.parentNode;
    var header = document.createElement("div");
    var headert = document.createElement("table");
    var scroller = document.createElement("div");
    thead.classList.add('top-fixed');
    table.removeChild(thead);
    page.insertBefore(header,table);
    header.appendChild(headert);
    headert.appendChild(thead);
    page.insertBefore(scroller,table);
    page.removeChild(table);
    scroller.style.display = "block";
    ["position","width","height","maxWidth","maxHeight","minWidth","minHeight",
    "top","left","bottom","right"].forEach(function(prop){
      scroller.style[prop] = table.style[prop];
    });
    ["movable","rotable","sizable"].forEach(function(cls){
			if(table.classList.contains(cls)) {
				scroller.classList.add(cls);
				table.classList.remove(cls);
			}
		});
    table.style.width = "100%";
    scroller.style.overflow = "scroll";
    scroller.appendChild(table);
  }

  var elements = document.getElementsByClassName('fix-top');
  for (var i = elements.length-1; elements.length > 0;i = elements.length-1) {
    var table = elements[i].parentNode;
    var head = elements[i].cloneNode(true);
    table.removeChild(thead);
    var theadt = document.createElement("table");
    theadt.appendChild(thead);
    head.classList.remove('fix-top');
    var fixed = table.parentNode.insertBefore(document.createElement("table"),table);
    fixed.classList.add('top-fixed');
    fixed.appendChild(head);
    fixed.style.position = "sticky";
    fixed.style.top = "0px";
    fixed.style.width = "100%";
    table.removeChild(elements[i]);
  }
  window.addEventListener('resize', onResize, false);
  onResize();

  function onResize() {
    var elements = document.getElementsByClassName('top-fixed');
    for (var e = 0; e < elements.length; e++) {
      var head = elements[e].rows[0].cells;
      var body = elements[e].parentNode.parentNode.nextSibling.firstChild.tBodies[0]
      if (body.rows.length==0) return(0);
      body = body.rows[0].cells;
      for (var i=0;i<body.length;i++) {
        head[i].style.minWidth = body[i].clientWidth + "px";
      }
    }
  }

})();
<commit_msg>Add: refresh call in scrolling.js for header resize<commit_after>/*!
 * scrolling.js
 *
 * Copyright © 2016 Jorge M. Peláez | MIT license
 * http://j-pel.github.io/dynamize
 *
 */

(function(exports) {

  'use strict';

  /*!
   * refresh()
   * Resizes the fixed headers for all columns in accordance to
   * the table contents.
   *
   * @api public
   */
  var refresh = exports.refresh = function() {
    var elements = document.getElementsByClassName('top-fixed');
    for (var e = 0; e < elements.length; e++) {
      var head = elements[e].rows[0].cells;
      var body = elements[e].parentNode.parentNode.nextSibling.firstChild.tBodies[0]
      if (body.rows.length==0) return(0);
      if (body.rows[0].cells.length>=head.length) {
        if (body.parentNode.parentNode.offsetWidth>body.offsetWidth) {
          var scroll_spacer = elements[e].firstChild.appendChild(document.createElement("th"));
          scroll_spacer.style.minWidth = (body.parentNode.parentNode.offsetWidth - body.offsetWidth)+"px";
        }
      }
      body = body.rows[0].cells;
      for (var i=0;i<body.length;i++) {
        head[i].style.minWidth = (body[i].clientWidth-2) + "px";
      }
    }
  }

  /*
   * Private utils to modify the DOM in order to create the fixed headers
   */

  var elements = document.getElementsByClassName('scrollable');
  for (var i = 0; i < elements.length; i++) {
    var table = elements[i];
    var thead = elements[i].tHead;
    var page = table.parentNode;
    var header = document.createElement("div");
    var headert = document.createElement("table");
    var scroller = document.createElement("div");
    thead.classList.add('top-fixed');
    table.removeChild(thead);
    page.insertBefore(header,table);
    header.appendChild(headert);
    headert.appendChild(thead);
    page.insertBefore(scroller,table);
    page.removeChild(table);
    scroller.style.display = "block";
    ["position","width","height","maxWidth","maxHeight","minWidth","minHeight",
    "top","left","bottom","right"].forEach(function(prop){
      scroller.style[prop] = table.style[prop];
    });
    ["movable","rotable","sizable"].forEach(function(cls){
			if(table.classList.contains(cls)) {
				scroller.classList.add(cls);
				table.classList.remove(cls);
			}
		});
    table.style.width = "100%";
    scroller.style.overflow = "scroll";
    scroller.appendChild(table);
  }

  var elements = document.getElementsByClassName('fix-top');
  for (var i = elements.length-1; elements.length > 0;i = elements.length-1) {
    var table = elements[i].parentNode;
    var head = elements[i].cloneNode(true);
    table.removeChild(thead);
    var theadt = document.createElement("table");
    theadt.appendChild(thead);
    head.classList.remove('fix-top');
    var fixed = table.parentNode.insertBefore(document.createElement("table"),table);
    fixed.classList.add('top-fixed');
    fixed.appendChild(head);
    fixed.style.position = "sticky";
    fixed.style.top = "0px";
    fixed.style.width = "100%";
    table.removeChild(elements[i]);
  }
  window.addEventListener('resize', onResize, false);

  function onResize() {
    refresh();
  }

/* NOTE: for triggering the resize event, in all browsers, use:
  var evt = window.document.createEvent('UIEvents');
  evt.initUIEvent('resize', true, false, window, 0);
  window.dispatchEvent(evt);
*/

})(typeof exports === 'undefined'? this['scrolling']={}: exports);
<|endoftext|>


<commit_before>/*
Charlie Roberts 2012 MIT License
Requires gibber.js and chord.js found in the Gibber download.

Usage (assume s is a sine oscillator that has the Gibber mod method) :
a = audioLib.Arp(s, "Cm7", 2, .25, "updown");
*/

(function myPlugin(){

function initPlugin(audioLib){
(function(audioLib){

function Arp(notation, beats, mode, mult) {
	this.speed = isNaN(beats) ? _4 : beats;
	this.mode = mode || "up";
	this.notation = notation || "Cm7";
	this.mult = mult || 1;

	this.type = "complex";
	this.name = "Arp";

	this.notes = [];
	this.modded = [];

	this.seq = Seq();

	this.chord(this.notation);
	this.original = this.notes.slice(0);

	(function() {
		var speed = this.speed;
		var _that = this;

		Object.defineProperties(_that, {
			"speed": {
				get: function(){ return speed; },
				set: function(value) {
					speed = value;
					this.seq.setSequence(this.notes, speed, false);
				}
			}
		});
	})();
}

Arp.prototype = {
	chord : function(_chord, shouldReset) {
		var arr = [];

		this.notation = _chord;

		for(var i = 0; i < this.mult; i++) {
			var tmp = [];

			var _root = this.notation.slice(0,1);
			var _octave, _quality;
			if(isNaN(this.notation.charAt(1))) { 	// if true, then there is a sharp or flat...
				_root += this.notation.charAt(1);	// ... so add it to the root name
				_octave = parseInt( this.notation.slice(2,3) );
				_quality = this.notation.slice(3);
			}else{
				_octave = parseInt( this.notation.slice(1,2) );
				_quality = this.notation.slice(2);
			}
			_octave += i;

			var _chord = teoria.note(_root + _octave).chord(_quality);
			for(var j = 0; j < _chord.notes.length; j++) {
				var n = _chord.notes[j];
				tmp[j] = n;
			}
			arr = arr.concat(tmp);
		}
		this.notes = this.modes[this.mode]( arr );
		this.seq.setSequence(this.notes, this.speed, shouldReset);
	},
	set : function(_chord, _speed, _mode, octaveMult, shouldReset) {
		this.speed = _speed || this.speed;
		this.mode = _mode || this.mode;
		this.mult = octaveMult || this.mult;

		this.chord(_chord, shouldReset); // also sets sequence
	},

	slave : function(gen) {
		this.gen = gen;
		this.seq.slave(this.gen);
		if(typeof this.gen.note === "undefined") { this.seq.outputMessage = "freq"; }
	},

	modes : {
		up : function(array) {
			return array;
		},
		down : function(array) {
			return array.reverse();
		},
		updown : function(array) {
			var _tmp = array.slice(0);
			_tmp.reverse();
			return array.concat(_tmp);
		}
	},
	shuffle: function() { this.seq.shuffle(); },
	reset : function(num)  {
		if(isNaN(num)) {
			this.seq.reset();
		}else{
			this.seq.reset(num);
		}
	},

	retain : function(num) {
		if(isNaN(num)) {
			this.seq.retain();
		}else{
			this.seq.retain(num);
		}
	},

	replace : function(replacement){
		if(replacement.name != "Arp") {
			if(replacement.type == "mod") {
				var idx = jQuery.inArray( this.step, this.gen.mods );
				if(idx > -1) {
					this.gen.mods.splice(idx,1,replacement);
					replacement.gens.push(this.gen);
				}
			}
		}else{
			var idx = jQuery.inArray( this.step, this.gen.mods );
			if(idx > -1) {
				this.gen.mods.splice(idx,1,replacement.step);
				replacement.gens.push(this.gen);
			}
		}
	},
}

audioLib.Arpeggiator = Arp;

}(audioLib));
audioLib.plugins('Arpeggiator', myPlugin);
}

if (typeof audioLib === 'undefined' && typeof exports !== 'undefined'){
	exports.init = initPlugin;
} else {
	initPlugin(audioLib);
}

}());

function Arp(notation, beats, mode, mult) {
	return new audioLib.Arpeggiator(notation, beats, mode, mult);
}<commit_msg>fixed bug in Arpeggiator related to metaprogramming<commit_after>/*
Charlie Roberts 2012 MIT License
Requires gibber.js and chord.js found in the Gibber download.

Usage (assume s is a sine oscillator that has the Gibber mod method) :
a = audioLib.Arp(s, "Cm7", 2, .25, "updown");
*/

(function myPlugin(){

function initPlugin(audioLib){
(function(audioLib){

function Arp(notation, beats, mode, mult) {
	this.mode = mode || "up";
	this.notation = notation || "Cm7";
	this.mult = mult || 1;
	this.speed = isNaN(beats) ? _4 : beats;

	this.type = "complex";
	this.name = "Arp";

	this.notes = [];
	this.modded = [];

	this.seq = Seq();

	this.original = this.notes.slice(0);

	(function(obj) {
		var that = obj;
		var speed = obj.speed;

		Object.defineProperties(that, {
			"speed": {
				get: function(){ return speed; },
				set: function(value) {
					speed = value;
					this.seq.setSequence(this.notes, speed, false);
				}
			}
		});
	})(this);

	this.chord(this.notation);
}

Arp.prototype = {
	chord : function(_chord, shouldReset) {
		var arr = [];

		this.notation = _chord;

		for(var i = 0; i < this.mult; i++) {
			var tmp = [];

			var _root = this.notation.slice(0,1);
			var _octave, _quality;
			if(isNaN(this.notation.charAt(1))) { 	// if true, then there is a sharp or flat...
				_root += this.notation.charAt(1);	// ... so add it to the root name
				_octave = parseInt( this.notation.slice(2,3) );
				_quality = this.notation.slice(3);
			}else{
				_octave = parseInt( this.notation.slice(1,2) );
				_quality = this.notation.slice(2);
			}
			_octave += i;

			var _chord = teoria.note(_root + _octave).chord(_quality);
			for(var j = 0; j < _chord.notes.length; j++) {
				var n = _chord.notes[j];
				tmp[j] = n;
			}
			arr = arr.concat(tmp);
		}
		this.notes = this.modes[this.mode]( arr );
		this.seq.setSequence(this.notes, this.speed, shouldReset);
	},
	set : function(_chord, _speed, _mode, octaveMult, shouldReset) {
		this.speed = _speed || this.speed;
		this.mode = _mode || this.mode;
		this.mult = octaveMult || this.mult;

		this.chord(_chord, shouldReset); // also sets sequence
	},

	slave : function(gen) {
		this.gen = gen;
		this.seq.slave(this.gen);
		if(typeof this.gen.note === "undefined") { this.seq.outputMessage = "freq"; }
	},

	modes : {
		up : function(array) {
			return array;
		},
		down : function(array) {
			return array.reverse();
		},
		updown : function(array) {
			var _tmp = array.slice(0);
			_tmp.reverse();
			return array.concat(_tmp);
		}
	},
	shuffle: function() { this.seq.shuffle(); },
	reset : function(num)  {
		if(isNaN(num)) {
			this.seq.reset();
		}else{
			this.seq.reset(num);
		}
	},

	retain : function(num) {
		if(isNaN(num)) {
			this.seq.retain();
		}else{
			this.seq.retain(num);
		}
	},

	replace : function(replacement){
		if(replacement.name != "Arp") {
			if(replacement.type == "mod") {
				var idx = jQuery.inArray( this.step, this.gen.mods );
				if(idx > -1) {
					this.gen.mods.splice(idx,1,replacement);
					replacement.gens.push(this.gen);
				}
			}
		}else{
			var idx = jQuery.inArray( this.step, this.gen.mods );
			if(idx > -1) {
				this.gen.mods.splice(idx,1,replacement.step);
				replacement.gens.push(this.gen);
			}
		}
	},
}

audioLib.Arpeggiator = Arp;

}(audioLib));
audioLib.plugins('Arpeggiator', myPlugin);
}

if (typeof audioLib === 'undefined' && typeof exports !== 'undefined'){
	exports.init = initPlugin;
} else {
	initPlugin(audioLib);
}

}());

function Arp(notation, beats, mode, mult) {
	return new audioLib.Arpeggiator(notation, beats, mode, mult);
}<|endoftext|>


<commit_before>var Fiber = Npm.require('fibers');
var Future = Npm.require('fibers/future');

var PHASE = {
  INITIALIZING: 1,
  FETCHING: 2,
  STEADY: 3
};

// OplogObserveDriver is an alternative to PollingObserveDriver which follows
// the Mongo operation log instead of just re-polling the query. It obeys the
// same simple interface: constructing it starts sending observeChanges
// callbacks (and a ready() invocation) to the ObserveMultiplexer, and you stop
// it by calling the stop() method.
OplogObserveDriver = function (options) {
  var self = this;

  self._usesOplog = true;  // tests look at this

  self._cursorDescription = options.cursorDescription;
  self._mongoHandle = options.mongoHandle;
  self._multiplexer = options.multiplexer;
  if (options.ordered)
    throw Error("OplogObserveDriver only supports unordered observeChanges");

  self._stopped = false;
  self._stopHandles = [];

  Package.facts && Package.facts.Facts.incrementServerFact(
    "mongo-livedata", "oplog-observers", 1);

  self._phase = PHASE.INITIALIZING;

  self._published = new LocalCollection._IdMap;
  var selector = self._cursorDescription.selector;
  self._selectorFn = LocalCollection._compileSelector(
    self._cursorDescription.selector);
  var projection = self._cursorDescription.options.fields || {};
  self._projectionFn = LocalCollection._compileProjection(projection);
  // Projection function, result of combining important fields for selector and
  // existing fields projection
  var sharedProjection = LocalCollection._combineSelectorAndProjection(
    selector, projection);
  self._sharedProjectionFn = LocalCollection._compileProjection(
    sharedProjection);

  self._needToFetch = new LocalCollection._IdMap;
  self._currentlyFetching = new LocalCollection._IdMap;

  self._writesToCommitWhenWeReachSteady = [];

  forEachTrigger(self._cursorDescription, function (trigger) {
    self._stopHandles.push(self._mongoHandle._oplogHandle.onOplogEntry(
      trigger, function (notification) {
        var op = notification.op;
        if (op.op === 'c') {
          // XXX actually, drop collection needs to be handled by doing a
          // re-query
          self._published.forEach(function (fields, id) {
            self._remove(id);
          });
        } else {
          // All other operators should be handled depending on phase
          if (self._phase === PHASE.INITIALIZING)
            self._handleOplogEntryInitializing(op);
          else
            self._handleOplogEntrySteadyOrFetching(op);
        }
      }
    ));
  });

  // XXX ordering w.r.t. everything else?
  self._stopHandles.push(listenAll(
    self._cursorDescription, function (notification, complete) {
      // If we're not in a write fence, we don't have to do anything.
      var fence = DDPServer._CurrentWriteFence.get();
      if (!fence) {
        complete();
        return;
      }
      var write = fence.beginWrite();
      // This write cannot complete until we've caught up to "this point" in the
      // oplog, and then made it back to the steady state.
      Meteor.defer(complete);
      self._mongoHandle._oplogHandle.waitUntilCaughtUp();
      if (self._stopped) {
        // We're stopped, so just immediately commit.
        write.committed();
      } else if (self._phase === PHASE.STEADY) {
        // Make sure that all of the callbacks have made it through the
        // multiplexer and been delivered to ObserveHandles before committing
        // writes.
        self._multiplexer.onFlush(function () {
          write.committed();
        });
      } else {
        self._writesToCommitWhenWeReachSteady.push(write);
      }
    }
  ));

  // Give _observeChanges a chance to add the new ObserveHandle to our
  // multiplexer, so that the added calls get streamed.
  Meteor.defer(function () {
    self._runInitialQuery();
  });
};

_.extend(OplogObserveDriver.prototype, {
  _add: function (doc) {
    var self = this;
    var id = doc._id;
    var fields = _.clone(doc);
    delete fields._id;
    if (self._published.has(id))
      throw Error("tried to add something already published " + id);
    self._published.set(id, self._sharedProjectionFn(fields));
    self._multiplexer.added(id, self._projectionFn(fields));
  },
  _remove: function (id) {
    var self = this;
    if (!self._published.has(id))
      throw Error("tried to remove something unpublished " + id);
    self._published.remove(id);
    self._multiplexer.removed(id);
  },
  _handleDoc: function (id, newDoc) {
    var self = this;
    newDoc = _.clone(newDoc);
    var matchesNow = newDoc && self._selectorFn(newDoc);
    var matchedBefore = self._published.has(id);
    if (matchesNow && !matchedBefore) {
      self._add(newDoc);
    } else if (matchedBefore && !matchesNow) {
      self._remove(id);
    } else if (matchesNow) {
      var oldDoc = self._published.get(id);
      if (!oldDoc)
        throw Error("thought that " + id + " was there!");
      delete newDoc._id;
      self._published.set(id, self._sharedProjectionFn(newDoc));
      var changed = LocalCollection._makeChangedFields(_.clone(newDoc), oldDoc);
      changed = self._projectionFn(changed);
      if (!_.isEmpty(changed))
        self._multiplexer.changed(id, changed);
    }
  },
  _fetchModifiedDocuments: function () {
    var self = this;
    self._phase = PHASE.FETCHING;
    while (!self._stopped && !self._needToFetch.empty()) {
      if (self._phase !== PHASE.FETCHING)
        throw new Error("phase in fetchModifiedDocuments: " + self._phase);

      self._currentlyFetching = self._needToFetch;
      self._needToFetch = new LocalCollection._IdMap;
      var waiting = 0;
      var anyError = null;
      var fut = new Future;
      // This loop is safe, because _currentlyFetching will not be updated
      // during this loop (in fact, it is never mutated).
      self._currentlyFetching.forEach(function (cacheKey, id) {
        waiting++;
        self._mongoHandle._docFetcher.fetch(
          self._cursorDescription.collectionName, id, cacheKey,
          function (err, doc) {
            if (err) {
              if (!anyError)
                anyError = err;
            } else if (!self._stopped) {
              self._handleDoc(id, doc);
            }
            waiting--;
            if (waiting == 0)
              fut.return();
          });
      });
      fut.wait();
      if (anyError)
        throw anyError;
      self._currentlyFetching = new LocalCollection._IdMap;
    }
    self._beSteady();
  },
  _beSteady: function () {
    var self = this;
    self._phase = PHASE.STEADY;
    var writes = self._writesToCommitWhenWeReachSteady;
    self._writesToCommitWhenWeReachSteady = [];
    self._multiplexer.onFlush(function () {
      _.each(writes, function (w) {
        w.committed();
      });
    });
  },
  _handleOplogEntryInitializing: function (op) {
    var self = this;
    self._needToFetch.set(idForOp(op), op.ts.toString());
  },
  _handleOplogEntrySteadyOrFetching: function (op) {
    var self = this;
    var id = idForOp(op);
    // If we're already fetching this one, or about to, we can't optimize; make
    // sure that we fetch it again if necessary.
    if (self._currentlyFetching.has(id) || self._needToFetch.has(id)) {
      if (self._phase !== PHASE.FETCHING)
        throw Error("map not empty during steady phase");
      self._needToFetch.set(id, op.ts.toString());
      return;
    }

    if (op.op === 'd') {
      if (self._published.has(id))
        self._remove(id);
    } else if (op.op === 'i') {
      if (self._published.has(id))
        throw new Error("insert found for already-existing ID");

      // XXX what if selector yields?  for now it can't but later it could have
      // $where
      if (self._selectorFn(op.o))
        self._add(op.o);
    } else if (op.op === 'u') {
      // Is this a modifier ($set/$unset, which may require us to poll the
      // database to figure out if the whole document matches the selector) or a
      // replacement (in which case we can just directly re-evaluate the
      // selector)?
      var isReplace = !_.has(op.o, '$set') && !_.has(op.o, '$unset');

      if (isReplace) {
        self._handleDoc(id, _.extend({_id: id}, op.o));
      } else if (self._published.has(id)) {
        // Oh great, we actually know what the document is, so we can apply
        // this directly.
        var newDoc = EJSON.clone(self._published.get(id));
        newDoc._id = id;
        LocalCollection._modify(newDoc, op.o);
        self._handleDoc(id, self._sharedProjectionFn(newDoc));
      } else if (LocalCollection._canSelectorBecomeTrueByModifier(
        self._cursorDescription.selector, op.o)) {
        self._needToFetch.set(id, op.ts.toString());
        if (self._phase === PHASE.STEADY)
          self._fetchModifiedDocuments();
      }
    } else {
      throw Error("XXX SURPRISING OPERATION: " + op);
    }
  },
  _runInitialQuery: function () {
    var self = this;
    if (self._stopped)
      throw new Error("oplog stopped surprisingly early");

    var initialCursor = new Cursor(self._mongoHandle, self._cursorDescription);
    initialCursor.forEach(function (initialDoc) {
      self._add(initialDoc);
    });
    if (self._stopped)
      throw new Error("oplog stopped quite early");
    // Allow observeChanges calls to return. (After this, it's possible for
    // stop() to be called.)
    self._multiplexer.ready();

    if (self._stopped)
      return;
    self._mongoHandle._oplogHandle.waitUntilCaughtUp();

    if (self._stopped)
      return;
    if (self._phase !== PHASE.INITIALIZING)
      throw Error("Phase unexpectedly " + self._phase);

    if (self._needToFetch.empty()) {
      self._beSteady();
    } else {
      self._fetchModifiedDocuments();
    }
  },
  // This stop function is invoked from the onStop of the ObserveMultiplexer, so
  // it shouldn't actually be possible to call it until the multiplexer is
  // ready.
  stop: function () {
    var self = this;
    if (self._stopped)
      return;
    self._stopped = true;
    _.each(self._stopHandles, function (handle) {
      handle.stop();
    });

    // Note: we *don't* use multiplexer.onFlush here because this stop
    // callback is actually invoked by the multiplexer itself when it has
    // determined that there are no handles left. So nothing is actually going
    // to get flushed (and it's probably not valid to call methods on the
    // dying multiplexer).
    _.each(self._writesToCommitWhenWeReachSteady, function (w) {
      w.committed();
    });
    self._writesToCommitWhenWeReachSteady = null;

    // Proactively drop references to potentially big things.
    self._published = null;
    self._needToFetch = null;
    self._currentlyFetching = null;
    self._oplogEntryHandle = null;
    self._listenersHandle = null;

    Package.facts && Package.facts.Facts.incrementServerFact(
      "mongo-livedata", "oplog-observers", -1);
  }
});

// Does our oplog tailing code support this cursor? For now, we are being very
// conservative and allowing only simple queries with simple options.
// (This is a "static method".)
OplogObserveDriver.cursorSupported = function (cursorDescription) {
  // First, check the options.
  var options = cursorDescription.options;

  // Did the user say no explicitly?
  if (options._disableOplog)
    return false;

  // This option (which are mostly used for sorted cursors) require us to figure
  // out where a given document fits in an order to know if it's included or
  // not, and we don't track that information when doing oplog tailing.
  if (options.limit || options.skip) return false;

  // If a fields projection option is given check if it is supported by
  // minimongo (some operators are not supported).
  if (options.fields) {
    try {
      LocalCollection._checkSupportedProjection(options.fields);
    } catch (e) {
      if (e.name === "MinimongoError")
        return false;
      else
        throw e;
    }
  }

  // For now, we're just dealing with equality queries: no $operators, regexps,
  // or $and/$or/$where/etc clauses. We can expand the scope of what we're
  // comfortable processing later. ($where will get pretty scary since it will
  // allow selector processing to yield!)
  return _.all(cursorDescription.selector, function (value, field) {
    // No logical operators like $and.
    if (field.substr(0, 1) === '$')
      return false;
    // We only allow scalars, not sub-documents or $operators or RegExp.
    // XXX Date would be easy too, though I doubt anyone is doing equality
    // lookups on dates
    return typeof value === "string" ||
      typeof value === "number" ||
      typeof value === "boolean" ||
      value === null ||
      value instanceof Meteor.Collection.ObjectID;
  });
};

MongoTest.OplogObserveDriver = OplogObserveDriver;
<commit_msg>Make _currentlyFetching null unless FETCHING<commit_after>var Fiber = Npm.require('fibers');
var Future = Npm.require('fibers/future');

var PHASE = {
  INITIALIZING: 1,
  FETCHING: 2,
  STEADY: 3
};

// OplogObserveDriver is an alternative to PollingObserveDriver which follows
// the Mongo operation log instead of just re-polling the query. It obeys the
// same simple interface: constructing it starts sending observeChanges
// callbacks (and a ready() invocation) to the ObserveMultiplexer, and you stop
// it by calling the stop() method.
OplogObserveDriver = function (options) {
  var self = this;

  self._usesOplog = true;  // tests look at this

  self._cursorDescription = options.cursorDescription;
  self._mongoHandle = options.mongoHandle;
  self._multiplexer = options.multiplexer;
  if (options.ordered)
    throw Error("OplogObserveDriver only supports unordered observeChanges");

  self._stopped = false;
  self._stopHandles = [];

  Package.facts && Package.facts.Facts.incrementServerFact(
    "mongo-livedata", "oplog-observers", 1);

  self._phase = PHASE.INITIALIZING;

  self._published = new LocalCollection._IdMap;
  var selector = self._cursorDescription.selector;
  self._selectorFn = LocalCollection._compileSelector(
    self._cursorDescription.selector);
  var projection = self._cursorDescription.options.fields || {};
  self._projectionFn = LocalCollection._compileProjection(projection);
  // Projection function, result of combining important fields for selector and
  // existing fields projection
  var sharedProjection = LocalCollection._combineSelectorAndProjection(
    selector, projection);
  self._sharedProjectionFn = LocalCollection._compileProjection(
    sharedProjection);

  self._needToFetch = new LocalCollection._IdMap;
  self._currentlyFetching = null;

  self._writesToCommitWhenWeReachSteady = [];

  forEachTrigger(self._cursorDescription, function (trigger) {
    self._stopHandles.push(self._mongoHandle._oplogHandle.onOplogEntry(
      trigger, function (notification) {
        var op = notification.op;
        if (op.op === 'c') {
          // XXX actually, drop collection needs to be handled by doing a
          // re-query
          self._published.forEach(function (fields, id) {
            self._remove(id);
          });
        } else {
          // All other operators should be handled depending on phase
          if (self._phase === PHASE.INITIALIZING)
            self._handleOplogEntryInitializing(op);
          else
            self._handleOplogEntrySteadyOrFetching(op);
        }
      }
    ));
  });

  // XXX ordering w.r.t. everything else?
  self._stopHandles.push(listenAll(
    self._cursorDescription, function (notification, complete) {
      // If we're not in a write fence, we don't have to do anything.
      var fence = DDPServer._CurrentWriteFence.get();
      if (!fence) {
        complete();
        return;
      }
      var write = fence.beginWrite();
      // This write cannot complete until we've caught up to "this point" in the
      // oplog, and then made it back to the steady state.
      Meteor.defer(complete);
      self._mongoHandle._oplogHandle.waitUntilCaughtUp();
      if (self._stopped) {
        // We're stopped, so just immediately commit.
        write.committed();
      } else if (self._phase === PHASE.STEADY) {
        // Make sure that all of the callbacks have made it through the
        // multiplexer and been delivered to ObserveHandles before committing
        // writes.
        self._multiplexer.onFlush(function () {
          write.committed();
        });
      } else {
        self._writesToCommitWhenWeReachSteady.push(write);
      }
    }
  ));

  // Give _observeChanges a chance to add the new ObserveHandle to our
  // multiplexer, so that the added calls get streamed.
  Meteor.defer(function () {
    self._runInitialQuery();
  });
};

_.extend(OplogObserveDriver.prototype, {
  _add: function (doc) {
    var self = this;
    var id = doc._id;
    var fields = _.clone(doc);
    delete fields._id;
    if (self._published.has(id))
      throw Error("tried to add something already published " + id);
    self._published.set(id, self._sharedProjectionFn(fields));
    self._multiplexer.added(id, self._projectionFn(fields));
  },
  _remove: function (id) {
    var self = this;
    if (!self._published.has(id))
      throw Error("tried to remove something unpublished " + id);
    self._published.remove(id);
    self._multiplexer.removed(id);
  },
  _handleDoc: function (id, newDoc) {
    var self = this;
    newDoc = _.clone(newDoc);
    var matchesNow = newDoc && self._selectorFn(newDoc);
    var matchedBefore = self._published.has(id);
    if (matchesNow && !matchedBefore) {
      self._add(newDoc);
    } else if (matchedBefore && !matchesNow) {
      self._remove(id);
    } else if (matchesNow) {
      var oldDoc = self._published.get(id);
      if (!oldDoc)
        throw Error("thought that " + id + " was there!");
      delete newDoc._id;
      self._published.set(id, self._sharedProjectionFn(newDoc));
      var changed = LocalCollection._makeChangedFields(_.clone(newDoc), oldDoc);
      changed = self._projectionFn(changed);
      if (!_.isEmpty(changed))
        self._multiplexer.changed(id, changed);
    }
  },
  _fetchModifiedDocuments: function () {
    var self = this;
    self._phase = PHASE.FETCHING;
    while (!self._stopped && !self._needToFetch.empty()) {
      if (self._phase !== PHASE.FETCHING)
        throw new Error("phase in fetchModifiedDocuments: " + self._phase);

      self._currentlyFetching = self._needToFetch;
      self._needToFetch = new LocalCollection._IdMap;
      var waiting = 0;
      var anyError = null;
      var fut = new Future;
      // This loop is safe, because _currentlyFetching will not be updated
      // during this loop (in fact, it is never mutated).
      self._currentlyFetching.forEach(function (cacheKey, id) {
        waiting++;
        self._mongoHandle._docFetcher.fetch(
          self._cursorDescription.collectionName, id, cacheKey,
          function (err, doc) {
            if (err) {
              if (!anyError)
                anyError = err;
            } else if (!self._stopped) {
              self._handleDoc(id, doc);
            }
            waiting--;
            if (waiting == 0)
              fut.return();
          });
      });
      fut.wait();
      if (anyError)
        throw anyError;
      self._currentlyFetching = null;
    }
    self._beSteady();
  },
  _beSteady: function () {
    var self = this;
    self._phase = PHASE.STEADY;
    var writes = self._writesToCommitWhenWeReachSteady;
    self._writesToCommitWhenWeReachSteady = [];
    self._multiplexer.onFlush(function () {
      _.each(writes, function (w) {
        w.committed();
      });
    });
  },
  _handleOplogEntryInitializing: function (op) {
    var self = this;
    self._needToFetch.set(idForOp(op), op.ts.toString());
  },
  _handleOplogEntrySteadyOrFetching: function (op) {
    var self = this;
    var id = idForOp(op);
    // If we're already fetching this one, or about to, we can't optimize; make
    // sure that we fetch it again if necessary.
    if (self._phase === PHASE.FETCHING &&
        (self._currentlyFetching.has(id) || self._needToFetch.has(id))) {
      self._needToFetch.set(id, op.ts.toString());
      return;
    }

    if (op.op === 'd') {
      if (self._published.has(id))
        self._remove(id);
    } else if (op.op === 'i') {
      if (self._published.has(id))
        throw new Error("insert found for already-existing ID");

      // XXX what if selector yields?  for now it can't but later it could have
      // $where
      if (self._selectorFn(op.o))
        self._add(op.o);
    } else if (op.op === 'u') {
      // Is this a modifier ($set/$unset, which may require us to poll the
      // database to figure out if the whole document matches the selector) or a
      // replacement (in which case we can just directly re-evaluate the
      // selector)?
      var isReplace = !_.has(op.o, '$set') && !_.has(op.o, '$unset');

      if (isReplace) {
        self._handleDoc(id, _.extend({_id: id}, op.o));
      } else if (self._published.has(id)) {
        // Oh great, we actually know what the document is, so we can apply
        // this directly.
        var newDoc = EJSON.clone(self._published.get(id));
        newDoc._id = id;
        LocalCollection._modify(newDoc, op.o);
        self._handleDoc(id, self._sharedProjectionFn(newDoc));
      } else if (LocalCollection._canSelectorBecomeTrueByModifier(
        self._cursorDescription.selector, op.o)) {
        self._needToFetch.set(id, op.ts.toString());
        if (self._phase === PHASE.STEADY)
          self._fetchModifiedDocuments();
      }
    } else {
      throw Error("XXX SURPRISING OPERATION: " + op);
    }
  },
  _runInitialQuery: function () {
    var self = this;
    if (self._stopped)
      throw new Error("oplog stopped surprisingly early");

    var initialCursor = new Cursor(self._mongoHandle, self._cursorDescription);
    initialCursor.forEach(function (initialDoc) {
      self._add(initialDoc);
    });
    if (self._stopped)
      throw new Error("oplog stopped quite early");
    // Allow observeChanges calls to return. (After this, it's possible for
    // stop() to be called.)
    self._multiplexer.ready();

    if (self._stopped)
      return;
    self._mongoHandle._oplogHandle.waitUntilCaughtUp();

    if (self._stopped)
      return;
    if (self._phase !== PHASE.INITIALIZING)
      throw Error("Phase unexpectedly " + self._phase);

    if (self._needToFetch.empty()) {
      self._beSteady();
    } else {
      self._fetchModifiedDocuments();
    }
  },
  // This stop function is invoked from the onStop of the ObserveMultiplexer, so
  // it shouldn't actually be possible to call it until the multiplexer is
  // ready.
  stop: function () {
    var self = this;
    if (self._stopped)
      return;
    self._stopped = true;
    _.each(self._stopHandles, function (handle) {
      handle.stop();
    });

    // Note: we *don't* use multiplexer.onFlush here because this stop
    // callback is actually invoked by the multiplexer itself when it has
    // determined that there are no handles left. So nothing is actually going
    // to get flushed (and it's probably not valid to call methods on the
    // dying multiplexer).
    _.each(self._writesToCommitWhenWeReachSteady, function (w) {
      w.committed();
    });
    self._writesToCommitWhenWeReachSteady = null;

    // Proactively drop references to potentially big things.
    self._published = null;
    self._needToFetch = null;
    self._currentlyFetching = null;
    self._oplogEntryHandle = null;
    self._listenersHandle = null;

    Package.facts && Package.facts.Facts.incrementServerFact(
      "mongo-livedata", "oplog-observers", -1);
  }
});

// Does our oplog tailing code support this cursor? For now, we are being very
// conservative and allowing only simple queries with simple options.
// (This is a "static method".)
OplogObserveDriver.cursorSupported = function (cursorDescription) {
  // First, check the options.
  var options = cursorDescription.options;

  // Did the user say no explicitly?
  if (options._disableOplog)
    return false;

  // This option (which are mostly used for sorted cursors) require us to figure
  // out where a given document fits in an order to know if it's included or
  // not, and we don't track that information when doing oplog tailing.
  if (options.limit || options.skip) return false;

  // If a fields projection option is given check if it is supported by
  // minimongo (some operators are not supported).
  if (options.fields) {
    try {
      LocalCollection._checkSupportedProjection(options.fields);
    } catch (e) {
      if (e.name === "MinimongoError")
        return false;
      else
        throw e;
    }
  }

  // For now, we're just dealing with equality queries: no $operators, regexps,
  // or $and/$or/$where/etc clauses. We can expand the scope of what we're
  // comfortable processing later. ($where will get pretty scary since it will
  // allow selector processing to yield!)
  return _.all(cursorDescription.selector, function (value, field) {
    // No logical operators like $and.
    if (field.substr(0, 1) === '$')
      return false;
    // We only allow scalars, not sub-documents or $operators or RegExp.
    // XXX Date would be easy too, though I doubt anyone is doing equality
    // lookups on dates
    return typeof value === "string" ||
      typeof value === "number" ||
      typeof value === "boolean" ||
      value === null ||
      value instanceof Meteor.Collection.ObjectID;
  });
};

MongoTest.OplogObserveDriver = OplogObserveDriver;
<|endoftext|>


<commit_before>import DS from "ember-data";

var attr = DS.attr;

var Contest = DS.Model.extend({
  title             : attr('string'),
  description       : attr('string'),
  startTime         : attr('number'),
  duration          : attr(),
  alreadyRegistered : attr('number'),

  problems          : DS.hasMany('problem', {async : true})
});

export default Contest;
<commit_msg>Add more attributes to contest's model<commit_after>import DS from "ember-data";

var attr = DS.attr;

var Contest = DS.Model.extend({
  author            : attr('string'),
  title             : attr('string'),
  description       : attr('string'),
  createdAt         : attr('string'),
  updatedAt         : attr('string'),
  startTime         : attr('number'),
  duration          : attr(),
  alreadyRegistered : attr('number'),

  problems          : DS.hasMany('problem', {async : true})
});

export default Contest;
<|endoftext|>


<commit_before>// Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
//
// MIT License (MIT)
//
// 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.
//

cur_frm.cscript.doc_type = function(doc, dt, dn) {
	cur_frm.call({
		method: "get",
		doc: cur_frm.doc,
		callback: function(r) {
			cur_frm.refresh();
		}
	});
}

cur_frm.cscript.onload = function(doc, dt, dn) {
	$('div.grid_tbarlinks').parent().toggle(false);
	cur_frm.add_fields_help();
}

cur_frm.fields_dict.doc_type.get_query = function(doc, dt, dn) {
	return 'SELECT name FROM `tabDocType` \
	WHERE IFNULL(issingle,0)=0 AND \
	IFNULL(in_create, 0)=0 AND \
	name not in ("DocType", "DocField", "DocPerm", "Profile", "Role", "UserRole", "Page", \
		"Page Role", "Module Def", "Print Format", "Report", "Search Criteria") AND \
	name LIKE "%s%%" ORDER BY name ASC LIMIT 50';
}

cur_frm.cscript.refresh = function(doc, dt, dn) {
	//cur_frm.disable_save();
	cur_frm.frm_head.appframe.clear_buttons();

	cur_frm.add_custom_button('Update', function() {
		if(cur_frm.doc.doc_type) {
			cur_frm.call({
				doc: cur_frm.doc,
				method: "post",
				callback: function(r) {
					if(!r.exc && r.server_messages) {
						cur_frm.cscript.doc_type(doc, doc.doctype, doc.name);
						cur_frm.frm_head.set_label(['Updated', 'label-success']);
					}
				}
			});
		}
	});

	cur_frm.add_custom_button('Refresh Form', function() {
		cur_frm.cscript.doc_type(doc, dt, dn);
	});

	cur_frm.add_custom_button('Reset to defaults', function() {
		cur_frm.confirm('This will remove the customizations defined for this form.

'
		+ 'Are you sure you want to reset to defaults?', doc, dt, dn);
	});

	if(!doc.doc_type) {
		var frm_head = cur_frm.frm_head.appframe;
		$(frm_head.buttons['Update']).attr('disabled', true);
		$(frm_head.buttons['Refresh Form']).attr('disabled', true);
		$(frm_head.buttons['Reset to defaults']).attr('disabled', true);
	}

	cur_frm.cscript.hide_allow_attach(doc, dt, dn);
}

cur_frm.cscript.hide_allow_attach = function(doc, dt, dn) {
	var allow_attach_list = ['Website Settings', 'Web Page', 'Timesheet', 'Ticket',
		'Support Ticket', 'Supplier', 'Style Settings', 'Stock Reconciliation',
		'Stock Entry', 'Serial No', 'Sales Order', 'Sales Invoice',
		'Quotation', 'Question', 'Purchase Receipt', 'Purchase Order',
		'Project', 'Profile', 'Production Order', 'Product', 'Print Format',
		'Price List', 'Purchase Invoice', 'Page', 'Module Def',
		'Maintenance Visit', 'Maintenance Schedule', 'Letter Head',
		'Leave Application', 'Lead', 'Journal Voucher', 'Item', 'Material Request',
		'Expense Claim', 'Opportunity', 'Employee', 'Delivery Note',
		'Customer Issue', 'Customer', 'Contact Us Settings', 'Company',
		'Blog', 'BOM', 'About Us Settings'];

	if(inList(allow_attach_list, doc.doc_type)) {
		unhide_field('allow_attach');
	} else {
		hide_field('allow_attach');
	}
}

cur_frm.confirm = function(msg, doc, dt, dn) {
	var d = new wn.ui.Dialog({
		title: 'Reset To Defaults',
		width: 500
	});

	$y(d.body, {padding: '32px', textAlign: 'center'});

	$a(d.body, 'div', '', '', msg);

	var button_wrapper = $a(d.body, 'div');
	$y(button_wrapper, {paddingTop: '15px'});

	var proceed_btn = $btn(button_wrapper, 'Proceed', function() {
		cur_frm.call({
			doc: cur_frm.doc,
			method: "delete",
			callback: function(r) {
				if(r.exc) {
					msgprint(r.exc);
				} else {
					cur_frm.confirm.dialog.hide();
					cur_frm.refresh();
					cur_frm.frm_head.set_label(['Saved', 'label-success']);
				}
			}
		});
	});

	$y(proceed_btn, {marginRight: '20px', fontWeight: 'bold'});

	var cancel_btn = $btn(button_wrapper, 'Cancel', function() {
		cur_frm.confirm.dialog.hide();
	});

	$(cancel_btn).addClass('btn-small btn-info');
	$y(cancel_btn, {fontWeight: 'bold'});

	cur_frm.confirm.dialog = d;
	d.show();
}

cur_frm.add_fields_help = function() {
	$(cur_frm.grids[0].parent).before(
		'
\
			Help\

');
	$('#fields_help').click(function() {
		var d = new wn.ui.Dialog({
			title: 'Help: Field Properties',
			width: 600
		});

		var help =
			"
\

\
					Label	\
					Set the display label for the field	\

\

\
					Type	\
					Change type of field. (Currently, Type change is \
						allowed among 'Currency and Float')	\

\

\
					Options	\
					Specify the value of the field	\

\

\
					Perm Level	\
					\
						Assign a permission level to the field.
\
						(Permissions can be managed via Setup > Permission Manager)\
						\

\

\
					Width	\
					\
						Width of the input box
\
						Example: 120px\
						\

\

\
					Reqd	\
					Mark the field as Mandatory	\

\

\
					In Filter	\
					Use the field to filter records	\

\

\
					Hidden	\
					Hide field in form	\

\

\
					Print Hide	\
					Hide field in Standard Print Format	\

\

\
					Report Hide	\
					Hide field in Report Builder	\

\

\
					Allow on Submit	\
					Allow field to remain editable even after submission	\

\

\
					Depends On	\
					\
						Show field if a condition is met
\
						Example: eval:doc.status=='Cancelled'\
						 on a field like \"reason_for_cancellation\" will reveal \
						\"Reason for Cancellation\" only if the record is Cancelled.\
						\

\

\
					Description	\
					Show a description below the field	\

\

\
					Default	\
					Specify a default value	\

\

\
						\
					Press Esc to close\
						\

\

"

		$y(d.body, {padding: '32px', textAlign: 'center', lineHeight: '200%'});

		$a(d.body, 'div', '', {textAlign: 'left'}, help);

		d.show();

		cur_frm.fields_help_dialog = d;

	});
}
<commit_msg>Customize Form - allow Item Group<commit_after>// Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
//
// MIT License (MIT)
//
// 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.
//

cur_frm.cscript.doc_type = function(doc, dt, dn) {
	cur_frm.call({
		method: "get",
		doc: cur_frm.doc,
		callback: function(r) {
			cur_frm.refresh();
		}
	});
}

cur_frm.cscript.onload = function(doc, dt, dn) {
	$('div.grid_tbarlinks').parent().toggle(false);
	cur_frm.add_fields_help();
}

cur_frm.fields_dict.doc_type.get_query = function(doc, dt, dn) {
	return 'SELECT name FROM `tabDocType` \
	WHERE ((IFNULL(issingle,0)=0 AND \
	IFNULL(in_create, 0)=0 AND \
	name not in ("DocType", "DocField", "DocPerm", "Profile", "Role", "UserRole", "Page", \
		"Page Role", "Module Def", "Print Format", "Report", "Search Criteria")) \
	or name = "Item Group") \
	AND name LIKE "%s%%" ORDER BY name ASC LIMIT 50';
}

cur_frm.cscript.refresh = function(doc, dt, dn) {
	//cur_frm.disable_save();
	cur_frm.frm_head.appframe.clear_buttons();

	cur_frm.add_custom_button('Update', function() {
		if(cur_frm.doc.doc_type) {
			cur_frm.call({
				doc: cur_frm.doc,
				method: "post",
				callback: function(r) {
					if(!r.exc && r.server_messages) {
						cur_frm.cscript.doc_type(doc, doc.doctype, doc.name);
						cur_frm.frm_head.set_label(['Updated', 'label-success']);
					}
				}
			});
		}
	});

	cur_frm.add_custom_button('Refresh Form', function() {
		cur_frm.cscript.doc_type(doc, dt, dn);
	});

	cur_frm.add_custom_button('Reset to defaults', function() {
		cur_frm.confirm('This will remove the customizations defined for this form.

'
		+ 'Are you sure you want to reset to defaults?', doc, dt, dn);
	});

	if(!doc.doc_type) {
		var frm_head = cur_frm.frm_head.appframe;
		$(frm_head.buttons['Update']).attr('disabled', true);
		$(frm_head.buttons['Refresh Form']).attr('disabled', true);
		$(frm_head.buttons['Reset to defaults']).attr('disabled', true);
	}

	cur_frm.cscript.hide_allow_attach(doc, dt, dn);
}

cur_frm.cscript.hide_allow_attach = function(doc, dt, dn) {
	var allow_attach_list = ['Website Settings', 'Web Page', 'Timesheet', 'Ticket',
		'Support Ticket', 'Supplier', 'Style Settings', 'Stock Reconciliation',
		'Stock Entry', 'Serial No', 'Sales Order', 'Sales Invoice',
		'Quotation', 'Question', 'Purchase Receipt', 'Purchase Order',
		'Project', 'Profile', 'Production Order', 'Product', 'Print Format',
		'Price List', 'Purchase Invoice', 'Page', 'Module Def',
		'Maintenance Visit', 'Maintenance Schedule', 'Letter Head',
		'Leave Application', 'Lead', 'Journal Voucher', 'Item', 'Material Request',
		'Expense Claim', 'Opportunity', 'Employee', 'Delivery Note',
		'Customer Issue', 'Customer', 'Contact Us Settings', 'Company',
		'Blog', 'BOM', 'About Us Settings'];

	if(inList(allow_attach_list, doc.doc_type)) {
		unhide_field('allow_attach');
	} else {
		hide_field('allow_attach');
	}
}

cur_frm.confirm = function(msg, doc, dt, dn) {
	var d = new wn.ui.Dialog({
		title: 'Reset To Defaults',
		width: 500
	});

	$y(d.body, {padding: '32px', textAlign: 'center'});

	$a(d.body, 'div', '', '', msg);

	var button_wrapper = $a(d.body, 'div');
	$y(button_wrapper, {paddingTop: '15px'});

	var proceed_btn = $btn(button_wrapper, 'Proceed', function() {
		cur_frm.call({
			doc: cur_frm.doc,
			method: "delete",
			callback: function(r) {
				if(r.exc) {
					msgprint(r.exc);
				} else {
					cur_frm.confirm.dialog.hide();
					cur_frm.refresh();
					cur_frm.frm_head.set_label(['Saved', 'label-success']);
				}
			}
		});
	});

	$y(proceed_btn, {marginRight: '20px', fontWeight: 'bold'});

	var cancel_btn = $btn(button_wrapper, 'Cancel', function() {
		cur_frm.confirm.dialog.hide();
	});

	$(cancel_btn).addClass('btn-small btn-info');
	$y(cancel_btn, {fontWeight: 'bold'});

	cur_frm.confirm.dialog = d;
	d.show();
}

cur_frm.add_fields_help = function() {
	$(cur_frm.grids[0].parent).before(
		'
\
			Help\

');
	$('#fields_help').click(function() {
		var d = new wn.ui.Dialog({
			title: 'Help: Field Properties',
			width: 600
		});

		var help =
			"
\

\
					Label	\
					Set the display label for the field	\

\

\
					Type	\
					Change type of field. (Currently, Type change is \
						allowed among 'Currency and Float')	\

\

\
					Options	\
					Specify the value of the field	\

\

\
					Perm Level	\
					\
						Assign a permission level to the field.
\
						(Permissions can be managed via Setup > Permission Manager)\
						\

\

\
					Width	\
					\
						Width of the input box
\
						Example: 120px\
						\

\

\
					Reqd	\
					Mark the field as Mandatory	\

\

\
					In Filter	\
					Use the field to filter records	\

\

\
					Hidden	\
					Hide field in form	\

\

\
					Print Hide	\
					Hide field in Standard Print Format	\

\

\
					Report Hide	\
					Hide field in Report Builder	\

\

\
					Allow on Submit	\
					Allow field to remain editable even after submission	\

\

\
					Depends On	\
					\
						Show field if a condition is met
\
						Example: eval:doc.status=='Cancelled'\
						 on a field like \"reason_for_cancellation\" will reveal \
						\"Reason for Cancellation\" only if the record is Cancelled.\
						\

\

\
					Description	\
					Show a description below the field	\

\

\
					Default	\
					Specify a default value	\

\

\
						\
					Press Esc to close\
						\

\

"

		$y(d.body, {padding: '32px', textAlign: 'center', lineHeight: '200%'});

		$a(d.body, 'div', '', {textAlign: 'left'}, help);

		d.show();

		cur_frm.fields_help_dialog = d;

	});
}
<|endoftext|>


<commit_before>angular.module('feedbackcontrol', [])
.directive('transform', function(FeedbackSignal) {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind('click', function(e) {
                var currentUrl = window.location.pathname;
                var me = $(element);
                var data = FeedbackSignal.data;

                if(currentUrl.match(/inbox\/all|deleted/g)) {
                    if(data.id.length > 0) {
                        hide_the_children(me);
                        $(".checky-box-container").show();
                    }
                }

                if(currentUrl.match(/published/g)) {

                    if(me.attr('return-policy') == 1) {
                        hide_the_children(me);
                        $(".checky-box-container").show();
                    }

                    if(data.status == "feature") {
                        var state = {
                            activate: {'background-position': '-64px -31px'}
                          , deactivate_sibling: {'background-position': '-32px 0px'}
                          , activation_color: 'featured'
                          , state_change_inbox: '{"status": "inbox", "id": ' + data.id + ', "catid": ' + data.catid + ', "origin": "feature"}'
                          , state_change: '{"status": "publish", "id": ' + data.id + ', "catid": ' + data.catid + ', "origin": "publish"}'
                          , present_status: "feature"
                        }
                        published_state(me, '.publish', 'publish feedback', state);
                    }

                    if(data.status == "publish") {
                        var state = {
                            activate: {'background-position': '-32px -31px'}
                          , deactivate_sibling: {'background-position': '-64px 0px'}
                          , activation_color: 'published'
                          , state_change_inbox: '{"status": "inbox", "id": ' + data.id + ', "catid": ' + data.catid + ', "origin": "publish"}'
                          , state_change: '{"status": "feature", "id": ' + data.id + ', "catid": ' + data.catid + ', "origin": "feature"}'
                          , present_status: "publish"
                        }
                        published_state(me, '.feature', 'feature feedback', state);
                    }

                    if(data.status == "delete" || data.status == "fileas") {
                        hide_the_children(me);
                        $(".checky-box-container").show();
                    }

                }

                if(currentUrl.match(/filed/g)) {

                    var data_status = data.status;

                    if(data_status == "publish" || data_status == "feature" || data_status == "delete") {
                        hide_the_children(me);
                        $(".checky-box-container").show();
                    }

                    if(data_status == "fileas") {
                        $(me).parents(".dashboard-feedback")
                               .children("div.feedback-contents")
                               .children(".responsive-padding")
                               .children(".feedback-details")
                               .children(".filed")
                               .html($(me).text())
                    }

                }

                e.preventDefault();
            });
        }
    }
})
.directive('undo', function(FeedbackSignal, FeedbackControlService) {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind("click", function(e) {

                var currentUrl = window.location.pathname;

                $(".checky-box-container").hide();
                if (FeedbackSignal.data.id instanceof Array) {
                    for(var i=0; i < FeedbackSignal.data.id.length ; i++) {
                        var feedback = $(".dashboard-feedback[feedback=" + FeedbackSignal.data.id[i] + "]");

                        feedback.show();
                        $(feedback).parents('.feedback-group').show();

                        if(currentUrl.match(/inbox\/all|deleted|published/g)) {
                            var catpicks = $(".dashboard-feedback[feedback=" + FeedbackSignal.data.id[i] + "] li .cat-picks");
                            catpicks.css({'background': '#598499'});
                        }
                    }
                } else {
                    var feedback = $(".dashboard-feedback[feedback=" + FeedbackSignal.data.id + "]");

                    feedback.show();
                    $(feedback).parents('.feedback-group').show();

                    if(currentUrl.match(/inbox\/all|deleted|published/g)) {
                        var catpicks = $(".dashboard-feedback[feedback=" + FeedbackSignal.data.id + "] li .cat-picks");
                        catpicks.css({'background': '#598499'});
                    }

                    var checkbox = $(".feed-checkbox[value=" + FeedbackSignal.data.id + "]");

                    if(checkbox.is(":checked")) {
                        checkbox.click();
                    }
                }

                if($(".sorter-checkbox").is(":checked")) {
                    $(".sorter-checkbox").click();
                }

                if($('.feed-checkbox').is(":checked")) {
                    $('.feed-checkbox').prop("checked", false);
                }

                FeedbackControlService.expunge();
                e.preventDefault();
            });
        }
    }
})
.directive('close', function(FeedbackControlService) {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind("click", function(e) {
                $(".checky-box-container").hide();
                FeedbackControlService.expunge();
                e.preventDefault();
            });
        }
    }
})
.directive('feedcheckbox', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            var checkbox = $(element);

            checkbox.bind('change', function() {
                if(checkbox.is(":checked")) {
                    checkbox.parents('.dashboard-feedback').css({'background-color': '#F7F7F7'});
                } else {
                    checkbox.parents('.dashboard-feedback').css({'background-color': '#FFF'});
                }
            });

        }
    }
})
.directive('statuschange', function(FeedbackService) {
    return {
        restrict: 'A'
      , scope: {
            feedid: "@feedid"
          , statustype: "@statustype"
        }
      , link: function(scope, element, attrs) {
            $(element).bind('change', function() {
                var status_class, value;
                var myvalue = $(this).val();
                if(scope.statustype == "status") {
                   status_class = ".status-line";
                   console.log(myvalue);
                   if(myvalue == "new") { value = "New"; }
                   if(myvalue == "inprogress") { value = "In Progress"; }
                   if(myvalue == "closed") { value = "Closed"; }
                } else {
                   status_class = ".priority-line";
                   console.log(myvalue);
                   if(myvalue == 0) { value = "Low"; }
                   if(myvalue == 60) { value = "Medium"; }
                   if(myvalue == 100) { value = "High"; }
                }

                $(this).parents(".dashboard-feedback")
                       .children("div.feedback-contents")
                       .children(".responsive-padding")
                       .children(".feedback-details")
                       .children(".feedback-details-status")
                       .children(status_class)
                       .html(value)

                FeedbackService.inline_change($(this).val(), scope.feedid, scope.statustype);

            })
        }
    }
})
.directive('deleteBlock', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind('click', function(e) {
                $(this).parents('.custom-att').fadeOut(400, function() {
                     var new_uploaded_images = new Array;
                     var new_attached_link;

                     var div = $(this).parents('.uploaded-images-and-links');
                     var images = div.find('.uploaded_image');
                     var media_attachment = div.find('.attached_link');

                     var remove_image = {
                        'small_url'    :$(this).find('.small-image-url').val(),
                        'medium_url'   :$(this).find('.medium-image-url').val(),
                        'large_url'    :$(this).find('.large-image-url').val()
                     }

                    if(images.length > 0){
                        var us = images.not(":hidden");
                        for(var i=0; i < us.length; i++) {
                            new_uploaded_images.push({
                                'name': $(us[i]).find('.image-name').val()
                            });
                        }
                    }

                    if(!media_attachment.is(":hidden")) {
                        new_attached_link = {
                            title           : media_attachment.find('.link-title').val(),
                            description     : media_attachment.find('.link-description').val(),
                            image           : media_attachment.find('.link-image').val(),
                            url             : media_attachment.find('.link-url').val(),
                            video           : media_attachment.find('.link-video').val(),
                        }
                    }

                    var remaining = {
                        uploaded_images : new_uploaded_images
                      , attached_link   : new_attached_link
                    }

                    var attachment_data = {
                        feedbackId      : div.find('.attachment_feedback_id').val()
                      , attachments     : remaining
                      , remove_image    : remove_image
                    }

                    //place this in service you lazy bastard!
                    $.ajax({
                        type: "POST"
                      , url: "/inbox/update_feedback_attachment"
                      , dataType: "json"
                      , data: attachment_data
                    });
                });
                e.preventDefault();
            })
        }
    }
})
.directive('flag', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind('click', function(e) {
                var policy = $(this).attr("return-policy");
                if(policy == 1) {
                    $(this).removeAttr("style");
                    $(this).attr("return-policy", 0);
                } else {
                    $(this).attr("style", "background-position: -194px -31px");
                    $(this).attr("return-policy", 1);
                }
                e.preventDefault();
            });
        }
    }
})

function published_state(obj, sibling_id, msg, state) {
    //kill me....
    if(state.activation_color == 'featured') {
        obj.parents('.dashboard-feedback').addClass(state.activation_color);
        obj.parents('.dashboard-feedback').removeClass('published');
    } else {
        obj.parents('.dashboard-feedback').addClass(state.activation_color);
        obj.parents('.dashboard-feedback').removeClass('featured');
    }

    obj.css(state.activate);
    obj.children('.action-tooltip').children('span').html("Return to Inbox");
    obj.siblings(sibling_id).css(state.deactivate_sibling);
    obj.siblings(sibling_id).children('.action-tooltip').children('span').html(msg);
    obj.siblings(sibling_id).attr('return-policy', 0);
    obj.siblings(sibling_id).attr('data-feed', state.state_change);
    obj.attr('return-policy', 1);
    obj.attr('data-feed', state.state_change_inbox);

    var origin_cat_data = obj.siblings('.save')
                             .children('div.the-categories-menu')
                             .children('.the-categories-menu-content')
                             .children(".the-categories")
                             .children(".grids")
                             .children('li')
                             .children('a');

    for(var i=0;i<origin_cat_data.length;i++) {
        var cat = $(origin_cat_data[i]);

        var feed = $.parseJSON(cat.attr('data-feed'));
        feed.status = "fileas";
        feed.origin = state.present_status

        var repackaged_json = JSON.stringify(feed);
        cat.attr('data-feed', repackaged_json);
    }

    var action_delete = obj.parents('.grids').siblings('.grids').children('.action-delete');
    var delete_button = obj.siblings('.save')
                           .children('div.the-categories-menu')
                           .children('.the-categories-menu-content')
                           .children(".the-categories-delete")
                           .children('a');

    console.log(action_delete);
    console.log(delete_button);

    console.log(action_delete.attr('data-feed'));
    console.log(delete_button.attr('data-feed'));
}

function hide_the_children(obj) {
    obj.parents('.dashboard-feedback').hide();
    var child_count = obj.parents('.feedback-group').children('.dashboard-feedback:visible');
    if(child_count.length == 0) {
        obj.parents('.feedback-group').hide();
    }
}
<commit_msg>Jessica Alba<commit_after>angular.module('feedbackcontrol', [])
.directive('transform', function(FeedbackSignal) {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind('click', function(e) {
                var currentUrl = window.location.pathname;
                var me = $(element);
                var data = FeedbackSignal.data;

                if(currentUrl.match(/inbox\/all|deleted/g)) {
                    if(data.id.length > 0) {
                        hide_the_children(me);
                        $(".checky-box-container").show();
                    }
                }

                if(currentUrl.match(/published/g)) {

                    if(me.attr('return-policy') == 1) {
                        hide_the_children(me);
                        $(".checky-box-container").show();
                    }

                    if(data.status == "feature") {
                        var state = {
                            activate: {'background-position': '-64px -31px'}
                          , deactivate_sibling: {'background-position': '-32px 0px'}
                          , activation_color: 'featured'
                          , state_change_inbox: '{"status": "inbox", "id": ' + data.id + ', "catid": ' + data.catid + ', "origin": "feature"}'
                          , state_change: '{"status": "publish", "id": ' + data.id + ', "catid": ' + data.catid + ', "origin": "publish"}'
                          , present_status: "feature"
                        }
                        published_state(me, '.publish', 'publish feedback', state);
                    }

                    if(data.status == "publish") {
                        var state = {
                            activate: {'background-position': '-32px -31px'}
                          , deactivate_sibling: {'background-position': '-64px 0px'}
                          , activation_color: 'published'
                          , state_change_inbox: '{"status": "inbox", "id": ' + data.id + ', "catid": ' + data.catid + ', "origin": "publish"}'
                          , state_change: '{"status": "feature", "id": ' + data.id + ', "catid": ' + data.catid + ', "origin": "feature"}'
                          , present_status: "publish"
                        }
                        published_state(me, '.feature', 'feature feedback', state);
                    }

                    if(data.status == "delete" || data.status == "fileas") {
                        hide_the_children(me);
                        $(".checky-box-container").show();
                    }

                }

                if(currentUrl.match(/filed/g)) {

                    var data_status = data.status;

                    if(data_status == "publish" || data_status == "feature" || data_status == "delete") {
                        hide_the_children(me);
                        $(".checky-box-container").show();
                    }

                    if(data_status == "fileas") {
                        $(me).parents(".dashboard-feedback")
                               .children("div.feedback-contents")
                               .children(".responsive-padding")
                               .children(".feedback-details")
                               .children(".filed")
                               .html($(me).text())
                    }

                }

                e.preventDefault();
            });
        }
    }
})
.directive('undo', function(FeedbackSignal, FeedbackControlService) {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind("click", function(e) {

                var currentUrl = window.location.pathname;

                $(".checky-box-container").hide();
                if (FeedbackSignal.data.id instanceof Array) {
                    for(var i=0; i < FeedbackSignal.data.id.length ; i++) {
                        var feedback = $(".dashboard-feedback[feedback=" + FeedbackSignal.data.id[i] + "]");

                        feedback.show();
                        $(feedback).parents('.feedback-group').show();

                        if(currentUrl.match(/inbox\/all|deleted|published/g)) {
                            var catpicks = $(".dashboard-feedback[feedback=" + FeedbackSignal.data.id[i] + "] li .cat-picks");
                            catpicks.css({'background': '#598499'});
                        }
                    }
                } else {
                    var feedback = $(".dashboard-feedback[feedback=" + FeedbackSignal.data.id + "]");

                    feedback.show();
                    $(feedback).parents('.feedback-group').show();

                    if(currentUrl.match(/inbox\/all|deleted|published/g)) {
                        var catpicks = $(".dashboard-feedback[feedback=" + FeedbackSignal.data.id + "] li .cat-picks");
                        catpicks.css({'background': '#598499'});
                    }

                    var checkbox = $(".feed-checkbox[value=" + FeedbackSignal.data.id + "]");

                    if(checkbox.is(":checked")) {
                        checkbox.click();
                    }
                }

                if($(".sorter-checkbox").is(":checked")) {
                    $(".sorter-checkbox").click();
                }

                if($('.feed-checkbox').is(":checked")) {
                    $('.feed-checkbox').prop("checked", false);
                }

                FeedbackControlService.expunge();
                e.preventDefault();
            });
        }
    }
})
.directive('close', function(FeedbackControlService) {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind("click", function(e) {
                $(".checky-box-container").hide();
                FeedbackControlService.expunge();
                e.preventDefault();
            });
        }
    }
})
.directive('feedcheckbox', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            var checkbox = $(element);

            checkbox.bind('change', function() {
                if(checkbox.is(":checked")) {
                    checkbox.parents('.dashboard-feedback').css({'background-color': '#F7F7F7'});
                } else {
                    checkbox.parents('.dashboard-feedback').css({'background-color': '#FFF'});
                }
            });

        }
    }
})
.directive('statuschange', function(FeedbackService) {
    return {
        restrict: 'A'
      , scope: {
            feedid: "@feedid"
          , statustype: "@statustype"
        }
      , link: function(scope, element, attrs) {
            $(element).bind('change', function() {
                var status_class, value;
                var myvalue = $(this).val();
                if(scope.statustype == "status") {
                   status_class = ".status-line";
                   console.log(myvalue);
                   if(myvalue == "new") { value = "New"; }
                   if(myvalue == "inprogress") { value = "In Progress"; }
                   if(myvalue == "closed") { value = "Closed"; }
                } else {
                   status_class = ".priority-line";
                   console.log(myvalue);
                   if(myvalue == 0) { value = "Low"; }
                   if(myvalue == 60) { value = "Medium"; }
                   if(myvalue == 100) { value = "High"; }
                }

                $(this).parents(".dashboard-feedback")
                       .children("div.feedback-contents")
                       .children(".responsive-padding")
                       .children(".feedback-details")
                       .children(".feedback-details-status")
                       .children(status_class)
                       .html(value)

                FeedbackService.inline_change($(this).val(), scope.feedid, scope.statustype);

            })
        }
    }
})
.directive('deleteBlock', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind('click', function(e) {
                $(this).parents('.custom-att').fadeOut(400, function() {
                     var new_uploaded_images = new Array;
                     var new_attached_link;

                     var div = $(this).parents('.uploaded-images-and-links');
                     var images = div.find('.uploaded_image');
                     var media_attachment = div.find('.attached_link');

                     var remove_image = {
                        'small_url'    :$(this).find('.small-image-url').val(),
                        'medium_url'   :$(this).find('.medium-image-url').val(),
                        'large_url'    :$(this).find('.large-image-url').val()
                     }

                    if(images.length > 0){
                        var us = images.not(":hidden");
                        for(var i=0; i < us.length; i++) {
                            new_uploaded_images.push({
                                'name': $(us[i]).find('.image-name').val()
                            });
                        }
                    }

                    if(!media_attachment.is(":hidden")) {
                        new_attached_link = {
                            title           : media_attachment.find('.link-title').val(),
                            description     : media_attachment.find('.link-description').val(),
                            image           : media_attachment.find('.link-image').val(),
                            url             : media_attachment.find('.link-url').val(),
                            video           : media_attachment.find('.link-video').val(),
                        }
                    }

                    var remaining = {
                        uploaded_images : new_uploaded_images
                      , attached_link   : new_attached_link
                    }

                    var attachment_data = {
                        feedbackId      : div.find('.attachment_feedback_id').val()
                      , attachments     : remaining
                      , remove_image    : remove_image
                    }

                    //place this in service you lazy bastard!
                    $.ajax({
                        type: "POST"
                      , url: "/inbox/update_feedback_attachment"
                      , dataType: "json"
                      , data: attachment_data
                    });
                });
                e.preventDefault();
            })
        }
    }
})
.directive('flag', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind('click', function(e) {
                var policy = $(this).attr("return-policy");
                if(policy == 1) {
                    $(this).removeAttr("style");
                    $(this).attr("return-policy", 0);
                } else {
                    $(this).attr("style", "background-position: -194px -31px");
                    $(this).attr("return-policy", 1);
                }
                e.preventDefault();
            });
        }
    }
})

function published_state(obj, sibling_id, msg, state) {
    //kill me....
    if(state.activation_color == 'featured') {
        obj.parents('.dashboard-feedback').addClass(state.activation_color);
        obj.parents('.dashboard-feedback').removeClass('published');
    } else {
        obj.parents('.dashboard-feedback').addClass(state.activation_color);
        obj.parents('.dashboard-feedback').removeClass('featured');
    }

    obj.css(state.activate);
    obj.children('.action-tooltip').children('span').html("Return to Inbox");
    obj.siblings(sibling_id).css(state.deactivate_sibling);
    obj.siblings(sibling_id).children('.action-tooltip').children('span').html(msg);
    obj.siblings(sibling_id).attr('return-policy', 0);
    obj.siblings(sibling_id).attr('data-feed', state.state_change);
    obj.attr('return-policy', 1);
    obj.attr('data-feed', state.state_change_inbox);

    var origin_cat_data = obj.siblings('.save')
                             .children('div.the-categories-menu')
                             .children('.the-categories-menu-content')
                             .children(".the-categories")
                             .children(".grids")
                             .children('li')
                             .children('a');

    for(var i=0;i<origin_cat_data.length;i++) {
        var cat = $(origin_cat_data[i]);

        var feed = $.parseJSON(cat.attr('data-feed'));
        feed.status = "fileas";
        feed.origin = state.present_status

        var repackaged_json = JSON.stringify(feed);
        cat.attr('data-feed', repackaged_json);
    }

    var action_delete = obj.parents('.grids').siblings('.grids').children('.action-delete');
    var delete_button = obj.siblings('.save')
                           .children('div.the-categories-menu')
                           .children('.the-categories-menu-content')
                           .children(".the-categories-delete")
                           .children('a');

    var delete_feed_attr = $.parseJSON(action_delete.attr('data-feed')):
    delete_feed_attr.origin = state.present_status;
    var repackaged_feed_attr = JSON.stringify(delete_feed_attr);

    action_delete.attr('data-feed', repackaged_feed_attr);
    delete_button.attr('data-feed', repackaged_feed_attr);
}

function hide_the_children(obj) {
    obj.parents('.dashboard-feedback').hide();
    var child_count = obj.parents('.feedback-group').children('.dashboard-feedback:visible');
    if(child_count.length == 0) {
        obj.parents('.feedback-group').hide();
    }
}
<|endoftext|>


<commit_before>var common = require("../common");

describe("parse", function() {
  var sampleJSON = JSON.stringify({
    data: {
      type: "products",
      id: "1",
      attributes: {
        "title": "Awesome product 1"
      },
      relationships: {
        creator: {
          data: {
            id: "1",
            type: "users"
          }
        }
        tags: {
          data: [
            {
              id: "1",
              type: "tags"
            }
          ]
        },
        comments: {
          data: [
            {
              id: "1",
              type: "comments"
            }
          ]
        }
      }
    },
    included: [
      {
        type: "users",
        id: "1",
        attributes: {
          name: "example user 1"
        }
      },
      {
        type: "tags",
        id: "1",
        attributes: {
          name: "example tag 1"
        }
      },
      {
        type: "comments",
        id: "1",
        attributes: {
          body: "example comment 1"
        }
      }
    ]
  });

  it("should parse json-api format json", function() {
    var result = common.parse(sampleJSON);
    expect(result["data"]["creator"]).toEqual([{
      type: "users",
      id: "1",
      attributes: {
        body: "example user 1"
      },
      body: "example user 1"
    }]);
    expect(result["data"]["tags"]).toEqual([{
      type: "tags",
      id: "1",
      attributes: {
        name: "example tag 1"
      },
      name: "example tag 1"
    }]);
    expect(result["data"]["comments"]).toEqual([{
      type: "comments",
      id: "1",
      attributes: {
        body: "example comment 1"
      },
      body: "example comment 1"
    }]);
  });
});
<commit_msg>Fixing common test user validation.  The name field in the user attribute was being set to body incorrectly.<commit_after>var common = require("../common");

describe("parse", function() {
  var sampleJSON = JSON.stringify({
    data: {
      type: "products",
      id: "1",
      attributes: {
        "title": "Awesome product 1"
      },
      relationships: {
        creator: {
          data: {
            id: "1",
            type: "users"
          }
        },
        tags: {
          data: [
            {
              id: "1",
              type: "tags"
            }
          ]
        },
        comments: {
          data: [
            {
              id: "1",
              type: "comments"
            }
          ]
        }
      }
    },
    included: [
      {
        type: "users",
        id: "1",
        attributes: {
          name: "example user 1"
        }
      },
      {
        type: "tags",
        id: "1",
        attributes: {
          name: "example tag 1"
        }
      },
      {
        type: "comments",
        id: "1",
        attributes: {
          body: "example comment 1"
        }
      }
    ]
  });

  it("should parse json-api format json", function() {
    var result = common.parse(sampleJSON);
    expect(result["data"]["creator"]).toEqual({
      type: "users",
      id: "1",
      attributes: {
        name: "example user 1"
      },
      name: "example user 1"
    });
    expect(result["data"]["tags"]).toEqual([{
      type: "tags",
      id: "1",
      attributes: {
        name: "example tag 1"
      },
      name: "example tag 1"
    }]);
    expect(result["data"]["comments"]).toEqual([{
      type: "comments",
      id: "1",
      attributes: {
        body: "example comment 1"
      },
      body: "example comment 1"
    }]);
  });
});
<|endoftext|>