<commit_before>
/*
jasmine-stealth Makes Jasmine spies a bit more robust
site: https://github.com/searls/jasmine-stealth
*/

(function() {
  var Captor, isFunction, whatToDoWhenTheSpyGetsCalled,
    __hasProp = Object.prototype.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };

  isFunction = function(thing) {
    return Object.prototype.toString.call(thing) === "[object Function]";
  };

  beforeEach(function() {
    return this.stubFor = this.spyOn;
  });

  jasmine.createStub = jasmine.createSpy;

  jasmine.createStubObj = function(baseName, stubbings) {
    var name, obj, stubbing;
    if (stubbings.constructor === Array) {
      return jasmine.createSpyObj(baseName, stubbings);
    } else {
      obj = {};
      for (name in stubbings) {
        stubbing = stubbings[name];
        obj[name] = jasmine.createSpy(baseName + "." + name);
        if (isFunction(stubbing)) {
          obj[name].andCallFake(stubbing);
        } else {
          obj[name].andReturn(stubbing);
        }
      }
      return obj;
    }
  };

  whatToDoWhenTheSpyGetsCalled = function(spy) {
    var matchesStub, priorStubbing;
    matchesStub = function(stubbing, args, context) {
      switch (stubbing.type) {
        case "args":
          return jasmine.getEnv().equals_(stubbing.ifThis, jasmine.util.argsToArray(args));
        case "context":
          return jasmine.getEnv().equals_(stubbing.ifThis, context);
      }
    };
    priorStubbing = spy.plan();
    return spy.andCallFake(function() {
      var i, stubbing;
      i = 0;
      while (i < spy._stealth_stubbings.length) {
        stubbing = spy._stealth_stubbings[i];
        if (matchesStub(stubbing, arguments, this)) {
          if (Object.prototype.toString.call(stubbing.thenThat) === "[object Function]") {
            return stubbing.thenThat();
          } else {
            return stubbing.thenThat;
          }
        }
        i++;
      }
      return priorStubbing;
    });
  };

  jasmine.Spy.prototype.whenContext = function(context) {
    var addStubbing, spy;
    spy = this;
    spy._stealth_stubbings || (spy._stealth_stubbings = []);
    whatToDoWhenTheSpyGetsCalled(spy);
    addStubbing = function(thenThat) {
      spy._stealth_stubbings.push({
        type: 'context',
        ifThis: context,
        thenThat: thenThat
      });
      return spy;
    };
    return {
      thenReturn: addStubbing,
      thenCallFake: addStubbing
    };
  };

  jasmine.Spy.prototype.when = function() {
    var addStubbing, ifThis, spy;
    spy = this;
    ifThis = jasmine.util.argsToArray(arguments);
    spy._stealth_stubbings || (spy._stealth_stubbings = []);
    whatToDoWhenTheSpyGetsCalled(spy);
    addStubbing = function(thenThat) {
      spy._stealth_stubbings.push({
        type: 'args',
        ifThis: ifThis,
        thenThat: thenThat
      });
      return spy;
    };
    return {
      thenReturn: addStubbing,
      thenCallFake: addStubbing
    };
  };

  jasmine.Spy.prototype.mostRecentCallThat = function(callThat, context) {
    var i;
    i = this.calls.length - 1;
    while (i >= 0) {
      if (callThat.call(context || this, this.calls[i]) === true) {
        return this.calls[i];
      }
      i--;
    }
  };

  jasmine.Matchers.ArgThat = (function(_super) {

    __extends(ArgThat, _super);

    function ArgThat(matcher) {
      this.matcher = matcher;
    }

    ArgThat.prototype.matches = function(actual) {
      return this.matcher(actual);
    };

    return ArgThat;

  })(jasmine.Matchers.Any);

  jasmine.argThat = function(expected) {
    return new jasmine.Matchers.ArgThat(expected);
  };

  jasmine.Matchers.Capture = (function(_super) {

    __extends(Capture, _super);

    function Capture(captor) {
      this.captor = captor;
    }

    Capture.prototype.matches = function(actual) {
      this.captor.value = actual;
      return true;
    };

    return Capture;

  })(jasmine.Matchers.Any);

  Captor = (function() {

    function Captor() {}

    Captor.prototype.capture = function() {
      return new jasmine.Matchers.Capture(this);
    };

    return Captor;

  })();

  jasmine.captor = function() {
    return new Captor();
  };

}).call(this);
<commit_msg>compilin<commit_after>// Generated by CoffeeScript 1.3.1

/*
jasmine-stealth 0.1.9
Makes Jasmine spies a bit more robust
site: https://github.com/searls/jasmine-stealth
*/

(function() {
  var Captor, fake, root, unfakes, whatToDoWhenTheSpyGetsCalled, _,
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };

  root = this;

  _ = function(obj) {
    return {
      each: function(iterator) {
        var item, _i, _len, _results;
        _results = [];
        for (_i = 0, _len = obj.length; _i < _len; _i++) {
          item = obj[_i];
          _results.push(iterator(item));
        }
        return _results;
      },
      isFunction: function() {
        return Object.prototype.toString.call(obj) === "[object Function]";
      },
      isString: function() {
        return Object.prototype.toString.call(obj) === "[object String]";
      }
    };
  };

  root.spyOnConstructor = function(owner, classToFake, methodsToSpy) {
    var fakeClass, spies;
    if (methodsToSpy == null) {
      methodsToSpy = [];
    }
    if (_(methodsToSpy).isString()) {
      methodsToSpy = [methodsToSpy];
    }
    spies = {
      constructor: jasmine.createSpy("" + classToFake + "'s constructor")
    };
    fakeClass = (function() {

      function _Class() {
        spies.constructor.apply(this, arguments);
      }

      return _Class;

    })();
    _(methodsToSpy).each(function(methodName) {
      spies[methodName] = jasmine.createSpy("" + classToFake + "#" + methodName);
      return fakeClass.prototype[methodName] = function() {
        return spies[methodName].apply(this, arguments);
      };
    });
    fake(owner, classToFake, fakeClass);
    return spies;
  };

  unfakes = [];

  afterEach(function() {
    _(unfakes).each(function(u) {
      return u();
    });
    return unfakes = [];
  });

  fake = function(owner, thingToFake, newThing) {
    var originalThing;
    originalThing = owner[thingToFake];
    owner[thingToFake] = newThing;
    return unfakes.push(function() {
      return owner[thingToFake] = originalThing;
    });
  };

  root.stubFor = root.spyOn;

  jasmine.createStub = jasmine.createSpy;

  jasmine.createStubObj = function(baseName, stubbings) {
    var name, obj, stubbing;
    if (stubbings.constructor === Array) {
      return jasmine.createSpyObj(baseName, stubbings);
    } else {
      obj = {};
      for (name in stubbings) {
        stubbing = stubbings[name];
        obj[name] = jasmine.createSpy(baseName + "." + name);
        if (_(stubbing).isFunction()) {
          obj[name].andCallFake(stubbing);
        } else {
          obj[name].andReturn(stubbing);
        }
      }
      return obj;
    }
  };

  whatToDoWhenTheSpyGetsCalled = function(spy) {
    var matchesStub, priorStubbing;
    matchesStub = function(stubbing, args, context) {
      switch (stubbing.type) {
        case "args":
          return jasmine.getEnv().equals_(stubbing.ifThis, jasmine.util.argsToArray(args));
        case "context":
          return jasmine.getEnv().equals_(stubbing.ifThis, context);
      }
    };
    priorStubbing = spy.plan();
    return spy.andCallFake(function() {
      var i, stubbing;
      i = 0;
      while (i < spy._stealth_stubbings.length) {
        stubbing = spy._stealth_stubbings[i];
        if (matchesStub(stubbing, arguments, this)) {
          if (Object.prototype.toString.call(stubbing.thenThat) === "[object Function]") {
            return stubbing.thenThat();
          } else {
            return stubbing.thenThat;
          }
        }
        i++;
      }
      return priorStubbing;
    });
  };

  jasmine.Spy.prototype.whenContext = function(context) {
    var addStubbing, spy;
    spy = this;
    spy._stealth_stubbings || (spy._stealth_stubbings = []);
    whatToDoWhenTheSpyGetsCalled(spy);
    addStubbing = function(thenThat) {
      spy._stealth_stubbings.push({
        type: 'context',
        ifThis: context,
        thenThat: thenThat
      });
      return spy;
    };
    return {
      thenReturn: addStubbing,
      thenCallFake: addStubbing
    };
  };

  jasmine.Spy.prototype.when = function() {
    var addStubbing, ifThis, spy;
    spy = this;
    ifThis = jasmine.util.argsToArray(arguments);
    spy._stealth_stubbings || (spy._stealth_stubbings = []);
    whatToDoWhenTheSpyGetsCalled(spy);
    addStubbing = function(thenThat) {
      spy._stealth_stubbings.push({
        type: 'args',
        ifThis: ifThis,
        thenThat: thenThat
      });
      return spy;
    };
    return {
      thenReturn: addStubbing,
      thenCallFake: addStubbing
    };
  };

  jasmine.Spy.prototype.mostRecentCallThat = function(callThat, context) {
    var i;
    i = this.calls.length - 1;
    while (i >= 0) {
      if (callThat.call(context || this, this.calls[i]) === true) {
        return this.calls[i];
      }
      i--;
    }
  };

  jasmine.Matchers.ArgThat = (function(_super) {

    __extends(ArgThat, _super);

    ArgThat.name = 'ArgThat';

    function ArgThat(matcher) {
      this.matcher = matcher;
    }

    ArgThat.prototype.matches = function(actual) {
      return this.matcher(actual);
    };

    return ArgThat;

  })(jasmine.Matchers.Any);

  jasmine.argThat = function(expected) {
    return new jasmine.Matchers.ArgThat(expected);
  };

  jasmine.Matchers.Capture = (function(_super) {

    __extends(Capture, _super);

    Capture.name = 'Capture';

    function Capture(captor) {
      this.captor = captor;
    }

    Capture.prototype.matches = function(actual) {
      this.captor.value = actual;
      return true;
    };

    return Capture;

  })(jasmine.Matchers.Any);

  Captor = (function() {

    Captor.name = 'Captor';

    function Captor() {}

    Captor.prototype.capture = function() {
      return new jasmine.Matchers.Capture(this);
    };

    return Captor;

  })();

  jasmine.captor = function() {
    return new Captor();
  };

}).call(this);
<|endoftext|>


<commit_before>var x;
var y;
var dx;
var dy;
var r;
var px;
var py;
var cx;
var cy;
var speed = 5;

function setup() {
	createCanvas(windowWidth, windowHeight);
	noStroke();
	x = width/2;
	y = height/2;
	dx = random(-10, 10);
	dy = random(-5, 5);
	r = height/25;
	rectMode(CENTER);
	px = 15;
	py = height/2;
	cx = width-px;
	cy = py;
}

function draw() {
	field();
	ball();
	paddle1();
	paddle2();
	checkScore();
	checkKeys();
}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
}

function field() {
	background(0);
	var NUM = 10;
	rectMode(CENTER);
	fill(255);
	for(var i = 0; i < NUM; i++)
		rect(width/2, 2*i*height/NUM, width/100, height/NUM);
}

function ball() {
	ellipse(x, y, r*2, r*2);

	x+=dx;
	y+=dy;

	if(y > py - height/10 && y < py + height/10) {
		if(x - r < px + width/200 && x > 0) {
			var slope = dy / dx;
			dx *= -1.1;
			dy = dx * slope;
		}
	}

	if(y > cy - height/10 && y < cy + height/10) {
		if(x + r > cx + width/200 && x < width)
			var slope = dy / dx;
			dx *= -1.1;
			dy = dx * slope;
	}

	if(y < r || y > height-r) dy = -dy;
}

