Вход Регистрация
Файл: IPBMafia.ru_IPB_3.4.6_Final_Rus _Nulled/board/upload/public/js/ips.skin_gen.js
Строк: 2072
<?php
/************************************************/
/* IPB3 Javascript                                */
/* -------------------------------------------- */
/* ips.skin_gen.js - VSE                        */
/* (c) IPS, Inc 2011                            */
/* -------------------------------------------- */
/* Author: Rikki Tissier, Matt Mecham            */
/************************************************/

var defaultTemplates = {
    
css_wrapper: new Template("#{selector} {n#{contents}n}"),
    
bg_color: new Template("tnbackground: #{value} !important;tbackground-color: #{value} !important;n"),
    
bgcolonly_color: new Template("tntbackground-color: #{value} !important;n"),
    
font_color: new Template("tcolor: #{value};n"),
    
border_color: new Template("tborder-color: #{value} !important;n"),
    
box_shadow_color: new Template("tbox-shadow: #{extra} #{value} !important;nt-moz-box-shadow: #{extra} #{value} !important;nnt-webkit-box-shadow: #{extra} #{value} !important;")
}

var 
skingen = {
    
    
currentClass: null,
    
showingLocations: false,
    
classList: [],
    
classStored: {},
    
updatedImages: $H(),
    
classBackup: null,
    
pickers: {},
    
    
//------------------------------------------
    // Initialize
    //------------------------------------------
    
boot: function(){

        if( !
this.checkDB() ){
            
alert("Вы должны использовать браузер, поддерживающий локальное хранилище, пока мы не добавили поддержку Gears");
            return;
        }
    
        
/* Fix image */
        
$('logo').down('img').writeAttribute('src', ipb.vars['img_url'] + "/logo_transparent.png" );
        
        
this.dropper._parent = this.xray._parent = this.db._parent = this.cssManipulator._parent = this.imageEditor._parent = this.hueChanger._parent = this;
        
        
this.loadStoredValues();
        
        if( 
this.db.load("storedImages") ){
            
this.loadStoredImages();
        }
        
        
this.buildEditor();
        
this.buildMasterClassList();
        
        
this.cssManipulator.createInjectedStylesheet();
    },
    
    
//-----------------------------------------
    // Get hex from selector value
    //-----------------------------------------
    
getHexFromSelector: function( val, type )
    {
        if ( 
type == 'background-color' )
        {
            
type = 'background';
        }
        
        
Debug.write( val + '-' + type );
        
        if ( ! 
Object.isUndefined( val ) )
        {
            if ( 
typeof( val ) == 'string' )
            {
                
val = this.skinClasses.get( val )[3][ type ];
                
                if ( 
Object.isUndefined( val ) || Object.isUndefined( val[0] ) )
                {
                    return 
false;
                }
                else
                {
                    
Debug.write( "Got " + val[0] + ' - ' + val[1] );
                }
            }
            
            if ( ! 
Object.isUndefined( val[0] ) )
            {
                return 
this._cleanHex( val[0] );
            }
        }
        
        return 
false;
    },
    
    
//------------------------------------------
    // Builds the panel
    //------------------------------------------
    
buildEditor: function(){
        if( $(
'skingen_editor') ){ return; }
        
pushLater = new Array();
        
        
this.body = $$('body')[0]; // quick reference to body
        // Build list
        
var list = [];
        if( 
this.skinClasses.size() && this.skinGroups.size() ){
            
this.skinGroups.each( function( group ){
                var 
items = [];
                if( 
group.value[1].length ){
                    
$H(group.value[1]).each( function(item){
                        
item = item[1];
                        if( 
this.skinClasses.get( item ) )
                        {
                            var 
bg = this.getHexFromSelector( item, 'background' );
                            var 
fc = this.getHexFromSelector( item, 'color' );
                            
                            
items.push( this.templates.sectionItem.evaluate( { id: item, name: this.skinClasses.get( item )[1], style: 'background: ' + ( bg ? bg : fc ) } ) );
                        }
                    }.
bind(this));
                    
                    if ( 
group.value[0].match( /^app: /i ) )
                    {
                        
pushLater.push( this.templates.sectionGroup.evaluate( { id: group.key, title: group.value[0], content: items.join('') } ) );
                    }
                    else
                    {
                        list.
push( this.templates.sectionGroup.evaluate( { id: group.key, title: group.value[0], content: items.join('') } ) );
                    }
                }
            }.
bind(this));
        }
        
        
// Build HTML
        
$(this.body).insert({bottom: this.templates.editor.evaluate( { sections: list.join('') + pushLater.join('') } )});
        
        
// Existing coords?
        
if( this.db.load('editorPos') ){
            var 
newPos     = this.db.load('editorPos');
            var 
screendims = document.viewport.getDimensions();
            var 
wrapSize   = $('skingen_editor').getDimensions();
            
            if ( 
newPos.left > ( screendims.width - wrapSize.width ) )
            {
                
newPos.left = ( ( screendims.width - wrapSize.width ) / 2 );
            }
            
            if ( 
newPos.left < 1 )
            {
                
newPos.left = ( ( screendims.width - wrapSize.width ) / 2 );
            }
            
            if ( 
newPos.top > ( screendims.height - wrapSize.height ) || newPos.top < 0)
              {
                   
newPos.top = ( ( screendims.height - wrapSize.height ) / 2 );
               }
   
            $(
'skingen_editor').setStyle('left: ' + newPos.left + 'px; top: ' + newPos.top + 'px');
        }
        
        if( 
this.db.load('editorState') && this.db.load('editorState') == 'hide' ){
            $(
'skingen_content').hide();
        }
        
        
// Any pane loaded?
        
if( this.db.load('editorPane') ){
            var 
current = this.db.load('editorPane');
        } else {
            var 
current = 'body';
        }
        
        
// Build the first pane
        
this.showPane( current );
        
        
// Make draggable
        
new Draggable( 'skingen_editor', { handle: $('skingen_editor').down('h1'), onEnd: this.updateDragPos.bind(this), onStart: this.hidePickers.bind(this) } );
        
        
// Add Events
        
this.setUpEditorEvents();
    },
    
    
//------------------------------------------
    // Hides all open color pickers (used when window is dragged)
    //------------------------------------------
    
hidePickers: function(e){
        
this.skinClasses.each( function(item){
            if( 
Object.isUndefined( this.pickers[ item.key ] ) ){
                return;
            }
             
            
$H( item.value[3] ).each( function(style){
                if( !
Object.isUndefined( this.pickers[ item.key ][ style.key ] ) ){
                    
this.pickers[ item.key ][ style.key ].hidePicker();
                }
            }.
bind(this));
        }.
bind(this));    
    },

    
//------------------------------------------
    // Builds a simple array of classnames from our
    // customizable list. Used for matching.
    //------------------------------------------
    
buildMasterClassList: function(){
        
this.classList = [];
        
this.skinClasses.each( function(item){
            
this.classList.push( item.value[0] );
        }.
bind(this));
    },
    
    
    
//-----------------------------------------
    // Get the template for CSS we'll need
    //-----------------------------------------
    
getClassTemplate: function( classArray )
    {
        
template = defaultTemplates.css_wrapper;
        
name     = classArray[0];
        
contents = '';
        
        if ( ! 
Object.isUndefined( classArray[3] ) )
        {
            
$H(classArray[3]).each( function( dec )
            {
                switch( 
dec.key )
                {
                    case 
'background':
                        if ( 
classArray[1] == 'Search Button' )
                        {
                            
contents += defaultTemplates.bgcolonly_color.evaluate( { value: dec.value[0], extra: dec.value[1] } );
                        }
                        else
                        {
                            
contents += defaultTemplates.bg_color.evaluate( { value: dec.value[0], extra: dec.value[1] } );
                        }
                    break;
                    case 
'color':
                        
contents += defaultTemplates.font_color.evaluate( { value: dec.value[0], extra: dec.value[1] } );
                    break;
                    case 
'border':
                        
contents += defaultTemplates.border_color.evaluate( { value: dec.value[0], extra: dec.value[1] } );
                    break;
                    case 
'boxshadow':
                        
contents += defaultTemplates.box_shadow_color.evaluate( { value: dec.value[0], extra: dec.value[1] } );
                    break;
                }
            } );
        }
        
        return 
template.evaluate( { 'selector': name, 'contents': contents } );
    },
    
    
    
//------------------------------------------
    // Events that make the editor work
    //------------------------------------------
    
setUpEditorEvents: function(){
        $(
'skingen_locate').on("click", this.showLocations.bind(this));
        $(
'skingen_select').on("click", this.selectByClick.bind(this));
        $(
'skingen_editor').on("dblclick", 'h1', this.toggleEditor.bind(this));
        $(
'skingen_sections').on('click', 'li', this.showPaneEv.bind(this));
        $(
'skingen_save').on('click', this.buildSkin.bind(this));
        $(
'skingen_revert').on('click', this.revertSkin.bind(this));
        $(
'skingen_sections').on('click', 'h3', this.toggleGroup.bind(this));
        $(
'skingen_colorize').on('click', this.toggleColorizer.bind(this));
        $(
'skingen_settings').on('click', this.toggleSettings.bind(this));
        
//$('skingen_images').on('click', this.imageEditor.toggleImageEditor.bind( this.imageEditor ));
        
        
ipb.delegate.register(".sg_dropper", this.showDropper.bind(this) );
    },
    
    
//------------------------------------------
    // This would build the skin CSS,
    // but for now just we just pretend 
    //------------------------------------------
    
buildSkin: function(e){
        
        
Event.stop(e);
        
        if ( ! $(
'skingen_buildskin_editor') )
        {
            
this.body.insert( { bottom: this.templates.buildSkin.evaluate() } );
        
            new 
Draggable( 'skingen_buildskin_editor', { handle: $("skingen_buildskin_editor").down('h1') } );
            
            $(
'skingen_buildskin_editor').hide();
        }
        
        if ( $(
'skingen_buildskin_editor').visible() )
        {
            new 
Effect.Appear( $('skingen_editor'), { duration: 0.3 } );
            new 
Effect.Fade( $('skingen_buildskin_editor'), { duration: 0.2 } );
            
            
/* Click handlers */
            
$('skingen_buildskin_cancel').stopObserving('click');
            $(
'skingen_buildskin_save').stopObserving('click');
        }
        else
        {
            
/* Position correctly */
            
$('skingen_buildskin_editor').setStyle( { 'top': $('skingen_editor').getStyle('top'), 'left': $('skingen_editor').getStyle('left') } );
        
            new 
Effect.Appear( $('skingen_buildskin_editor'), { duration: 0.3 } );
            new 
Effect.Fade( $('skingen_editor'), { duration: 0.2 } );
            
            
/* Click handlers */
            
$('skingen_buildskin_cancel').on( 'click', this.buildSkin.bindAsEventListener(this) );
            $(
'skingen_buildskin_save').on( 'click', this.buildSkinProcess.bindAsEventListener(this) );
        }

    },
    
    
//------------------------------------------
    // Throw everything back to PHP
    //------------------------------------------
    
buildSkinProcess: function(e)
    {
        
/* Fix form */
        
$('skingen_buildskin_save').writeAttribute('disabled', 'true' );
        $(
'skingen_buildskin_save').update( 'Сохранение...' );
        
        var 
css = [];
        
        
this.skinClasses.each( function(item){
            
css.push( this.buildRenderedRule( item.key ) );
        }.
bind(this) )
        
        
output = css.join("nn");
        
        var 
settings = this.db.load("storedSettings");
        var 
width    = ( Object.isUndefined( settings['width_value'] ) ) ? '87' : settings['width_value'];
        var 
px_pc    = ( Object.isUndefined( settings['width_type'] ) )  ? '%' : settings['width_type'];
        
        
// I dislike the following parts immensly for being terrible hacks,
        // but right now, it's the most effective way of ensuring some parts of
        // our CSS do not get overwritten by VSE styles.
        
output += '#content, .main_width { width: ' + width + px_pc + ' !important; }';
        
        
output += ".topic_buttons li.non_button a {
        background: transparent !important;
        background-color: transparent !important;
        border: 0 !important;
        box-shadow: none !important;
        -moz-box-shadow: none !important;
        -webkit-box-shadow: none !important;
        text-shadow: none !important;
        min-width: 0px;
        color: #777777;
        font-weight: normal;
        }"
;

        
output += ".moderated, body .moderated td, .moderated td.altrow, .post_block.moderated,
                    body td.moderated, body td.moderated {
                    background-color: #f8f1f3 !important;
                    }
                    .post_block.moderated { border-color: #e9d2d7 !important; }
                    .moderated .row2 { background-color: #f0e0e3 !important; }
                    .moderated, .moderated a { color: #6f3642 !important; }"
;

        
Debug.write( $H( this.db.load("storedClasses") ).toJSON() );
        var 
params = { 'storedClasses' : JSON.stringify( this.db.load("storedClasses") ),
                       
'storedSettings': JSON.stringify( this.db.load("storedSettings") ),
                       
'css': output };
                       
        var 
url    = ipb.vars['base_url'] + 'app=core&section=skingen&module=ajax&do=save&md5check=' + ipb.vars['secure_hash'];
        
Debug.write( url );
        new 
Ajax.Request( url,
                            {
                                
method: 'post',
                                
parameters: params,
                                
onSuccess: function(t)
                                {
                                    if ( 
t.responseJSON['status'] == 'ok' )
                                    {
                                        new 
Effect.Fade( $('skingen_buildskin_editor'), { duration: 0.1 } );
                                        
                                        
/* Clear storage */
                                        
this.dropStoredValues();
                                        
                                        
/* Reload yo */
                                        
document.location.reload();
                                    }
                                    else
                                    {
                                        
alert( ipb.lang['action_failed'] );
                                        return;
                                    }
                                }.
bind(this)
                            });
    },
    
    
//------------------------------------------
    // Reverts a skin to the default values
    // and drops the database
    //------------------------------------------
    
revertSkin: function(e){
        if( 
confirm("Вы действительно хотите отменить все внесенные изменения?") ){
            
this.dropStoredValues();
            
this.dropStoredImages();
            
document.location.reload();
        }        
    },
    
    
//------------------------------------------
    // Toggles a style group
    //------------------------------------------
    
toggleGroup: function(e, elem){
        var 
group = $(elem).readAttribute('data-group');
        
        if( 
elem.hasClassName('open') && $('skingen_group_' + group).visible() ){
            new 
Effect.BlindUp( $('skingen_group_' + group), { duration: 0.3, afterFinish: function(){
                $(
elem).removeClassName('open').addClassName('closed');
            } } );
        } else {
            new 
Effect.BlindDown( $('skingen_group_' + group), { duration: 0.3, afterFinish: function(){
                $(
elem).addClassName('open').removeClassName('closed');
            } } );
        }
    },
    
    
//------------------------------------------
    // Toggle the settings panel
    //------------------------------------------
    
toggleSettings: function(e){
        
Event.stop(e);
        
        if( !$(
'skingen_settings_editor') ){
            
this.buildSettings();
        }
        
        if ( $(
'skingen_settings_editor').visible() )
        {
            new 
Effect.Appear( $('skingen_editor'), { duration: 0.3 } );
            new 
Effect.Fade( $('skingen_settings_editor'), { duration: 0.2 } );
        }
        else
        {
            new 
Effect.Appear( $('skingen_settings_editor'), { duration: 0.3 } );
            new 
Effect.Fade( $('skingen_editor'), { duration: 0.2 } );
        }
    },
    
    
//------------------------------------------
    // Build the settings panel
    //------------------------------------------
    
buildSettings: function(e){
        
settings = this.db.load("storedSettings");
        
        var 
width = ( Object.isUndefined( settings['width_value'] ) ) ? '87' : settings['width_value'];
        var 
px_pc = ( Object.isUndefined( settings['width_type'] ) )  ? '%' : settings['width_type'];
        
        
this.body.insert( { bottom: this.templates.settingsEditor.evaluate( { 'width': width } ) } );
        
        
/* Set drop down up correctly */
        
if ( px_pc == 'px' )
        {
            $(
'skingen_setting_widthunit').options[0].selected = true;
        }
        else
        {
            $(
'skingen_setting_widthunit').options[1].selected = true;
        }
        
        
/* Position correctly */
        
$('skingen_settings_editor').setStyle( { 'top': $('skingen_editor').getStyle('top'), 'left': $('skingen_editor').getStyle('left') } );
        
        
/* Click handlers */
        
$('skingen_settings_cancel').on( 'click', this.toggleSettings.bindAsEventListener(this) );
        $(
'skingen_settings_save').on( 'click', this.saveSettings.bindAsEventListener(this) );
        
        $(
'skingen_settings_editor').hide();
        
        new 
Draggable( 'skingen_settings_editor', { handle: $("skingen_settings_editor").down('h1') } );
    },
    
    
//-----------------------------------------
    // Save settings
    //-----------------------------------------
    
saveSettings: function(e)
    {
        
Event.stop(e);
        
        var 
width = $F('skingen_setting_width');
        var 
px_pc = ( $F('skingen_setting_widthunit') == 'percent' ) ? '%' : 'px';
        
        if ( 
px_pc == 'px' && parseInt( width ) < 900 )
        {
            
width = 900;
        }
        else if ( 
px_pc == 'pc' && parseInt( width ) < 60 )
        {
            
width = 60;
        }
        
        
/* write */
        
this.db.write("storedSettings", { 'width_value': width, 'width_type': px_pc } );
        
        
/* update stylesheet */
        
this.cssManipulator.updateWidth();
        

        
this.toggleSettings(e);
    },
    
    
//------------------------------------------
    // Shows the colorizer
    //------------------------------------------
    
toggleColorizer: function(e){
        
Event.stop(e);
        
        if( !$(
'skingen_colorize_editor') ){
            
this.buildColorizer();            
        }
        
        if( $(
'skingen_colorize_editor').visible() ){
            new 
Effect.Appear( $('skingen_editor'), { duration: 0.3 } );
            new 
Effect.Fade( $('skingen_colorize_editor'), { duration: 0.2 } );
            $(
'skingen_colorize').removeClassName('active');
            
this.db.write("currentWindow", "main");
            return;
        } else {
            
// Back up our class values temporarily, so that
            // we can cancel the change if necessary
            
var backup = {};
            
            
this.skinClasses.each( function(item){
                
backup[ item.key ] = item.value[3];
            }.
bind(this));
            
            
this.db.write("classBackup", backup);
            
            
/* Position correctly */
            
$('skingen_colorize_editor').setStyle( { 'top': $('skingen_editor').getStyle('top'), 'left': $('skingen_editor').getStyle('left') } );
            
            
// Fade main window/show colorizer
            
new Effect.Fade( $('skingen_editor'), { duration: 0.3 } );
            new 
Effect.Appear( $('skingen_colorize_editor'), { duration: 0.2 } );
            $(
'skingen_colorize').addClassName('active');
            
this.db.write("currentWindow", "colorize");
            return;
        }
    },
    
    
//-----------------------------------------
    // Returns BG color of colourizer group
    //-----------------------------------------
    
getFirstBackgroundColorOfColorizerGroup: function( group )
    {
        var 
hex        = this.getHexFromSelector( 'maintitle', 'background' );
        var 
background = false;
        var 
text       = false;
        
        if ( ! 
Object.isUndefined(this.colorizeGroups.get( group )) )
        {
            
this.colorizeGroups.get( group ).each( function(item)
            {
                if ( 
$H( this.skinClasses ).get( item ) )
                {
                    
$H(this.skinClasses.get( item )[3] ).each( function(property)
                    { 
                        if ( 
background === false && property.key == 'background' )
                        {
                            
background = this.getHexFromSelector( item, 'background' );
                        }
                        
                        if ( 
text === false && property.key == 'color' )
                        {
                            
text = this.getHexFromSelector( item, 'color' );
                        }
                        
                    }.
bind(this) );
                }
            }.
bind(this) );
        }
        
        
/* Failsafe */
        
return ( background ) ? background : ( text ? text : hex );
    },
    
    
//------------------------------------------
    // Builds the colorizer window
    //------------------------------------------
    
buildColorizer: function(){
        
this.body.insert( { bottom: this.templates.colorizeEditor.evaluate() } );
        $(
'skingen_colorize_editor').hide();
        new 
Draggable( 'skingen_colorize_editor', { handle: $("skingen_colorize_editor").down('h1') } );
        
        
// Set up pickers
        
['base', 'secondary', 'tertiary', 'text'].each( function(item){
            new 
colorPicker( 'skingen_colorize_' + item, {
                    
color: this.getFirstBackgroundColorOfColorizerGroup( item ),
                     
livePreview: true,
                     
previewElement: 'skingen_colorize_' + item,
                     
onHide: this.updateColorizer.bind(this, item),
                    
onSubmit: this.updateColorizer.bind(this, item)
            });
        }.
bind(this));
        
        $(
'skingen_colorize_cancel').on('click', this.cancelColorizer.bind(this));
        $(
'skingen_colorize_save').on('click', this.saveColorizer.bind(this));
        return;
    },
    
    
//------------------------------------------
    // Event handler for colorizer picker
    // Updates all of our classes with a new color
    //------------------------------------------
    
updateColorizer: function( type, picker ){
        var 
newHue = picker.color['h'];
        var 
newSat = picker.color['s'];
        
        if ( ! 
Object.isUndefined( this.colorizeGroups.get( type ) ) )
        {
            
this.colorizeGroups.get( type ).each( function(item){
                if( 
this.skinClasses.get( item )){
                    
$H(this.skinClasses.get( item )[3]).each( function(property){
                        if( 
property.key == 'background' || property.key == 'color' || property.key == 'border'  || property.key == 'boxshadow'  ){
                            
val = this.getHexFromSelector( item, property.key );
                            if ( 
val )
                            {
                                
this.skinClasses.get( item )[3][ property.key ][0] = '#' + this.hueChanger.convertHex( val, newHue, newSat );
                            }
                        }
                    }.
bind(this));
                    
// Now manipulate the CSS for the full preview
                    
this.cssManipulator.updateSelector( item );            
                }
            }.
bind(this));
        }
    },
    
    
//------------------------------------------
    // Cancels a colorize change without saving
    //------------------------------------------
    
cancelColorizer: function(e){
        var 
backup = $H( this.db.load('classBackup') );

        
backup.each( function(item){
            
this.skinClasses.get( item.key )[3] = item.value;
        }.
bind(this));
        
        
this.skinClasses.each( function(item){
            
this.cssManipulator.updateSelector( item.key );
        }.
bind(this));
        
        
this.db.write('classBackup', false);
        
this.toggleColorizer( e );
    },
    
    
//------------------------------------------
    // Save the changes that have been made
    //------------------------------------------
    
saveColorizer: function(e){
        
this.updateStoredValues();
        
this.resetTextboxValues();
        
this.db.write('classBackup', false);
        
this.toggleColorizer( e );
    },
    
    
//------------------------------------------
    // Updates all of the textbox pickers with current values
    //------------------------------------------
    
resetTextboxValues: function( id ){
        
this.skinClasses.each( function(item){
            if( 
Object.isUndefined( this.pickers[ item.key ] ) ){
                return;
            }
             
            
$H( item.value[3] ).each( function(style){
                if( !
Object.isUndefined( this.pickers[ item.key ][ style.key ] ) ){
                    var 
val = this.getHexFromSelector( style.value, style.key );
                    
                    
this.pickers[ item.key ][ style.key ].setColor( val.replace('#', '') );
                    
this.pickers[ item.key ][ style.key ].el.value = val.replace('#', '');
                    $( 
this.pickers[ item.key ][ style.key ].options.previewElement ).setStyle( { 'background-color': val } );
                }
            }.
bind(this));
        }.
bind(this));            
    },
    
    
//------------------------------------------
    // Shows an editor pane
    //------------------------------------------
    
showPaneEv: function(e, elem){
        
this.showPane( elem.id.replace("section_", '') );
    },    
    
showPane: function( id, otherClasses ){        
        $$(
"#skingen_editor .skingen_pane").invoke("hide");
        
        if( $(
'skingen_pane_' + id ) ){
            $(
'skingen_pane_' + id ).show();
        } else {
            
this.buildPane( id );
        }
        
        if ( ! 
Object.isUndefined( otherClasses ) )
        {
            $(
'skingen_pane_' + id + '_others').stopObserving('click');
            $(
'skingen_pane_' + id + '_others').update( this.buildOtherClassesForPane( otherClasses ) ).show();
            $(
'skingen_pane_' + id + '_others').on('click', 'li', this.showPaneEv.bind(this));
        }
        else
        {
            $(
'skingen_pane_' + id + '_others').hide();
        }
        
        
this.currentClass = id;
        
this.db.write("editorPane", id);
    },
    
//-----------------------------------------
    // Show others
    //-----------------------------------------
    
buildOtherClassesForPane: function( otherClasses )
    {
        var 
items = [];
        
        
$H(otherClasses).each( function(item){
            
item = item[1];
            
            if( 
this.skinClasses.get( item ) )
            {
                var 
bg = this.getHexFromSelector( item, 'background' );
                var 
fc = this.getHexFromSelector( item, 'color' );
                
                
items.push( this.templates.sectionItem.evaluate( { id: item, name: this.skinClasses.get( item )[1], style: 'background: ' + ( bg ? bg : fc ) } ) );
            }
        }.
bind(this));
        
        return 
this.templates.otherClassesGroup.evaluate( { content: items.join('') } );
    },
    
    
//------------------------------------------
    // Builds an editor pane
    //------------------------------------------
    
buildPane: function( id ){
        var 
content = [];
        var 
colors = [];
        var 
borders = [];
        var 
classInfo = this.skinClasses.get( id );
    
        
$H(classInfo[3]).each( function(item){
            switch( 
item.key ){
                case 
'background':
                    
colors.push( this.templates.widgetBackground.evaluate({ id: id, current: item.key }) );
                break;
                case 
'color':
                    
colors.push( this.templates.widgetForeground.evaluate({ id: id, current: item.key }) );
                break;
                case 
'border':
                    
borders.push( this.templates.widgetBorder.evaluate({ id: id, current: item.key }) );
                break;
                case 
'boxshadow':
                    
borders.push( this.templates.widgetBoxShadow.evaluate({ id: id, current: item.key }) );
                break;
            }
        }.
bind(this));
        
        if( 
colors.length ){
            
content.push( this.templates.sectionColors.evaluate({ id: id, content: colors.join('') }) );
        }
        
        if( 
borders.length ){
            
content.push( this.templates.sectionBorders.evaluate({ id: id, content: borders.join('') }) );
        }
        
        var 
pane = this.templates.paneWrap.evaluate({ id: id, selector: classInfo[0], name: classInfo[1], description: classInfo[2], content: content.join('') });
        $(
'skingen_panes').insert({bottom: pane});

        
// Set up color pickers
        
[ 'background', 'color', 'border', 'boxshadow' ].each( function(item){
            if( $( 
item + '_' + id ) ){
                if( !
this.pickers[ id ] ){
                    
this.pickers[ id ] = {};
                }

                
this.pickers[ id ][ item ] = this.activatePicker( id, item );
            }
        }.
bind(this) );
    },
    
    
//------------------------------------------
    // Creates a new color picker object
    //------------------------------------------
    
activatePicker: function( id, type ){
        var 
val = this.getHexFromSelector( id, type );
        
        return new 
colorPicker( type + '_' + id, {
                
color: val,
                 
livePreview: true,
                 
previewElement: type + '_preview_' + id,
                 
onHide: this.updateColor.bind(this),
                
onSubmit: this.updateColor.bind(this),
                
onLoad: function(picker){
                    
picker.el.value = val.replace('#', '')
                }.
bind(this)
        });        
    },
    
//-----------------------------------------
    // Update picker from external source
    //-----------------------------------------
    
updatePicker: function( id, type, color )
    {
        
this.pickers[ id ][ type ].setColor( color );
        
        $( 
type + '_' + id ).value = color;
        
        
this.updateColor( this.pickers[ id ][ type ] ); 
    },
    
    
//------------------------------------------
    // Event handler for the picker
    //------------------------------------------
    
updateColor: function(picker){
        
// Get the element
        
var elem = picker.el;
        if( !
elem.id.match( this.currentClass ) ){ return; }
        
        
// Type
        
var type = $(elem).readAttribute('data-type');
        var 
obj = {};
        
        if( 
type == 'background' || type == 'color' || type == 'border' || type == 'boxshadow' ){
            
elemValue = '#' + $(elem).value;
        } else {
            
elemValue = $(elem).value;
        }
        
        
obj[ type ] = elemValue;
        
        
this.updateClassList( this.currentClass, obj );
        
        
this.updatePreview( this.currentClass, obj );
        
        
// Now manipulate the CSS for the full preview
        
this.cssManipulator.updateSelector( this.currentClass );
        
        return 
true;
    },
    
    
//------------------------------------------
    // Updates the preview boxes
    //------------------------------------------
    
updatePreview: function( selector, values ){        
        
values = $H(values);
        
        if( 
values.size() ){
            
values.each( function(item){
                $(
'section_' + selector).down('span').setStyle( { 'backgroundColor' : item.value + ' !important' } );
            }.
bind(this));
        }
    },
    
    
//------------------------------------------
    // Updates the master class list with new values
    //------------------------------------------
    
updateClassList: function( selector, values ){        
        
values = $H(values);
        if( 
values.size() ){
            
values.each( function(item){
                
this.skinClasses.get( selector )[3][ item.key ][0] = item.value;
            }.
bind(this));
        }
        
        
this.updateStoredValues();                
    },
    
    
//------------------------------------------
    // Builds an object we can write to the database
    // for cross-page styling
    //------------------------------------------
    
updateStoredValues: function(){
        
this.classStored = {};
        
        
this.skinClasses.each( function(item){
            
this.classStored[ item.key ] = item.value[3];
        }.
bind(this));
        
        
this.db.write("storedClasses", this.classStored);        
    },
    
    
loadStoredValues: function(){
        var 
storedValues   = this.db.load("storedClasses");
        var 
storedSettings = this.db.load("storedSettings");
        
        if ( ! 
storedValues && typeof(IPS_SKIN_GEN_SAVED_DATA) != 'undefined' )
        {
            if ( ! 
Object.isUndefined( IPS_SKIN_GEN_SAVED_DATA['storedClasses'] ) )
            {
                
storedValues = $H( IPS_SKIN_GEN_SAVED_DATA['storedClasses'] );
            }
        }
        
        if ( ! 
storedSettings && typeof(IPS_SKIN_GEN_SAVED_DATA) != 'undefined' )
        {
            if ( ! 
Object.isUndefined( IPS_SKIN_GEN_SAVED_DATA['storedSettings'] ) )
            {
                
this.db.write("storedSettings", $H( IPS_SKIN_GEN_SAVED_DATA['storedSettings'] ) );
            }
        }
        
        
$H(storedValues).each( function(item){
            var 
itemObj = this.skinClasses.get( item.key );

            if( !
Object.isUndefined( itemObj ) ){
                
this.skinClasses.get( item.key )[3] = item.value;
            }
        }.
bind(this));
    },
    
    
dropStoredValues: function(){
        
this.db.write("storedClasses", false);
        
this.db.write("storedSettings", false );
    },
    
    
updateStoredImages: function(){
        
this.db.write("storedImages", this.updatedImages);
    },
    
    
loadStoredImages: function(){
        
/*var storedImages = this.db.load("storedImages");
        
        $H( storedImages ).each( function(item){
            this.imageEditor.updateImageReferences( item.value, item.key );
        }.bind(this));*/
    
},
    
    
dropStoredImages: function(){
        
this.db.write("storedImages", false);
    },
    
    
//------------------------------------------
    // Start the XRay
    //------------------------------------------
    
selectByClick: function(e){
        
Event.stop(e);
        
this.xray.start();
    },
    
    
//-----------------------------------------
    // Do the dropper background_dropper_ setColor 
    //-----------------------------------------
    
showDropper: function( e, elem )
    {
        
Event.stop(e);
        
        var 
item = elem.id.replace( /^(.+?)_.*$/, "$1" );
        var 
id   = elem.id.replace( /^(?:[^_]+?)_(?:[^_]+?)_(.+?)$/, "$1" );
        
        
this.dropper.start( item, id );
    },
    
    
//------------------------------------------
    // Highlight the current elements
    //------------------------------------------
    
showLocations: function(e){
        
Event.stop(e);
        
        if( 
this.showingLocations ){
            $(
'skingen_locate').removeClassName('active');
            $$(
'.skingen_highlight').invoke("remove");
            
this.showingLocations = false;
            return;
        }
        
        
// Find elements matching the selector
        
var elements = $$( this.skinClasses.get( this.currentClass )[0] );
        
        if( !
elements.size() ){
            
alert("Данный элемент отсутсвует на этой странице! Попробуйте поискать его на другой странице");
            return;
        } 
        
        $(
'skingen_locate').addClassName('active');
        
        
elements.each( function(item){
            var 
offset = item.cumulativeOffset();
            var 
dims = item.getLayout();
            var 
newElem = new Element('div').addClassName('skingen_highlight').setStyle({
                            
width: (dims.get('padding-box-width') + 2) + "px",
                            
height: (dims.get('padding-box-height') + 2) + "px",
                            
top: (offset.top - 2) + "px",
                            
left: (offset.left - 2) + "px"
                        
});
                        
            
this.body.insert({bottom: newElem});            
        }.
bind(this));
        
        
this.showingLocations = true;
    },
    
    
//------------------------------------------
    // Check whether localStorage is supported
    //------------------------------------------
    
checkDB: function(){        
        try {
            return
'localStorage' in window && window['localStorage'] !== null;
        } catch (
e) {
            return 
false;
        }
    },
    
    
//------------------------------------------
    // Updates the position of the editor pane in the DB
    //------------------------------------------
    
updateDragPos: function(e){
        var 
pos = $('skingen_editor').cumulativeOffset();
        
this.db.write("editorPos", pos);
    },
    
    
//------------------------------------------
    // Shows/hides the editor
    //------------------------------------------
    
toggleEditor: function(e){
        if( $(
'skingen_content').visible() ){
            new 
Effect.BlindUp( $('skingen_content'), { duration: 0.3 } );
            
this.db.write("editorState", 'hide');
        } else {
            new 
Effect.BlindDown( $('skingen_content'), { duration: 0.3 } );
            
this.db.write("editorState", 'show');
        }        
    },
    
    
//------------------------------------------
    // Builds a fully-formed CSS rule
    //------------------------------------------
    
buildRenderedRule: function( selector ){
        return 
this.getClassTemplate( this.skinClasses.get( selector ) );
    },
    
    
//-----------------------------------------
    // Clean up hex
    //-----------------------------------------
    
_cleanHex: function( hex )
    {
        if ( 
hex.length == 4 )
        {
            
hex = hex.replace( /#/, '' );
            
rbg = hex.split('');
            
            
hex = '#' + rbg[0] + rbg[0] + rbg[1] + rbg[1] + rbg[2] + rbg[2];
        }
        
        return 
hex;
    },
    
    
//============================================================
    // HUE CHANGER
    // Changes the hue of a class
    //============================================================
    
hueChanger: {
        
_parent: null,
        
        
//------------------------------------------
        // Main function for changing the hue of a hex
        //------------------------------------------
        
convertHex: function( hex, toHue, toSat ){
            
// Remove #
            
hex = hex.replace(/#/, '');
            
            // Check for shorthand hex
            
if( hex.length == 3 ){
                
hex = hex.slice(0,1) + hex.slice(0,1) + hex.slice(1,2) + hex.slice(1,2) + hex.slice(2,3) + hex.slice(2,3);
            }
            
            if( 
hex.length != 6 ){
                
Debug.write("Not a valid hex");
                return;
            }
            
            
Debug.write("Converting " + hex + " to hue " + toHue );
            
// Split the hex into pieces, convert to RGB, and create fraction
            
var r = ( this.hexToRGB( hex.slice(0,2) ) / 255 );
            var 
g = ( this.hexToRGB( hex.slice(2,4) ) / 255 );
            var 
b = ( this.hexToRGB( hex.slice(4,6) ) / 255 );
            
            
// Convert to HSL
            
var hsl = this.RGBtoHSL( r, g, b );
            
            
Debug.dir( hsl );
            
            
// Change our hue to a fraction
            
hsl[0] = (1 / 360) * toHue;            
            
hsl[1] = (1 / 100) * toSat;
            
// Back to RGB
            
var rgb = this.HSLtoRGB( hsl[0], hsl[1], hsl[2] );
            
            return 
this.RGBtoHex( rgb[0], rgb[1], rgb[2] );
        },
        
        
//------------------------------------------
        // Converts an HSL value to RGB
        //------------------------------------------
        
HSLtoRGB: function( h, s, l ){            
            var 
red = 0;
            var 
green = 0;
            var 
blue = 0;
            
            if( 
s == 0 ){
                
red = l * 255;
                
green = l * 255;
                
blue = l * 255;
            } else {
                if( 
l < 0.5 ){
                    var 
v2 = l * ( 1 + s );
                } else {
                    var 
v2 = ( l + s ) - ( s * l );
                }
                
                var 
v1 = 2 * l - v2;
                
                
red = 255 * this.HueToRGB( v1, v2, (h + ( 1 / 3 ) ) );
                
green = 255 * this.HueToRGB( v1, v2, h );
                
blue = 255 * this.HueToRGB( v1, v2, (h - ( 1 / 3 ) ) );
            }
            
            return [ 
Math.round( red ), Math.round( green ), Math.round( blue ) ];
        },
        
        
//------------------------------------------
        // Converts a hue to an RGB decimal value
        //------------------------------------------
        
HueToRGB: function( v1, v2, h ){
            if( 
h < 0 ){ h += 1; }
            if( 
h > 1 ){ h -= 1; }
            
            if( ( 
6 * h ) < 1 ){
                return ( 
v1 + ( v2 - v1 ) * 6 * h );
            }            
            if( ( 
2 * h ) < 1 ){
                return 
v2;
            }            
            if( ( 
3 * h ) < 2 ){
                return ( 
v1 + ( v2 - v1 ) * ( ( 2 / 3 ) - h ) * 6 );
            }    
            
            return 
v1;
        },
        
        
//------------------------------------------
        // Converts an RGB to a HSL value
        //------------------------------------------
        
RGBtoHSL: function( r, g, b ){            
            var 
lightness, hue, saturation = 0;
            
            var 
min = [ r, g, b ].min();
            var 
max = [ r, g, b ].max();
            var 
delta = max - min;
            
            
lightness = ( max + min ) / 2;
            
            if( 
delta == 0 ){     // Grey
                
hue = 0;
                
saturation = 0;
            } else {
                if( 
lightness < 0.5 ){
                    
saturation = delta / ( max + min );
                } else {
                    
saturation = delta / ( 2 - max - min );
                }
                
                var 
delta_r = ( ( ( max - r ) / 6 ) + ( delta / 2 ) ) / delta;
                var 
delta_g = ( ( ( max - g ) / 6 ) + ( delta / 2 ) ) / delta;
                var 
delta_b = ( ( ( max - b ) / 6 ) + ( delta / 2 ) ) / delta;
                
                if( 
r == max ){
                    
hue = delta_b - delta_g;
                } else if( 
g == max ){
                    
hue = ( 1 / 3 ) + delta_r - delta_b;
                } else if( 
b == max ){
                    
hue = ( 2 / 3 ) + delta_g - delta_r;
                }
                
                if( 
hue < 0 ){
                    
hue += 1;
                }
                
                if( 
hue > 1 ){
                    
hue -= 1;
                }
            }
            
            return [ 
hue, saturation, lightness ];
        },
        
        
//------------------------------------------
        // Converts a hex to an RGB value
        //------------------------------------------
        
hexToRGB: function( hex ){
            return 
parseInt(hex,16);
        },
        
        
RGBtoHex: function( r, g, b ){
            var 
hex = [ r.toString(16), g.toString(16), b.toString(16) ];
            
hex.each(function(val,nr) {
                if(
val.length == 1){
                    
hex[nr] = '0' + val;
                }
            });
            return 
hex.join('');
        }
    },
    
    
//============================================================
    // IMAGE EDITOR
    // Accepts uploads of images
    //============================================================
    
imageEditor: {
        
_parent: null,
        
        
//------------------------------------------
        // Shows/hides the image editor
        //------------------------------------------
        
toggleImageEditor: function(e){
            if( 
typeof FileReader === 'undefined' ){
                
alert("Ваш браузер не поддерживает работу с редактированием изображений");
                return;
            }
            
            if( !$(
'skingen_images_editor') ){
                
this.buildImageEditor();
            }        
        },
        
        
//------------------------------------------
        // Builds the image editor window
        //------------------------------------------
        
buildImageEditor: function(e){
            var 
content = [];
            
            
// Build image entries
            
this._parent.imageReplacements.each( function(item){
                
content.push( this._parent.templates.imageEditorItem.evaluate( { 
                                    
id: item.key,
                                    
img: this.buildImage( item ),
                                    
upload: this.buildUploadControl( item ) } ) );                
            }.
bind(this));
            
            var 
imageEditor = this._parent.templates.imageEditor.evaluate( { content: content.join('') } );
            $(
'skingen_editor').insert( { bottom: imageEditor } );
            
            $(
'skingen_images_editor').on('click', 'input[type=button][data-img]', this.uploadImage.bind(this));
            
            
// Make draggable
            
new Draggable( 'skingen_images_editor', { handle: "#skingen_images_editor h1" } );
        },

        
//------------------------------------------
        // Event handler for uploading an image
        //------------------------------------------
        
uploadImage: function( e, elem ){
            
// Find upload control
            
var img = elem.readAttribute('data-img');
            var 
thumb = $('img_' + img);
            var 
uploader = $('skingen_images_content').select("input[type=file][data-img=" + img + "]")[0];
            
            if( !
thumb || !uploader || !uploader.files[0] ){ return; }
            
            var 
file = uploader.files[0];
            
            if( !(/
image/i).test( file.type ) ){
                
alert("Этот файл не является файлом изображения, поробуйте другой!");
                return;
            }
            
            var 
reader = new FileReader();
            
reader.onload = function(e) { 
                
this.updateImageReferences( e.target.result, img );
            }.
bind(this);
            
            
reader.readAsDataURL( file );
        },
        
        
//------------------------------------------
        // Updates all instances of an image on the page
        // to use the data url returned by FileReader
        //------------------------------------------
        
updateImageReferences: function( dataURL, img ){
            
// Update preview image first
            
if( $('img_' + img) ){
                $(
'img_' + img).src = dataURL;
            }
            
            var 
itemObj = this._parent.imageReplacements.get( img );
            
            
// find all places the image is used
            
$$( itemObj[1] + " img" ).each( function( item ){
                if( 
item.src.match( itemObj[0] ) || item.readAttribute('data-img') == img ){
                    
item.src = dataURL;
                    
item.writeAttribute('data-img', img);
                }
            });
            
            
// Update customized image in the object
            
this._parent.updatedImages.set( img, dataURL );
            
this._parent.updateStoredImages();
        },
        
        
//------------------------------------------
        // Returns an image tag
        //------------------------------------------
        
buildImage: function( item ){
            return 
"<img src='" + ipb.vars['img_url'] + item.value[2] + item.value[0] + "' id='img_" + item.key + "' />";
        },
        
        
//------------------------------------------
        // Returns an upload control
        //------------------------------------------
        
buildUploadControl: function(item){
            return 
"<input type='file' id='upload_img_" + item.key + "' data-img='" + item.key + "'  /> <input type='button' id='upload_img_btn_" + item.key + "' data-img='" + item.key + "' value='Save' />";            
        }
    },
    
    
//============================================================
    // CSS MANIPULATOR
    // Manipulates CSS in the stylesheet in order to preview styles
    //============================================================
    
cssManipulator: {
        
_parent: null,
        
styleSheet: null,
        
        
//------------------------------------------
        // Update one selector in the injected stylesheet
        //------------------------------------------
        
updateSelector: function( selector ){
            if( !$(
'injected_stylesheet') ){
                
this.createInjectedStylesheet();
                return;
            }
            
            var 
getRules = '';
            var 
styleSheet = this.fetchStyleSheet();
            
            
// Build our rule
            
var newRule      = this._parent.buildRenderedRule( selector );
            var 
realSelector = this._unifyRule( this._parent.skinClasses.get( selector )[0] );
            
            
Debug.write( "Updating - " + selector + ' - :' + realSelector + ':' );
            
            
// Compatibility issue        
            
getRules = ( styleSheet['cssRules'] ) ? 'cssRules' : 'rules';            

            
// Loop through rules
            
for ( rules = 0; rules < styleSheet[ getRules ].length; rules++ )
            {
                
Debug.write( "Looking at... :" + styleSheet[ getRules ][ rules ].selectorText + ':' );
                
                if ( 
this._unifyRule( styleSheet[ getRules ][ rules ].selectorText ) == realSelector )
                {
                    
Debug.write( "Found it... :" + newRule  + ':');
                    
                    
// Remove rule completely then readd it
                    
styleSheet.deleteRule( rules );
                    
styleSheet.insertRule( newRule, rules );
                }
            }
        },
        
        
updateWidth: function( selector ){
            if( !$(
'injected_stylesheet') ){
                
this.createInjectedStylesheet();
                return;
            }
            
            var 
getRules = '';
            var 
styleSheet = this.fetchStyleSheet();
            
            
/* figure out width, etc */
            
var settings = this._parent.db.load("storedSettings");
            var 
width    = ( Object.isUndefined( settings['width_value'] ) ) ? '87' : settings['width_value'];
            var 
px_pc    = ( Object.isUndefined( settings['width_type'] ) )  ? '%' : settings['width_type'];
            
            
// Build our rule
            
var newRule = '#content, .main_width { width: ' + width + px_pc + ' !important; }';
            var 
realSelector = '#content, .main_width';
            
            
// Compatibility issue        
            
getRules = ( styleSheet['cssRules'] ) ? 'cssRules' : 'rules';            

            
// Loop through rules
            
for( rules = 0; rules < styleSheet[ getRules ].length; rules++ ){
                if( 
styleSheet[ getRules ][ rules ].selectorText == realSelector ){
                    
// Remove rule completely then readd it
                    
styleSheet.deleteRule( rules );
                    
styleSheet.insertRule( newRule, rules );
                }
            }
        },
        
        
//------------------------------------------
        // Finds and returns the injected stylesheet
        //------------------------------------------
        
fetchStyleSheet: function(){
            if( 
this.styleSheet ){
                return 
this.styleSheet;
            }
            
            var 
styleSheets = document.styleSheets;
            
            for( 
sheet = 0; sheet < styleSheets.length; sheet++ ){
                if( 
styleSheets[ sheet ].ownerNode.id == 'injected_stylesheet' ){
                    
this.styleSheet = styleSheets[ sheet ];
                    return 
this.styleSheet;
                }
            }
            
            return 
false;
        },
        
        
//------------------------------------------
        // Build an injected stylesheet from scratch
        //------------------------------------------
        
createInjectedStylesheet: function(){
            var 
output = '';
            
            
$H( this._parent.skinClasses ).each( function(item){
                
output += this._parent.getClassTemplate( this._parent.skinClasses.get( item.key ) );
            }.
bind(this));
            
            
/* figure out width, etc */
            
var settings = this._parent.db.load("storedSettings");
            var 
width    = ( Object.isUndefined( settings['width_value'] ) ) ? '87' : settings['width_value'];
            var 
px_pc    = ( Object.isUndefined( settings['width_type'] ) )  ? '%' : settings['width_type'];
            
            
output += '#content, .main_width { width: ' + width + px_pc + ' !important; }';
            
            
output += ".topic_buttons li.non_button a {
        background: transparent !important;
        background-color: transparent !important;
        border: 0 !important;
        box-shadow: none !important;
        -moz-box-shadow: none !important;
        -webkit-box-shadow: none !important;
        text-shadow: none !important;
        min-width: 0px;
        color: #777777;
        font-weight: normal;
    }"
;

        
output += ".moderated, body .moderated td, .moderated td.altrow, .post_block.moderated,
                    body td.moderated, body td.moderated {
                    background-color: #f8f1f3 !important;
                    }
                    .post_block.moderated { border-color: #e9d2d7 !important; }
                    .moderated .row2 { background-color: #f0e0e3 !important; }
                    .moderated, .moderated a { color: #6f3642 !important; }"
;
    
            
Debug.write(output);
            var 
stylesheet = new Element("style", { id: 'injected_stylesheet' }).update( output );
            
                        
            
            $$(
'head')[0].insert( { bottom: stylesheet } );
            
        },
        
//-----------------------------------------
        // Cleans rule to make sure spacing isn't an issue
        //-----------------------------------------
        
_unifyRule: function( rule )
        {
            
rule = rule.replace( /,s{1,}/g, ',' );
            
            return 
rule;
        }
    },
    
    
//============================================================
    // DB OBJECT
    // Simple DB wrapper with a few standard methods
    //============================================================
    
db: {
        
_parent: null,
        
        
write: function( saveTo, saveValue ){            
            
localStorage.setItem("skingen." + saveTo, JSON.stringify( saveValue ) );
        },
        
        
load: function( loadKey ){
            if( 
localStorage.getItem("skingen." + loadKey) ){
                return 
JSON.parse( localStorage.getItem("skingen." + loadKey) );
            }
            
            return 
false;
        }
    },
    
/* ! xray */
    //============================================================
    // XRAY INSPECTOR
    // Click to select elements, finds IP.Board classes that apply
    //============================================================
    
xray: {
        
_parent: null,
        
matched: null,
        
e: {},
        
        
//------------------------------------------
        // Find eligible elements, and set events
        //------------------------------------------
        
start: function(){
            
// All elements except the skingen_editor
            
this.exclude = $$("#skingen_editor, #skingen_editor *");
            
            $(
'skingen_select').addClassName('active');
            
            
this.e['md'] = $(document).on('mousedown', this.doXray.bind(this));
            
this.e['mm'] = $(document).on('mousemove', this.doFalse.bind(this));
            
this.e['mo'] = $(document).on('mouseover', this.doFalse.bind(this));
        },
        
        
//------------------------------------------
        // Unset events
        //------------------------------------------
        
finish: function(){
            $(
'skingen_select').removeClassName('active');
            
this.exclude = null;
            
this.e['md'].stop();
            
this.e['mm'].stop();
            
this.e['mo'].stop();
            
this._parent.body.removeClassName('selecting');
        },
        
        
//------------------------------------------
        // mousedown handler; shows the xray flash box
        //------------------------------------------
        
doXray: function(e){
            
Event.stop(e);
            
            var 
item = Event.findElement(e);
            
            if( 
this.exclude.include( item ) ){
                return;
            }
                        
            var 
offset = item.cumulativeOffset();
            var 
dims = item.getLayout();
            var 
newElem = new Element('div', { id: 'skingen_xray' }).addClassName('skingen_xray').setStyle({
                            
width: dims.get('padding-box-width') + "px",
                            
height: dims.get('padding-box-height') + "px",
                            
top: (offset.top ) + "px",
                            
left: (offset.left) + "px"
                        
}).writeAttribute('elem', id);
                        
            
this._parent.body.insert({bottom: newElem});
            new 
Effect.Fade( newElem, { duration: 0.7, afterFinish: function(){ newElem.remove() } } );
            
            
this.finish();
            
this.findMatchingSelectors( item );
        },
        
        
//------------------------------------------
        // Simply return false and set the default cursor
        //------------------------------------------
        
doFalse: function(e){
            
this._parent.body.addClassName('selecting');
            
Event.stop(e);
        },
        
        
//------------------------------------------
        // Finds the nearest customizable selector
        // to the clicked element
        //------------------------------------------
        
findMatchingSelectors: function( item ){
            
//Debug.write( this._parent.classList );

            // Get ancestors and add item itself to it
            
var ancestors = $(item).ancestors();
            
ancestors.unshift( item );
            
            var 
matchedClass = false;
            var 
className     = false;
            var 
others       = new Array();
            
            
// Double loop - go through ancestors, checking each class for a match
            
var matching = ancestors.find( function(n){
                return 
this._parent.classList.find( function(m){

                    
// Bug fix: prototype .match cannot handle psuedo classes
                    // We don't need to check them here anyway
                    
if( m.match(/:hover/gi) ){
                        return 
false;
                    }

                    
matchedClass = m;
                    return $(
n).match( m );
                }.
bind(this));
            }.
bind(this));
            
            if ( ! 
matchedClass ) {
                
alert("Не найдено ни одного стиля удовлетворяющего элементу.");
            }
            
            
/* Look for any parents */
            
var matching = ancestors.find( function(n)
            {
                var 
gotIt = this._parent.classList.find( function(m)
                {
                    
// Bug fix: prototype.match cannot handle psuedo classes
                    
if( m.match(/:hover/gi) ){
                        return 
false;
                    }

                    
className = m;
                    
                    if( 
matchedClass == className ){
                        return 
false;
                    } else {
                        return $(
n).match( m );
                    }
                }.
bind(this) );
                
                if ( 
gotIt && className )
                {
                    
this._parent.skinClasses.find( function(c){
                        if ( 
c.value[0] == className ){
                            
others.push( c.key );
                        }
                    }.
bind(this) );
                }
            }.
bind(this));
            
            
// So we know the real classname
            // Now loop through our hash of customizable values
            // and find the one that matches the classname
            
this._parent.skinClasses.find( function(c){
                if( 
c.value[0] == matchedClass ){
                    
this._parent.showPane( c.key, others );
                    return 
true;
                } else {
                    return 
false;
                }
            }.
bind(this));
        }    
    },
    
/* ! dropper */
    //============================================================
    // DROPPER
    // Selects a hex from mouse position
    //============================================================
    
dropper: {
        
_parent: null,
        
e: {},
        
item: null,
        
id: null,
        
        
//------------------------------------------
        // Find eligible elements, and set events
        //------------------------------------------
        
start: function( item, id ){
            
// All elements except the skingen_editor
            
this.exclude = $$("#skingen_editor, #skingen_editor *");
            
this.item = item;
            
this.id   = id;
            
            
this.e['md'] = $(document).on('mousedown', this.doDropper.bind(this));
            
this.e['mm'] = $(document).on('mousemove', this.doFalse.bind(this));
            
this.e['mo'] = $(document).on('mouseover', this.doFalse.bind(this));
        },
        
        
//------------------------------------------
        // Unset events
        //------------------------------------------
        
finish: function(){
            
this.exclude = null;
            
this.e['md'].stop();
            
this.e['mm'].stop();
            
this.e['mo'].stop();
            
this._parent.body.removeClassName('selecting');
        },
        
        
//------------------------------------------
        // mousedown handler; shows the xray flash box
        //------------------------------------------
        
doDropper: function(e){
            
Event.stop(e);
            
            var 
item = Event.findElement(e);
            
            if( 
this.exclude.include( item ) ){
                return;
            }
                        
            var 
offset = item.cumulativeOffset();
            var 
dims = item.getLayout();
            var 
newElem = new Element('div', { id: 'skingen_dropper' }).addClassName('skingen_xray').setStyle({
                            
width: dims.get('padding-box-width') + "px",
                            
height: dims.get('padding-box-height') + "px",
                            
top: (offset.top ) + "px",
                            
left: (offset.left) + "px"
                        
}).writeAttribute('elem', id);
                        
            
this._parent.body.insert({bottom: newElem});
            new 
Effect.Fade( newElem, { duration: 0.3, afterFinish: function(){ newElem.remove() } } );
            
            
this.finish();
            
this.setColorPickerFromKnownSelectors( item );
        },
        
        
//------------------------------------------
        // Simply return false and set the default cursor
        //------------------------------------------
        
doFalse: function(e){
            
this._parent.body.addClassName('selecting');
            
Event.stop(e);
        },
        
        
//------------------------------------------
        // Sets the color picker
        //------------------------------------------
        
setColorPickerFromKnownSelectors: function( item ){
            
// Get ancestors and add item itself to it
            
var ancestors = $(item).ancestors();
            
ancestors.unshift( item );
            
            var 
matchedClass = '';
            
            
// Double loop - go through ancestors, checking each class for a match
            
var matching = ancestors.find( function(n){ 
                return 
this._parent.classList.find( function(m){
                
                    
// Bug fix: prototype.match cannot handle psuedo classes
                    
if( m.match(/:hover/gi) ){
                        return 
false;
                    }
                
                    
matchedClass = m;
                    return $(
n).match( m );
                }.
bind(this));
            }.
bind(this));
            
            if( !
matchedClass ){
                
alert("Не найдено ни одного стиля соответствующего элементу.");
            } 
            
            
// So we know the real classname
            // Now loop through our hash of customizable values
            // and find the one that matches the classname
            
this._parent.skinClasses.find( function(c){
                if( 
c.value[0] == matchedClass ){
                    try
                    {
                        var 
bg = this._parent.getHexFromSelector( c.key, 'background' );
                        var 
fc = this._parent.getHexFromSelector( c.key, 'color' );
                        var 
hex = ( bg ) ? bg : fc;
                        
                        if ( 
hex !== false )
                        {
                            
hex = hex.replace( '#', '' );
                            
                            
this._parent.updatePicker( this.id, this.item, hex );
                        }
                    }
                    catch( 
e ) { }
                    
                    return 
true;
                } else {
                    return 
false;
                }
            }.
bind(this));
        }    
    },

    
    
//============================================================
    // TEMPLATES
    // Various templates for the editor
    //============================================================
    
templates: {
        
editor: new Template("<div id='skingen_editor' class='skingen_editor'>                                
                                <h1>Визуальный редактор стиля</h1>                                                    
                                <div id='skingen_content' class='skingen_content'>                            
                                    <div id='skingen_toolbar'>                                                
                                        <!--<a href='#' id='skingen_images'>Редактирование изображений</a>&nbsp;&nbsp;-->    
                                        <a href='#' id='skingen_settings'><img src='" 
+ skingen_imgs + "/settings.png' />&nbsp; Настройки стиля</a>&nbsp;&nbsp;        
                                        <a href='#' id='skingen_colorize'><img src='" 
+ skingen_imgs + "/colorize.png' />&nbsp; Колорайзер</a>&nbsp;&nbsp; 
                                        <a href='#' id='skingen_revert'><img src='" 
+ skingen_imgs + "/delete.png' />&nbsp; Сброс</a>&nbsp;&nbsp;        
                                        <a href='#' id='skingen_save'><img src='" 
+ skingen_imgs + "/build.png' />&nbsp; Создать стиль</a>&nbsp;&nbsp;            
                                        <a href='#' id='skingen_locate' class='right' title='Найти элементы, использующие выбранный стиль на этой странице'><img src='" 
+ skingen_imgs + "/show_locations.png' /></a>&nbsp;&nbsp;
                                        <a href='#' id='skingen_select' class='right' title='Выбор стиля, путем выбора элемента на странице'><img src='" 
+ skingen_imgs + "/select_element.png' /></a>
                                    </div>                                                                    
                                    <div id='skingen_sections' class='skingen_sections'>#{sections}</div>                            
                                    <div id='skingen_panes'></div>                                            
                                </div>                                                                        
                            </div>"
),
        
otherClassesGroup: new Template("<h3 class='open'>Связанные классы</h3><ul>#{content}</ul>"),
        
sectionGroup: new Template("<h3 class='open' data-group='#{id}'><a href='#' class='skingen_toggle_group'>&nbsp;</a> #{title}</h3><ul id='skingen_group_#{id}' data-group='#{id}'>#{content}</ul>"),
        
sectionItem: new Template("<li id='section_#{id}' class='clearfix'><span style='#{style}' class='color'></span>#{name}</li>"),
        
paneWrap: new Template("<div id='skingen_pane_#{id}' class='skingen_pane'><p class='right skingen_selector' title='Данный селектор используется для стилизации элемента в CSS'><span>#{selector}</span></p><h2>#{name}</h2><p>#{description}</p><div class='skingen_pane_contents'>#{content}</div><div id='skingen_pane_#{id}_others' class='skingen_sections otherClasses' style='display:none'></div></div>"),
        
sectionColors: new Template("<fieldset class='colors'><span class='legend'>Цвета</span>#{content}</fieldset>"),
        
sectionBorders: new Template("<fieldset class='border'><span class='legend'>Рамка</span>#{content}</fieldset>"),
        
widgetBackground: new Template("<span class='control' title='Цвет фона'><img src='" + skingen_imgs + "/background.png' /> <input type='text' class='' id='background_#{id}' data-type='background' /><span id='background_preview_#{id}' class='skingen_preview'></span> <a href='#' class='sg_dropper' title='Пипетка' id='background_dropper_#{id}'><img src='" + skingen_imgs + "/color-picker.png' /></a></span>"),
        
widgetForeground: new Template("<span class='control' title='Цвет текста'><img src='" + skingen_imgs + "/color.png' /> <input type='text' class='' id='color_#{id}' data-type='color' /><span id='color_preview_#{id}' class='skingen_preview'></span> <a href='#' class='sg_dropper' title='Пипетка' id='color_dropper_#{id}'><img src='" + skingen_imgs + "/color-picker.png' /></a></span>"),
        
widgetBorder: new Template("<span class='control' title='Цвет рамки'><img src='" + skingen_imgs + "/border-color.png' /> <input type='text' class='' id='border_#{id}' data-type='border' /><span id='border_preview_#{id}' class='skingen_preview'></span> <a href='#' class='sg_dropper' title='Пипетка' id='border_dropper_#{id}'><img src='" + skingen_imgs + "/color-picker.png' /></a></span>"),
        
widgetBoxShadow: new Template("<span class='control' title='Цвет тени'><img src='" + skingen_imgs + "/box-shadow.png' /> <input type='text' class='' id='boxshadow_#{id}' data-type='boxshadow' /><span id='boxshadow_preview_#{id}' class='skingen_preview'></span> <a href='#' class='sg_dropper' title='Пипетка' id='boxshadow_dropper_#{id}'><img src='" + skingen_imgs + "/color-picker.png' /></a></span>"),
        
settingsEditor: new Template("<div id='skingen_settings_editor' class='skingen_editor'>                
                                        <h1>Настройки стиля</h1>                                                
                                        <div id='skingen_settings_content' class='skingen_content'>            
                                            <p class='skingen_desc'>Основные настройки вашего стиля.</p>    
                                                <br />                                                        
                                                <table style='margin: 10px auto; width: 80%'>                
                                                <tr>                                                        
                                                    <td>Основная Ширина</td>                                        
                                                    <td><input type='text' id='skingen_setting_width' value='#{width}' /> <select id='skingen_setting_widthunit'><option value='px'>pixels</option><option value='percent'>%</option></select>                                        
                                                    </td>                                                    
                                                </tr>                                                        
                                            </table>                                                        
                                            <br />                                                                                
                                            <p class='skingen_buttons'>                                                            
                                                <a href='#' id='skingen_settings_cancel'>Отменить</a>&nbsp;&nbsp;&nbsp;<a href='#' id='skingen_settings_save'>Сохранить</a>
                                            </p>                                                                                
                                        </div>                                                                                    
                                    </div>"
),
        
buildSkin: new Template("<div id='skingen_buildskin_editor' class='skingen_editor'>                
                                        <h1>Создание стиля</h1>                                                
                                        <div id='skingen_buildskin_content' class='skingen_content'>            
                                            <p class='skingen_desc'>Сохранение изменений и создание стиля.</p>    
                                                <br />                                                        
                                                <table style='margin: 10px auto; width: 80%'>                
                                                <tr>                                                        
                                                    <td><p>Все изменения будут внесены в стиль. Редактор будет закрыт.</p>    </td>                                                    
                                                </tr>                                                            
                                            </table>                                                        
                                            <br />                                                                                
                                            <p class='skingen_buttons'>                                                            
                                                <a href='#' id='skingen_buildskin_cancel'>Отмена</a>&nbsp;&nbsp;&nbsp;<a href='#' id='skingen_buildskin_save'>Создать</a>
                                            </p>                                                                                
                                        </div>                                                                                    
                                    </div>"
),
        
colorizeEditor: new Template("<div id='skingen_colorize_editor' class='skingen_editor' style='display: none'>            
                                        <h1>Раскраска стиля</h1>                                                                
                                        <div id='skingen_colorize_content' class='skingen_content'>                                
                                            <p class='skingen_desc'>Используйте инструмент для изменения оттенка (цвета) всех соответствующих стилей в один прием. Затем можно редактировать отдельные стили, используя главный редактор. ВНИМАНИЕ: использование инструмента приведет к перезаписи любых изменений в стилях, которые вы уже настрили.</p>                                                                                            
                                            <table style='margin: 10px 0'>                                                    
                                                <tr>                                                                            
                                                    <td style='width: 50%'><p id='skingen_colorize_base' class='color' data-type='base'></p><br />Первичный цвет</td>
                                                    <td style='width: 50%'><p id='skingen_colorize_secondary' class='color' data-type='secondary'></p><br />Вторичный цвет</td>
                                                </tr>                                                                            
                                                <tr>                                                                            
                                                    <td><p id='skingen_colorize_tertiary' class='color' data-type='tertiary'></p><br />Третичный Color</td>
                                                    <td><p id='skingen_colorize_text' class='color' data-type='text'></p><br />Цвет текста</td>
                                                </tr>                                                                            
                                            </table>                                                                            
                                            <br />                                                                                
                                            <p class='skingen_buttons'>                                                            
                                                <a href='#' id='skingen_colorize_cancel'>Отменить</a>&nbsp;&nbsp;&nbsp;<a href='#' id='skingen_colorize_save'>Применить</a>                                                                                                                    
                                            </p>                                                                                
                                        </div>                                                                                    
                                    </div>"
),                
        
imageEditor: new Template("<div id='skingen_images_editor' class='skingen_editor'><h1>Редактор изображений</h1><div id='skingen_images_content' class='skingen_content'>#{content}</div></div>"),
        
imageEditorItem: new Template("<div id='image_#{id}' class='skingen_image_item clearfix'>#{img}<p class='right'>#{upload}</p></div>")
    },
    
    
//============================================================
    // SKIN CLASSES
    // Our master hash of the classes that can be customized
    //============================================================
    
skinClasses: $H( IPS_SKIN_GEN_DATA['classes'] ),
    
    
//============================================================
    // SKIN GROUPS
    // This object groups the classes in the main display
    //============================================================
    
skinGroups: $H( IPS_SKIN_GEN_DATA['skinGroups'] ),    
    
    
//============================================================
    // SKIN GROUPS
    // This object defines which classes are altered when one of the colorize selectors is altered
    //============================================================
    
colorizeGroups: $H( IPS_SKIN_GEN_DATA['colorizeGroups'] ),
    
    
imageReplacements: $H({
        
logo:     [    'logo.png',                                                // Filename
                    
'#logo',                                                // Scope to find image in (default: *)
                    
'/',                                                    // Path to find this image in the skin folder
                    
'Логотип сообщества'                                // Description
                
],
                
        
defaultPhoto: [     'default_large.png',
                            
'',
                            
'/profile/',
                            
'Фотография по умолчанию'
                    
]
    })
};

document.observe("dom:loaded", function(){
    
skingen.boot();
});
?>
Онлайн: 2
Реклама