Das Deutsche PHP Forum

Einklappen
Keine Ankündigung bisher.

Das Deutsche PHP Forum

Einklappen
Dieses Thema ist geschlossen.
X
Das ist ein wichtiges Thema.
X
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • EditorMod 2nd Edition

    Hallo liebe Community,

    nachdem tomtaz mich vorhin darauf angesprochen hatte, ob mein GreaseMonkey-EditorMod mittlerweile auch mit den dynamischen QucikEditoren funktioniert, die beim Klick auf die Schaltfläche „Bearbeiten“ auftauchen, habe ich mal ein wenig daran herumgewerkelt, um das Feature einzubauen. Hier der Code:

    Achtung! Der folgende Code ist veraltet, bitte lade den aktuellen von http://userscripts.org/scripts/show/65984 herunter.
    Code:
    // ==UserScript==
    // @name           vBulletin Editor Mod
    // @namespace      tag:Manko10@php.de,2008-03-09:MankoEdMod
    // @description    Customize the vBulletin default editor on php.de
    // @include        http://www.php.de/*
    // ==/UserScript==
    
    
    /**
     * Part I: preparation
    */
    
    // correct window.Node
    window.Node = {
        ELEMENT_NODE                : 1,
        ATTRIBUTE_NODE              : 2,
        TEXT_NODE                   : 3,
        CDATA_SECTION_NODE          : 4,
        ENTITY_REFERENCE_NODE       : 5,
        ENTITY_NODE                 : 6,
        PROCESSING_INSTRUCTION_NODE : 7,
        COMMENT_NODE                : 8,
        DOCUMENT_NODE               : 9,
        DOCUMENT_TYPE_NODE          : 10,
        DOCUMENT_FRAGMENT_NODE      : 11,
        NOTATION_NODE               : 12 
    };
    
    
    /**
     * Part II: internationalization
    */
    var i18n =  {
        phrases : {
            'en-US' : {
                'confMenuEntry'       : 'Add/Remove Buttons',
                'defaultConf'         : '<?xml version="1.0" encoding="utf-8"?>\n<!DOCTYPE editorOverlay SYSTEM "http://www.openwebboard.org/editor-mod/editor-mod-2.dtd">\n<editorOverlay xmlns="http://www.openwebboard.org/editor-mod">\n    <menustrip>\n        <section type="fieldset" legend="I am legend ;-)">\n            <!-- Your buttons here -->\n        </section>\n    </menustrip>\n</editorOverlay>',
                'cancelConfirmation'  : 'Are you sure you want to cancel?\nYou\'ll loose all changes!',
                'XMLCompilationError' : 'Failed the test of well-formedness.\nSee the error message below:\n\n',
                'noDOMAvailable'      : 'Sorry, but I couldn\'t process anything since there\'s no DOM available.',
                'XMLNotValid'         : 'Sorry, but your XML is not valid!',
                'saveMsg'             : 'You must reload the page for the changes to take effect.'
            }
        },
        
        curLocale : 'en-US',
        
        setLocale : function(locale) {
            if (this.phrases[locale]) {
                this.curLocale = locale;
            };
        },
        
        get : function() {
            return this.phrases[this.curLocale];
        },
        
        getPhrase : function(key) {
            return this.phrases[this.curLocale][key];
        }
    };
    
    
    /**
     * Part III: configuration
    */
    GM_registerMenuCommand(i18n.get().confMenuEntry, function() {
        Cfg.showConfigLightBox();
    });
    
    var Cfg = {
        showConfigLightBox : function() {
            var layer = document.createElement('div');
            layer.appendChild(document.createElement('div'));
            Hlp_assignStyles(layer.lastChild, {
                'backgroundColor' : '#000',
                'opacity'         : .6,
                'position'        : 'absolute',
                'height'          : '100%',
                'width'           : '100%',
                'top'             : document.getElementsByTagName('html')[0].scrollTop  + 'px',
                'left'            : document.getElementsByTagName('html')[0].scrollLeft + 'px'
            });
            Hlp_assignStyles(document.body, {
                'overflow' : 'hidden'
            });
            
            // create wrapped textarea
            var txtareaWrapper  = document.createElement('div');
            Hlp_assignStyles(txtareaWrapper, {
                'width'      : '50%',
                'height'     : '50%',
                'position'   : 'absolute',
                'top'        : '25%',
                'left'       : '25%',
                'marginTop'  : document.getElementsByTagName('html')[0].scrollTop  + 'px',
                'marginLeft' : document.getElementsByTagName('html')[0].scrollLeft + 'px'
            });
            layer.appendChild(txtareaWrapper);
            
            var txtarea = document.createElement('textarea');
            with (txtarea) {
                cols = 70;
                rows = 20;
                appendChild(document.createTextNode(GM_getValue('xmlConfig', i18n.get().defaultConf)));
            };
            Hlp_assignStyles(txtarea, {
                'border'     : '3px double #333',
                'width'      : '100%',
                'height'     : '100%',
                'fontFamily' : 'monospace',
                'padding'    : '.4em'
            });
            txtareaWrapper.appendChild(txtarea);
            
            txtareaWrapper.appendChild(document.createElement('div'));
            Hlp_assignStyles(txtareaWrapper.lastChild, {
                'margin'    : '5px',
                'textAlign' : 'center'
            });
            
            // create buttons
            var cmdOK = document.createElement('button');
            cmdOK.appendChild(document.createTextNode('OK'));
            txtareaWrapper.lastChild.appendChild(cmdOK);
            Hlp_assignStyles(cmdOK, {
                'marginRight' : '3px',
                'width'       : '80px'
            });
            var cmdCancel = document.createElement('button');
            cmdCancel.appendChild(document.createTextNode('Cancel'));
            txtareaWrapper.lastChild.appendChild(cmdCancel);
            Hlp_assignStyles(cmdCancel, {
                'marginLeft' : '3px',
                'width'      : '80px'
            });
            
            
            // add event listeners to layer and buttons
            layer.addEventListener('click', function(e) {
                if (e.target == txtarea) {
                    return;
                };
                
                if (confirm(i18n.get().cancelConfirmation)) {
                    Cfg.hideConfigLightBox(layer);
                };
                e.stopPropagation();
            }, false);
            
            cmdCancel.addEventListener('click', function(e) {
                if (confirm(i18n.get().cancelConfirmation)) {
                    Cfg.hideConfigLightBox(layer);
                };
                e.stopPropagation();
            }, true);
            
            cmdOK.addEventListener('click', function(e) {
                if (Cfg.saveConfigFromLightBox(layer)) {
                    Cfg.hideConfigLightBox(layer);
                    //alert(i18n.get().saveMsg);
                };
                e.stopPropagation();
            }, true);
            
            
            // attach layer to body
            document.body.appendChild(layer);
        },
        
        hideConfigLightBox : function(lightbox) {
            document.body.removeChild(lightbox);
            Hlp_assignStyles(document.body, {
                'overflow' : 'visible'
            });
        },
        
        saveConfigFromLightBox : function(lightbox) {
            var cfgTxt = lightbox.getElementsByTagName('textarea')[0].value;
            
            // check for well-formedness
            if (Hlp_checkXMLWellFormedness(cfgTxt)) {
                // save to about:config
                GM_setValue('xmlConfig', cfgTxt);
                return true;
            };
            return false;
        },
    };
    
    
    /**
     * Part IV: process buttons
    */
    var editorMod = {
        srcDOM : null,
        
        editorElement : {
            element        : null,
            insertPosition : null,
            editCounter    : 1
        },
        
        // This method does the initialization automatically, you just have to call processButtons().
        __init__ : function(onlyQuickEditor) {
            // retrieve and parse XML
            var srcText = GM_getValue('xmlConfig');
            
            if (!Hlp_checkXMLWellFormedness(srcText, true)) {
                GM_log(i18n.get().XMLNotValid);
                return false;
            };
            this.srcDOM = new DOMParser().parseFromString(srcText, 'text/xml');
            
            if (null === this.srcDOM) {
                GM_log(i18n.get().noDOMAvailable);
                return false;
            };
            
            return this.findEditor(onlyQuickEditor);
        },
        
        findEditor : function(onlyQuickEditor) {
            if (!onlyQuickEditor) {
                if (document.getElementById('vB_Editor_QR')) {
                    this.editorElement.element        = document.getElementById('vB_Editor_QR');
                    this.editorElement.insertPosition = document.getElementById('vB_Editor_QR_controls');
                    
                    return true;
                } else if (document.getElementById('vB_Editor_001')) {
                    this.editorElement.element        = document.getElementById('vB_Editor_001');
                    
                    // insert <div> 'cause the textarea is also in the same div so appendChild
                    // would append buttons after the textarea
                    var lastTable = null;
                    var childNodes = document.getElementById('vB_Editor_001_controls').childNodes;
                    for (var i = 0; i < childNodes.length; ++i) {
                        if (childNodes[i].nodeName.toLowerCase() == 'table') {
                            lastTable = childNodes[i];
                        };
                    };
                    this.editorElement.insertPosition = document.getElementById('vB_Editor_001_controls').insertBefore(
                        document.createElement('div'),
                        lastTable
                    );
                    
                    return true;
                };
            } else {
                this.editorElement.element        = document.getElementById('vB_Editor_QE_' + this.editorElement.editCounter + '_editor');
                this.editorElement.insertPosition = document.getElementById('vB_Editor_QE_' + this.editorElement.editCounter + '_controls');
                return true;
            };
            
            return false;
        },
        
        // only call this method, all the others are called automatically.
        processButtons : function(onlyQuickEditor) {
            if (!this.__init__(onlyQuickEditor)) {
                return;
            };
            
            var XMLRoot   = (Node.DOCUMENT_TYPE_NODE == this.srcDOM.firstChild.nodeType) ? this.srcDOM.childNodes[1] : this.srcDOM.firstChild;
            // it's irrelevant which (block) element it is, it's just a container to which the menustrips will be appended:
            var resultDOM = document.createElement('div');
            
            for (var msCnt = 0; msCnt < XMLRoot.childNodes.length; ++msCnt) {
                if (Node.TEXT_NODE == XMLRoot.childNodes[msCnt].nodeType || 'menustrip' != XMLRoot.childNodes[msCnt].nodeName) {
                    continue;
                };
                var curXMLMenuStrip = XMLRoot.childNodes[msCnt];
                
                var HTMLMenuStrip = Hlp_createTableStructure();
                var curHTMLEl     = HTMLMenuStrip.lastChild.lastChild;
                
                // process section
                for (var scnCnt = 0; scnCnt < curXMLMenuStrip.childNodes.length; ++scnCnt) {
                    var curXMLSection = curXMLMenuStrip.childNodes[scnCnt];
                    if ('section' != curXMLSection.nodeName) {
                        continue;
                    };
                    
                    // HTMLSection:    current section (<td>)
                    // HTMLSectionIns: pointer to the element to which following elements shall be appended
                    var HTMLSection    = document.createElement('td');
                    var HTMLSectionIns = HTMLSection;                
                    
                    if (curXMLSection.getAttribute('type') == 'fieldset') {
                        HTMLSectionIns                  = HTMLSection.appendChild(document.createElement('fieldset'));
                        HTMLSection.lastChild.className = 'fieldseteditor';
                        
                        // set legend if available
                        if (curXMLSection.getAttribute('legend')) {
                            HTMLSectionIns.appendChild(document.createElement('legend'));
                            HTMLSectionIns.lastChild.appendChild(document.createTextNode(curXMLSection.getAttribute('legend')));
                        };
                    };
                    
                    HTMLSectionIns.appendChild(Hlp_createTableStructure());
                    HTMLSectionIns = HTMLSection.getElementsByTagName('tr')[HTMLSection.getElementsByTagName('tr').length - 1];
                    
                    var XMLButtons = curXMLSection.getElementsByTagName('button');
                    for (var btnCnt = 0; btnCnt < XMLButtons.length; ++btnCnt) {
                        HTMLSectionIns.appendChild(document.createElement('td'));
                        
                        
                        // insert XMLButtons (I hate vBulletins morbid overuse of tables!!!)
                        var btnContainer     = Hlp_createTableStructure();
                        var buttonProperties = {};
                        var params           = XMLButtons[btnCnt].getElementsByTagName('param');
                        for (var i = 0; i < params.length; ++i) {
                            buttonProperties[params[i].getAttribute('name')] = params[i].getAttribute('value');
                        };
                        
                        // if not all required parameters are set
                        if ((!buttonProperties.url && !buttonProperties.text) || (!buttonProperties.insertBefore && !buttonProperties.insertAfter)) {
                            continue;
                        };
                        
                        var button       = document.createElement('div');
                        button.className = 'imagebutton';
                        Hlp_assignStyles(button, {
                            'border'                   : 'medium none',
                            'cursor'                   : 'default',
                            'padding'                  : '1px',
                            'background'               : 'rgb(225, 225, 226) none repeat scroll 0% 0%',
                            'MozBackgroundClip'        : '-moz-initial',
                            'MozBackgroundOrigin'      : '-moz-initial',
                            'MozBackgroundInlinePolicy': '-moz-initial',
                            'color'                    : 'rgb(0, 0, 0)'
                        });
                        
                        
                        if (XMLButtons[btnCnt].getAttribute('id')) {
                            button.setAttribute('id', XMLButtons[btnCnt].getAttribute('id'));
                        };
                        
                        // if graphical button
                        if (buttonProperties.url) {
                            button.appendChild(document.createElement('img'));
                            with (button.lastChild) {
                                setAttribute('src',    buttonProperties.url);
                                setAttribute('alt',    buttonProperties.text   ? buttonProperties.text   : '');
                                setAttribute('title',  buttonProperties.text   ? buttonProperties.text   : '');
                                setAttribute('height', buttonProperties.height ? buttonProperties.height : '');
                                setAttribute('width',  buttonProperties.width  ? buttonProperties.width  : '');
                            };
                        } else {
                            // else: text button
                            button.appendChild(document.createTextNode(buttonProperties.text));
                        };
                        
                        
                        // events (hover, click)
                        button.addEventListener('mouseover', function() {
                            Hlp_assignStyles(this, {
                                'border'                   : '1px solid rgb(49, 106, 197)',
                                'padding'                  : '0px',
                                'background'               : 'rgb(193, 210, 238) none repeat scroll 0% 0%',
                                'MozBackgroundClip'        : '-moz-initial',
                                'MozBackgroundOrigin'      : '-moz-initial',
                                'MozBackgroundInlinePolicy': '-moz-initial',
                                'color'                    : 'rgb(0, 0, 0)'
                            });
                        }, true);
                        
                        button.addEventListener('mouseout', function() {
                            Hlp_assignStyles(this, {
                                'border'                   : 'medium none',
                                'padding'                  : '1px',
                                'background'               : 'rgb(225, 225, 226) none repeat scroll 0% 0%',
                                'MozBackgroundClip'        : '-moz-initial',
                                'MozBackgroundOrigin'      : '-moz-initial',
                                'MozBackgroundInlinePolicy': '-moz-initial',
                                'color'                    : 'rgb(0, 0, 0)'
                            });
                        }, true);
                        
                        // use workaround to assign insert text to particular elements
                        button.setAttribute('insertBefore', buttonProperties.insertBefore);
                        button.setAttribute('insertAfter',  buttonProperties.insertAfter);
                        if (XMLButtons[btnCnt].getElementsByTagName('script')[0]) {
                            button.setAttribute('script', XMLButtons[btnCnt].getElementsByTagName('script')[0].firstChild.nodeValue);
                        };
                        
                        
                        button.addEventListener('click', function() {
                            var insBefore = this.getAttribute('insertBefore').replace(/\\n/g, '\n');
                            var insAfter  = this.getAttribute('insertAfter').replace(/\\n/g, '\n');
                            
                            if (this.hasAttribute('script')) {
                                try {
                                    eval('var tmpFunc = function() { ' + this.getAttribute('script') + ' };');
                                    returnValues = tmpFunc();
                                    
                                    if (typeof returnValues != 'object') {
                                        returnValues = [returnValues];
                                    };
                                    
                                    for (var i in returnValues) {
                                        insBefore = Hlp_replaceVariables(i, returnValues[i], insBefore);
                                        insAfter  = Hlp_replaceVariables(i, returnValues[i], insAfter);
                                    };
                                } catch(ex) {
                                    GM_log('User script error: ' + ex);
                                };
                            };
                            
                            var editorId = this.getAttribute('editorId');
                            editorMod.insertText(insBefore, insAfter, editorId);
                        }, true);
                        
                        
                        // Set editor information to make more than one editor at once working
                        button.setAttribute('editorId', this.editorElement.element.getAttribute('id'));
                        
                        // Add button to DOM fragment
                        HTMLSectionIns.lastChild.appendChild(button);
                    };
                    
                    // append to last <tr>
                    HTMLMenuStrip.lastChild.lastChild.appendChild(HTMLSection);
                };
                
                
                // append menustrip to result DOM (our simple container <div>)
                resultDOM.appendChild(HTMLMenuStrip);
            };
            
            // finally insert into editor
            var len = resultDOM.childNodes.length;
            for (var i = 0; i < len; ++i) {
                this.editorElement.insertPosition.appendChild(resultDOM.firstChild);
            };
        },
        
        insertText : function(startTag, endTag, editorId) {
            if (!this.editorElement.element) {
                return;
            };
            var textareaElement = document.getElementById(editorId).getElementsByTagName('textarea')[0];
            textareaElement.focus();
            
            // save current scrolling position
            var scrollTop  = textareaElement.scrollTop;
            var scrollLeft = textareaElement.scrollLeft;
            
            var start      = textareaElement.selectionStart;
            var end        = textareaElement.selectionEnd;
            var insText    = textareaElement.value.substring(start, end);
            textareaElement.value = textareaElement.value.substr(0, start) + startTag + insText + endTag + textareaElement.value.substr(end);
            
            var pos;
            if (insText.length == 0) {
                pos = start + startTag.length;
            } else {
                pos = start + startTag.length + insText.length + endTag.length;
            };
            textareaElement.selectionStart = pos;
            textareaElement.selectionEnd   = pos;
            
            // reset scrolling
            textareaElement.scrollTop  = scrollTop;
            textareaElement.scrollLeft = scrollLeft;
        }
    };
    
    
    
    /**
     * Helper methods
    */
    
    // assign styles to a specified element. These styles must have JavaScript syntax (camelCase instead of dashes -)
    function Hlp_assignStyles(el, styles) {
        for (var msCnt in styles) {
            el.style[msCnt] = styles[msCnt];
        };
    };
    
    // check a XML string for well-formedness. If you don't set the second parameter to false an alert with
    // a error message will be shown in case of compilation errors
    function Hlp_checkXMLWellFormedness(xmlString, suppressAlert) {
        var DOM = new DOMParser().parseFromString(xmlString, 'text/xml');
        with (DOM.documentElement) {
            if (tagName == 'parseerror' || namespaceURI == 'http://www.mozilla.org/newlayout/xml/parsererror.xml') {
                if (!suppressAlert) {
                    alert(i18n.get().XMLCompilationError + firstChild.nodeValue);
                };
                return false;
            };
        };
        
        return true;
    };
    
    // create a table structure which vBulletin loves (yes, they're all the same stupid tables over and over...)
    function Hlp_createTableStructure() {
        var table = document.createElement('table');
        
        // I'm sorry, but these bad attributes are preset by the original tables:
        with (table) {
            setAttribute('cellpadding', 0);
            setAttribute('cellspacing', 0);
            setAttribute('border',      0);
            appendChild(document.createElement('tbody'));
            lastChild.appendChild(document.createElement('tr'));
        };
        
        return table;        
    };
    
    // replace variables with a replacement string
    function Hlp_replaceVariables(variableName, variableValue, originalString) {
        var pos = 0, prevPos = 0, newString = originalString;
        
        while ((pos = newString.indexOf('$' + variableName, prevPos)) > -1) {
            if (!/[^\w_]/.test(newString.charAt(pos + variableName.length + 1)) && pos + variableName.length + 1 < newString.length) {
                prevPos = pos + variableName.length + 1;
                continue;
            };
            
            var escPos = pos;
            while (-1 < escPos && '\\' == newString.charAt(escPos - 1)) {
                --escPos;
            };
            
            var before  = newString.slice(0, escPos);
            var after   = newString.slice(pos + 1 + variableName.length);
            var escPart = newString.slice(escPos, pos);
            var varPart = (escPart.length & 1) ? '$' + variableName : variableValue;
            escPart     = escPart.substr(0, Math.floor(escPart.length / 2));
            
            newString = before  + escPart + varPart + after;
            prevPos   = (before + escPart + varPart).length;
        };
        
        if (!prevPos) {
            return originalString;
        };
        return newString;
    };
    
    
    
    /**
     * Part IV: initialization
    */
    i18n.setLocale('en-US');
    
    
    /**
     * Part V: set event listeners and insert buttons
     */
    
    // Prepare inserting buttons for dynamic quick editors
    var links = document.getElementsByTagName('a');
    for (var i = 0; i < links.length; ++i) {
        if (links[i].getAttribute('name') && 0 == links[i].getAttribute('name').indexOf('vB::QuickEdit::')) {
            links[i].addEventListener('click', function() {
                var postId = this.getAttribute('name').match(/::(\d+)$/)[1];
                
                // Workaround for GreaseMonkey bug
                var callEventListener = function() {
                    setTimeout(eventListener, 0);
                };
                
                var eventListener = function() {
                    if (document.getElementById('vB_Editor_QE_' + editorMod.editorElement.editCounter + '_controls')) {console.log('Running!');
                        editorMod.findEditor(true);
                        //console.log(editorMod.editorElement.insertPosition);
                        editorMod.processButtons(true);
                        document.getElementById('post_message_' + postId).removeEventListener('DOMNodeInserted', callEventListener, false);
                        
                        // Increase counter for next quick editor
                        ++editorMod.editorElement.editCounter;
                    };
                };
                
                document.getElementById('post_message_' + postId).addEventListener('DOMNodeInserted', callEventListener, false);
            }, false);
        };
    };
    
    // Process buttons for static editor
    editorMod.processButtons();
    Die Buttons lassen sich nach wie vor über das Kontextmenü von GreaseMonkey (Benutzerscript-Befehle -> Add/Remove Buttons) in XML-Form bearbeiten. Es sind nach wie vor einfache Buttons, Textbuttons und erweiterte Buttons mit Skriptinhalten möglich. Die XML-Syntax ist nicht sonderlich schwer zu verstehen, hier mal eine Beispielkonfiguration, wie der Editor bei mir gerade aussieht:
    HTML-Code:
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE editorOverlay SYSTEM "http://www.openwebboard.org/editor-mod/editor-mod-2.dtd">
    <editorOverlay xmlns="http://www.openwebboard.org/editor-mod">
        <menustrip>
            <section type="fieldset" legend="Post">
                <button>
                    <param name="url" value="http://www.php.de/members/manko10-albums-editor-icons-picture15-post-edited.png" />
                    <param name="text" value="Beitrag bearbeitet" />
                    <param name="height" value="20" />
                    <param name="width" value="21" />
                    <param name="insertBefore" value='[B][COLOR="DarkRed"]Beitrag editiert:[/COLOR][/B]\n[I][…] ' />
                    <param name="insertAfter" value='[/I]' />
                </button>
            </section>
            <section type="fieldset" legend="Hinweise">
                <button>
                    <param name="url" value="http://www.php.de/members/manko10-albums-editor-icons-picture16-done.png" />
                    <param name="text" value="Thread bitte als [Erledigt] markieren" />
                    <param name="height" value="20" />
                    <param name="width" value="21" />
                    <param name="insertBefore" value='Dann noch fix den [QUOTE][IMG]http://www.php.de/images/buttons/marksolved.gif[/IMG] [URL="http://www.php.de/solved.php?do=marksolved&amp;t=$0"]Beitrag als erledigt markieren![/URL][/QUOTE]\nDanke!' />
                    <param name="insertAfter" value='' />
                    <script>
                        /\/(\d+)\-/.exec(location.href);
                        return RegExp.$1;
                    </script>
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/manko10-albums-editor-icons-picture59-no-man-tag.png" />
                    <param name="text" value="Bitte [PHP]-Tags statt [MAN]-Tags verwenden" />
                    <param name="height" value="20" />
                    <param name="width" value="21" />
                    <param name="insertBefore" value='Für das Highlighting von PHP-Code sind die [PHP]-Tags und nicht die [MAN]-Tags zuständig. Bitte ändere das noch.' />
                    <param name="insertAfter" value='' />
                </button>
                <button>
                    <param name="text" value="Titel ändern" />
                    <param name="height" value="20" />
                    <param name="width" value="21" />
                    <param name="insertBefore" value='Dein Thread-Titel ist schlecht bzw. unglücklich gewählt. Bitte ändere diesen und beachte dabei [URL=http://www.php.de/php-einsteiger/46456-bitte-aussagekraeftige-threadtitel-verwenden.html]Bitte aussagekräftige Threadtitel verwenden[/URL]' />
                    <param name="insertAfter" value='' />
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/manko10-albums-editor-icons-picture58-what-php.png" />
                    <param name="text" value="Was ist PHP?" />
                    <param name="height" value="20" />
                    <param name="width" value="21" />
                    <param name="insertBefore" value='Bitte lies dir den Artikel [url=http://www.php.de/wiki-php/index.php/Was_ist_PHP]Was ist PHP[/url] aus unserem Wiki aufmerksam durch.' />
                    <param name="insertAfter" value='' />
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/manko10-albums-editor-icons-picture30-crossposting.png" />
                    <param name="text" value="Multiposting" />
                    <param name="height" value="20" />
                    <param name="width" value="21" />
                    <param name="insertBefore" value='[B][COLOR="DarkRed"]Crossposting:[/COLOR][/B]\n[I][→] $0' />
                    <param name="insertAfter" value='\nBitte lies die [url=http://www.php.de/php-einsteiger/announcements.html#Anmerkung_zu_Multipostings]Anmerkungen zu Multipostings[/url]![/I]' />
                    <script>
                        var returnValue = prompt('Please enter the URL of the crossposting (optional):');
                        return returnValue ? returnValue : '';
                    </script>
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/ptc-albums-icons-picture62-regel.png" />
                    <param name="text" value="Forenregeln beachten" />
                    <param name="height" value="20" />
                    <param name="width" value="21" />
                    <param name="insertBefore" value='Bitte beachte die [URL="http://www.php.de/php-einsteiger/announcements.html"]Forenregeln[/URL].' />
                    <param name="insertAfter" value='' />
                </button>
            </section>
            <section type="fieldset" legend="Mörderration">
                <button>
                    <param name="url" value="http://www.php.de/members/manko10-albums-editor-icons-picture21-mod-post-edited.png" />
                    <param name="text" value="Mod: Beitrag editiert" />
                    <param name="height" value="20" />
                    <param name="width" value="21" />
                    <param name="insertBefore" value='[B][COLOR="DarkRed"]Beitragsmoderation (Manko10):[/COLOR][/B]\n[I][‼] ' />
                    <param name="insertAfter" value='[/I]' />
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/manko10-albums-editor-icons-picture23-mod-thread-moved.png" />
                    <param name="text" value="Mod: Thema verschoben" />
                    <param name="height" value="20" />
                    <param name="width" value="21" />
                    <param name="insertBefore" value='[B][COLOR="DarkRed"]Themenmoderation:[/COLOR][/B]\n[I][→] Verschoben von $0' />
                    <param name="insertAfter" value='[/I]' />
                    <script>
                        return document.getElementsByTagName('div')[0].getElementsByTagName('a')[3].firstChild.nodeValue;
                    </script>
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/manko10-albums-editor-icons-picture57-mod-thread-divided.png" />
                    <param name="text" value="Mod: Beiträge abgetrennt" />
                    <param name="height" value="20" />
                    <param name="width" value="21" />
                    <param name="insertBefore" value='[B][COLOR="DarkRed"]Themenmoderation:[/COLOR][/B]\n[I][╦] Abgetrennt von [URL="$0"]$1[/URL]' />
                    <param name="insertAfter" value='[/I]' />
                    <script>
                        return [location.href, document.getElementById('posts').getElementsByTagName('td')[3].getElementsByTagName('strong')[0].childNodes[1].nodeValue];
                    </script>
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/manko10-albums-editor-icons-picture22-mod-thread-closed.png" />
                    <param name="text" value="Mod: Thema geschlossen" />
                    <param name="height" value="20" />
                    <param name="width" value="21" />
                    <param name="insertBefore" value='[B][COLOR="DarkRed"]Themenmoderation:[/COLOR][/B]\n[I][Ω] Thema geschlossen[/I]' />
                    <param name="insertAfter" value='' />
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/manko10-albums-editor-icons-picture26-mod-trash.png" />
                    <param name="text" value="Mod: Trash" />
                    <param name="height" value="20" />
                    <param name="width" value="21" />
                    <param name="insertBefore" value='[B][COLOR="DarkRed"]Themenmoderation:[/COLOR][/B]\n[I][↓] Trash[/I]' />
                    <param name="insertAfter" value='' />
                </button>
            </section>
            <section type="fieldset" legend="Smileys">
                <button>
                    <param name="url" value="http://www.php.de/members/nikosch-albums-emots-picture34-zahnweissy.gif" />
                    <param name="text" value="Smiley Zahnweissy" />
                    <param name="insertBefore" value='[IMG]http://www.php.de/members/nikosch-albums-emots-picture34-zahnweissy.gif[/IMG]' />
                    <param name="insertAfter" value='' />
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/nikosch-albums-emots-picture46-whats-next.gif" />
                    <param name="text" value="Smiley What's next?" />
                    <param name="insertBefore" value='[IMG]http://www.php.de/members/nikosch-albums-emots-picture46-whats-next.gif[/IMG]' />
                    <param name="insertAfter" value='' />
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/nikosch-albums-emots-picture45-harhar.gif" />
                    <param name="text" value="Smiley Harhar" />
                    <param name="insertBefore" value='[IMG]http://www.php.de/members/nikosch-albums-emots-picture45-harhar.gif[/IMG]' />
                    <param name="insertAfter" value='' />
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/nikosch-albums-emots-picture35-blinker.gif" />
                    <param name="text" value="Smiley Blinker" />
                    <param name="insertBefore" value='[IMG]http://www.php.de/members/nikosch-albums-emots-picture35-blinker.gif[/IMG]' />
                    <param name="insertAfter" value='' />
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/nikosch-albums-emots-picture44-argh-wpskm.gif" />
                    <param name="text" value="Smiley Argh Wpskm" />
                    <param name="insertBefore" value='[IMG]http://www.php.de/members/nikosch-albums-emots-picture44-argh-wpskm.gif[/IMG]' />
                    <param name="insertAfter" value='' />
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/nikosch-albums-emots-picture42-duedeldue-pfeif.gif" />
                    <param name="text" value="Smiley Düdeldü Pfeif" />
                    <param name="insertBefore" value='[IMG]http://www.php.de/members/nikosch-albums-emots-picture42-duedeldue-pfeif.gif[/IMG]' />
                    <param name="insertAfter" value='' />
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/nikosch-albums-emots-picture41-hmm-kopfkratz.gif" />
                    <param name="text" value="Smiley Hmm Kopfkratz" />
                    <param name="insertBefore" value='[IMG]http://www.php.de/members/nikosch-albums-emots-picture41-hmm-kopfkratz.gif[/IMG]' />
                    <param name="insertAfter" value='' />
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/nikosch-albums-emots-picture40-gaehn.gif" />
                    <param name="text" value="Smiley Gähn" />
                    <param name="insertBefore" value='[IMG]http://www.php.de/members/nikosch-albums-emots-picture40-gaehn.gif[/IMG]' />
                    <param name="insertAfter" value='' />
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/nikosch-albums-emots-picture39-dumdidum.gif" />
                    <param name="text" value="Smiley Dumdidum" />
                    <param name="height" value="20" />
                    <param name="insertBefore" value='[IMG]http://www.php.de/members/nikosch-albums-emots-picture39-dumdidum.gif[/IMG]' />
                    <param name="insertAfter" value='' />
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/nikosch-albums-emots-picture38-haeaeaeaeh.gif" />
                    <param name="text" value="Smiley Hääääh?" />
                    <param name="height" value="20" />
                    <param name="insertBefore" value='[IMG]http://www.php.de/members/nikosch-albums-emots-picture38-haeaeaeaeh.gif[/IMG]' />
                    <param name="insertAfter" value='' />
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/nikosch-albums-emots-picture37-infantil-grins.gif" />
                    <param name="text" value="Smiley Infantil grins" />
                    <param name="insertBefore" value='[IMG]http://www.php.de/members/nikosch-albums-emots-picture37-infantil-grins.gif[/IMG]' />
                    <param name="insertAfter" value='' />
                </button>
                <button>
                    <param name="url" value="http://www.php.de/members/nikosch-albums-emots-picture36-goin-locco.gif" />
                    <param name="text" value="Smiley Goin' locco" />
                    <param name="insertBefore" value='[IMG]http://www.php.de/members/nikosch-albums-emots-picture36-goin-locco.gif[/IMG]' />
                    <param name="insertAfter" value='' />
                </button>
            </section>
        </menustrip>
    </editorOverlay>
    An alle diejenigen, die es wie ich machen und den Firefox vor dem Herunterfahren des Computers nicht schließen, damit er beim nächsten Hochfahren automatisch gleich wieder gestartet wird: ihr müsst den Firefox nach dem Bearbeiten der Konfiguration einmal ordnungsgemäß schließen und wieder starten, damit die Konfiguration auch wirklich auf der Platte gespeichert wird.

    Viel Spaß
    Manko10
    Zuletzt geändert von Manko10; 09.01.2010, 20:42.
    Refining Linux: “Performing Push Backups – Part 1: rdiff-backup

  • #2
    Ich komm nicht mit, was macht das Teil?

    Kommentar


    • #3
      Damit kannst du deinen Editor hier im Forum um eigene Buttons erweitern.
      Refining Linux: “Performing Push Backups – Part 1: rdiff-backup

      Kommentar


      • #4
        I love it.

        Falls es jemand nicht installiert bekommt: Ich hab' das Script lokal als temp.user.js gespeichert und die Datei mit dem Browser aufgerufen, dann sollte sich Greasemonkey automatisch melden. Danach ein Neustart, damit das User-Command im Kontextmenü erscheint. Dann Mankos Toolbars reinkopiert, dann wieder Neustart -- fertig.
        PHP-Wissenssammlung Composer Awesome PHP PHP: The Right Way Free Programming Books @mermshaus

        Kommentar


        • #5
          Für Nicht-Mods ist das nicht so unbedingt nötig glaub ich

          Kommentar


          • #6
            @mermshaus Geht aber auch einfacher über den Kontextmenueintrag „Neues Benutzerskript“ und dann mit Copy&Paste.
            Mal schauen, vielleicht lade ich das irgendwann mal auf userscripts.org hoch, dann wird es noch einfacher.
            Refining Linux: “Performing Push Backups – Part 1: rdiff-backup

            Kommentar


            • #7
              Was bringt das mit sich wenn man nicht Mod ist? Lohnt sich das?

              Kommentar


              • #8
                Musst du selbst entscheiden. Es ist halt sehr praktisch, wenn du häufig gepostete Links wie zum Lerne-Grundlagen-Thread, dem PHP.de-Wiki oder den Forenregeln, als Buttons im Editor ablegen kannst.
                Ich weiß von einigen Nicht-Mods hier, dass sie den Mod nutzen und sehr zufrieden damit sind. Ich selbst kann mir den Forenalltag ohne gar nicht mehr vorstellen, aber gut, ich bin auch Moderator.
                Refining Linux: “Performing Push Backups – Part 1: rdiff-backup

                Kommentar


                • #9
                  Man kann ja die Texte und Buttons relativ einfach austauschen. Somit kannst du dir deine eigenen Buttons kreieren die Textsnippets bereitstellen. Die Frage ist halt welche man als normaler User so braucht.

                  Kommentar


                  • #10
                    Z.B. die, die immer noch nciht alle Editoren hier einheitlich anbieten.
                    --
                    ^^ O.O
                    „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                    Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


                    --

                    Kommentar


                    • #11
                      Du kannst auch deine Smiley-Auswahl vergrößern oder vom Board bereitgestellte Smileys auch auf den kleinen Editoren darstellen.
                      Refining Linux: “Performing Push Backups – Part 1: rdiff-backup

                      Kommentar


                      • #12
                        Zitat von Manko10 Beitrag anzeigen
                        @mermshaus Geht aber auch einfacher über den Kontextmenueintrag „Neues Benutzerskript“ und dann mit Copy&Paste.
                        Mal schauen, vielleicht lade ich das irgendwann mal auf userscripts.org hoch, dann wird es noch einfacher.

                        es würde reichen das script mit namen irgendwas.user.js auf nen xbeliebigen server zu laden, wenn mans aufruft erkennts greasemonkey sofort.

                        Kommentar


                        • #13
                          Zitat von Manko10 Beitrag anzeigen
                          Ich weiß von einigen Nicht-Mods hier, dass sie den Mod nutzen und sehr zufrieden damit sind. Ich selbst kann mir den Forenalltag ohne gar nicht mehr vorstellen, aber gut, ich bin auch Moderator.
                          Dem Stimme ich zu, und da jetzt der Mod auch beim Bearbeiten von Beiträgen geht, bin ich überglücklich.

                          Einen Alltag hier im Forum ohne diesen Mod währe nicht mehr vorstellbar!
                          Mfg Tomtaz
                          "Es soll jetzt diese Erfindung geben.... Kugel oder so heißt die. Ist so eine Art Suchmaschine..."

                          Kommentar


                          • #14
                            EditorMod Ultimate Edition

                            Hi Leuts,

                            nachdem nikosch versucht hat, seinen Mod des Mods einzupflegen, um auch Select-Felder zu ermöglichen, habe ich beschlossen, die Parser-Routine des Mods umzuschreiben, um sie durch ControlHandler erweiterbar zu machen. Fortan lässt sich für jedes Element ein ControlHandler registrieren, um eigene Elemente nutzen zu können. Der DOM-Baum wird dabei rekursiv durchlaufen und die Handler dabei aufgerufen. Da die Handler selbst für die Fortsetzung der Rekursion über die eigenen Kindelemente verantwortlich sind, ist es ganz einfach möglich, die <param>-Elemente unterhalb der Buttons oder Selects nicht weiter zu rekursieren, sondern als Parameter für diesen Button zu nutzen.

                            Somit freue ich mich nun, so kurz nach der 2nd Edition (die eigentlich schon die 3rd Edition war), die Ultimate Edition präsentieren zu können.

                            Hier ist der Code:
                            ***CODE SIEHE NÄCHSTER POST***

                            Der ist mittlerweile stolze 729 Zeilen lang. Es ist jeder herzlich eingeladen, eigene ControlHandler zu schreiben, bisher implementiert sind folgende:
                            • editoroverlay
                              Dieser Handler ist essentiell wichtig, er kümmert sich um den Root-Node. Bitte da lassen, wo er ist.
                            • menustrip
                              Es lassen sich mehrere Menustrips (=Reihen) von Control-Elementen (ich sage bewusst nicht Buttons, weil der Mod ja nicht auf Buttons beschränkt ist) nutzen.
                            • section
                              Für die einzelnen Fieldsets. Dieser CH lässt sich auch einfach erweitern um weitere Typen, bisher ist nur type="fieldset" implementiert und (wenn kein type-Attribut vorhanden ist) ein einfaches Div
                            • button
                              CH für die Erstellung von Bild- und Text-Buttons (je nachdem ob ein Parameter "url" vorhanden ist, der den URL zum Bild angibt)
                            • select
                              Dieser Control Handler kümmert sich um das Parsen der Select-Felder.

                            Viel Spaß!
                            Manko10
                            Zuletzt geändert von Manko10; 05.01.2010, 20:26.
                            Refining Linux: “Performing Push Backups – Part 1: rdiff-backup

                            Kommentar


                            • #15
                              Hi,
                              ich dachte, wenn ich schon dabei bin, kann ich auch mal eine deutschsprachige Version bereitstellen (jetzt ist der Code 742 Zeilen lang. ). Das Ding hat seit Ewigkeiten i18n-Funktionalität, die ich mal implementiert, aber nie wirklich genutzt habe. Jetzt gibt es neben der en-US-Version auch eine de-DE-Version:
                              ***CODE SIEHE NÄCHSTER POST***

                              Um die Sprache umzuschalten, einfach ganz nach unten scrollen und dort
                              Code:
                              i18n.setLocale('de-DE');
                              oder eben für en-US
                              Code:
                              i18n.setLocale('en-US');
                              setzen.

                              Grüße
                              Manko10
                              Zuletzt geändert von Manko10; 05.01.2010, 22:34.
                              Refining Linux: “Performing Push Backups – Part 1: rdiff-backup

                              Kommentar

                              Lädt...
                              X