function paddle1() {
	rect(px, py, width/100, height/5);
}

function paddle2() {
	if(y > cy+8) cy += speed;
	else if (y < cy-8) cy -= speed;

	if(cy > height-height/10) cy = height-height/10;
	else if(cy < height/10) cy = height/10;
	rect(cx, cy, width/100, height/5);
}

function checkKeys() {
	if(keyIsPressed) {
		if(keyCode == UP_ARROW)
			py -= speed;
		else if(keyCode == DOWN_ARROW)
			py += speed;
	}
}

function checkScore() {
	if(x < -4*r || x > width + 4*r) {
		console.log("GOAL!");
		x = width/2;
		y = height/2;
		dx = random(-10, 10);
		dy = random(-5, 5);
	}
}<commit_msg>restore to old version<commit_after>var x;
var y;
var dx;
var dy;
var r;
var px;
var py;
var cx;
var cy;
var speed = 5;

function setup() {
	createCanvas(windowWidth, windowHeight);
	noStroke();
	x = width/2;
	y = height/2;
	dx = random(-10, 10);
	dy = random(-5, 5);
	r = height/25;
	rectMode(CENTER);
	px = 15;
	py = height/2;
	cx = width-px;
	cy = py;
}

function draw() {
	field();
	ball();
	paddle1();
	paddle2();
	checkScore();
	checkKeys();
}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
}

function field() {
	background(0);
	var NUM = 10;
	rectMode(CENTER);
	fill(255);
	for(var i = 0; i < NUM; i++)
		rect(width/2, 2*i*height/NUM, width/100, height/NUM);
}

function ball() {
	ellipse(x, y, r*2, r*2);

	x+=dx;
	y+=dy;

	if(y > py - height/10 && y < py + height/10) {
<<<<<<< HEAD
		if(x - r < px + width/200 && x > 0) {
			var slope = dy / dx;
=======
		if(x - r < px + width/200)
>>>>>>> parent of 2004207... prevent bounces from behind paddles
			dx *= -1.1;
			dy = dx * slope;
		}
	}

	if(y > cy - height/10 && y < cy + height/10) {
<<<<<<< HEAD
		if(x + r > cx + width/200 && x < width)
			var slope = dy / dx;
=======
		if(x + r > cx + width/200)
>>>>>>> parent of 2004207... prevent bounces from behind paddles
			dx *= -1.1;
			dy = dx * slope;
	}

	if(y < r || y > height-r) dy = -dy;
}

function paddle1() {
	rect(px, py, width/100, height/5);
}

function paddle2() {
	if(y > cy+8) cy += speed;
	else if (y < cy-8) cy -= speed;

	if(cy > height-height/10) cy = height-height/10;
	else if(cy < height/10) cy = height/10;
	rect(cx, cy, width/100, height/5);
}

function checkKeys() {
	if(keyIsPressed) {
		if(keyCode == UP_ARROW)
			py -= speed;
		else if(keyCode == DOWN_ARROW)
			py += speed;
	}
}

function checkScore() {
	if(x < -4*r || x > width + 4*r) {
		console.log("GOAL!");
		x = width/2;
		y = height/2;
		dx = random(-10, 10);
		dy = random(-5, 5);
	}
}<|endoftext|>


<commit_before>angular
	.module('ngSharepoint')
	.factory('$spLoader', ['$q', '$http', '$sp', function($q, $http, $sp) {
		var scripts = {};
		return ({
			loadScript: function(lib) {
				var query = $q(function(resolve, reject) {
					var element = document.createElement('script');
					element.type = 'text/javascript';
					element.src = '_layouts/15/' + lib;
					element.onload = resolve;
					element.onerror = reject;
				});
				scripts[lib] = query;
				return query;
			},
			waitUntil: function(lib) {
				return query[lib];
			},
			query: function(queryObject) {
				var query = {
					url: $sp.getSiteUrl() + queryObject.url,
					method: queryObject.method,
					headers: {
						'Accept': 'application/json; odata=verbose',
						'Content-Type': 'application/json; odata=verbose'
					}
				};
				if ($sp.getConnectionMode() === 'REST' && !$sp.getAccessToken()) {
					return $q(function(resolve, reject) {
						query.body = queryObject.data;
						query.success = resolve;
						query.error = reject;
						new SP.RequestExecutor($sp.getSiteUrl()).executeAsync(query);
					});
				}else {
					return $q(function(resolve, reject) {
						query.data = queryObject.data;
						query.headers.Authorization = 'Bearer ' + $sp.getAccessToken;
						$http(query).then(resolve, reject);
					});
				}
			}
		});
	}]);<commit_msg>Use right array...<commit_after>angular
	.module('ngSharepoint')
	.factory('$spLoader', ['$q', '$http', '$sp', function($q, $http, $sp) {
		var scripts = {};
		return ({
			loadScript: function(lib) {
				var query = $q(function(resolve, reject) {
					var element = document.createElement('script');
					element.type = 'text/javascript';
					element.src = '_layouts/15/' + lib;
					element.onload = resolve;
					element.onerror = reject;
				});
				scripts[lib] = query;
				return query;
			},
			waitUntil: function(lib) {
				return scripts[lib];
			},
			query: function(queryObject) {
				var query = {
					url: $sp.getSiteUrl() + queryObject.url,
					method: queryObject.method,
					headers: {
						'Accept': 'application/json; odata=verbose',
						'Content-Type': 'application/json; odata=verbose'
					}
				};
				if ($sp.getConnectionMode() === 'REST' && !$sp.getAccessToken()) {
					return $q(function(resolve, reject) {
						query.body = queryObject.data;
						query.success = resolve;
						query.error = reject;
						new SP.RequestExecutor($sp.getSiteUrl()).executeAsync(query);
					});
				}else {
					return $q(function(resolve, reject) {
						query.data = queryObject.data;
						query.headers.Authorization = 'Bearer ' + $sp.getAccessToken;
						$http(query).then(resolve, reject);
					});
				}
			}
		});
	}]);<|endoftext|>


