Вход Регистрация
Файл: public/js/ips.tags.js
Строк: 528
<?php
/************************************************/
/* IPB3 Javascript                                */
/* -------------------------------------------- */
/* ips.tags.js - Adds tokenizing tags to a textbox */
/* (c) IPS, Inc 2011                            */
/* -------------------------------------------- */
/* Author: Rikki Tissier                        */
/************************************************/

var Tags = {};

Element.addMethods( {
    
tagify: function( elementoptions )
    {
        
options Object.extend( {
            
existingTags: []
        }, 
options);
        
        if( !
options.isEnabled ){ return; }
        
        if( 
options.isOpenSystem ){
            new 
Tags.Openelementoptions );
        } else {
            new 
Tags.Closedelementoptions );
        }        
    }
});

//==================================================
// Base class for tag operations
//==================================================
Tags.Base = {
    
parentInit: function(){
        
// Set up prefixes
        
if( this.options.prefixesEnabled && $( this.id '_prefix' ) ){
            
this.setUpPrefixes();
        }
        
        
// Store a reference to this on the tag box
        
this.element.store('obj'this);
    },
    
    
setUpPrefixes: function(){
        var 
prefixCheck = $( this.id '_prefix' );
        
        var 
prefixFunc = function(e){
            if( $(
prefixCheck).checked ){
                $( 
this.tagWrapper ).addClassName('with_prefixes');
            } else {
                $( 
this.tagWrapper ).removeClassName('with_prefixes');
            }
        }.
bind(this);
        
        
prefixFunc();
        
        $( 
prefixCheck ).observe('click'prefixFunc);
    },
    
    
importTags: function(){
        
        if( 
this.options.existingTags && this.options.existingTags.size() ){
            
$A(this.options.existingTags).each( function(item){
                if( !
item.blank() )
                {
                    
this.addTagitem );
                }
            }.
bind(this));
        }
    },
    
    
buildWrapper: function(){
        
// The original textbox, which we'll remember
        
this.oldInput = $(this.element).observe('focus', function(e){ this.newInput.focus() }.bind(this))
                                        .
observe('blur', function(e){ this.newInput.blur() }.bind(this));

        
// The wrapper which holds our tags
        
this.tagWrapper = new Element("ul", { 'id'this.id '_wrapper' })
                                    .
addClassName("ipsTagBox_wrapper")
                                    .
observe('click'this.eventClickWrapper.bindAsEventListener(this));

        
this.oldInput.insert({ 'before'this.tagWrapper }).hide();

        
// Create an item for the invisible textbox
        
this.inputItem = new Element("li", { 'id'this.id '_inputItem' }).insertthis.newInput );
        
this.tagWrapper.insert({ 'bottom'this.inputItem });
    },
    
    
addTag: function( item ){
        
item item.strip();
        
        if( 
parseInt(this.options.forceLowercase) ){
            
item item.toLowerCase();
        }
        
        var 
closeTag = new Element("span")
                            .
addClassName('ipsTagBox_closetag')
                            .
update("&times;")
                            .
observe('click', function(e){
                                
this.deleteTagEvent.findElement(e'li') );
                            }.
bind(this));
        var 
newTag = new Element("li")
                        .
writeAttribute("tValue"item)
                        .
addClassName('ipsTagBox_tag')
                        .
updateitem )
                        .
insert({'bottom'closeTag});
                        
        
this.inputItem.insert( { 'before'newTag } );
        
        
// Add to hidden input
        
this.oldInput.value += item+',';
        
        if( 
Object.isFunctionthis._afterAdd ) ){
            
this._afterAdd(item);
        }
    },
    
    
selectTag: function( tag ){
        
this.deselectAll();
        $( 
tag ).addClassName('selected');
        
this.selectedTag = $( tag );
        
        if( 
Object.isFunctionthis._afterSelect ) ){
            
this._afterSelect(tag);
        }
    },
    
    
