javascript/taggr.js
author terom
Sun, 20 Jan 2008 01:07:02 +0000
changeset 24 001f52cd057e
parent 23 10841abbc01f
child 25 4b3cf12848c2
permissions -rw-r--r--
tagging/untagging should now work fully in taggr
/*
 * dir-list manipulation
 */
function toggle_dir (header_a_tag) {
    var div = Element.next(header_a_tag);
    
    if (div._have_contents) {
        if (div.visible()) {
            Effect.BlindUp(div, {duration: 0.5});
            func = hide_tag_image;
        } else {
            Effect.BlindDown(div, {duration: 0.5});
            func = show_tag_image;
        }
        
        Element.up(header_a_tag)._images.each(function(key){
            $("img_" + key)._tags.each(function(tag){
                func(tag, key);
            });
        });

    } else {

        new Ajax.Updater(div, "taggr2.py", {
            parameters: {
                act: "dirlist",
                path: div.id,
            },
            method: 'get',
            onSuccess: function () {
                Effect.BlindDown(div, {duration: 0.5});
                div._have_contents = true;
            }
        });
    }
}

var g_last_select;
function image_click (img, ev) {
    var updiv = img.up(2);

    if (img.hasClassName("selection")) {
        img.removeClassName("selection");

    } else if (ev.shiftKey && g_last_select && g_last_select.up(2) == updiv) {
        var from = Math.min(img._offset, g_last_select._offset);
        var to = Math.max(img._offset, g_last_select._offset);

        for (var i = from; i <= to; i++) {
            $("img_" + updiv._images[i]).addClassName("selection");
        }

        g_last_select = img;
    } else {
        
        g_last_select = img;
        img.addClassName("selection");
    }
}

function selection_clear () {
    $$(".selection").each(function(e){
        e.removeClassName("selection");
    });
}

/*
 * image-loading callback
 */
function image_info (img, offset, key, tags) {
    img._key = key;
    img._tags = $A(tags);
    img._offset = offset;
    
    img._tags.each(function(tag){
        if (!$('tag_' + tag + '_images'))
            new_tag(tag);

        tag_add_image(img, null, tag, false);
    });

    var dir = img.up(2);

    if (!dir._images)
        dir._images = new Array();

    dir._images.push(img._key);
}

/*
 * tag list manipulation code
 */
function _tag_name (tag_name) {
    var tag_name_p = Builder.node("p", {id:"tag_" + tag_name + "_name", className: "draggable tag_name"}, [tag_name]);

    tag_name_p._tag = tag_name;

    return tag_name_p;
}

function new_tag (tag_name) {
    var tag_images = Builder.node("td", {className:"tag_images", id:"tag_" + tag_name + "_images"});

    tag_images._tag = tag_name;
    tag_images._visibleCount = 0;
    tag_images._images = new Array();

    var tag_row = Builder.node("tr", {className:"tag_row", id:"tag_" + tag_name}, [
        Builder.node("td", {className:"tag", id:"tag_" + tag_name + "_tags"}, [
            _tag_name(tag_name)
        ]),
        tag_images
    ]);

    tag_row._tag = tag_name;
    tag_row._tags = new Array(tag_name);

    $("tag_table").appendChild(tag_row);
}

function tag_add_tag (new_tag, tag) {
    var tag_row = $("tag_" + tag);

    if (tag_row._tags.indexOf(new_tag) != -1)
        return false;
    
    tag_row._tags.push(new_tag);

    $("tag_" + tag + "_tags").appendChild(_tag_name(new_tag));

/*
    new Ajax.Request("taggr2.py", {
        parameters: {
            act: 'tag',
            tag: new_tag,
            img: $("tag_" + tag + "_images")._images,
        },
        method: 'get'
    });
*/
}

function tag_remove_tag (tag_name) {
    var tag_row = $("tag_" + tag_name + "_name").up(1);
    array_remove(tag_row._tags, tag_name);
    
    $("tag_" + tag_row._tag + "_tags").removeChild($("tag_" + tag_name + "_name"));

    if (tag_row._tags.length == 0)
        $("tag_table").removeChild(tag_row);
}