<commit_before>window[appName].controller('sdn_graph_controller', function ($rootScope, $scope, $state, $stateParams, $http, $window, $location, $q, $filter) {

    console.log("Called");

    if ($scope.logged_in == undefined || $scope.logged_in == "") {
        window.location = "index.html";
    }

    function HttpRequest(method, action, URL, parameter) {

        $rootScope.showLoader = true;

        var $promise = '';
        if (method === "post") {
            $promise = $http.post(URL, parameter);
        } else {
            $promise = $http.get(URL, parameter);
        }
        $promise.then(function (response) {
            var result = angular.fromJson(response.data);
            processTheData(action, result);

            $rootScope.showLoader = false;

        });
    };

    function processTheData(action, response) {

        switch (action) {

            case 'get_switch':

                $scope.switch_detail = response["rows"][1]["id"];

                break;

            case 'get_switch_info':
                $scope.switch_info = response;
                $scope.flow_info = response["rows"];
                break;

            case 'get_flow_info':
                table= get_popuptable(response);
                bootbox.alert(table);

                break;

            case 'get_toplogy':
                $scope.topology = response;
                break;
        }

    }

    //HttpRequest('get', 'get_toplogy', window.flaskURL + 'get_toplogy', '');

    //update();

    var mousex = 0;
    var mousey = 0;

    var w = 1280,
        h = 800,
        node,
        link,
        root;

    var force = d3.layout.force()
        .on("tick", tick)
        .charge(function (d) {
            return d._rows ? -d.size / 100 : -30;
        })
        .linkDistance(function (d) {
            return d.target._rows ? 100 : 200;
        })
        .size([w, h - 160]);
    var zoom = d3.behavior.zoom().on("zoom", redraw);

    var vis = d3.select("#visual").append("svg:svg")
        .attr("width", w)
        .attr("height", h)
        .call(zoom)
        .on("mousewheel.zoom", null)
        .append('svg:g');

    d3.json(window.flaskURL + 'get_toplogy', function (json) {
     root = json;
     root.rows = root.rows;

     root.fixed = true;
     root.x = w / 2;
     root.y = h / 2 - 80;
     update();
     });

    function redraw() {
    console.log("zoom", d3.event.translate, d3.event.scale);
  vis.attr("transform",
      "translate(" + d3.event.translate + ")"
      + " scale(" + d3.event.scale + ")");
    }

    function update() {
        var nodes = flatten(root),
            links = d3.layout.tree().links(nodes);

        // Restart the force layout.
        force
            .nodes(nodes)
            .links(links)
            .start();

        // Update the links…
        link = vis.selectAll("line.link")
            .data(links, function (d) {
                return d.target.id;
            });

        // Enter any new links.
        link.enter().insert("svg:line", ".node")
            .attr("class", "link")
            .attr("x1", function (d) {
                return d.source.x;
            })
            .attr("y1", function (d) {
                return d.source.y;
            })
            .attr("x2", function (d) {
                return d.target.x;
            })
            .attr("y2", function (d) {
                return d.target.y;
            });

        // Exit any old links.
        link.exit().remove();

        // Update the nodes…
        node = vis.selectAll("circle.node")
            .data(nodes, function (d) {
                return d.id;
            })
            .style("fill", color);

        node.transition()
            .attr("r", function (d) {
                return 10;
            });

        // Enter any new nodes.
        node.enter().append("svg:circle")
            .attr("class", "node")
            .attr("cx", function (d) {
                return d.x;
            })
            .attr("cy", function (d) {
                return d.y;
            })
            .attr("r", function (d) {
                return 10;
            })
            .style("fill", color)
            .on("click", click)
            //.on("mouseenter",function(d){ Tooltip(d);})
            //.on("mouseleave",function(d){ TooltipRemove(d);})
            .call(force.drag);

        // Exit any old nodes.
        node.exit().remove();
    }

    function tick() {
        link.attr("x1", function (d) {
                return d.source.x;
            })
            .attr("y1", function (d) {
                return d.source.y;
            })
            .attr("x2", function (d) {
                return d.target.x;
            })
            .attr("y2", function (d) {
                return d.target.y;
            });

        node.attr("cx", function (d) {
                return d.x;
            })
            .attr("cy", function (d) {
                return d.y;
            });
    }

// Color leaf nodes orange, and packages white or blue.
    function color(d) {
        if (d.rows == undefined) {
            return "green"
        }

        return "red";

    }

// Toggle rows on click.
    function click(d) {

        if (!d.rows) {
            HttpRequest('post', 'get_flow_info', window.flaskURL + 'get_flow_info', {"flow_id": d.id});

        }

    }

// Returns a list of all nodes under the root.
    function flatten(root) {
        var nodes = [], i = 0;

        function recurse(node) {
            if (node.rows) node.size = node.rows.reduce(function (p, v) {
                return p + recurse(v);
            }, 0);
            if (!node.id) node.id = ++i;
            nodes.push(node);
            return node.size;
        }

        root.size = recurse(root);
        return nodes;
    }

    function Tooltip(data) {
        d3.select("#tooltip")
            .attr("class", "hover")
            .style("x", (mousex + 40) + 'px')
            .style("y", (mousey - 60) + "px")
            .style("left", (mousex + 40) + 'px')
            .style("top", (mousey - 60) + "px")
            .text(TooltipContent(data));
    }

    function TooltipRemove(data) {
        d3.select("#tooltip").attr("class", "").text("");
    }

    function TooltipContent(data) {
        console.log(data.toSource());
        var htmlstr = "
";
        htmlstr = htmlstr + "
";
        htmlstr = htmlstr + "Tooltip";
        htmlstr = htmlstr + "
";
        htmlstr = htmlstr + "
";
        return htmlstr;
    }

    function get_popuptable(k)
    {
        var table_text= "
";
        table_text = table_text + "
Command	"+k.data.OFPFlowMod.command+"
";
        table_text = table_text + "
out_group	"+k.data.OFPFlowMod.out_group+"
";
        table_text = table_text + "
out_port	"+k.data.OFPFlowMod.out_port+"
";
        table_text = table_text + "
idle_timeout	"+k.data.OFPFlowMod.idle_timeout+"
";
        table_text = table_text + "
OFPMatch	"+k.data.OFPFlowMod.match.OFPMatch.toSource()+"
";
        table_text = table_text + "
type	"+k.data.OFPFlowMod.match.OFPMatch.type+"
";
        table_text = table_text + "
";
        return table_text;

    }

});
<commit_msg>delete from pop up ( issue #1 )<commit_after>window[appName].controller('sdn_graph_controller', function ($rootScope, $scope, $state, $stateParams, $http, $window, $location, $q, $filter) {

    console.log("Called");

    if ($scope.logged_in == undefined || $scope.logged_in == "") {
        window.location = "index.html";
    }

    function HttpRequest(method, action, URL, parameter) {

        $rootScope.showLoader = true;

        var $promise = '';
        if (method === "post") {
            $promise = $http.post(URL, parameter);
        } else {
            $promise = $http.get(URL, parameter);
        }
        $promise.then(function (response) {
            var result = angular.fromJson(response.data);
            processTheData(action, result);

            $rootScope.showLoader = false;

        });
    };

    function processTheData(action, response) {

        switch (action) {

            case 'get_switch':

                $scope.switch_detail = response["rows"][1]["id"];

                break;

            case 'get_switch_info':
                $scope.switch_info = response;
                $scope.flow_info = response["rows"];
                break;

            case 'get_flow_info':
                table= get_popuptable(response);
                bootbox.alert(table);

                break;

            case 'get_toplogy':
                $scope.topology = response;
                break;
        }

    }

    $scope.flow_delete = function (id, rev) {

        var param = {"cancel": true};

        bootbox.confirm("Are you sure you want to delete the flow " + id + "?", function (result) {
            if (result) {
                param = {"id": id, "rev": rev};
                HttpRequest('post', 'delete_flow', window.flaskURL + 'delete_flow', param);
            }
        });

    }

    //HttpRequest('get', 'get_toplogy', window.flaskURL + 'get_toplogy', '');

    //update();

    var mousex = 0;
    var mousey = 0;

    var w = 1280,
        h = 800,
        node,
        link,
        root;

    var force = d3.layout.force()
        .on("tick", tick)
        .charge(function (d) {
            return d._rows ? -d.size / 100 : -30;
        })
        .linkDistance(function (d) {
            return d.target._rows ? 100 : 200;
        })
        .size([w, h - 160]);
    var zoom = d3.behavior.zoom().on("zoom", redraw);

    var vis = d3.select("#visual").append("svg:svg")
        .attr("width", w)
        .attr("height", h)
        .call(zoom)
        .on("mousewheel.zoom", null)
        .append('svg:g');

    d3.json(window.flaskURL + 'get_toplogy', function (json) {
     root = json;
     root.rows = root.rows;

     root.fixed = true;
     root.x = w / 2;
     root.y = h / 2 - 80;
     update();
     });

    function redraw() {
    console.log("zoom", d3.event.translate, d3.event.scale);
  vis.attr("transform",
      "translate(" + d3.event.translate + ")"
      + " scale(" + d3.event.scale + ")");
    }

    function update() {
        var nodes = flatten(root),
            links = d3.layout.tree().links(nodes);

        // Restart the force layout.
        force
            .nodes(nodes)
            .links(links)
            .start();

        // Update the links…
        link = vis.selectAll("line.link")
            .data(links, function (d) {
                return d.target.id;
            });

        // Enter any new links.
        link.enter().insert("svg:line", ".node")
            .attr("class", "link")
            .attr("x1", function (d) {
                return d.source.x;
            })
            .attr("y1", function (d) {
                return d.source.y;
            })
            .attr("x2", function (d) {
                return d.target.x;
            })
            .attr("y2", function (d) {
                return d.target.y;
            });

        // Exit any old links.
        link.exit().remove();

        // Update the nodes…
        node = vis.selectAll("circle.node")
            .data(nodes, function (d) {
                return d.id;
            })
            .style("fill", color);

        node.transition()
            .attr("r", function (d) {
                return 10;
            });

        // Enter any new nodes.
        node.enter().append("svg:circle")
            .attr("class", "node")
            .attr("cx", function (d) {
                return d.x;
            })
            .attr("cy", function (d) {
                return d.y;
            })
            .attr("r", function (d) {
                return 10;
            })
            .style("fill", color)
            .on("click", click)
            //.on("mouseenter",function(d){ Tooltip(d);})
            //.on("mouseleave",function(d){ TooltipRemove(d);})
            .call(force.drag);

        // Exit any old nodes.
        node.exit().remove();
    }

    function tick() {
        link.attr("x1", function (d) {
                return d.source.x;
            })
            .attr("y1", function (d) {
                return d.source.y;
            })
            .attr("x2", function (d) {
                return d.target.x;
            })
            .attr("y2", function (d) {
                return d.target.y;
            });

        node.attr("cx", function (d) {
                return d.x;
            })
            .attr("cy", function (d) {
                return d.y;
            });
    }

// Color leaf nodes orange, and packages white or blue.
    function color(d) {
        if (d.rows == undefined) {
            return "green"
        }

        return "red";

    }

// Toggle rows on click.
    function click(d) {

        if (!d.rows) {
            HttpRequest('post', 'get_flow_info', window.flaskURL + 'get_flow_info', {"flow_id": d.id});

        }

    }

// Returns a list of all nodes under the root.
    function flatten(root) {
        var nodes = [], i = 0;

        function recurse(node) {
            if (node.rows) node.size = node.rows.reduce(function (p, v) {
                return p + recurse(v);
            }, 0);
            if (!node.id) node.id = ++i;
            nodes.push(node);
            return node.size;
        }

        root.size = recurse(root);
        return nodes;
    }

    function Tooltip(data) {
        d3.select("#tooltip")
            .attr("class", "hover")
            .style("x", (mousex + 40) + 'px')
            .style("y", (mousey - 60) + "px")
            .style("left", (mousex + 40) + 'px')
            .style("top", (mousey - 60) + "px")
            .text(TooltipContent(data));
    }

    function TooltipRemove(data) {
        d3.select("#tooltip").attr("class", "").text("");
    }

    function TooltipContent(data) {
        console.log(data.toSource());
        var htmlstr = "
";
        htmlstr = htmlstr + "
";
        htmlstr = htmlstr + "Tooltip";
        htmlstr = htmlstr + "
";
        htmlstr = htmlstr + "
";
        return htmlstr;
    }

    function get_popuptable(k)
    {
        var table_text= "
";
        var table_text= "
k.id
";
        table_text = table_text + "

";
        table_text = table_text + "
Command	"+k.data.OFPFlowMod.command+"
";
        table_text = table_text + "
out_group	"+k.data.OFPFlowMod.out_group+"
";
        table_text = table_text + "
out_port	"+k.data.OFPFlowMod.out_port+"
";
        table_text = table_text + "
idle_timeout	"+k.data.OFPFlowMod.idle_timeout+"
";
        table_text = table_text + "
OFPMatch	"+k.data.OFPFlowMod.match.OFPMatch.toSource()+"
";
        table_text = table_text + "
type	"+k.data.OFPFlowMod.match.OFPMatch.type+"
";
        table_text = table_text + "
";
        return table_text;

    }

});
<|endoftext|>


<commit_before>/**
 * Created by zarges on 29/05/15.
 */
