--- tag_complete/tag_complete.js 2006/08/18 23:10:48 48 +++ tag_complete/tag_complete.js 2006/08/19 23:11:12 53 @@ -7,16 +7,23 @@ var _tag = { name: new Array(), obj: new Array(), - selected_obj: new Array(), + tag2i: new Array(), + selected: new Array(), + entered: { // array of entered tags + i: new Array(), // offset to tags + tag: new Array() // mapping from tag i to entered + }, + + current: null, // current selected suggestion + last_tags: '', select: function( tag ) { $.log.info('filter '+tag); - _tag.selected_obj = Array(); var j = 0; var tag_len = tag.length; - var suggest = ''; - $('#suggest').html( suggest ); if (j > 0) { - $('#suggest li:nth(0)').addClass('selected'); + $('#suggest a:nth(0)').addClass('selected'); _tag.current = 0; } }, clean_selected: function() { - for(var i = 0; i < _tag.selected_obj.length; i++) { - jQuery.className.remove( _tag.selected_obj[i], 'selected' ); + for(var i = 0; i < _tag.selected.length; i++) { + jQuery.className.remove( _tag.selected[i].obj, 'selected' ); } var c = _tag.current; @@ -63,28 +70,68 @@ return true; } - var s = $('#suggest li:nth('+c+')').html(); + var s = $('#suggest a:nth('+c+')').html(); if (s == null) { $.log.debug('no suggest, return true'); return true; } - _tag.add_tag( s ); - _tag.clean_selected(); + var i = _tag.selected[c].i; + $.log.debug('take_suggested '+i+':'+s); + _tag.add_tag( s, i ); return false; }, - add_tag: function( t ) { - $.log.info('add: '+t); + add_tag: function( t, i ) { + $.log.info('add '+i+': '+t); + _tag.focus(); + jQuery.className.add( _tag.obj[i], 'entered' ); + var entered_i = _tag.entered.i.length; + _tag.entered.i[ entered_i ] = i; + _tag.entered.tag[i] = entered_i; + _tag.clean_selected(); $('#tags').val( $('#tags').val().replace( /[^ ]*$/, t + ' ' ) ); + return false; + }, + + remove_tag: function( t, i ) { + $.log.info('remove '+i+': '+t); _tag.focus(); + jQuery.className.remove( _tag.obj[i], 'entered' ); + // remove selected tag and rebuild tags + + var ent_i = _tag.entered.tag[i]; + $.log.debug('entered i:'+ent_i); + _tag.entered.i.splice(ent_i,1); + _tag.entered.tag[i] = null; + + $.log.debug("tags "+_tag.entered.i.join(",")); + + var tags = ''; + for (var j = 0; j < _tag.entered.i.length; j++) { + var tag_i = _tag.entered.i[j]; + tags += _tag.name[ tag_i ] + ' '; + _tag.entered.tag[ tag_i ] = j; + } + + _tag.clean_selected(); + $.log.debug('tags left: '+tags); + $('#tags').val( tags ); return false; }, + tag: function( t, i ) { + if (_tag.entered.tag[i] != null) { + _tag.remove_tag( t, i ); + } else { + _tag.add_tag( t, i ); + } + }, + move_suggested: function( where ) { var c = _tag.current; if (c == null) { @@ -93,22 +140,57 @@ } var to = c + where; $.log.info('move_suggested('+where+') '+c+' -> '+to); - if (to < 0 || to >= _tag.selected_obj.length) { + if (to < 0 || to >= _tag.selected.length) { $.log.error('move to invalid element '+to); return; } - var s = '#suggest li:nth('+c+')'; + var s = '#suggest a:nth('+c+')'; $( s ).removeClass('selected'); $.log.debug('remove selected from '+s); - s = '#suggest li:nth('+to+')'; + s = '#suggest a:nth('+to+')'; $( s ).addClass('selected'); $.log.debug('add selected to '+s); _tag.current = to; }, - last_tag: function() { - return $('#tags').val().replace(/^([^ ][^ ]* )*/, ''); + parse: function() { + $.log.info('re-parse tags'); + + var t = $('#tags').val().replace(/^ */,'').replace(/ *$/,'').split(/ /); + + _tag.entered = { + i: new Array(), + tag: new Array() + }; + + $('.entered').removeClass('entered'); + + var ids = ''; + for (var i = 0; i < t.length; i++) { + var tag = t[i]; + if (_tag.tag2i[ tag ] != null) { + var tag_i = _tag.tag2i[ tag ]; + _tag.entered.tag[ tag ] = + _tag.entered.i.push( tag_i ) - 1; + jQuery.className.add( _tag.obj[ tag_i ], 'entered' ); + ids += i + ':' + tag_i + ' '; + } else { + ids += i + ':{' + tag + '} '; + } + } + $.log.debug('tags: '+t.join(','), 'ids:'+ids); + + }, + + current_tag: function() { + var tags = $('#tags').val(); + if (tags != _tag.last_tags) { + _tag.last_tags = tags; + _tag.parse(); + } + return tags.replace(/^([^ ][^ ]* )*/, ''); }, + focus: function() { // $('#tags').focus() doesn't work! document.getElementById('tags').focus(); @@ -122,9 +204,11 @@ var n = this.firstChild.nodeValue; _tag.name[i] = n; _tag.obj[i] = this; + _tag.tag2i[n] = i; this.onclick = function() { - return _tag.add_tag( n ); + return _tag.tag( n, i ); } + this.href = '#'+i; // FIXME debug }); $.log.info( 'found ' + _tag.name.length + ' tags' ); @@ -147,10 +231,14 @@ if (_tag.current != null) _tag.focus(); e.preventDefault(); return false; + case 8: // backspace + case 46: // del + _tag.parse(); + return false; } - var t = _tag.last_tag(); + var t = _tag.current_tag(); $.log.debug('tag: ' + t + ' ['+t.length+']'); @@ -160,7 +248,7 @@ _tag.select(t); - $.log.info('selected ' + _tag.selected_obj.length + ' tags'); + $.log.info('selected ' + _tag.selected.length + ' tags'); return true; }).submit( function() {