function get_tag (tag_name, postfix) {
    return $("tag_" + $("tag_" + tag_name).up(1)._tag + "_" + postfix);
}

function tag_add_image (orig_img, copy_img, tag, saveToDB) {
    var tag_images = $('tag_' + tag + '_images');

    if (tag_images._images.indexOf(orig_img._key) != -1)
        return false;

    if (!copy_img)
        copy_img = image_copy(orig_img);

    tag_images._images.push(orig_img._key)
    orig_img._tags.push(tag);

    copy_img.id = "tag_" + tag + "_img_" + orig_img._key
    copy_img._tag = tag;

    tag_images.appendChild(copy_img);
    tag_images._visibleCount++;
    
    if (saveToDB) {
        new Ajax.Request("taggr2.py", {
            parameters: {
                act: 'tag',
                img: orig_img._key,
                tag: tag,
            },
            method: 'get'

        });
    }
}

function tag_add_images (images, tag_name) {
    var tag_images = $('tag_' + tag_name + '_images');
    var copy_img, img_keys = new Array();

    images.each(function(orig_img){
        tag_add_image(orig_img, null, tag_name, false);
        img_keys.push(orig_img._key);
    });

    new Ajax.Request("taggr2.py", {
        parameters: {
            act: 'tag',
            img: img_keys,
            tag: tag_name,
        },
        method: 'get'

    });
}

function tag_remove_image (img_key, tag_name) {
    var tag_images = $("tag_" + tag_name + "_images");

    tag_images.removeChild($("tag_" + tag_name + "_img_" + img_key));
    array_remove(tag_images._images, img_key);

    if (tag_images._images.length == 0)
        $("tag_" + tag_name).hide();

    new Ajax.Request("taggr2.py", {
        parameters: {
            act: 'untag',
            img: img_key,
            tag: tag_name,
        },
        method: 'get',
    });
}

function hide_tag_image (tag, img) {
    $("tagimg_" + tag + "_" + img).hide();

    if (--$("tag_" + tag + "_images")._visibleCount == 0)
        $("tag_" + tag).hide();
}

function show_tag_image (tag, img) {
    $("tagimg_" + tag + "_" + img).hide();

    if ($("tag_" + tag + "_images")._visibleCount++ == 0)
         $("tag_" + tag).show();
}

/*
 * Frontend image drag code
 */
var g_ghost;
function drag_start (e) {
    if (e.hasClassName("image") || e.hasClassName("tag_image"))
        g_ghost = image_copy(e);
    else {
        var name;

        if (e.hasClassName("tag_name"))
            name = e._tag;
        else
            name = $F($('new_tag'));

        g_ghost = Builder.node("span", {className: 'dragged'}, [name]);
    }

    $('taggr').appendChild(g_ghost);

    g_ghost.style.position = "absolute";
}

function drag_move (e, ev) {
    g_ghost.style.left = ev.pointerX() - g_offset.left + "px";
    g_ghost.style.top = ev.pointerY() - g_offset.top + "px";
}

function drag_end_drop (e, s, ev) {
    g_ghost.style.position = "static";
    $('taggr').removeChild(g_ghost);
    
    if (e.hasClassName("image") || e.hasClassName("tag_image")) {
        var selection = $$(".selection");

        if (selection.length)
            tag_add_images($$(".selection"), s._tag);
        else
            tag_add_image(e, g_ghost, s._tag, true);
            
/*
        if (!tag_add_image(e, g_ghost, s._tag, true))
            // it was already in there
            Effect.Shake("tagimg_" + s._tag + "_" + g_ghost._key);
*/            
    } else if (e.hasClassName("tag_name")) {
        null;   // breakpoint
    } else {
        tag_add_tag($F($('new_tag')), s._tag);
    }
}