describe('mwUi mwIcon Service', function () {
  var mwIconProvider;

  beforeEach(module('mwUI'));

  beforeEach(function () {
    module('mwUI', function (_mwIconProvider_){
      mwIconProvider =_mwIconProvider_;
    });
  });

  beforeEach(inject(function (mwIcon, $templateRequest, $rootScope, $httpBackend) {
    this.mwIcon = mwIcon;
    this.$templateRequest = $templateRequest;
    this.$rootScope = $rootScope;
    this.$httpBackend = $httpBackend;
  }));

  describe('configuring provider', function () {

    it('registers an icon', function () {
      mwIconProvider.addIconSet({
        id: 'fa',
        icons: {
          USER: 'fa-user'
        }
      });

      expect(this.mwIcon.getIconSet('fa').id).toBe('fa');
    });

    it('registers an icon where the icon mapping comes from a file', function () {
      mwIconProvider.addIconSet({
        id: 'fa',
        iconsUrl: '/test/fa.json'
      });

      expect(this.mwIcon.getIconSet('fa').id).toBe('fa');
    });

    it('throws an error when you try to register an icon without nay icon mappping or file', function () {
      expect(function(){
        mwIconProvider.addIconSet({
          id: 'fa'
        });
      }).toThrow();
    });
  });

  describe('using mwIcon', function(){

    describe('querying icons', function(){
      it('returns the iconkey', function(){
        var uSpy =jasmine.createSpy('userKeySpy');
        mwIconProvider.addIconSet({
          id: 'fa',
          icons: {
            user: 'fa-user'
          }
        });

        mwIconProvider.getIconSet('fa').getIconForKey('user').then(uSpy);

        expect(uSpy).toHaveBeenCalledWith('fa-user');
      });

      it('returns the iconkey for nested icons', function(){
        var uSpy =jasmine.createSpy('userKeySpy');
        mwIconProvider.addIconSet({
          id: 'fa',
          icons: {
            user: {
              opaque: 'fa-user-o',
              black: 'fa-user-b'
            }
          }
        });

        mwIconProvider.getIconSet('fa').getIconForKey('user.opaque').then(uSpy);

        expect(uSpy).toHaveBeenCalledWith('fa-user-o');
      });
    });

    describe('testing remote icon files', function(){
      beforeEach(function(){
        mwIconProvider.addIconSet({
          id: 'fa',
          iconsUrl: '/test/fa.json'
        });
        this.$httpBackend.when('GET', '/test/fa.json').respond(200, JSON.stringify({
          USER: 'fa-user',
          GROUP: 'fa-group'
        }));
      });

      it('loads file during runtime when a fileUrl has been set and the icon set has not been loaded yet', function(){
        var spy = jasmine.createSpy('iconsUrlResolver');
        this.mwIcon.getIconSet('fa').getIconForKey('USER').then(spy);

        this.$httpBackend.flush();
      });

      it('loads file only once', function(){
        spyOn(this.mwIcon.getIconSet('fa'), 'loadFn').and.callThrough();
        this.mwIcon.getIconSet('fa').getIconForKey('USER');
        this.mwIcon.getIconSet('fa').getIconForKey('GROUP');

        this.$httpBackend.flush();

        expect(this.mwIcon.getIconSet('fa').loadFn).toHaveBeenCalledTimes(1);
      });

      it('return icon key', function(){
        var uSpy = jasmine.createSpy('userIconKey');
        this.mwIcon.getIconSet('fa').getIconForKey('USER').then(uSpy);

        this.$httpBackend.flush();

        expect(uSpy).toHaveBeenCalledWith('fa-user');
      });

      it('replaces icons when file is loaded', function(){
        var uSpy = jasmine.createSpy('userIconKey');
        this.mwIcon.getIconSet('fa').replaceIcons({USER:'other-icon'});
        this.mwIcon.getIconSet('fa').getIconForKey('USER').then(uSpy);

        this.$httpBackend.flush();

        expect(uSpy).toHaveBeenCalledWith('other-icon');
      });

    });
  });
});
<commit_msg>triggers digest cycle so promises are resolved<commit_after>describe('mwUi mwIcon Service', function () {
  var mwIconProvider;

  beforeEach(module('mwUI'));

  beforeEach(function () {
    module('mwUI', function (_mwIconProvider_){
      mwIconProvider =_mwIconProvider_;
    });
  });

  beforeEach(inject(function (mwIcon, $templateRequest, $rootScope, $httpBackend) {
    this.mwIcon = mwIcon;
    this.$templateRequest = $templateRequest;
    this.$rootScope = $rootScope;
    this.$httpBackend = $httpBackend;
  }));

  describe('configuring provider', function () {

    it('registers an icon', function () {
      mwIconProvider.addIconSet({
        id: 'fa',
        icons: {
          USER: 'fa-user'
        }
      });

      expect(this.mwIcon.getIconSet('fa').id).toBe('fa');
    });

    it('registers an icon where the icon mapping comes from a file', function () {
      mwIconProvider.addIconSet({
        id: 'fa',
        iconsUrl: '/test/fa.json'
      });

      expect(this.mwIcon.getIconSet('fa').id).toBe('fa');
    });

    it('throws an error when you try to register an icon without nay icon mappping or file', function () {
      expect(function(){
        mwIconProvider.addIconSet({
          id: 'fa'
        });
      }).toThrow();
    });
  });

  describe('using mwIcon', function(){

    describe('querying icons', function(){
      it('returns the iconkey', function(){
        var uSpy =jasmine.createSpy('userKeySpy');
        mwIconProvider.addIconSet({
          id: 'fa',
          icons: {
            user: 'fa-user'
          }
        });

        mwIconProvider.getIconSet('fa').getIconForKey('user').then(uSpy);
        this.$rootScope.$digest();

        expect(uSpy).toHaveBeenCalledWith('fa-user');
      });

      it('returns the iconkey for nested icons', function(){
        var uSpy =jasmine.createSpy('userKeySpy');
        mwIconProvider.addIconSet({
          id: 'fa',
          icons: {
            user: {
              opaque: 'fa-user-o',
              black: 'fa-user-b'
            }
          }
        });

        mwIconProvider.getIconSet('fa').getIconForKey('user.opaque').then(uSpy);
        this.$rootScope.$digest();

        expect(uSpy).toHaveBeenCalledWith('fa-user-o');
      });
    });

    describe('testing remote icon files', function(){
      beforeEach(function(){
        mwIconProvider.addIconSet({
          id: 'fa',
          iconsUrl: '/test/fa.json'
        });
        this.$httpBackend.when('GET', '/test/fa.json').respond(200, JSON.stringify({
          USER: 'fa-user',
          GROUP: 'fa-group'
        }));
      });

      it('loads file during runtime when a fileUrl has been set and the icon set has not been loaded yet', function(){
        var spy = jasmine.createSpy('iconsUrlResolver');
        this.mwIcon.getIconSet('fa').getIconForKey('USER').then(spy);

        this.$httpBackend.flush();
      });

      it('loads file only once', function(){
        spyOn(this.mwIcon.getIconSet('fa'), 'loadFn').and.callThrough();
        this.mwIcon.getIconSet('fa').getIconForKey('USER');
        this.mwIcon.getIconSet('fa').getIconForKey('GROUP');

        this.$httpBackend.flush();

        expect(this.mwIcon.getIconSet('fa').loadFn).toHaveBeenCalledTimes(1);
      });

      it('return icon key', function(){
        var uSpy = jasmine.createSpy('userIconKey');
        this.mwIcon.getIconSet('fa').getIconForKey('USER').then(uSpy);

        this.$httpBackend.flush();

        expect(uSpy).toHaveBeenCalledWith('fa-user');
      });

      it('replaces icons when file is loaded', function(){
        var uSpy = jasmine.createSpy('userIconKey');
        this.mwIcon.getIconSet('fa').replaceIcons({USER:'other-icon'});
        this.mwIcon.getIconSet('fa').getIconForKey('USER').then(uSpy);

        this.$httpBackend.flush();

        expect(uSpy).toHaveBeenCalledWith('other-icon');
      });

    });
  });
});
<|endoftext|>


<commit_before>// tipsy, facebook style tooltips for jquery
// version 1.0.0a
// (c) 2008-2010 jason frame [jason@onehackoranother.com]
// released under the MIT license

(function($) {

    function maybeCall(thing, ctx) {
        return (typeof thing == 'function') ? (thing.call(ctx)) : thing;
    };

    function Tipsy(element, options) {
        this.$element = $(element);
        this.options = options;
        this.enabled = true;
        this.fixTitle();
    };

    Tipsy.prototype = {
        show: function() {
            var title = this.getTitle();
            if (title && this.enabled) {
                var $tip = this.tip();

                $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
                $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
                $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body);

                var pos = $.extend({}, this.$element.offset(), {
                    width: this.$element[0].offsetWidth,
                    height: this.$element[0].offsetHeight
                });

                var actualWidth = $tip[0].offsetWidth,
                    actualHeight = $tip[0].offsetHeight,
                    gravity = maybeCall(this.options.gravity, this.$element[0]);

                var tp;
                switch (gravity.charAt(0)) {
                    case 'n':
                        tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
                        break;
                    case 's':
                        tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
                        break;
                    case 'e':
                        tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
                        break;
                    case 'w':
                        tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
                        break;
                }

                if (gravity.length == 2) {
                    if (gravity.charAt(1) == 'w') {
                        tp.left = pos.left + pos.width / 2 - 15;
                    } else {
                        tp.left = pos.left + pos.width / 2 - actualWidth + 15;
                    }
                }

                $tip.css(tp).addClass('tipsy-' + gravity);
                $tip.find('.tipsy-arrow')[0].className = 'tipsy-arrow tipsy-arrow-' + gravity.charAt(0);
                if (this.options.className) {
                    $tip.addClass(maybeCall(this.options.className, this.$element[0]));
                }

                if (this.options.fade) {
                    $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity});
                } else {
                    $tip.css({visibility: 'visible', opacity: this.options.opacity});
                }
            }
        },

        hide: function() {
            if (this.options.fade) {
                this.tip().stop().fadeOut(function() { $(this).remove(); });
            } else {
                this.tip().remove();
            }
        },

        fixTitle: function() {
            var $e = this.$element;
            if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') {
                $e.attr('original-title', $e.attr('title') || '').removeAttr('title');
            }
        },

        getTitle: function() {
            var title, $e = this.$element, o = this.options;
            this.fixTitle();
            var title, o = this.options;
            if (typeof o.title == 'string') {
                title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
            } else if (typeof o.title == 'function') {
                title = o.title.call($e[0]);
            }
            title = ('' + title).replace(/(^\s*|\s*$)/, "");
            return title || o.fallback;
        },

        tip: function() {
            if (!this.$tip) {
                this.$tip = $('

').html('

');
            }
            return this.$tip;
        },

        validate: function() {
            if (!this.$element[0].parentNode) {
                this.hide();
                this.$element = null;
                this.options = null;
            }
        },

        enable: function() { this.enabled = true; },
        disable: function() { this.enabled = false; },
        toggleEnabled: function() { this.enabled = !this.enabled; }
    };

    $.fn.tipsy = function(options) {

        if (options === true) {
            return this.data('tipsy');
        } else if (typeof options == 'string') {
            var tipsy = this.data('tipsy');
            if (tipsy) tipsy[options]();
            return this;
        }

        options = $.extend({}, $.fn.tipsy.defaults, options);

        function get(ele) {
            var tipsy = $.data(ele, 'tipsy');
            if (!tipsy) {
                tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
                $.data(ele, 'tipsy', tipsy);
            }
            return tipsy;
        }

        function enter() {
            var tipsy = get(this);
            tipsy.hoverState = 'in';
            if (options.delayIn == 0) {
                tipsy.show();
            } else {
                tipsy.fixTitle();
                setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
            }
        };

        function leave() {
            var tipsy = get(this);
            tipsy.hoverState = 'out';
            if (options.delayOut == 0) {
                tipsy.hide();
            } else {
                setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
            }
        };

        if (!options.live) this.each(function() { get(this); });

        if (options.trigger != 'manual') {
            var binder   = options.live ? 'live' : 'bind',
                eventIn  = options.trigger == 'hover' ? 'mouseenter' : 'focus',
                eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
            this[binder](eventIn, enter)[binder](eventOut, leave);
        }

        return this;

    };

    $.fn.tipsy.defaults = {
        className: null,
        delayIn: 0,
        delayOut: 0,
        fade: false,
        fallback: '',
        gravity: 'n',
        html: false,
        live: false,
        offset: 0,
        opacity: 0.8,
        title: 'title',
        trigger: 'hover'
    };

    // Overwrite this method to provide options on a per-element basis.
    // For example, you could store the gravity in a 'tipsy-gravity' attribute:
    // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
    // (remember - do not modify 'options' in place!)
    $.fn.tipsy.elementOptions = function(ele, options) {
        return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
    };

    $.fn.tipsy.autoNS = function() {
        return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
    };

    $.fn.tipsy.autoWE = function() {
        return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
    };

    /**
     * yields a closure of the supplied parameters, producing a function that takes
     * no arguments and is suitable for use as an autogravity function like so:
     *
     * @param margin (int) - distance from the viewable region edge that an
     *        element should be before setting its tooltip's gravity to be away
     *        from that edge.
     * @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer
     *        if there are no viewable region edges effecting the tooltip's
     *        gravity. It will try to vary from this minimally, for example,
     *        if 'sw' is preferred and an element is near the right viewable
     *        region edge, but not the top edge, it will set the gravity for
     *        that element's tooltip to be 'se', preserving the southern
     *        component.
     */
     $.fn.tipsy.autoBounds = function(margin, prefer) {
		return function() {
			var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)},
			    boundTop = $(document).scrollTop() + margin,
			    boundLeft = $(document).scrollLeft() + margin,
			    $this = $(this);

			if ($this.offset().top < boundTop) dir.ns = 'n';
			if ($this.offset().left < boundLeft) dir.ew = 'w';
			if ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e';
			if ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's';

			return dir.ns + (dir.ew ? dir.ew : '');
		}
	};

})(jQuery);
<commit_msg>jquery tipsy upgrade<commit_after>// tipsy, facebook style tooltips for jquery
// version 1.0.0a
// (c) 2008-2010 jason frame [jason@onehackoranother.com]
// released under the MIT license

