Nested Tag Browser

by paultyng

HTML

<div class="root">
    <span>Event Tags</span>
    <div>
        <div class="tag-drop-before"></div>
        <div class="tag">
            <span><span class="handle"></span> Leaf 1</span>
            <div class="tag-drop-after"></div>
        </div>
        <div class="tag">
            <span><span class="handle"></span> Folder 2</span>
            <div class="tag-children">
                <div class="tag-drop-before"></div>
                <div class="tag">
                    <span><span class="handle"></span> Leaf 2.1</span>
                    <div class="tag-drop-after"></div>
                </div>
                <div class="tag">
                    <span><span class="handle"></span> Folder 2.2</span>
                    <div class="tag-children">
                        <div class="tag-drop-before"></div>
                        <div class="tag">
                            <span><span class="handle"></span> Leaf 2.2.1</span>
                            <div class="tag-drop-after"></div>
                        </div>
                        <div class="tag">
                            <span><span class="handle"></span> Leaf 2.2.2</span>
                            <div class="tag-drop-after"></div>
                        </div>
                    </div>
                    <div class="tag-drop-after"></div>
                </div>
                <div class="tag">
                    <span><span class="handle"></span> Leaf 2.3</span>
                    <div class="tag-drop-after"></div>
                </div>
            </div>
            <div class="tag-drop-after"></div>
        </div>
        <div class="tag">
            <span><span class="handle"></span> Leaf 3</span>
            <div class="tag-drop-after"></div>
        </div>
    </div>
    <div class="clearfix"></div>
</div>

CSS

body {
    background-color: #f0f0f0;
}

.root {
    margin: 20px;
    color: #000066;
}

.tag {
}

.tag > span {
    border: 1px solid #B8C8DA;
    background-color: #DAE5F0;
    border-radius: 4px;
    padding: 5px;
}

.tag > span > .handle {
    display: inline-block;
    border-left: 1px solid #B8C8DA;
    border-right: 1px solid #B8C8DA;
    width: 3px;
    height: 15px;
    cursor: move;
}

.tag-children {
    margin: 0 0 0 20px;
    border: 1px solid #ddd;
    border-right: none;
    padding: 2px 0 0 8px;
}

.ui-draggable-dragging > .tag-children,
.ui-draggable-dragging > .tag-drop-after {
    display: none;
}

.tag-drop-before, .tag-drop-after {
    height: 10px;
    margin: 7px 0;
    border-radius: 4px;
}

.tag-drop-before.active, .tag-drop-after.active {
    background-color: #ccc;
}

.tag-drop-before.hover, .tag-drop-after.hover {
    background-color: #999;
}


/************* CLEARFIX ************/
/* For modern browsers */
.clearfix:before,
.clearfix:after {
    content:"";
    display:table;
}
.clearfix:after {
    clear:both;
}
/* For IE 6/7 (trigger hasLayout) */
.clearfix {
    zoom:1;
}

JavaScript

(function() {
    $('.tag').draggable({
        addClasses: false,
        containment: '.root',
        helper: 'clone',
        revert: 'invalid'
    });
    
    $('.tag-drop-before,.tag-drop-after').droppable({
        accept: '.tag',
        activeClass: 'active',
        addClasses: false,
        hoverClass: 'hover',
        tolerance: 'pointer'
    });
})();