deleteTag: function( tag ){
        
        if( 
this.selectedTag == $(tag) ){
            
this.selectedTag null;
        }
        
        var 
value = $(tag).readAttribute('tvalue');
        $(
tag).remove();
        
        
// Add to hidden input
        
this.oldInput.value this.oldInput.value.replace(value+',''');
        
        if( 
Object.isFunctionthis._afterDelete ) ){
            
this._afterDeletevalue );
        }
    },
    
    
deselectAll: function(){
        $( 
this.tagWrapper ).select("li").invoke("removeClassName"'selected');
        
this.selectedTag null;
    },
    
    
calculateTotal: function(){
        return $( 
this.tagWrapper ).select("li:not(#"+this.id+"_inputItem)").size();
    },
    
    
eventClickWrapper: function(e){
        var 
elem Event.findElement(e'li');
        if( 
elem && $(elem) != $(this.id '_inputItem') && $(elem).hasClassName('ipsTagBox_tag') ){
            
this.selectTag( $(elem) );
        } else {
            $( 
this.newInput ).focus();
        }
        return 
false;
    },

    
//--------------------------------------------------------------
    // Public Methods
    //--------------------------------------------------------------
    
    
getTagCount: function(){
        return 
this.calculateTotal();
    },
    
    
serializeTags: function(){
        var 
tags $A();
        $( 
this.tagWrapper ).select("li:not(#"+this.id+"_inputItem)").each(function(elem){
            
tags.push( $(elem).readAttribute('tvalue') );
        });
        return 
tags;
    }
}

//==================================================
// 'Closed' tagging (i.e. predefined tags)
//==================================================
Tags.Closed = Class.createObject.extend( {
    
    
initialize: function( elementoptions ){
        
this.element = $( element );
        
this.id this.element.id;
        
this.options options;
        
this.handlers = {};
        
        if( 
Object.isUndefinedthis.options.predefinedTags ) || !this.options.predefinedTags || !this.options.predefinedTags.size() ){
            
Debug.write"No predefined tags available" );
            try {
                $( 
this.element ).up('.tag_field').hide();
            } catch(
err){ }
            return;
        }
        
        
this.newInput = new Element("a", { 'href''#' })
                                    .
updatethis.options.lang['tag_add_link'] )
                                    .
addClassName("ipsTagBox_addlink")
                                    .
observe('click'this.eventAddNewTag.bindAsEventListener(this));
                                    
        
// Finish building wrapper
        
this.buildWrapper();
        
        
// Build options dropdown
        
this.tagDropdown = new Element("div", { 'id'this.id '_tagdropdown' })
                                    .
addClassName("ipsTagBox_dropdown")
                                    .
setStyle({
                                        
'width': $(this.tagWrapper).measure('padding-box-width') + 'px',
                                        
'position''absolute'
                                    
})
                                    .
hide();
        
        
this.tagDropdown.insert( {'bottom' : new Element('ul') } );
        
this.options.predefinedTags.each( function(item){
            $( 
this.tagDropdown ).down('ul').insert({'bottom':    new Element('li')
                                                        .
update(item)
                                                        .
addClassName("ipsTagBox_dditem")
                                                        .
writeAttribute("tvalue"item)
                                                        .
observe('click'this.eventClickItem.bindAsEventListener(this))
                                        });
                                        
            if ( ! 
Object.isUndefinedthis.options.existingTags ) && this.options.existingTags && this.options.existingTags.size() > )
            { 
                
this.options.existingTags.each( function(existing)
                {
                    if ( 
item == existing )
                    {
                        $( 
this.tagDropdown ).select('li[tvalue="'+item+'"]')[0].hide();
                    }
                }.
bind(this));
            }
        }.
bind(this));
        $(
this.tagWrapper).insert({'after'this.tagDropdown});
        
        
this.importTags();
        
        
// Do global init
        
this.parentInit();
        
        
/* Is this a touch device? */
        
if ( ipb.vars['is_touch'] && ! Object.isUndefined'iScroll' ) )
        {
            
this.myScroll = new iScrollthis.tagDropdown.id, { hideScrollbarfalsehScrolltrue } );
        }
    },
    
    