(function($) {

    function maybeCall(thing, ctx) {
        return (typeof thing == 'function') ? (thing.call(ctx)) : thing;
    };

    function isElementInDOM(ele) {
      while (ele = ele.parentNode) {
        if (ele == document) return true;
      }
      return false;
    };

    function Tipsy(element, options) {
        this.$element = $(element);
        this.options = options;
        this.enabled = true;
        this.fixTitle();
    };

    Tipsy.prototype = {
        show: function() {
            var title = this.getTitle();
            if (title && this.enabled) {
                var $tip = this.tip();

                $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
                $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
                $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body);

                var pos = $.extend({}, this.$element.offset(), {
                    width: this.$element[0].offsetWidth,
                    height: this.$element[0].offsetHeight
                });

                var actualWidth = $tip[0].offsetWidth,
                    actualHeight = $tip[0].offsetHeight,
                    gravity = maybeCall(this.options.gravity, this.$element[0]);

                var tp;
                switch (gravity.charAt(0)) {
                    case 'n':
                        tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
                        break;
                    case 's':
                        tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
                        break;
                    case 'e':
                        tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
                        break;
                    case 'w':
                        tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
                        break;
                }

                if (gravity.length == 2) {
                    if (gravity.charAt(1) == 'w') {
                        tp.left = pos.left + pos.width / 2 - 15;
                    } else {
                        tp.left = pos.left + pos.width / 2 - actualWidth + 15;
                    }
                }

                $tip.css(tp).addClass('tipsy-' + gravity);
                $tip.find('.tipsy-arrow')[0].className = 'tipsy-arrow tipsy-arrow-' + gravity.charAt(0);
                if (this.options.className) {
                    $tip.addClass(maybeCall(this.options.className, this.$element[0]));
                }

                if (this.options.fade) {
                    $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity});
                } else {
                    $tip.css({visibility: 'visible', opacity: this.options.opacity});
                }
            }
        },

        hide: function() {
            if (this.options.fade) {
                this.tip().stop().fadeOut(function() { $(this).remove(); });
            } else {
                this.tip().remove();
            }
        },

        fixTitle: function() {
            var $e = this.$element;
            if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') {
                $e.attr('original-title', $e.attr('title') || '').removeAttr('title');
            }
        },

        getTitle: function() {
            var title, $e = this.$element, o = this.options;
            this.fixTitle();
            var title, o = this.options;
            if (typeof o.title == 'string') {
                title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
            } else if (typeof o.title == 'function') {
                title = o.title.call($e[0]);
            }
            title = ('' + title).replace(/(^\s*|\s*$)/, "");
            return title || o.fallback;
        },

        tip: function() {
            if (!this.$tip) {
                this.$tip = $('

').html('

');
                this.$tip.data('tipsy-pointee', this.$element[0]);
            }
            return this.$tip;
        },

        validate: function() {
            if (!this.$element[0].parentNode) {
                this.hide();
                this.$element = null;
                this.options = null;
            }
        },

        enable: function() { this.enabled = true; },
        disable: function() { this.enabled = false; },
        toggleEnabled: function() { this.enabled = !this.enabled; }
    };

    $.fn.tipsy = function(options) {

        if (options === true) {
            return this.data('tipsy');
        } else if (typeof options == 'string') {
            var tipsy = this.data('tipsy');
            if (tipsy) tipsy[options]();
            return this;
        }

        options = $.extend({}, $.fn.tipsy.defaults, options);

        function get(ele) {
            var tipsy = $.data(ele, 'tipsy');
            if (!tipsy) {
                tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
                $.data(ele, 'tipsy', tipsy);
            }
            return tipsy;
        }

        function enter() {
            var tipsy = get(this);
            tipsy.hoverState = 'in';
            if (options.delayIn == 0) {
                tipsy.show();
            } else {
                tipsy.fixTitle();
                setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
            }
        };

        function leave() {
            var tipsy = get(this);
            tipsy.hoverState = 'out';
            if (options.delayOut == 0) {
                tipsy.hide();
            } else {
                setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
            }
        };

        if (!options.live) this.each(function() { get(this); });

        if (options.trigger != 'manual') {
            var binder   = options.live ? 'live' : 'bind',
                eventIn  = options.trigger == 'hover' ? 'mouseenter' : 'focus',
                eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
            this[binder](eventIn, enter)[binder](eventOut, leave);
        }

        return this;

    };

    $.fn.tipsy.defaults = {
        className: null,
        delayIn: 0,
        delayOut: 0,
        fade: false,
        fallback: '',
        gravity: 'n',
        html: false,
        live: false,
        offset: 0,
        opacity: 0.8,
        title: 'title',
        trigger: 'hover'
    };

    $.fn.tipsy.revalidate = function() {
      $('.tipsy').each(function() {
        var pointee = $.data(this, 'tipsy-pointee');
        if (!pointee || !isElementInDOM(pointee)) {
          $(this).remove();
        }
      });
    };

    // Overwrite this method to provide options on a per-element basis.
    // For example, you could store the gravity in a 'tipsy-gravity' attribute:
    // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
    // (remember - do not modify 'options' in place!)
    $.fn.tipsy.elementOptions = function(ele, options) {
        return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
    };

    $.fn.tipsy.autoNS = function() {
        return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
    };

    $.fn.tipsy.autoWE = function() {
        return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
    };

    /**
     * yields a closure of the supplied parameters, producing a function that takes
     * no arguments and is suitable for use as an autogravity function like so:
     *
     * @param margin (int) - distance from the viewable region edge that an
     *        element should be before setting its tooltip's gravity to be away
     *        from that edge.
     * @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer
     *        if there are no viewable region edges effecting the tooltip's
     *        gravity. It will try to vary from this minimally, for example,
     *        if 'sw' is preferred and an element is near the right viewable
     *        region edge, but not the top edge, it will set the gravity for
     *        that element's tooltip to be 'se', preserving the southern
     *        component.
     */
     $.fn.tipsy.autoBounds = function(margin, prefer) {
		return function() {
			var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)},
			    boundTop = $(document).scrollTop() + margin,
			    boundLeft = $(document).scrollLeft() + margin,
			    $this = $(this);

			if ($this.offset().top < boundTop) dir.ns = 'n';
			if ($this.offset().left < boundLeft) dir.ew = 'w';
			if ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e';
			if ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's';

			return dir.ns + (dir.ew ? dir.ew : '');
		}
	};

})(jQuery);
<|endoftext|>


<commit_before>var init = require('../main/init');
var l = require('../main/l');
var dt = require('../main/dt');
var userl = require('../main/user');
var photol = require('../main/photo');
var express = require('../main/express');

init.add(function () {

	var app = express.app;

	console.log('users-html:');

	app.get('/users/:id([0-9]+)', function (req, res) {
		var id = parseInt(req.params.id) || 0;
		var user = res.locals.user;
		userl.findUserForView(id, user, function (err, tuser) {
			if (err) return res.renderErr(err);
			var pg = photol.getPage(req.query.pg);
			var ps = photol.getPageSize(req.query.ps);
			photol.findPhotosByUser(id, pg, ps, function (err, photos, last) {
				if (err) return res.renderErr(err);
				prevNext(id, pg, last, function (prevUrl, nextUrl) {
					res.render('user-profile', {
						tuser: tuser,
						showActions: user && (user.admin || user._id === id),
						photos: photos,
						prevUrl: prevUrl,
						nextUrl: nextUrl,
						firstPage: pg == 1
					});
				});
			});
		});
	});

	function prevNext(id, pg, last, next) {
		var prevUrl, nextUrl;
		var u;
		if (pg > 1) {
			u = new UrlMaker('/users/' + id)
			u.add('pg', pg - 1, 1);
			prevUrl = u.toString();
		}
		if (!last) {
			u = new UrlMaker('/users/' + id);
			u.add('pg', pg + 1, 1);
			nextUrl = u.toString();
		}
		next(prevUrl, nextUrl);
	}

	app.get('/users/:id([0-9]+)/edit', function (req, res) {
		req.findUser(function (err, user) {
			if (err) return res.renderErr(err);
			var id = parseInt(req.params.id) || 0;
			userl.findUserForEdit(id, user, function (err, tuser) {
				if (err) return res.renderErr(err);
				res.render('user-profile-edit', {
					tuser: tuser
				});
			});
		});
	});

});
<commit_msg>minor.<commit_after>var init = require('../main/init');
var l = require('../main/l');
var dt = require('../main/dt');
var userl = require('../main/user');
var photol = require('../main/photo');
var express = require('../main/express');
var UrlMaker = require('../main/UrlMaker');

init.add(function () {

	var app = express.app;

	console.log('users-html:');

	app.get('/users/:id([0-9]+)', function (req, res) {
		var id = parseInt(req.params.id) || 0;
		var user = res.locals.user;
		userl.findUserForView(id, user, function (err, tuser) {
			if (err) return res.renderErr(err);
			var pg = photol.getPage(req.query.pg);
			var ps = photol.getPageSize(req.query.ps);
			photol.findPhotosByUser(id, pg, ps, function (err, photos, last) {
				if (err) return res.renderErr(err);
				prevNext(id, pg, last, function (prevUrl, nextUrl) {
					res.render('user-profile', {
						tuser: tuser,
						showActions: user && (user.admin || user._id === id),
						photos: photos,
						prevUrl: prevUrl,
						nextUrl: nextUrl,
						firstPage: pg == 1
					});
				});
			});
		});
	});

	function prevNext(id, pg, last, next) {
		var prevUrl, nextUrl;
		var u;
		if (pg > 1) {
			u = new UrlMaker('/users/' + id)
			u.add('pg', pg - 1, 1);
			prevUrl = u.toString();
		}
		if (!last) {
			u = new UrlMaker('/users/' + id);
			u.add('pg', pg + 1, 1);
			nextUrl = u.toString();
		}
		next(prevUrl, nextUrl);
	}

	app.get('/users/:id([0-9]+)/edit', function (req, res) {
		req.findUser(function (err, user) {
			if (err) return res.renderErr(err);
			var id = parseInt(req.params.id) || 0;
			userl.findUserForEdit(id, user, function (err, tuser) {
				if (err) return res.renderErr(err);
				res.render('user-profile-edit', {
					tuser: tuser
				});
			});
		});
	});

});
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import cx from 'classnames';
import { props, t } from '../utils';
import { warn } from '../utils/log';

/**
 * ### Absolute dimmed layer with loading spinner in the center
 */
@props({
  /**
  * spinner size
  */
  size: t.maybe(t.union([t.String, t.Number])),
  /**
  * spinner main color
  */
  color: t.maybe(t.String),
  /**
  * spinner message
  */
  message: t.maybe(t.struct({
    content: t.String,
    color: t.maybe(t.String),
    size: t.maybe(t.union([t.String, t.Number]))
  })),
  /**
  * dimmed-overlay color
  */
  overlayColor: t.maybe(t.String),
  id: t.maybe(t.String),
  className: t.maybe(t.String),
  style: t.maybe(t.Object)
})
export default class LoadingSpinner extends React.Component {

  static defaultProps = {
    size: '3em',
    overlayColor: 'rgba(255, 255, 255, .9)'
  };

  componentDidMount() {
    this.logWarnings();
  }

  getMessage = () => {
    if (this.props.message) {
      const { message, size } = this.props;
      const messageStyle = {
        marginTop: size,
        fontSize: message.size || 16,
        color: message.color
      };

      return (

          {message.content}

      );
    }
  };

  logWarnings = () => {
    warn(() => {
      const { parentNode } = ReactDOM.findDOMNode(this.refs.loadingSpinner);
      const { position } = window.getComputedStyle(parentNode);
      if (position !== 'relative' && position !== 'absolute') {
        return ['LoadingSpinner\'s parent node style should have "position: relative" or "position: absolute"', parentNode];
      }
    });
  };

  render() {
    const { size, color, overlayColor, id, className, style } = this.props;

    const overlayStyle = { backgroundColor: overlayColor };
    const spinnerStyle = {
      fontSize: size,
      color
    };

    return (

          {this.getMessage()}

    );
  }

}
<commit_msg>update comments for LoadingSpinner<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import cx from 'classnames';
import { props, t } from '../utils';
import { warn } from '../utils/log';

/**
 * Absolute dimmed layer with loading spinner in the center
 * @param size - spinner size
 * @param color - spinner main color
 * @param message - spinner message
 * @param overlayColor - dimmed-overlay color
 */
@props({
  size: t.maybe(t.union([t.String, t.Number])),
  color: t.maybe(t.String),
  message: t.maybe(t.struct({
    content: t.String,
    color: t.maybe(t.String),
    size: t.maybe(t.union([t.String, t.Number]))
  })),
  overlayColor: t.maybe(t.String),
  id: t.maybe(t.String),
  className: t.maybe(t.String),
  style: t.maybe(t.Object)
})
export default class LoadingSpinner extends React.Component {

