// TODO: this depends on global state and stuff module.exports = function () { if (popover) { return; } var angular = window.angular; popover = angular.element( '
' + '
' + '
{ Please select a scope }
' + '' + '' + '' + '' + '
' + '
'); angular.element(window.document.body).append(popover); var popoverContent = angular.element(angular.element(popover.children('div')[0]).children()[0]); var dragElt = angular.element(angular.element(popover.children('div')[0]).children()[1]); var selectElt = angular.element(angular.element(popover.children('div')[0]).children()[2]); var closeElt = angular.element(angular.element(popover.children('div')[0]).children()[3]); var currentScope = null, currentElt = null; function onMove (ev) { var x = ev.clientX, y = ev.clientY; if (x > window.outerWidth - 100) { x = window.outerWidth - 100; } else if (x < 0) { x = 0; } if (y > window.outerHeight - 100) { y = window.outerHeight - 100; } else if (y < 0) { y = 0; } x += 5; y += 5; popover.css('left', x + 'px'); popover.css('top', y + 'px'); } closeElt.bind('click', function () { popover.remove(); popover = null; }); selectElt.bind('click', bindSelectScope); var selecting = false; function bindSelectScope () { if (selecting) { return; } setTimeout(function () { selecting = true; selectElt.attr('disabled', true); angular.element(document.body).css('cursor', 'crosshair'); angular.element(document.getElementsByClassName('ng-scope')) .bind('click', onSelectScope) .bind('mouseover', onHoverScope); }, 30); } var hoverScopeElt = null; function markHoverElt () { if (hoverScopeElt) { hoverScopeElt.addClass('bat-selected'); } } function unmarkHoverElt () { if (hoverScopeElt) { hoverScopeElt.removeClass('bat-selected'); } } function onSelectScope (ev) { render(this); angular.element(document.getElementsByClassName('ng-scope')) .unbind('click', onSelectScope) .unbind('mouseover', onHoverScope); unmarkHoverElt(); selecting = false; selectElt.attr('disabled', false); angular.element(document.body).css('cursor', ''); hovering = false; } var hovering = false; function onHoverScope (ev) { if (hovering) { return; } hovering = true; var that = this; setTimeout(function () { unmarkHoverElt(); hoverScopeElt = angular.element(that); markHoverElt(); hovering = false; render(that); }, 100); } function onUnhoverScope (ev) { angular.element(this).css('border', ''); } dragElt.bind('mousedown', function (ev) { ev.preventDefault(); rendering = true; angular.element(document).bind('mousemove', onMove); }); angular.element(document).bind('mouseup', function () { angular.element(document).unbind('mousemove', onMove); setTimeout(function () { rendering = false; }, 120); }); function renderTree (data) { var tree = angular.element('
'); angular.forEach(data, function (val, key) { var toAppend; if (val === undefined) { toAppend = 'undefined'; } else if (val === null) { toAppend = 'null'; } else if (val instanceof Array) { toAppend = '[ ... ]'; } else if (val instanceof Object) { toAppend = '{ ... }'; } else { toAppend = val.toString(); } if (data instanceof Array) { toAppend = '
' + toAppend + ((key === (data.length - 1))?'':',') + '
'; } else { toAppend = '
' + key + ': ' + toAppend + (key!==0?'':',') + '
'; } toAppend = angular.element(toAppend); if (val instanceof Array || val instanceof Object) { function recur () { toAppend.unbind('click', recur); toAppend.html(''); toAppend .append(angular.element('' + key + ': ' + ((val instanceof Array)?'[':'{') + '').bind('click', collapse)) .append(renderTree(val)) .append('' + ((val instanceof Array)?']':'}') + ''); } function collapse () { toAppend.html(''); toAppend.append(angular.element('
' + key + ': ' + ((val instanceof Array)?'[ ... ]':'{ ... }') + '
').bind('click', recur)); } toAppend.bind('click', recur); } tree.append(toAppend); }); return tree; } var isEmpty = function (object) { var prop; for (prop in object) { if (object.hasOwnProperty(prop)) { return false; } } return true; }; var objLength = function (object) { var prop, len = 0; for (prop in object) { if (object.hasOwnProperty(prop)) { len += 1; } } return len; }; var rendering = false; var render = function (elt) { if (rendering) { return; } rendering = true; setTimeout(function () { var scope = angular.element(elt).scope(); rendering = false; if (scope === currentScope) { return; } currentScope = scope; currentElt = elt; var models = getScopeLocals(scope); popoverContent.children().remove(); if (isEmpty(models)) { popoverContent.append(angular.element('This scope has no models')); } else { popoverContent.append(renderTree(models)); } }, 100); }; };