/*! dom-outliner - v0.1.3 - 2015-06-19 * https://github.com/vitorhsb/dom-outliner * Copyright (c) 2015 Vitor Barbosa; Licensed MIT */ (function ($) { var initialized = false, active = false, paused = false, options = {}, namespace = 'dom-outliner', selectedClass = namespace + '-selected', labelClass = namespace + '-label', labelSelectedClass = labelClass + '-selected', glassClass = namespace + '-glass', transparentClass = namespace + '-transparent-glass', glasses = {}, helpers = {}, currentSelection = null; var utils = (function(){ var $window = $(), $document = $(), $body = $(); return { getWindow : function() { return $window.length ? $window : ($window = $(window)); }, getDocument : function() { return $document.length ? $document : ($document = $(document)); }, getBody : function() { return $body.length ? $body : ($body = $('body')); } }; })(); function initialize() { createHelpers(); createGlassElements(); initStylesheet(); } function destroy() { removeOutlineMessage(); removeHelpers(); removeGlassElements(); } function writeCSS(css) { var el = document.createElement('style'); el.type = 'text/css'; document.getElementsByTagName('head')[0].appendChild(el); if (el.styleSheet) { el.styleSheet.cssText = css; // IE } else { el.innerHTML = css; // Non-IE } } function initStylesheet() { var css = '.' + namespace + ' {' + 'outline: ' + options.outlineWidth + 'px ' + options.outlineStyle + ' ' + options.outlineColor + ';' + '}' + '.' + labelClass + ' {' + 'display: none;' + 'background: ' + options.outlineColor + ';' + 'color: #fff;' + 'font: bold 12px/12px Helvetica, Arial, sans-serif;' + 'padding: 5px;' + 'margin: 0;' + 'position: absolute;' + 'z-index: 1000001;' + '}' + '.' + selectedClass + ' {' + 'outline: ' + options.outlineWidth + 'px ' + options.outlineStyle + ' ' + options.outlineSelectedColor + ';' + '}' + '.' + labelSelectedClass + ' {' + 'background: ' + options.outlineSelectedColor + ';' + 'z-index: 2000002;' + '}' + '.' + glassClass + ' {' + 'opacity: ' + options.glassOpacity + ' !important;' + '-moz-opacity: ' + options.glassOpacity + ' !important;' + 'filter: alpha(opacity=' + options.glassOpacity + ') !important;' + '-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=(' + options.glassOpacity + '*100))" !important;' + 'background: ' + options.glassColor + ';' + 'position: absolute;' + 'top: 0;' + 'left: 0;' + 'z-index: 2000001;' + 'min-height: 0 !important;' + 'min-width: 0 !important;' + '}'+ '.' + transparentClass + ' {' + 'background: rgba(0, 0, 0, 0);' + 'opacity: 1.0 !important;' + '-moz-opacity: 1 !important;' + 'filter: alpha(opacity=1) !important;' + '-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=(1*100))" !important;' + '}' + '#' + namespace + '-glass-message {' + 'height: 100%;' + 'width: 100%;' + 'background: rgba(255, 255, 0, 0.4);' + 'cursor: pointer;' + '}' + '#' + namespace + '-glass-message > div {' + 'position: relative;' + 'top: 50%;' + 'transform: translateY(-50%);' + 'text-align: center;' + 'margin: 0 auto;' + '}'; writeCSS(css); } function createHelpers() { helpers = { label: $('
').addClass(labelClass).appendTo(utils.getBody()) }; } function removeHelpers() { $.each(helpers, function(name, $el) { $el.remove(); }); helpers = {}; } function createGlassElements() { glasses = { center : $('') .appendTo(utils.getBody()), top : $('').appendTo(utils.getBody()), right : $('').appendTo(utils.getBody()), bottom : $('').appendTo(utils.getBody()), left : $('').appendTo(utils.getBody()) }; } function removeGlassElements() { $.each(glasses, function(pos, $el){ $el.off('click.' + namespace).remove(); }); glasses = {}; } function setSelection($el) { var $doc = utils.getDocument(), docHeight = $doc.height(), docWidth = $doc.width(); currentSelection = $el; $el.each(function(){ $(this).addClass(selectedClass); }); if(options.showGlasses) { try { var offset = $el.offset(), height = $el.outerHeight(), width = $el.outerWidth(); glasses.center.css({ top: offset.top-options.outlineWidth, left: offset.left-options.outlineWidth, height: height + ( 2 * options.outlineWidth), width: width + ( 2 * options.outlineWidth) }).show(); glasses.top.css({ top: 0, left: 0, height: offset.top - options.outlineWidth, width: docWidth }).show(); glasses.right.css({ top: offset.top - options.outlineWidth, left: offset.left + width + options.outlineWidth, height: height + ( 2 * options.outlineWidth), width: (docWidth-offset.left-width) - options.outlineWidth }).show(); glasses.bottom.css({ top: (offset.top + height + options.outlineWidth), left: 0, height: (docHeight - offset.top - height - options.outlineWidth), width: docWidth }).show(); glasses.left.css({ top: offset.top - options.outlineWidth, left: 0, height: height + ( 2 * options.outlineWidth), width: offset.left - options.outlineWidth }).show(); } catch (err) { } finally {} } if(options.showLabel) { helpers.label.addClass(labelSelectedClass); } } function unsetSelection($el) { $el.removeClass(selectedClass).removeClass(namespace).off('.' + namespace); $el.trigger('deselect.outliner'); helpers.label.removeClass(labelSelectedClass).hide(); removeOutlineMessage(); } function onSelection($el, e, params) { setSelection($el); $el.trigger('select.outliner', e); if ($.isFunction(options.onSelection)) { options.onSelection($el.get(0), e, params); } } function cancelSelection() { $.each(glasses, function(dir, $el) { $el.hide(); }); if(currentSelection) { unsetSelection($(currentSelection)); if (active && $.isFunction(options.onCancel)) { options.onCancel(currentSelection); } currentSelection = null; } } function shouldIgnore($el) { var ignore = false; if (!active || paused) { return; } if(options.filter) { ignore = true; $.each(options.filter, function(i, exp) { ignore = ignore && !$el.is(exp); }); } if(!ignore && (options.exclude.length || $.outliner.options.exclude.length)) { $.each(options.exclude.concat($.outliner.options.exclude), function(i, exp) { ignore = ignore || $el.is(exp); // break cicle on ignore return ignore ? false : true; }); } // Prevent from losing focus on selected element if (!ignore && currentSelection) { if($el.filter(':outliner').length) { ignore = true; } } if (!ignore && (options.excludeClosest.length || $.outliner.options.excludeClosest.length)) { $.each(options.excludeClosest.concat($.outliner.options.excludeClosest), function(i, exp) { ignore = ignore || $el.closest(exp).length; // break cicle on ignore return ignore ? false : true; }); } return ignore; } function getElementLabel($el) { var el = $el.get(0), label = el.tagName.toLowerCase(), className = el.className; className = className.replace(selectedClass, ''); className = className.replace(namespace, ''); label += el.id ? '#' + el.id : ''; if (className) { label += ('.' + $.trim(className).replace(/ /g, '.')).replace(/\.\.+/g, '.'); } return label + ' (' + Math.round($el.width()) + 'x' + Math.round($el.height()) + ')'; } function updateOutlinePosition($el, e) { var label = '', offset = $el.offset(); $('.' + namespace).removeClass(namespace); $el.toggleClass(namespace); if ($el.hasClass(namespace)) { $el.trigger('mouseover.outliner', e); if ($.isFunction(options.onMouseOver)) { options.onMouseOver($el.get(0), e); } } else { $el.trigger('mouseout.outliner', e); if ($.isFunction(options.onMouseOut)) { options.onMouseOut($el.get(0), e); } } if(options.showLabel) { label = getElementLabel($el); helpers.label.html(label).show().css({ top: Math.max(0, offset.top - options.outlineWidth - helpers.label.outerHeight()), left: Math.max(0, offset.left - options.outlineWidth) }); if (!$el.hasClass(namespace)) { helpers.label.hide(); } } } function showOutlineMessage($el, opts) { var $glass = $('#' + namespace + '-glass-center'); if ($el.hasClass(namespace) && $glass.is(":visible")) { $glass.html( '