  static defaultProps = {
    size: '3em',
    overlayColor: 'rgba(255, 255, 255, .9)'
  };

  componentDidMount() {
    this.logWarnings();
  }

  getMessage = () => {
    if (this.props.message) {
      const { message, size } = this.props;
      const messageStyle = {
        marginTop: size,
        fontSize: message.size || 16,
        color: message.color
      };

      return (

          {message.content}

      );
    }
  };

  logWarnings = () => {
    warn(() => {
      const { parentNode } = ReactDOM.findDOMNode(this.refs.loadingSpinner);
      const { position } = window.getComputedStyle(parentNode);
      if (position !== 'relative' && position !== 'absolute') {
        return ['LoadingSpinner\'s parent node style should have "position: relative" or "position: absolute"', parentNode];
      }
    });
  };

  render() {
    const { size, color, overlayColor, id, className, style } = this.props;

    const overlayStyle = { backgroundColor: overlayColor };
    const spinnerStyle = {
      fontSize: size,
      color
    };

    return (

          {this.getMessage()}

    );
  }

}
<|endoftext|>


<commit_before>// var ObjectID = require('mongodb').ObjectID;
var DBRef = require('mongodb').DBRef;
// var EventProxy = require('eventproxy');
// var us = require('underscore');

// var db = require('./db');
// var ERR = require('../errorcode');
// var U = require('../util');

exports.save = function(params, callback){

    var key = params.key;
    var value = params.value;
    var loginUser = params.loginUser;

    db.storage.find({ key: key }, function(err, doc){
        if(err){
            return callback(err);
        }
        if(!doc){
            doc = {
                key: key
            };
        }
        doc.value = value;
        doc.updateTime = Date.now();
        doc.updateUser = new DBRef('user', loginUser._id);

        db.storage.save(doc, function(err){
            callback(err, doc);
        });

    });

};

exports.getConfig = function(query, callback){

    db.storage.find(query, callback);
};
<commit_msg>bugfix<commit_after>// var ObjectID = require('mongodb').ObjectID;
var DBRef = require('mongodb').DBRef;
// var EventProxy = require('eventproxy');
// var us = require('underscore');

// var db = require('./db');
// var ERR = require('../errorcode');
// var U = require('../util');

exports.save = function(params, callback){

    var key = params.key;
    var value = params.value;
    var loginUser = params.loginUser;

    db.storage.findOne({ key: key }, function(err, doc){
        if(err){
            return callback(err);
        }
        if(!doc){
            doc = {
                key: key,
                createTime: Date.now()
            };
        }
        doc.value = value;
        doc.updateTime = Date.now();
        doc.updateUser = new DBRef('user', loginUser._id);

        db.storage.save(doc, function(err){
            callback(err, doc);
        });

    });

};

exports.getConfig = function(query, callback){

    db.storage.findOne(query, callback);
};
<|endoftext|>


<commit_before>import React from 'react';
import cx from 'classnames';
import { warn } from '../utils/log';

/**
 * ### Absolute dimmed layer with loading spinner in the center
 */
const LoadingSpinner = React.createClass({

  propTypes: {
    /**
     * spinner size
     */
    size: React.PropTypes.oneOfType([
      React.PropTypes.string,
      React.PropTypes.number
    ]),
    /**
     * spinner main color
     */
    color: React.PropTypes.string,
    /**
     * spinner message
     */
    message: React.PropTypes.shape({
      content: React.PropTypes.string.isRequired,
      color: React.PropTypes.string,
      size: React.PropTypes.oneOfType([
        React.PropTypes.string,
        React.PropTypes.number
      ])
    }),
    /**
     * dimmed-overlay color
     */
    overlayColor: React.PropTypes.string,
    id: React.PropTypes.string,
    className: React.PropTypes.string,
    style: React.PropTypes.object
  },

  getDefaultProps() {
    return {
      size: '3em',
      overlayColor: 'rgba(255, 255, 255, .9)'
    };
  },

  componentDidMount() {
    this.logWarnings();
  },

  getMessage() {
    if (this.props.message) {
      const { message, size } = this.props;
      const messageStyle = {
        marginTop: size,
        fontSize: message.size || 16,
        color: message.color
      };

      return (

          {message.content}

      );
    }
  },

  logWarnings() {
    warn(() => {
      const { position } = this.refs.loadingSpinner.getDOMNode().parentNode.style;
      if (position !== 'relative' && position !== 'absolute') {
        return 'LoadingSpinner\'s parent node style should have "position: relative" or "position: absolute"';
      }
    });
  },

  render() {
    const { size, color, overlayColor, id, className, style } = this.props;

    const overlayStyle = { backgroundColor: overlayColor };
    const spinnerStyle = {
      fontSize: size,
      color
    };

    return (

          {this.getMessage()}

    );
  }

});

export default LoadingSpinner;
<commit_msg>better warning for loadingspinner<commit_after>import React from 'react';
import cx from 'classnames';
import { warn } from '../utils/log';

/**
 * ### Absolute dimmed layer with loading spinner in the center
 */
const LoadingSpinner = React.createClass({

  propTypes: {
    /**
     * spinner size
     */
    size: React.PropTypes.oneOfType([
      React.PropTypes.string,
      React.PropTypes.number
    ]),
    /**
     * spinner main color
     */
    color: React.PropTypes.string,
    /**
     * spinner message
     */
    message: React.PropTypes.shape({
      content: React.PropTypes.string.isRequired,
      color: React.PropTypes.string,
      size: React.PropTypes.oneOfType([
        React.PropTypes.string,
        React.PropTypes.number
      ])
    }),
    /**
     * dimmed-overlay color
     */
    overlayColor: React.PropTypes.string,
    id: React.PropTypes.string,
    className: React.PropTypes.string,
    style: React.PropTypes.object
  },

  getDefaultProps() {
    return {
      size: '3em',
      overlayColor: 'rgba(255, 255, 255, .9)'
    };
  },

  componentDidMount() {
    this.logWarnings();
  },

  getMessage() {
    if (this.props.message) {
      const { message, size } = this.props;
      const messageStyle = {
        marginTop: size,
        fontSize: message.size || 16,
        color: message.color
      };

      return (

          {message.content}

      );
    }
  },

  logWarnings() {
    warn(() => {
      const { parentNode } = this.refs.loadingSpinner.getDOMNode();
      const { position } = window.getComputedStyle(parentNode);
      if (position !== 'relative' && position !== 'absolute') {
        return ['LoadingSpinner\'s parent node style should have "position: relative" or "position: absolute"', parentNode];
      }
    });
  },

  render() {
    const { size, color, overlayColor, id, className, style } = this.props;

    const overlayStyle = { backgroundColor: overlayColor };
    const spinnerStyle = {
      fontSize: size,
      color
    };

    return (

          {this.getMessage()}

    );
  }

});

export default LoadingSpinner;
<|endoftext|>


<commit_before>
var fs = require('fs');

var dontPersist = true;

if(! fs.existsSync) {
  fs.existsSync = function(path) {
    try {
      fs.statSync(path);
      return true;
    } catch(e) {
      return false;
    }
  };
}

var amd = false;
if(typeof(exports) === 'undefined') {
  var exports = {};
  amd = true;
}

var config = {};