showDropdown: function(){
        
this.handlers['doc_click'] = $(document.body).on('click', function(e){
            if( !$(
e.target).descendantOf( $( this.tagDropdown ) ) && !$(e.target).descendantOf( $( this.tagWrapper ) ) ){
                
this.hideDropdown();
            }
        }.
bindAsEventListener(this));
        
        
this.handlers['doc_key'] =    $(document).on('keypress', function(e){
            if( 
e.keyCode == Event.KEY_ESC ){
                
this.hideDropdown();
            }
        }.
bindAsEventListener(this));
        
        new 
Effect.Appear( $( this.tagDropdown ), { duration0.2 } );
        
        
/* Is this a touch device? */
        
if ( ipb.vars['is_touch'] && ! Object.isUndefined'iScroll' ) )
        {
            
setTimeout(function () { this.myScroll.refresh(); }.bind(this), 300);
        }
    },
    
    
hideDropdown: function(){
        try {
            
this.handlers['doc_click'].stop();
            
this.handlers['doc_key'].stop();
        } catch(
err){ }
        
        new 
Effect.Fade( $( this.tagDropdown ), { duration0.3 } );
        
        if ( $( 
this.tagDropdown ).select('li').findAll(function(el) { return el.visible(); }).size() )
        {
            if ( ! 
this.options.maxTags )
            {
                
this.newInput.show();
            }
            else if( 
this.options.maxTags && this.calculateTotal() < this.options.maxTags )
            {
                
this.newInput.show();
            }
        }
    },
    
    
//--------------------------------------------------------------
    // Event Handlers
    //--------------------------------------------------------------
    
    
eventAddNewTag: function(e){
        
this.newInput.hide();
        
this.showDropdown();
        
        
Event.stop(e);
        return 
false;
    },
    
    
eventClickItem: function(e){
        var 
elem Event.findElement(e'li');
        if( !
elem.readAttribute('tvalue') ){ return; }
        var 
tagName elem.readAttribute('tvalue');
        
this.addTagtagName );
        
        $(
elem).hide();    
        
        
// See if all options are used
        
if( !$( this.tagDropdown ).select('li').findAll(function(el) { return el.visible(); }).size() ){
            
this.hideDropdown();
        }
    },
    
    
//--------------------------------------------------------------
    // Internal callbacks
    //--------------------------------------------------------------
    
    
_afterSelect: function(tag){
        new 
Effect.Fade( $(this.tagDropdown), { duration0.3 } );
        
        if( 
this.options.maxTags && this.calculateTotal() < this.options.maxTags ){
            
this.newInput.show();
        }
    },
    
    
_afterAdd: function(item){
        if( 
this.options.maxTags && this.calculateTotal() >= this.options.maxTags ){
            
this.tagDropdown.hide();
            
this.newInput.hide();
        }
    },
    
    
_afterDelete: function(value){
        if( ( ! 
this.options.maxTags ) || ( this.options.maxTags && this.calculateTotal() < this.options.maxTags ) ){
            $( 
this.tagDropdown ).select('li[tvalue="'+value+'"]')[0].show();
        }
    }
}
Tags.Base));

