Changeset 35

Show
Ignore:
Timestamp:
02/17/07 18:35:14 (2 years ago)
Author:
simon
Message:

Rather more lightweight (and functional) tag completion code.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/templates/header

    r12 r35  
    1010[% END %] 
    1111    <script type="text/javascript" src="[%base%]/static/prototype.js"></script> 
    12 [% IF request.params.active == "tagedit" %] 
    13     <script type="text/javascript" src="[%base%]/tag/list_js"></script> 
    14     <script type="text/javascript" src="[%base%]/static/upload.js"></script> 
    15 </head> 
    16 <body onload="init()"> 
    17 [% ELSE %] 
     12<script type="text/javascript" src="[%base%]/tag/list_js"></script> 
     13<script type="text/javascript" src="[%base%]/static/upload.js"></script> 
    1814</head> 
    1915<body> 
    20 [% END %] 
    2116[% INCLUDE nav %] 
    2217<table width="100%"> 
  • trunk/templates/photo/tagedit

    r2 r35  
     1 
    12<div class="messages"><small> 
    23<b>Tagging advice</b>: Tags should be words, (<i>portrait</i>, <i>henry</i>) or 
     
    1213 
    1314Delete tags: <form action="[%base%]/photo/edit_tags/[%photo.id%]" method="post"> 
    14 <ul> 
    1515[% FOR tagging = photo.taggings %] 
    16     <li> [% tagging.tag %] <input type="checkbox" name="delete_[%tagging.id%]"
     16    <span class="tagedittagdelete">[% tagging.tag %]<input type="checkbox" name="delete_[%tagging.id%]"></span
    1717[% END %] 
    18 </ul> 
    1918<p> Add tags: <input type="textbox" name="newtags" id="tags"> <input 
    2019type="submit" value="Tag it!"> </p> 
     20<script type="text/javascript"> addHandler($("tags")) </script> 
    2121</form> 
  • trunk/templates/photo/upload

    r2 r35  
    1 <html> 
    2 <head> 
    3     <title> Memories - Photo Sharing </title> 
    4     <link title="Maypole" href="[%base%]/static/memories.css" type="text/css" rel="stylesheet"/> 
    5     <script type="text/javascript" src="[%base%]/tag/list_js"></script> 
    6     <script type="text/javascript" src="[%base%]/static/upload.js"></script> 
    7 </head> 
    8 <body onload="init()"> 
    9 [% INCLUDE nav %] 
    10 <table width="100%"> 
    11     <tr> 
    12     <td valign="top"> 
    13     [% IF messages %] 
    14     <div class="messages"> 
    15     <ul> [% FOR m = messages %] <li> [%m%] </li> [% END %] 
    16     </ul></div> 
    17     [% END %] 
    18    <div id="main"> 
     1[% INCLUDE header %] 
    192<h1> Upload a photo </h1> 
    203<p> 
     
    3922    <tr><td> &nbsp; </td> <td> 
    4023<div class="messages"><small> 
     24<script type="text/javascript"> addHandler($("tags")) </script> 
    4125<b>Tagging advice</b>: Tags should be words, (<i>portrait</i>, <i>henry</i>) or 
    4226phrases surrounded by double quotes. (<i>"tall buildings"</i>) You can 
  • trunk/templates/photo/view

    r32 r35  
    7676    document.getElementsByClassName("active").each(function (x) { x.removeClassName("active")}); 
    7777    new Ajax.Updater("content","[%base%]/photo/"+name+"/[%photo.id%]", 
    78       { method: "get"
     78      { method: "get", evalScripts: true
    7979    ) 
    8080    $(name).addClassName("active"); 
  • trunk/templates/static/memories.css

    r23 r35  
    9494.frontpagetable { padding: 10px;  } 
    9595.frontpagetable th { border: 1px solid black; } 
     96 
     97.tagedittagdelete { margin-right: 2em; } 
     98 
    9699span.tagcloud0 { font-size: 9px;} 
    97100span.tagcloud1 { font-size: 10px;} 
  • trunk/templates/static/upload.js

    r2 r35  
    22String.prototype.escRegExp = function(){ return this.replace(/[\\$*+?()=!|,{}\[\]\.^]/g,'\\$&') } 
    33String.prototype.unescHtml = function(){ var i,t=this; for(i in e) t=t.replace(new RegExp(i,'g'),e[i]); return t } 
    4 function Suggestions() { this.length=0; this.picked=0 } 
    5 var suggestions = new Suggestions(); 
    6 var tagSearch='', lastEdit=''; 
    7 var h={}, sections=[{},{},{},{},{},{}], selected={}, currentTag={}, 
    8 e={'&lt;':'<','&gt;':'>','&amp;':'&','&quot;':'"'}; 
     4var availhash = {}; 
     5var tags = tagList.split(/\s+/);  
     6for (t in tags) { availhash[tags[t]] = 1 } 
    97 
    10 function init () { 
    11     document.onkeydown = document.onkeypress = document.onkeyup = handler 
    12     h.suggest = document.getElementById("suggestionlist"); 
    13     h.tags = document.getElementById("tags"); 
    14 
    15  
    16 function handler(event) { var e=(event||window.event) //w3||ie 
    17     if (e.type == 'keyup') { 
     8function addHandler( elt ) { 
     9    var params = { 
     10        elt: elt, 
     11        oldvalue: elt.value 
     12    }; 
     13    document.onkeyup = function (event) { 
     14       var e=(event||window.event) //w3||ie 
    1815        switch(e.keyCode) { 
    19             //case 8:  //backspace 
    20             //case 46: //delete 
    2116            case 35: //end 
    2217            case 36: //home 
     
    2419            case 37: // left 
    2520            case 32: // space 
    26                 hideSuggestions(); break 
    27             case 38: case 40: break
    28             case 9: break; 
    29             case 13: break; 
     21                params.elt.style.background = "#fff"; 
     22                $("suggestionlist").style.visibility='hidden'
     23                break 
     24            case 38: case 40: case 9: case 13: break; 
    3025            default:  
    31             updateSuggestions() 
    32 }} 
    33     else if (e.type == "keypress") { lastEdit = h.tags.value } 
     26            var tagArray = params.elt.value.toLowerCase().split(' '), 
     27            txt=tagArray[tagArray.length-1].trim().escRegExp(), tagHash={}, t 
     28            for(t in tagArray) tagHash[tagArray[t]] = true; 
     29            var sl = $("suggestionlist"); 
     30            if (!txt) { sl.style.visibility = 'hidden'; return; } 
     31 
     32            var search = tagList.match(new RegExp(("(?:^| )("+txt+"[^ ]+)"), "gi")) 
     33            if(search){  
     34                params.elt.style.background = availhash[txt] ? "#dfd" : "#fff"; 
     35                while(sl.childNodes.length > 0) { sl.removeChild(sl.firstChild) } 
     36                sl.style.visibility='visible'; 
     37                var i; 
     38                for (i in search) { 
     39                    if (!tagHash[search[i]]) { 
     40                        var tn = document.createTextNode(search[i]); 
     41                        var a = document.createElement("a"); 
     42                        var elt = params.elt; 
     43                        var closureTxt = txt; 
     44                        a.onclick = function () { 
     45                            elt.value = elt.value.replace(new RegExp(closureTxt+"$"),this.firstChild.nodeValue+" "); 
     46                            elt.focus();  
     47                            sl.style.visibility='hidden'; 
     48                        }; 
     49                        a.appendChild(tn); 
     50                        sl.appendChild(a); 
     51                    } 
     52                } 
     53            } else {  
     54                params.elt.style.background = availhash[txt] ? "#dfd" : "#fdd"; 
     55                sl.style.visibility='hidden'; 
     56           } 
     57        } 
     58    } 
    3459} 
    35  
    36 function makeTag(parent, tag, js) { 
    37     parent.appendChild(document.createTextNode(" "+ tag)) 
    38 } 
    39  
    40 function updateSuggestions() { 
    41     while (h.suggest.hasChildNodes()) h.suggest.removeChild(h.suggest.firstChild) 
    42     if(!getCurrentTag() || !currentTag.text) {  
    43         hideSuggestions(); return false  
    44     } 
    45     var tagArray = h.tags.value.toLowerCase().split(' '), 
    46     txt=currentTag.text.trim().escRegExp(), tagHash={}, t 
    47     for(t in tagArray) tagHash[tagArray[t]] = true; 
    48  
    49     var search = tagList.match(new RegExp(("(?:^| )("+txt+"[^ ]+)"), "gi")) 
    50     if(search){ 
    51         var i; 
    52         for (i=0; i<search.length; i++) { 
    53             var tl = search[i].trim() 
    54             if(tagHash[tl])  continue // do not suggest already typed tag 
    55             suggestions[suggestions.length] = makeTag(h.suggest, tl, 'complete') 
    56             suggestions.length++ 
    57     }}  
    58     if (suggestions.length > 0) { showSuggestions() }  
    59     else { hideSuggestions(); } 
    60 } 
    61  
    62 function getCurrentTag() { 
    63     if(h.tags.value == lastEdit) return true // no edit 
    64     if(h.tags == '') return false 
    65     currentTag = {} 
    66     var tagArray=h.tags.value.toLowerCase().split(' '), oldArray=lastEdit.toLowerCase().split(' '), currentTags = [], matched=false, t,o 
    67     for (t in tagArray) { 
    68         for (o in oldArray) { 
    69             if(typeof oldArray[o] == 'undefined') { oldArray.splice(o,1); break } 
    70             if(tagArray[t] == oldArray[o]) { matched = true; oldArray.splice(o,1); break; } 
    71         } 
    72         if(!matched) currentTags[currentTags.length] = t 
    73         matched=false 
    74     } 
    75     // more than one word changed... abort 
    76     currentTag = { text:tagArray[currentTags[0]], index:currentTags[0] } 
    77     return true 
    78 } 
    79  
    80  
    81 function hideSuggestions() { h.suggest.style.visibility='hidden' } 
    82 function showSuggestions() { h.suggest.style.visibility='visible' }