exports.server = (function() {
  var url=require('url'),
    crypto=require('crypto'),
    tokens, lastModified, contentType, content;

  var responseDelay = null;
  var capturedRequests = [];
  var doCapture = false;
  var silent = false;

  function log() {
    if(!silent) {
      console.log.apply(console, arguments);
    }
  }

  function captureRequests() {
    doCapture = true;
  }

  function resetState() {
    tokens = {}, lastModified = {}, contentType = {}, content = {};
    responseDelay = null;
    clearCaptured();
    doCapture = false;
  }

  function clearCaptured() {
    while(capturedRequests.length > 0) {
      capturedRequests.shift();
    }
  }

  function getState() {
    return {
      tokens: tokens,
      lastModified: lastModified,
      contentType: contentType,
      content: content
    };
  }

  function delayResponse(msec) {
    responseDelay = msec;
  }

  function saveState(name, value) {
    fs.writeFile("server-state/" + name + ".json", JSON.stringify(value), function() { });
  }

  function loadState(name) {
    if(fs.existsSync("server-state/" + name + ".json")) {
      return JSON.parse(fs.readFileSync("server-state/" + name + ".json"));
    } else {
      return {}
    }
  }

  function saveData() {
    if(dontPersist) {
      return;
    }
    if(! fs.existsSync("server-state")) {
      fs.mkdirSync("server-state");
    }
    saveState('tokens', tokens);
    saveState('lastModified', lastModified);
    saveState('contentType', contentType);
    saveState('content', content);
  }

  function loadData() {
    if(dontPersist) {
      return;
    }
    tokens = loadState('tokens');
    lastModified = loadState('lastModified');
    contentType = loadState('contentType');
    content = loadState('content');

    log("DATA LOADED", tokens, lastModified, contentType, content);
  }

  function makeScopePaths(userName, scopes) {
    var scopePaths=[];
    for(var i=0; i<scopes.length; i++) {
      var thisScopeParts = scopes[i].split(':');
      if(thisScopeParts[0]=='') {
        scopePaths.push(userName+'/:'+thisScopeParts[1]);
      } else {
        scopePaths.push(userName+'/'+thisScopeParts[0]+'/:'+thisScopeParts[1]);
        scopePaths.push(userName+'/public/'+thisScopeParts[0]+'/:'+thisScopeParts[1]);
      }
    }
    return scopePaths;
  }

  function addToken(token, scopes) {
    tokens[token] = makeScopePaths('me', scopes);
  }

  function createInitialTokens() {
    if(! config.initialTokens) {
      return;
    }
    for(var token in config.initialTokens) {
      var scopePaths = makeScopePaths(
        config.defaultUserName, config.initialTokens[token]
      );
      log('adding ',scopePaths,' for', token);
      tokens[token] = scopePaths;
    }
  }

  function createToken(userName, scopes, cb) {
    crypto.randomBytes(48, function(ex, buf) {
      var token = buf.toString('hex');
      var scopePaths = makeScopePaths(userName, scopes);
      log('createToken ',userName,scopes);
      log('adding ',scopePaths,' for',token);
      tokens[token] = scopePaths;
      cb(token);
    });
  }
  function mayRead(authorizationHeader, path) {
    if(authorizationHeader) {
      var scopes = tokens[authorizationHeader.substring('Bearer '.length)];
      if(scopes) {
        for(var i=0; i<scopes.length; i++) {
          var scopeParts = scopes[i].split(':');
          if(path.substring(0, scopeParts[0].length)==scopeParts[0]) {
            return true;
          } else {
            log(path.substring(0, scopeParts[0].length)+' != '+ scopeParts[0]);
          }
        }
      }
    } else {
      var pathParts = path.split('/');
      return (pathParts[0]=='' && pathParts[2]=='public' && path.substr(-1) != '/');
    }
  }
  function mayWrite(authorizationHeader, path) {
    if(authorizationHeader) {
      var scopes = tokens[authorizationHeader.substring('Bearer '.length)];
      if(scopes) {
        for(var i=0; i<scopes.length; i++) {
          var scopeParts = scopes[i].split(':');
          if(scopeParts.length==2 && scopeParts[1]=='rw' && path.substring(0, scopeParts[0].length)==scopeParts[0]) {
            return true;
          }
        }
      }
    }
  }
  function writeHead(res, status, origin, timestamp, contentType) {
    var headers = {
      'Access-Control-Allow-Origin': (origin?origin:'*'),
      'Access-Control-Allow-Headers': 'Content-Type, Authorization, Origin',
      'Access-Control-Allow-Methods': 'GET, PUT, DELETE',
    };
    if(timestamp) {
      headers['last-modified']= new Date(timestamp).toString();
    }
    if(contentType) {
      headers['content-type']= contentType;
    }
    res.writeHead(status, headers);
  }

  function writeRaw(res, contentType, content, origin, timestamp) {
    function doWrite() {
      log('access-control-allow-origin:'+ (origin?origin:'*'));
      log(contentType);
      log(content);
      writeHead(res, 200, origin, timestamp, contentType);
      res.write(content);
      res.end();
    }
    responseDelay ? setTimeout(doWrite, responseDelay) : doWrite();
  }

  function writeJson(res, obj, origin, timestamp) {
    writeRaw(res, 'application/json', JSON.stringify(obj), origin, timestamp);
  }
  function writeHtml(res, html) {
    res.writeHead(200, {
      'content-type': 'text/html'
    });
    res.write('<!DOCTYPE html lang="en"><title>'+config.host+'</title><meta charset="utf-8">'+html+'');
    res.end();
  }
  function give404(res, origin) {
    log('404');
    log(content);
    writeHead(res, 404, origin, 'now');
    res.end();
  }
  function computerSaysNo(res, origin) {
    log('COMPUTER_SAYS_NO');
    log(tokens);
    writeHead(res, 401, origin, 'now');
    res.end();
  }

  function toHtml(str) {
    return str
      .replace(/&/g, '&')
      .replace(/</g, '<')
      .replace(/>/g, '>')
      .replace(/"/g, '"');
  }
  function portal(urlObj, res) {
    res.writeHead(200, {
      'content-type': 'text/html'
    });
    res.write('<!DOCTYPE html lang="en"><title>'+config.host+'</title><meta charset="utf-8">
');
    var scopes = {
      'http://todomvc.michiel.5apps.com/': ['tasks:rw'],
      'http://litewrite.github.com/litewrite/': ['documents:rw'],
      'http://todo-mvc.michiel.5apps.com/labs/architecture-examples/remotestorage/': ['tasks:rw'],
      'http://unhosted-time-tracker.michiel.5apps.com/': ['tasks:rw'],
      'http://music.michiel.5apps.com/': ['music:rw'],
      'http://editor.michiel.5apps.com/': ['code:rw'],
      'http://remotestorage-browser.nilclass.5apps.com': [':rw'],
      'http://vidmarks.silverbucket.5apps.com': ['videos:rw'],
      'http://grouptabs.xmartin.5apps.com': ['grouptabs:rw']
    };
    var outstanding = 0;
    for(var i in scopes) {
      outstanding++;
      (function(i) {
        createToken(config.defaultUserName, scopes[i], function(token) {
          res.write('
'+i+'
');
                    +'&access_token='+token+'">'+i+'
');
          outstanding--;
          if(outstanding==0) {
            res.write('
');
            res.end();
          }
        });
      })(i);
    }
  }
  function webfinger(urlObj, res) {
    log('WEBFINGER');
    if(urlObj.query['resource']) {
      userAddress = urlObj.query['resource'].substring('acct:'.length);
      userName = userAddress.split('@')[0];
    }
    writeJson(res, {
      links:[{
        href: config.protocol+'://'+config.host+'/storage/'+userName,
        rel: "remoteStorage",
        type: "https://www.w3.org/community/rww/wiki/read-write-web-00#simple",
        properties: {
          'auth-method': "https://tools.ietf.org/html/draft-ietf-oauth-v2-26#section-4.2",
          'auth-endpoint': config.protocol+'://'+config.host+'/auth/'+userName
        }
      }]
    });
  }
  function oauth(urlObj, res) {
    log('OAUTH');
    var scopes = decodeURIComponent(urlObj.query['scope']).split(' '),
    clientId = decodeURIComponent(urlObj.query['client_id']),
    redirectUri = decodeURIComponent(urlObj.query['redirect_uri']),
    clientIdToMatch,
    userName;
    if(redirectUri.split('://').length<2) {
      clientIdToMatch=redirectUri;
    } else {
      clientIdToMatch = redirectUri.split('://')[1].split('/')[0];
    }
    if(clientId != clientIdToMatch) {
      writeHtml(res, 'we do not trust this combination of client_id and redirect_uri');
    } else {
      var userName = urlObj.pathname.substring('/auth/'.length);
      createToken(userName, scopes, function(token) {
        writeHtml(res, 'Allow');
      });
    }
  }

  function storage(req, urlObj, res) {
    var path=urlObj.pathname.substring('/storage/'.length);
    var capt = {
      method: req.method,
      path: path
    };

    if(doCapture) {
      capturedRequests.push(capt);
    }

    if(req.method=='OPTIONS') {
      log('OPTIONS ', req.headers);
      writeJson(res, null, req.headers.origin);
    } else if(req.method=='GET') {
      log('GET');
      if(mayRead(req.headers.authorization, path)) {
        if(content[path]) {
          if(path.substr(-1)=='/') {
            writeJson(res, content[path], req.headers.origin, 0);
          } else {
            writeRaw(res, contentType[path], content[path], req.headers.origin, lastModified[path]);
          }
        } else {
          if(path.substr(-1)=='/') {
            writeJson(res, {}, req.headers.origin, 0);
          } else {
            give404(res, req.headers.origin);
          }
        }
      } else {
        computerSaysNo(res, req.headers.origin);
      }
    } else if(req.method=='PUT') {
      log('PUT');
      if(mayWrite(req.headers.authorization, path) && path.substr(-1)!='/') {
        var dataStr = '';
        req.on('data', function(chunk) {
          dataStr+=chunk;
        });
        req.on('end', function(chunk) {
          var timestamp = new Date().getTime();
          capt.body = dataStr;
          content[path]=dataStr;
          contentType[path]=req.headers['content-type'];
          log('stored '+path, content[path], contentType[path]);
          lastModified[path]=timestamp;
          saveData();
          var pathParts=path.split('/');
          var timestamp=new Date().getTime();
          log(pathParts);
          var fileItself=true;
          while(pathParts.length > 1) {
            var thisPart = pathParts.pop();
            if(fileItself) {
              fileItself=false;
            } else {
              thisPart += '/';
            }
            if(!content[pathParts.join('/')+'/']) {
              content[pathParts.join('/')+'/'] = {};
            }
            content[pathParts.join('/')+'/'][thisPart]=timestamp;
            // log('stored parent '+pathParts.join('/')+'/ ['+thisPart+']='+timestamp, content[pathParts.join('/')+'/']);
          }
          // log('content:', content);
          // log('contentType:', contentType);
          // log('lastModified:', lastModified);
          writeJson(res, null, req.headers.origin, timestamp);
        });
      } else {
        computerSaysNo(res, req.headers.origin);
      }
    } else if(req.method=='DELETE') {
      log('DELETE');
      if(mayWrite(req.headers.authorization, path)) {
        var timestamp = new Date().getTime();
        delete content[path];
        delete contentType[path];
        lastModified[path]=timestamp;
        saveData();
        var pathParts=path.split('/');
        var thisPart = pathParts.pop();
        if(content[pathParts.join('/')+'/']) {
          log('delete content['+pathParts.join('/')+'/]['+thisPart+']');
          delete content[pathParts.join('/')+'/'][thisPart];
        }
        log(content);
        writeJson(res, null, req.headers.origin, timestamp);
      } else {
        computerSaysNo(res, req.headers.origin);
      }
    } else {
      log('ILLEGAL '+req.method);
      computerSaysNo(res, req.headers.origin);
    }
  }

  function serve(req, res) {
    var urlObj = url.parse(req.url, true), userAddress, userName;
    log(urlObj);
    if(urlObj.pathname == '/') {
      log('PORTAL');
      portal(urlObj, res);
    } else if(urlObj.pathname == '/.well-known/host-meta.json') {//TODO: implement rest of webfinger
      log('HOST-META');
      webfinger(urlObj, res);
    } else if(urlObj.pathname.substring(0, '/auth/'.length) == '/auth/') {
      log('OAUTH');
      oauth(urlObj, res);
    } else if(urlObj.pathname.substring(0, '/storage/'.length) == '/storage/') {
      log('STORAGE');
      storage(req, urlObj, res);
    } else if(req.method == 'POST' && urlObj.pathname.substring(0, '/reset'.length) == '/reset') { // clear data; used in tests.
      resetState();
      writeJson(res, { forgot: 'everything' });
    } else {
      log('UNKNOWN');
      writeJson(res, urlObj.query);
    }
  }

  resetState();
  loadData();
  createInitialTokens();

  return {
    serve: serve,
    getState: getState,
    resetState: resetState,
    addToken: addToken,
    delayResponse: delayResponse,
    captureRequests: captureRequests,
    captured: capturedRequests,
    clearCaptured: clearCaptured,
    enableLogs: function() {
      silent = false;
    },
    disableLogs: function() {
      silent = true;
    }
  };
})();

if((!amd) && (require.main==module)) {//if this file is directly called from the CLI
  config = require('./config').config;
  dontPersist = process.argv.length > 1 && (process.argv.slice(-1)[0] == ('--no-persistence'));
  require('http').createServer(exports.server.serve).listen(config.port);
  console.log("Example server started on 0.0.0.0:" + config.port);
}

if(amd) {
  define([], exports);
}
<commit_msg>fixed 'public' access bug in example server<commit_after>
var fs = require('fs');

var dontPersist = true;

if(! fs.existsSync) {
  fs.existsSync = function(path) {
    try {
      fs.statSync(path);
      return true;
    } catch(e) {
      return false;
    }
  };
}

var amd = false;
if(typeof(exports) === 'undefined') {
  var exports = {};
  amd = true;
}

var config = {};

exports.server = (function() {
  var url=require('url'),
    crypto=require('crypto'),
    tokens, lastModified, contentType, content;

  var responseDelay = null;
  var capturedRequests = [];
  var doCapture = false;
  var silent = false;

  function log() {
    if(!silent) {
      console.log.apply(console, arguments);
    }
  }

  function captureRequests() {
    doCapture = true;
  }

  function resetState() {
    tokens = {}, lastModified = {}, contentType = {}, content = {};
    responseDelay = null;
    clearCaptured();
    doCapture = false;
  }

  function clearCaptured() {
    while(capturedRequests.length > 0) {
      capturedRequests.shift();
    }
  }

  function getState() {
    return {
      tokens: tokens,
      lastModified: lastModified,
      contentType: contentType,
      content: content
    };
  }

  function delayResponse(msec) {
    responseDelay = msec;
  }

  function saveState(name, value) {
    fs.writeFile("server-state/" + name + ".json", JSON.stringify(value), function() { });
  }

  function loadState(name) {
    if(fs.existsSync("server-state/" + name + ".json")) {
      return JSON.parse(fs.readFileSync("server-state/" + name + ".json"));
    } else {
      return {}
    }
  }

  function saveData() {
    if(dontPersist) {
      return;
    }
    if(! fs.existsSync("server-state")) {
      fs.mkdirSync("server-state");
    }
    saveState('tokens', tokens);
    saveState('lastModified', lastModified);
    saveState('contentType', contentType);
    saveState('content', content);
  }

  function loadData() {
    if(dontPersist) {
      return;
    }
    tokens = loadState('tokens');
    lastModified = loadState('lastModified');
    contentType = loadState('contentType');
    content = loadState('content');

    log("DATA LOADED", tokens, lastModified, contentType, content);
  }

  function makeScopePaths(userName, scopes) {
    var scopePaths=[];
    for(var i=0; i<scopes.length; i++) {
      var thisScopeParts = scopes[i].split(':');
      if(thisScopeParts[0]=='') {
        scopePaths.push(userName+'/:'+thisScopeParts[1]);
      } else {
        scopePaths.push(userName+'/'+thisScopeParts[0]+'/:'+thisScopeParts[1]);
        scopePaths.push(userName+'/public/'+thisScopeParts[0]+'/:'+thisScopeParts[1]);
      }
    }
    return scopePaths;
  }

  function addToken(token, scopes) {
    tokens[token] = makeScopePaths('me', scopes);
  }

  function createInitialTokens() {
    if(! config.initialTokens) {
      return;
    }
    for(var token in config.initialTokens) {
      var scopePaths = makeScopePaths(
        config.defaultUserName, config.initialTokens[token]
      );
      log('adding ',scopePaths,' for', token);
      tokens[token] = scopePaths;
    }
  }

  function createToken(userName, scopes, cb) {
    crypto.randomBytes(48, function(ex, buf) {
      var token = buf.toString('hex');
      var scopePaths = makeScopePaths(userName, scopes);
      log('createToken ',userName,scopes);
      log('adding ',scopePaths,' for',token);
      tokens[token] = scopePaths;
      cb(token);
    });
  }
  function mayRead(authorizationHeader, path) {
    if(authorizationHeader) {
      var scopes = tokens[authorizationHeader.substring('Bearer '.length)];
      if(scopes) {
        for(var i=0; i<scopes.length; i++) {
          var scopeParts = scopes[i].split(':');
          if(path.substring(0, scopeParts[0].length)==scopeParts[0]) {
            return true;
          } else {
            log(path.substring(0, scopeParts[0].length)+' != '+ scopeParts[0]);
          }
        }
      }
    } else {
      var pathParts = path.split('/');
      console.log('pathParts are', pathParts);
      return (pathParts[0]=='me' && pathParts[1]=='public' && path.substr(-1) != '/');
    }
  }
  function mayWrite(authorizationHeader, path) {
    if(authorizationHeader) {
      var scopes = tokens[authorizationHeader.substring('Bearer '.length)];
      if(scopes) {
        for(var i=0; i<scopes.length; i++) {
          var scopeParts = scopes[i].split(':');
          if(scopeParts.length==2 && scopeParts[1]=='rw' && path.substring(0, scopeParts[0].length)==scopeParts[0]) {
            return true;
          }
        }
      }
    }
  }
  function writeHead(res, status, origin, timestamp, contentType) {
    var headers = {
      'Access-Control-Allow-Origin': (origin?origin:'*'),
      'Access-Control-Allow-Headers': 'Content-Type, Authorization, Origin',
      'Access-Control-Allow-Methods': 'GET, PUT, DELETE',
    };
    if(timestamp) {
      headers['last-modified']= new Date(timestamp).toString();
    }
    if(contentType) {
      headers['content-type']= contentType;
    }
    res.writeHead(status, headers);
  }

  function writeRaw(res, contentType, content, origin, timestamp) {
    function doWrite() {
      log('access-control-allow-origin:'+ (origin?origin:'*'));
      log(contentType);
      log(content);
      writeHead(res, 200, origin, timestamp, contentType);
      res.write(content);
      res.end();
    }
    responseDelay ? setTimeout(doWrite, responseDelay) : doWrite();
  }

  function writeJson(res, obj, origin, timestamp) {
    writeRaw(res, 'application/json', JSON.stringify(obj), origin, timestamp);
  }
  function writeHtml(res, html) {
    res.writeHead(200, {
      'content-type': 'text/html'
    });
    res.write('<!DOCTYPE html lang="en"><title>'+config.host+'</title><meta charset="utf-8">'+html+'');
    res.end();
  }
  function give404(res, origin) {
    log('404');
    log(content);
    writeHead(res, 404, origin, 'now');
    res.end();
  }
  function computerSaysNo(res, origin) {
    log('COMPUTER_SAYS_NO');
    log(tokens);
    writeHead(res, 401, origin, 'now');
    res.end();
  }

  function toHtml(str) {
    return str
      .replace(/&/g, '&')
      .replace(/</g, '<')
      .replace(/>/g, '>')
      .replace(/"/g, '"');
  }
  function portal(urlObj, res) {
    res.writeHead(200, {
      'content-type': 'text/html'
    });
    res.write('<!DOCTYPE html lang="en"><title>'+config.host+'</title><meta charset="utf-8">
');
    var scopes = {
      'http://todomvc.michiel.5apps.com/': ['tasks:rw'],
      'http://litewrite.github.com/litewrite/': ['documents:rw'],
      'http://todo-mvc.michiel.5apps.com/labs/architecture-examples/remotestorage/': ['tasks:rw'],
      'http://unhosted-time-tracker.michiel.5apps.com/': ['tasks:rw'],
      'http://music.michiel.5apps.com/': ['music:rw'],
      'http://editor.michiel.5apps.com/': ['code:rw'],
      'http://remotestorage-browser.nilclass.5apps.com': [':rw'],
      'http://vidmarks.silverbucket.5apps.com': ['videos:rw'],
      'http://grouptabs.xmartin.5apps.com': ['grouptabs:rw']
    };
    var outstanding = 0;
    for(var i in scopes) {
      outstanding++;
      (function(i) {
        createToken(config.defaultUserName, scopes[i], function(token) {
          res.write('
'+i+'
');
                    +'&access_token='+token+'">'+i+'
');
          outstanding--;
          if(outstanding==0) {
            res.write('
');
            res.end();
          }
        });
      })(i);
    }
  }
  function webfinger(urlObj, res) {
    log('WEBFINGER');
    if(urlObj.query['resource']) {
      userAddress = urlObj.query['resource'].substring('acct:'.length);
      userName = userAddress.split('@')[0];
    }
    writeJson(res, {
      links:[{
        href: config.protocol+'://'+config.host+'/storage/'+userName,
        rel: "remoteStorage",
        type: "https://www.w3.org/community/rww/wiki/read-write-web-00#simple",
        properties: {
          'auth-method': "https://tools.ietf.org/html/draft-ietf-oauth-v2-26#section-4.2",
          'auth-endpoint': config.protocol+'://'+config.host+'/auth/'+userName
        }
      }]
    });
  }
  function oauth(urlObj, res) {
    log('OAUTH');
    var scopes = decodeURIComponent(urlObj.query['scope']).split(' '),
    clientId = decodeURIComponent(urlObj.query['client_id']),
    redirectUri = decodeURIComponent(urlObj.query['redirect_uri']),
    clientIdToMatch,
    userName;
    if(redirectUri.split('://').length<2) {
      clientIdToMatch=redirectUri;
    } else {
      clientIdToMatch = redirectUri.split('://')[1].split('/')[0];
    }
    if(clientId != clientIdToMatch) {
      writeHtml(res, 'we do not trust this combination of client_id and redirect_uri');
    } else {
      var userName = urlObj.pathname.substring('/auth/'.length);
      createToken(userName, scopes, function(token) {
        writeHtml(res, 'Allow');
      });
    }
  }

  function storage(req, urlObj, res) {
    var path=urlObj.pathname.substring('/storage/'.length);
    var capt = {
      method: req.method,
      path: path
    };

    if(doCapture) {
      capturedRequests.push(capt);
    }

    if(req.method=='OPTIONS') {
      log('OPTIONS ', req.headers);
      writeJson(res, null, req.headers.origin);
    } else if(req.method=='GET') {
      log('GET');
      if(mayRead(req.headers.authorization, path)) {
        if(content[path]) {
          if(path.substr(-1)=='/') {
            writeJson(res, content[path], req.headers.origin, 0);
          } else {
            writeRaw(res, contentType[path], content[path], req.headers.origin, lastModified[path]);
          }
        } else {
          if(path.substr(-1)=='/') {
            writeJson(res, {}, req.headers.origin, 0);
          } else {
            give404(res, req.headers.origin);
          }
        }
      } else {
        computerSaysNo(res, req.headers.origin);
      }
    } else if(req.method=='PUT') {
      log('PUT');
      if(mayWrite(req.headers.authorization, path) && path.substr(-1)!='/') {
        var dataStr = '';
        req.on('data', function(chunk) {
          dataStr+=chunk;
        });
        req.on('end', function(chunk) {
          var timestamp = new Date().getTime();
          capt.body = dataStr;
          content[path]=dataStr;
          contentType[path]=req.headers['content-type'];
          log('stored '+path, content[path], contentType[path]);
          lastModified[path]=timestamp;
          saveData();
          var pathParts=path.split('/');
          var timestamp=new Date().getTime();
          log(pathParts);
          var fileItself=true;
          while(pathParts.length > 1) {
            var thisPart = pathParts.pop();
            if(fileItself) {
              fileItself=false;
            } else {
              thisPart += '/';
            }
            if(!content[pathParts.join('/')+'/']) {
              content[pathParts.join('/')+'/'] = {};
            }
            content[pathParts.join('/')+'/'][thisPart]=timestamp;
            // log('stored parent '+pathParts.join('/')+'/ ['+thisPart+']='+timestamp, content[pathParts.join('/')+'/']);
          }
          // log('content:', content);
          // log('contentType:', contentType);
          // log('lastModified:', lastModified);
          writeJson(res, null, req.headers.origin, timestamp);
        });
      } else {
        computerSaysNo(res, req.headers.origin);
      }
    } else if(req.method=='DELETE') {
      log('DELETE');
      if(mayWrite(req.headers.authorization, path)) {
        var timestamp = new Date().getTime();
        delete content[path];
        delete contentType[path];
        lastModified[path]=timestamp;
        saveData();
        var pathParts=path.split('/');
        var thisPart = pathParts.pop();
        if(content[pathParts.join('/')+'/']) {
          log('delete content['+pathParts.join('/')+'/]['+thisPart+']');
          delete content[pathParts.join('/')+'/'][thisPart];
        }
        log(content);
        writeJson(res, null, req.headers.origin, timestamp);
      } else {
        computerSaysNo(res, req.headers.origin);
      }
    } else {
      log('ILLEGAL '+req.method);
      computerSaysNo(res, req.headers.origin);
    }
  }

  function serve(req, res) {
    var urlObj = url.parse(req.url, true), userAddress, userName;
    log(urlObj);
    if(urlObj.pathname == '/') {
      log('PORTAL');
      portal(urlObj, res);
    } else if(urlObj.pathname == '/.well-known/host-meta.json') {//TODO: implement rest of webfinger
      log('HOST-META');
      webfinger(urlObj, res);
    } else if(urlObj.pathname.substring(0, '/auth/'.length) == '/auth/') {
      log('OAUTH');
      oauth(urlObj, res);
    } else if(urlObj.pathname.substring(0, '/storage/'.length) == '/storage/') {
      log('STORAGE');
      storage(req, urlObj, res);
    } else if(req.method == 'POST' && urlObj.pathname.substring(0, '/reset'.length) == '/reset') { // clear data; used in tests.
      resetState();
      writeJson(res, { forgot: 'everything' });
    } else {
      log('UNKNOWN');
      writeJson(res, urlObj.query);
    }
  }

  resetState();
  loadData();
  createInitialTokens();

  return {
    serve: serve,
    getState: getState,
    resetState: resetState,
    addToken: addToken,
    delayResponse: delayResponse,
    captureRequests: captureRequests,
    captured: capturedRequests,
    clearCaptured: clearCaptured,
    enableLogs: function() {
      silent = false;
    },
    disableLogs: function() {
      silent = true;
    }
  };
})();

if((!amd) && (require.main==module)) {//if this file is directly called from the CLI
  config = require('./config').config;
  dontPersist = process.argv.length > 1 && (process.argv.slice(-1)[0] == ('--no-persistence'));
  require('http').createServer(exports.server.serve).listen(config.port);
  console.log("Example server started on 0.0.0.0:" + config.port);
}

if(amd) {
  define([], exports);
}
<|endoftext|>