if (!Object.prototype.watch) { Object.defineProperty(Object.prototype, "watch", { enumerable: false, configurable: true, writable: false, value: function (prop, handler) { var oldval = this[prop], newval = oldval, getter = function () { return newval; }, setter = function (val) { oldval = newval; return newval = handler.call(this, prop, oldval, val); }; if (delete this[prop]) { // can't watch constants Object.defineProperty(this, prop, { get: getter, set: setter, enumerable: true, configurable: true }); } } }); } if (!Array.prototype.contains) { Array.prototype.contains = function(obj) { var i = this.length; while (i--) { if (this[i] === obj) { return true; } } return false; } } var returnJqueryObj = function (obj) { var isJqueryObject = obj instanceof jQuery; if (isJqueryObject) { return obj; } else { return $(obj); } }; var guid = (function() { function s4() { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1); } return function() { return s4() + '-' + s4(); }; })(); var getCenterPoints = function (element) { var y = $(element).offset().top + ($(element).height() / 2) - $('.container').offset().top; var x = $(element).offset().left + ($(element).width() / 2) - $('.container').offset().left; return {'y': y, 'x': x}; }; var lineDistance = function (point1, point2) { var length = (point1.x - point2.x) * (point1.x - point2.x) + (point1.y - point2.y) * (point1.y - point2.y); return Math.sqrt(length); } var getAngleBetween = function (element1, element2) { var $el1 = returnJqueryObj(element1); var $el2 = returnJqueryObj(element2); $el1.centerPoints = getCenterPoints(element1); $el2.centerPoints = getCenterPoints(element2); var lineLength = lineDistance($el1.centerPoints, $el2.centerPoints); var angle = 180 / Math.PI * Math.acos(($el1.centerPoints.y - $el2.centerPoints.y) / lineLength); if($el1.centerPoints.x > $el2.centerPoints.x) { angle *= -1; } return angle + 180; }; var drawLine = function (element1, element2) { var $el1 = returnJqueryObj(element1); var $el2 = returnJqueryObj(element2); var angleBetween = getAngleBetween(element1, element2); $el1.centerPoints = getCenterPoints(element1); $el2.centerPoints = getCenterPoints(element2); var lineTemplate = '
'; var lineElement = $(lineTemplate); var lineLength = lineDistance($el1.centerPoints, $el2.centerPoints); var lineName = element1.data('guid') + '_' + element2.data('guid'); var lineNameReverse = element2.data('guid') + '_' + element1.data('guid'); lineElement.attr('data-el1', element1.data('guid')); lineElement.attr('data-el2', element2.data('guid')); lineElement.attr('data-name', lineName); $('.container [data-name="' + lineName + '"]').remove(); $('.container [data-name="' + lineNameReverse + '"]').remove(); $('.container').append(lineElement); lineElement.css({ height: lineLength, top: $el1.centerPoints.y, left: $el1.centerPoints.x, transform: 'rotate(' + angleBetween + 'deg)' }); return lineElement; }; var $container = $('.container'); var draggablePoints = []; var draggablePointTemplate = ''; var draggablePointCreator = function (posX, posY) { var point = $(draggablePointTemplate); point.pointData = new Object(); point.pointData.watch("x", function (prop, oldval, newval) { point.css('left', newval); return newval; }); point.pointData.watch("y", function (prop, oldval, newval) { point.css('top', newval); return newval; }); point.pointData.x = posX; point.pointData.y = posY; point.pointData.guid = guid(); point.attr('data-guid', point.pointData.guid); draggablePoints.push(point); $container.append(point); return point; }; for (var i = 0; i < 5; i++) { var pointDeadZone = 100; var draggablePoint = draggablePointCreator(($container.width() - pointDeadZone) * Math.random(), ($container.height() - pointDeadZone) * Math.random()); } var loop = function () { }; (function() { var lastTime = 0; var vendors = ['webkit', 'moz']; for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; } if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback, element) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16 - (currTime - lastTime)); var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }; if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) { clearTimeout(id); }; }()); var renderLines = function () {}; renderLines.draggables = function () { draggablePoints.map(function (point1) { draggablePoints.map(function (point2) { var drawIt = true; if (point1 === point2) { drawIt = false; } if (drawIt) { drawLine(point1, point2); } }); }); }; (function animloop() { requestAnimationFrame(animloop); loop(); })(); var pointDrag = function ($target) { renderLines.draggables(); }; pointDrag(); $(document).ready(function() { var $body = $('body'); var $target = null; var dragTarget; var isDraggEnabled = false; $body.on("mousedown", "div", function(e) { $this = $(this); isDraggEnabled = $this.data("draggable"); if (isDraggEnabled) { if(e.offsetX === undefined){ x = e.pageX-$(this).offset().left; y = e.pageY-$(this).offset().top; }else{ x = e.offsetX; y = e.offsetY; }; $this.addClass('draggable'); $target = $(e.target); dragTarget = e.target; }; }); $body.on("mouseup vmouseup", function(e) { $target = null; $body.find(".draggable").removeClass('draggable'); }); $body.on("mousemove vmousemove", function(e) { if ($target) { $target.offset({ top: e.pageY - y, left: e.pageX - x }); pointDrag($target); }; }); });