//==================================================
// 'Open' tagging class (i.e. free choice)
//==================================================
Tags.Open = Class.createObject.extend( {
    
    
initialize: function( elementoptions ){
        
this.element = $( element );
        
this.id this.element.id;
        
this.options options;
        
this.handlers = {};
        
        
// Create new textbox which will be our typable area
        
this.newInput = new Element("input", { 'type''text''autocomplete''off'})
                                    .
addClassName("ipsTagBox_hiddeninput")
                                    
// Bug #34191 - IE9 would submit the page when enter is pressed. Changed to keydown event.
                                    
.observe('keydown'this.eventKeyPress.bindAsEventListener(this))
                                    .
observe('keyup'this.eventCommaPress.bindAsEventListener(this))
                                    .
observe('blur'this.eventBlurTextbox.bindAsEventListener(this));
                                    
                                    
/*.observe('focus', this.eventFocusTextbox.bindAsEventListener(this))*/

        
this.buildWrapper();
        
this.newInput.clear();
        
this.importTags();
        
        
// Do global init
        
this.parentInit();
        
        
// Set instructional text if there's no entries
        
if( !this.calculateTotal() && !$Fthis.newInput )){
            $( 
this.newInput ).addClassName('inactive').value this.options.lang['tip_text'];
            
            
this.handlers['text_focus'] = $( this.newInput ).on('focus', function(e){
                $( 
this.newInput ).removeClassName('inactive').value "";
                if( 
this.options.maxLen ){
                    
this.newInput.writeAttribute("maxlength"this.options.maxLen 1); // -1 to leave room for comma
                
}
                
this.handlers['text_focus'].stop();
            }.
bindAsEventListener(this));
        }
    },
    
    
//--------------------------------------------------------------
    // Event Handlers
    //--------------------------------------------------------------
    
    
eventKeyPress: function(e){    
        
//Debug.write( e.keyCode );
        
switch( e.keyCode ){
            case 
Event.KEY_BACKSPACE:
                
//alert( this.inputItem.previous().tagName );
                
if( !$F(this.newInput) )
                {
                    if( 
this.selectedTag ){
                        
this.deleteTagthis.selectedTag );
                    }
                    else
                    {
                        if( 
this.inputItem.previous() ){
                            
this.selectTagthis.inputItem.previous() );
                        }
                    }
                }                
            break;
            case 
Event.KEY_DELETE:
                if( 
this.selectedTag ){
                    
this.deleteTagthis.selectedTag );
                }
            break;    
            case 
Event.KEY_RETURN:
            case 
Event.KEY_TAB:            
                
// Bug #30286 - arabic/hebrew keyboards have a different character on
                // key 188. We have to check that the last character is really a latin
                // comma, and ignore it if not.
                //---------------
                // Bug #33967 - typing tags fast caused them to mess up. Instead of checking
                // if the last char is a comma, we now just check whether a comma exists in
                // the string at all.                
                
if( (e.keyCode == Event.KEY_TAB) && this.newInput.value == '' )
                {
                    return 
false;
                }
                
                
Event.stop(e);
                                
                var 
value this._stripHtmlthis.newInput.value.replace(/,/, '') );
                if( !
value ){
                    
this.newInput.value "";
                    return 
false;
                }
                                
                
this.addTagvalue );
                
this.newInput.value "";
            break;
        }
    },
    
    
// Separate event for comma press - event is keyup, not keydown, so that
    // international keyboard that share the comma key still work.
    
eventCommaPress: function(e){
        
// 188 = comma
        
if( e.keyCode != 188 ){
            return;
        }
        
        if( !
this.newInput.value.indexOf(",") ){
            return;
        }
        
        
Event.stop(e);
                        
        var 
value this._stripHtmlthis.newInput.value.replace(/,/, '') );
        if( !
value ){
            
this.newInput.value "";
            return 
false;
        }
                        
        
this.addTagvalue );
        
this.newInput.value "";
    },
     
    
eventBlurTextbox: function(e){
        if( 
this.newInput.value != '' && this.newInput.value != ',' )
        {
            var 
value this.newInput.value.replace(/,/, '');
            
this.addTagvalue );
            
this.newInput.value "";
        }
    },
    
    
_stripHtml: function( value )
    {
        var 
remove = [ '<''>''"'"'" ];
        
        
remove.each( function(item)
        {
            
value value.replace( new RegExpitem'g' ), '' );
        } );
        
        return 
value;
    },
    
    
//--------------------------------------------------------------
    // Internal callbacks
    //--------------------------------------------------------------
    
    
_afterSelect: function(tag){
        $( 
this.newInput ).setValue("").focus();
    },
    
    
_afterAdd: function(item){
        if( 
this.options.maxTags && this.calculateTotal() >= this.options.maxTags ){
            
this.newInput.hide();
        }
    },
    
    
_afterDelete: function(tag){
        if( 
this.options.maxTags && this.calculateTotal() < this.options.maxTags ){
            
this.newInput.show().focus();
        }
    }
}
Tags.Base));
?>
Онлайн: 1
Реклама