function drag_end_fail (e, ev) {
    if (e.hasClassName("tag_image")) {
        tag_remove_image(e._key, e._tag);
        $('taggr').removeChild(g_ghost);
    } else if (e.hasClassName("tag_name")) {
        tag_remove_tag(e._tag);
    } else {
        $('taggr').removeChild(g_ghost);
    }
}

function drag_cleanup (e, ev) {
    g_ghost = null;
}

function drag_hover (e, s, ev) {
    s.addClassName("hover");
}

function drag_unhover (e, s, ev) {
    s.removeClassName("hover");
}

/*
 * Backend image click/drag code
 */

var g_drag, g_hover, g_start, g_offset, g_targets;
function check_mouse_down (ev) {
    var e = ev.element();
    
    if (!ev.isLeftClick())
        return true;

    if (e.hasClassName("image") || e.hasClassName("draggable") || e.hasClassName("tag_image")) {
        g_drag = e;
        g_start = false;
        
        var offset = e.cumulativeOffset();

        g_offset = {
            'left': ev.pointerX() - offset.left,
            'top': ev.pointerY() - offset.top
        };

        g_hover = null;

        g_targets = $$(".tag_row");

    } else if (e.hasClassName("directory_link")) {
        toggle_dir(e);

    } else {
        return true;
    }
    
    ev.stop();
    return false;
}

function check_mouse_up (ev) {
    if (g_drag) {
        if (g_start) {
            if (g_hover) {
                drag_unhover(g_drag, g_hover, ev);
                drag_end_drop(g_drag, g_hover, ev);
            } else
                drag_end_fail(g_drag, ev);
            
            drag_cleanup(g_drag);
        } else if (g_drag.hasClassName("image") || g_drag.hasClassName("tag_image")) {
            // in case image_click blocks and we get a mouse_move during it
            var tmp = g_drag;
            g_drag = null;

            image_click(tmp, ev);
        }

        g_start = null;
        g_drag = null;
        g_hover = null;

        ev.stop();
        return false;
    }   
}

function check_mouse_move (ev) {
    if (g_drag) {
        if (!g_start) {
            drag_start(g_drag);
            g_start = true;
        }

        drag_move(g_drag, ev);
        
        Position.prepare();

        var px = ev.pointerX();
        var py = ev.pointerY();

        if (g_hover) {
            if (!Position.withinIncludingScrolloffsets(g_hover, px, py)) {
                drag_unhover(g_drag, g_hover, ev);
                g_hover = null;
            }
        } else {
            for (var i=0;i<g_targets.length;i++)
                if (Position.withinIncludingScrolloffsets(g_targets[i], px, py)) {
                    drag_hover(g_drag, g_targets[i], ev);
                    g_hover = g_targets[i];
                    break;
                }
        }

        ev.stop();
        return false;
    }
}

function check_drag_hover (ev) {
    if (g_start) {
        var e = ev.element();

        if (e.hasClassName("tag_row")) {
            drag_hover(g_drag, e, ev);
            g_hover = e;
        }
    }
}

function check_drag_nohover (ev) {
    if (g_start) {
        var e = ev.element();

        if (g_hover && e == g_hover) {
            drag_unhover(g_drag, g_hover, ev);
            g_hover = null;
        }
    }
}

/* 
 * utility code
 */
function image_copy (img) {
    copy = Builder.node("img", {
        src: img.src,
        className: "tag_image",
    });

    copy._key = img._key;
    copy._tags = img._tags;
    
    return copy;
}

function array_remove (a, i) {
    a.splice(a.indexOf(i), 1);
}

/*
 * events
 */
Event.observe(document, "mousedown", check_mouse_down);
Event.observe(document, "mouseup", check_mouse_up);
Event.observe(document, "mousemove", check_mouse_move);
Event.observe(document, "mouseover", check_drag_hover);
Event.observe(document, "mouseout", check_drag_nohover);
Event.observe(document, "dragenter", check_drag_hover);     // worth a try...
Event.observe(document, "dragexit", check_drag_nohover);