2011-02-14 17:19:44 -08:00
|
|
|
|
(function ($) {
|
|
|
|
|
$(function () {
|
2011-03-09 16:06:37 -08:00
|
|
|
|
// append the shape tracing window container at the end of the document
|
2011-03-10 22:37:50 -08:00
|
|
|
|
$('<div id="shape-tracing-container"> ' +
|
|
|
|
|
'<div id="shape-tracing-resize-handle" ></div>' +
|
2011-03-10 13:50:46 -08:00
|
|
|
|
'<div id="shape-tracing-toolbar">' +
|
2011-03-10 22:37:50 -08:00
|
|
|
|
'<div id="shape-tracing-toolbar-switch"></div>' +
|
2011-03-10 13:50:46 -08:00
|
|
|
|
'</div>' +
|
2011-03-11 15:12:53 -08:00
|
|
|
|
'<div id="shape-tracing-window"></div>' +
|
2011-03-10 13:50:46 -08:00
|
|
|
|
'</div>' +
|
2011-03-10 22:37:50 -08:00
|
|
|
|
'<div id="shape-tracing-container-ghost"></div>'
|
2011-03-10 13:50:46 -08:00
|
|
|
|
).appendTo('body');
|
2011-03-09 16:06:37 -08:00
|
|
|
|
|
|
|
|
|
// preload main objects
|
|
|
|
|
var shapeTracingContainer = $('#shape-tracing-container');
|
|
|
|
|
var shapeTracingToolbar = $('#shape-tracing-toolbar');
|
2011-03-10 13:50:46 -08:00
|
|
|
|
var shapeTracingToolbarSwitch = $('#shape-tracing-toolbar-switch');
|
2011-03-09 16:06:37 -08:00
|
|
|
|
var shapeTracingWindow = $('#shape-tracing-window');
|
|
|
|
|
var shapeTracingGhost = $('#shape-tracing-container-ghost');
|
|
|
|
|
|
2011-03-10 13:50:46 -08:00
|
|
|
|
// store the size of the container when it is closed (default in css)
|
|
|
|
|
var initialContainerSize = shapeTracingContainer.height();
|
|
|
|
|
var previousSize = 0;
|
|
|
|
|
|
2011-03-09 16:06:37 -08:00
|
|
|
|
// ensure the ghost has always the same size as the container
|
2011-03-10 13:50:46 -08:00
|
|
|
|
// and the container is always positionned correctly
|
|
|
|
|
var syncResize = function () {
|
|
|
|
|
var _window = $(window);
|
|
|
|
|
var containerHeight = shapeTracingContainer.height();
|
2011-03-11 11:36:38 -08:00
|
|
|
|
shapeTracingGhost.height(containerHeight);
|
|
|
|
|
|
2011-03-10 13:50:46 -08:00
|
|
|
|
var windowHeight = _window.height();
|
|
|
|
|
var scrollTop = _window.scrollTop();
|
|
|
|
|
|
|
|
|
|
shapeTracingContainer.offset({ top: windowHeight - containerHeight + scrollTop, left: 0 });
|
|
|
|
|
shapeTracingContainer.width('100%');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ensure the size/position is correct whenver the container or the browser is resized
|
|
|
|
|
shapeTracingContainer.resize(syncResize);
|
|
|
|
|
$(window).resize(syncResize);
|
|
|
|
|
$(window).resize();
|
|
|
|
|
|
|
|
|
|
// removes the position flickering by hiding it first, then showing when ready
|
|
|
|
|
shapeTracingContainer.show();
|
|
|
|
|
|
|
|
|
|
// expand/collapse behavior
|
|
|
|
|
// ensure the container has always a valid size when expanded
|
|
|
|
|
shapeTracingToolbarSwitch.click(function () {
|
|
|
|
|
var _this = $(this);
|
|
|
|
|
_this.toggleClass('expanded');
|
|
|
|
|
if (_this.hasClass('expanded')) {
|
|
|
|
|
shapeTracingContainer.height(Math.max(previousSize, 100));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// save previous height
|
|
|
|
|
previousSize = shapeTracingContainer.height();
|
|
|
|
|
shapeTracingContainer.height(initialContainerSize);
|
|
|
|
|
}
|
2011-03-10 22:37:50 -08:00
|
|
|
|
|
2011-03-10 13:50:46 -08:00
|
|
|
|
syncResize();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// add a resizable handle to the container
|
|
|
|
|
$('#shape-tracing-resize-handle').addClass('ui-resizable-handle ui-resizable-n');
|
|
|
|
|
shapeTracingContainer.resizable({ handles: { n: '#shape-tracing-resize-handle'} });
|
2011-02-25 23:52:45 -08:00
|
|
|
|
|
2011-03-11 15:12:53 -08:00
|
|
|
|
var shapeNodes = {}; // represents the main index of shape nodes, indexed by id
|
|
|
|
|
|
2011-03-10 22:37:50 -08:00
|
|
|
|
// projects the shape ids to each DOM element
|
2011-03-11 15:12:53 -08:00
|
|
|
|
var startShapeTracingBeacons = $('.shape-tracing-wrapper[shape-id]');
|
|
|
|
|
startShapeTracingBeacons.each(function () {
|
2011-03-10 22:37:50 -08:00
|
|
|
|
var _this = $(this);
|
2011-03-11 15:12:53 -08:00
|
|
|
|
|
|
|
|
|
var shapeNode = {
|
|
|
|
|
id: _this.attr('shape-id'),
|
|
|
|
|
type: _this.attr('shape-type'),
|
|
|
|
|
parent: null,
|
|
|
|
|
children: {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// register the new shape node into the main shape nodes index
|
|
|
|
|
shapeNodes[shapeNode.id] = shapeNode;
|
|
|
|
|
|
2011-03-11 11:36:38 -08:00
|
|
|
|
// assign the shape-id attribute to all elements, except wrappers themselves (it would erase their own shape-id)
|
2011-03-11 15:12:53 -08:00
|
|
|
|
_this
|
|
|
|
|
.nextUntil('[end-of="' + shapeNode.id + '"]') // all elements between the script beacons
|
|
|
|
|
.find(':not(.shape-tracing-wrapper)') // all children but not inner beacons
|
|
|
|
|
.andSelf() // add the first level items
|
|
|
|
|
.attr('shape-id', shapeNode.id) // add the shape-id attribute
|
|
|
|
|
.each(function () {
|
|
|
|
|
// assign a shapeNode instance to the DOM element
|
|
|
|
|
this.shapeNode = shapeNode;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.shapeNode = shapeNode;
|
2011-03-10 22:37:50 -08:00
|
|
|
|
});
|
|
|
|
|
|
2011-03-11 15:12:53 -08:00
|
|
|
|
// construct the shape tree based on all current nodes
|
|
|
|
|
// for each start beacon, search for the first parent beacon, and create nodes if they don't exist
|
|
|
|
|
startShapeTracingBeacons.each(function () {
|
|
|
|
|
var _this = $(this);
|
|
|
|
|
var shapeNode = this.shapeNode;
|
|
|
|
|
var parent = _this.parent('[shape-id!=' + shapeNode.id + ']').get(0);
|
|
|
|
|
|
|
|
|
|
shapeNodes[shapeNode.id] = shapeNode;
|
|
|
|
|
|
|
|
|
|
if (parent.shapeNode) {
|
|
|
|
|
var parentShapeNode = parent.shapeNode;
|
|
|
|
|
shapeNodes[parentShapeNode.id] = parentShapeNode;
|
|
|
|
|
shapeNode.parent = parentShapeNode;
|
|
|
|
|
parentShapeNode.children[shapeNode.id] = shapeNode;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// removes all beacons as we don't need them anymore
|
|
|
|
|
$('.shape-tracing-wrapper').remove();
|
|
|
|
|
|
|
|
|
|
var shapes = $('<ul></ul>');
|
|
|
|
|
for (var shapeId in shapeNodes) {
|
|
|
|
|
if (!shapeNodes[shapeId].parent) {
|
|
|
|
|
shapes.append(createTreeNode(shapeNodes[shapeId]));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
shapeTracingWindow.append(shapes);
|
2011-03-10 22:37:50 -08:00
|
|
|
|
|
2011-03-11 11:36:38 -08:00
|
|
|
|
//create an overlay on shapes' descendants
|
2011-03-10 22:37:50 -08:00
|
|
|
|
$('[shape-id]').hover(
|
|
|
|
|
function () {
|
2011-03-11 11:36:38 -08:00
|
|
|
|
$('.shape-tracing-overlay').removeClass('shape-tracing-overlay');
|
2011-03-10 22:37:50 -08:00
|
|
|
|
$(this).addClass('shape-tracing-overlay');
|
|
|
|
|
},
|
|
|
|
|
function () {
|
|
|
|
|
$(this).removeClass('shape-tracing-overlay');
|
|
|
|
|
}
|
|
|
|
|
);
|
2011-02-08 17:52:53 -08:00
|
|
|
|
});
|
2011-03-11 15:12:53 -08:00
|
|
|
|
|
|
|
|
|
function createTreeNode(shapeNode) {
|
|
|
|
|
var node = $('<li></li>');
|
|
|
|
|
node.text(shapeNode.type);
|
|
|
|
|
var list = $('<ul></ul>');
|
|
|
|
|
node.append(list);
|
|
|
|
|
if (shapeNode.children) {
|
|
|
|
|
for (var shapeId in shapeNode.children) {
|
|
|
|
|
var child = createTreeNode(shapeNode.children[shapeId]);
|
|
|
|
|
list.append(child);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-08 17:52:53 -08:00
|
|
|
|
})(jQuery);
|