Ankündigung

Einklappen
Keine Ankündigung bisher.

EditorMod 2nd Edition

Einklappen

Neue Werbung 2019

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

  • #16
    Sorry for inconvenience, da war doch tatsächlich noch ein kleiner Bug drinnen, der bewirkt hat, dass mehrere Menustrips zwar generiert, bis auf den ersten aber nicht ins Dokument eingefügt werden (thanks to nikosch fürs Reporten!).

    Hier nochmal 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' : {
                'ok'                  : 'OK',
                'cancel'              : 'Cancel',
                '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.'
            },
            'de-DE' : {
                'ok'                  : 'OK',
                'cancel'              : 'Abbrechen',
                'confMenuEntry'       : 'Buttons hinzufügen/entfernen',
                '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            <!-- Hier kommen deine Buttons hin -->\n        </section>\n    </menustrip>\n</editorOverlay>',
                'cancelConfirmation'  : 'Bist du sicher, dass du abbrechen willst?\nAlle Änderungen gehen dabei verloren!',
                'XMLCompilationError' : 'Test auf Wohlgeformtheit fehlgeschlagen.\nSiehe die folgende Fehlermeldung:\n\n',
                'noDOMAvailable'      : 'Entschuldigung, aber es war mir nicht möglich, etwas zu verarbeiten, weil schlicht kein DOM da ist.',
                'XMLNotValid'         : 'Entschuldige bitte, aber dein XML ist nicht valide!',
                'saveMsg'             : 'Du musst die Seite neu laden, damit die Änderungen sichtbar werden.'
            }
        },
        
        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'      : '70%',
                'height'     : '80%',
                'position'   : 'absolute',
                'top'        : '10%',
                'left'       : '15%',
                '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 = 120;
                rows = 30;
                setAttribute ('wrap' , 'off' , false);
                appendChild(document.createTextNode(GM_getValue('xmlConfig', i18n.get().defaultConf)));
            };      
    
            Hlp_assignStyles(txtarea, {
                'border'     : '3px double #333',
                'width'      : '100%'           ,
                'height'     : '100%'           ,
                'fontFamily' : 'monospace'      ,
                'padding'    : '.4em'           ,
                'whiteSpace' : 'pre'            ,
                'overflow'   : 'scroll'         ,
                'overflowX'  : 'scroll'
            });
            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(i18n.get().ok));
            txtareaWrapper.lastChild.appendChild(cmdOK);
            Hlp_assignStyles(cmdOK, {
                'marginRight' : '3px',
                'width'       : '80px'
            });
            var cmdCancel = document.createElement('button');
            cmdCancel.appendChild(document.createTextNode(i18n.get().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);
                };
                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');
                    this.editorElement.insertPosition = document.getElementById('vB_Editor_001_controls');
                    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.
        // this method does not cache the DOM once it's generated due to the cloneNode() problem
        // with DOM events. It would be more complicated to fix that than to parse
        // the code again.
        processButtons : function(onlyQuickEditor) {
            if (!this.__init__(onlyQuickEditor)) {
                return;
            };
            
            // get source DOM (ignore leading whitespace)
            var XMLRoot = (Node.DOCUMENT_TYPE_NODE == this.srcDOM.firstChild.nodeType) ? this.srcDOM.childNodes[1] : this.srcDOM.firstChild;
            
            // begin processing the DOM recursively
            var resultDOM = this.traverseSourceDOM(XMLRoot);
            if (false === resultDOM) {
                GM_log('Could not process controls.');
                return;
            };
            
            // insert resultDOM into document
            // be careful not to use resultDOM.childNodes.length directly in the
            // loop since it will decrease when you move the elements!
            var len = resultDOM.childNodes.length;
            for (var i = 0; i < len; ++i) {
                this.editorElement.insertPosition.appendChild(resultDOM.firstChild);
            };
        },
        
        // this method will return false when element is not an element node or if no
        // specific handler could be found for that element, otherwise the processed
        // element is returned
        traverseSourceDOM : function(DOMNode) {
            try {
                // ignore non-element nodes
                if (Node.ELEMENT_NODE !== DOMNode.nodeType) {
                    return false;
                };
                // if no handler for current element available, continue
                // yes, this is one of the few meaningful purposes for eval()
                if (typeof CtrlHandlers[DOMNode.nodeName.toLowerCase()] == 'undefined') {
                    GM_log('Could not find handler for element "' + DOMNode.nodeName.toLowerCase() + '", ignoring it.');
                    return false;
                };
                
                return CtrlHandlers[DOMNode.nodeName.toLowerCase()](DOMNode);
            } catch (ex) {
                GM_log('Error processing DOM! Message: ' + ex);
                return false;
            };
        }
    };
    
    
    
    /**
     * Part V: Control handlers for processing the control types like menustrip, section, button, select etc.
     * Control handlers have the the lowercase name of the element they shall process.
     * 
     * NOTE: it's each control handler's responsibility to check for child nodes and to append them.
     * This will give you the ability to control the processing of child nodes!
     * The return value must always be the resulting DOM.
     */
    
    var CtrlHandlers = {
        
        // ROOT NODE, DON'T MODIFY THIS CONTROL HANDLER!
        editoroverlay : function(element) {
            // it's irrelevant which (block level) element it is, it's just a root
            // container to which all other elements will be appended:
            var resultDOM = document.createElement('div');
            for (var i = 0; i < element.childNodes.length; ++i) {
                var processed = editorMod.traverseSourceDOM(element.childNodes[i]);
                if (false !== processed) {
                    resultDOM.appendChild(processed);
                };
            };
            
            return resultDOM;
        },
        
        // menustrips
        menustrip : function(element) {
            var resultDOM = Hlp_createTableStructure();
            for (var i = 0; i < element.childNodes.length; ++i) {
                var td        = document.createElement('td');
                var processed = editorMod.traverseSourceDOM(element.childNodes[i]);
                if (false !== processed) {
                    td.appendChild(processed);
                    resultDOM.getElementsByTagName('tr')[0].appendChild(td);
                };
            };
            return resultDOM;
        },
        
        // sections
        section : function(element) {
            var resultDOM   = null;
            var sectionType = element.getAttribute('type');
            
            // be generic to make it easy to implement other section types in future
            switch (sectionType) {
                case 'fieldset':
                    resultDOM = document.createElement(sectionType);
                    resultDOM.setAttribute('class', 'fieldseteditor');
                    if (element.getAttribute('legend')) {
                        var legend = document.createElement('legend')
                        legend.appendChild(document.createTextNode(element.getAttribute('legend')));
                        resultDOM.appendChild(legend);
                    };
                    break;
                
                default:
                    resultDOM = document.createElement('div');
            };
            
            
            resultDOM.appendChild(Hlp_createTableStructure());
            
            for (var i = 0; i < element.childNodes.length; ++i) {
                var td        = document.createElement('td');
                var processed = editorMod.traverseSourceDOM(element.childNodes[i]);
                if (false !== processed) {
                    td.appendChild(processed);
                    resultDOM.getElementsByTagName('tr')[0].appendChild(td);
                };
            };
            return resultDOM;
        },
        
        // buttons
        button : function(element) {
            var resultDOM = document.createElement('div');
            
            // parse parameters
            var paramNodes = element.getElementsByTagName('param');
            var params     = {
                'url'          : null,
                'text'         : null,
                'height'       : null,
                'width'        : null,
                'insertbefore' : null,
                'insertafter'  : null
            };
            for (var i = 0; i < paramNodes.length; ++i) {
                params[paramNodes[i].getAttribute('name').toLowerCase()] = paramNodes[i].getAttribute('value');
            };
            
            if (typeof params['text'] == 'undefined') {
                GM_log('Could not process button since no parameter "text" was specified');
                return;
            };
            
            if (params.url !== null) {
                // image button
                resultDOM.setAttribute('class', 'imagebutton');
                var img = document.createElement('img');
                
                if (params.height !== null) {
                    img.setAttribute('height', parseInt(params.height));
                };
                if (params.width !== null) {
                    img.setAttribute('width', parseInt(params.width));
                };
                
                img.setAttribute('src',   params.url);
                img.setAttribute('alt',   params.text);
                img.setAttribute('title', params.text);
                resultDOM.appendChild(img);
            } else {
                // text button
                resultDOM.appendChild(document.createTextNode(params.text));
            };
            
            if (params.insertbefore !== null) {
                resultDOM.setAttribute('vbmod-insertBefore', params.insertbefore);
            } else {
                resultDOM.setAttribute('vbmod-insertBefore', '');
            };
            if (params.insertafter !== null) {
                resultDOM.setAttribute('vbmod-insertAfter', params.insertafter);
            } else {
                resultDOM.setAttribute('vbmod-insertAfter', '');
            };
            
            // set script if specified
            var scriptNodes = element.getElementsByTagName('script');
            if (typeof scriptNodes[0] != 'undefined') {
                resultDOM.setAttribute('vbmod-script', scriptNodes[0].firstChild.nodeValue);
            };
            
            Hlp_assignStyles(resultDOM, {
                'border'                        : 'medium none',
                'cursor'                        : 'default',
                'padding'                       : '1px',
                'background'                    : 'rgb(225, 225, 226) none repeat scroll 0% 0%',
                '-moz-background-clip'          : 'border',
                '-moz-background-origin'        : 'paddingm',
                '-moz-background-inline-policy' : 'continuous',
                'color'                         : 'rgb(0, 0, 0)'
            });
            
            // hover events
            resultDOM.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);
            resultDOM.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);
            
            // set editor information to make more than one editor at once working
            resultDOM.setAttribute('vbmod-editorId', editorMod.editorElement.element.getAttribute('id'));
            
            // click event
            Hlp_registerActionEvent('click', resultDOM);
            
            return resultDOM;
        },
        
        // selects
        select : function(element) {
            var resultDOM = document.createElement('select');
            
            var options = element.getElementsByTagName('option');
            for (var i = 0; i < options.length; ++i) {
                var opt = document.createElement('option');
                var params = {
                    'text'         : null,
                    'insertbefore' : null,
                    'insertafter'  : null
                };
                
                // process paramters
                var paramNodes = options[i].getElementsByTagName('param');
                for (var paramCnt = 0; paramCnt < paramNodes.length; ++paramCnt) {
                    params[paramNodes[paramCnt].getAttribute('name').toLowerCase()] = paramNodes[paramCnt].getAttribute('value');
                };
                if (typeof params['text'] == 'undefined') {
                    GM_log('Could not process option since no parameter "text" was specified');
                    return;
                };
                
                if (params.insertbefore !== null) {
                    resultDOM.setAttribute('vbmod-insertBefore', params.insertbefore);
                } else {
                    resultDOM.setAttribute('vbmod-insertBefore', '');
                };
                if (params.insertafter !== null) {
                    resultDOM.setAttribute('vbmod-insertAfter', params.insertafter);
                } else {
                    resultDOM.setAttribute('vbmod-insertAfter', '');
                };
                
                opt.setAttribute('vbmod-insertbefore', params.insertbefore);
                opt.setAttribute('vbmod-insertafter',  params.insertafter);
                
                var scriptNodes = options[i].getElementsByTagName('script');
                if (typeof scriptNodes[0] != 'undefined') {
                    opt.setAttribute('vbmod-script', scriptNodes[0].firstChild.nodeValue);
                };
                
                opt.appendChild(document.createTextNode(params.text));
                resultDOM.appendChild(opt);
            };
            
            // set editor information to make more than one editor at once working
            resultDOM.setAttribute('vbmod-editorId', editorMod.editorElement.element.getAttribute('id'));
            
            // change event
            Hlp_registerActionEvent('change', resultDOM);
            
            return resultDOM;
        }
    };
    
    
    
    /**
     * Part VI: 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;
    };
    
    // add click event listener to performan the defined action for the given control element
    function Hlp_registerActionEvent(event, element) {
        element.addEventListener(event, function() {
            var script = null;
            
            // if select element
            if (event == 'change') {
                var insBefore = this.options[this.selectedIndex].getAttribute('vbmod-insertbefore').replace(/\\n/g, '\n');
                var insAfter  = this.options[this.selectedIndex].getAttribute('vbmod-insertafter').replace(/\\n/g, '\n');
                if (this.options[this.selectedIndex].hasAttribute('vbmod-script')) {
                    script = this.options[this.selectedIndex].getAttribute('vbmod-script');
                };
            } else {
                var insBefore = this.getAttribute('vbmod-insertbefore').replace(/\\n/g, '\n');
                var insAfter  = this.getAttribute('vbmod-insertafter').replace(/\\n/g, '\n');
                if (this.hasAttribute('vbmod-script')) {
                    script = this.getAttribute('vbmod-script');
                };
            };
            
            var editorId = this.getAttribute('vbmod-editorId');
            
            if (script !== null) {
                try {
                    var returnValues = eval('(function() { ' + script + ' })();');
                    
                    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);
                };
            };
            
            Hlp_insertText(insBefore, insAfter, editorId);
        }, true);
    };
    
    // insert text into specified editor
    function Hlp_insertText(startTag, endTag, editorId) {
        if (!editorId) {
            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;
    };
    
    
    /**
     * Part VI: set event listener for quick editors
     */
    var vbMod_quickEditEventHandler = function() {
        if (document.getElementById('vB_Editor_QE_' + editorMod.editorElement.editCounter + '_controls')) {
            editorMod.findEditor(true);
            editorMod.processButtons(true);
            // increase counter for next quick editor
            ++editorMod.editorElement.editCounter;
        };
    };
    
    document.addEventListener('DOMSubtreeModified', function() {
        // Workaround for GreaseMonkey bug
        setTimeout(vbMod_quickEditEventHandler, 0);
    }, true);
    
    
    /**
     * Part VIII: initialization
     */
    i18n.setLocale('de-DE');
    editorMod.processButtons();
    Refining Linux: “[url=http://www.refining-linux.org/archives/65/Performing-push-backups-Part-1-rdiff-backup/]Performing Push Backups – Part 1: rdiff-backup[/url]”

    Kommentar


    • #17
      Nur wir haben zu danken!
      [COLOR="#F5F5FF"]--[/COLOR]
      [COLOR="Gray"][SIZE="6"][FONT="Georgia"][B]^^ O.O[/B][/FONT] [/SIZE]
      „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
      [URL="http://www.php.de/javascript-ajax-und-mehr/107400-draggable-sorttable-setattribute.html#post788799"][B]Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“[/B][/URL][/COLOR]
      [COLOR="#F5F5FF"]
      --[/COLOR]

      Kommentar


      • #18
        Hi again,

        Code in #16 ist nochmal durch mich aktualisiert worden. Habe noch eine überflüssige Codestelle entfernt, die manchmal zu Problemen mit dem Quickeditor führte.
        Refining Linux: “[url=http://www.refining-linux.org/archives/65/Performing-push-backups-Part-1-rdiff-backup/]Performing Push Backups – Part 1: rdiff-backup[/url]”

        Kommentar


        • #19
          Argh, schon wieder ein Update. Es gab einige Konflikte mit der Quickbearbeitenfunktion von vBulletin und dem Einfügen der Menustrips in den Quickeditor, wenn der Beitrag frisch geschrieben und von vBulletin dann per JavaScript angehängt wurde. Ich habe den Code in #16 deshalb nochmal geupdatet und konnte dafür den entsprechenden Event-Code extrem kürzen und vereinfachen. Er sollte jetzt zuverlässig funktionieren.
          Refining Linux: “[url=http://www.refining-linux.org/archives/65/Performing-push-backups-Part-1-rdiff-backup/]Performing Push Backups – Part 1: rdiff-backup[/url]”

          Kommentar


          • #20
            Cool, das hatte ich auch schon gemerkt. Bin ich ja mal gespannt.

            [edit] 00:01 - Ist schon wieder Adventszeit?
            [COLOR="#F5F5FF"]--[/COLOR]
            [COLOR="Gray"][SIZE="6"][FONT="Georgia"][B]^^ O.O[/B][/FONT] [/SIZE]
            „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
            [URL="http://www.php.de/javascript-ajax-und-mehr/107400-draggable-sorttable-setattribute.html#post788799"][B]Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“[/B][/URL][/COLOR]
            [COLOR="#F5F5FF"]
            --[/COLOR]

            Kommentar


            • #21
              Hui, du bist aber schnell. Aber stopp, der Code war noch nicht ganz sauber. Jetzt aber.
              Und du hast den Thread angepinnt, deshalb habe ich ihn so lange weiter unten gesucht.

              [edit] 00:01 - Ist schon wieder Adventszeit?
              Öhh, nö erstmal will ich Sommer haben.
              Refining Linux: “[url=http://www.refining-linux.org/archives/65/Performing-push-backups-Part-1-rdiff-backup/]Performing Push Backups – Part 1: rdiff-backup[/url]”

              Kommentar


              • #22
                Ich weiß nich, ich bin wohl zu blöd dafür.
                Also, ich hab jetzt mehrfach versucht das zu installieren. Ohne Erfolg.
                Anfangs ging es noch relativ problemlos, aber die Funktion Benutzerskript-Befehle wurde nach dem Neustart nicht freigeschaltet.
                Jetzt geht nur mein Editor auf wenn ich über den Dialog "Neues Benutzerskript" zum Teil komme, wo ich die Datei auswählen kann.
                Wenn ich mit dem Firefox die Datei öffne sehe ich nur den Quelltext, kein Dialog von GM.
                Ich versuche mal GM neu zu installieren.
                Edit: Okay, konnte jetzt auch wieder das .js File auswählen, danach ging dann aber wieder ungewollt der Editor auf und ich kann immer noch keine Befehle ausführen wenn ich rechts auf das GM Symbol klicke.

                Kommentar


                • #23
                  Du hast es bestimmt richtig gemacht, ich schreibs trotzdem noch mal für alle anderen.
                  1. Oben den Scriptcode in Zwischenablage kopieren
                  2. Greasemonkey installieren. Browser (Firefox!) neu starten.
                  3. Unten rechts in der Leiste Rechtsklick auf den Affenkopp
                  4. „Neues Benutzerscript“
                  5. Beliebigen Namen vergeben, bei „auf diese Seite anwenden“ das eintragen: http://www.php.de/*
                  6. Scriptcode aus der Zwischenablage ins leere Fenster pasten, Save.
                  7. Aus Posting #1 oben den xml-Code in Zwischenablage kopieren
                  8. Rechtsklick auf den Affenkopp, „Benutzerskript-Befehle“, „Add/Remove Buttons“
                  9. xml Code pasten, OK drücken

                  Nun sollte alles loofen (nach F5).
                  [COLOR="#F5F5FF"]--[/COLOR]
                  [COLOR="Gray"][SIZE="6"][FONT="Georgia"][B]^^ O.O[/B][/FONT] [/SIZE]
                  „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                  [URL="http://www.php.de/javascript-ajax-und-mehr/107400-draggable-sorttable-setattribute.html#post788799"][B]Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“[/B][/URL][/COLOR]
                  [COLOR="#F5F5FF"]
                  --[/COLOR]

                  Kommentar


                  • #24
                    Ich habe es mal bei userscripts.org hochgeladen: vBulletin Editor Mod for Greasemonkey
                    Dort einfach auf den Button „Install“ klicken und der Rest ist ähnlich wie beim Installieren eines Firefox-Add-ons.
                    In der Version dort habe ich übrigens noch ein paar Änderungen unter der Haube vorgenommen und die XML-Eingabe-Lightbox auch dahingehend angepasst, dass sie einen beim Abbruch nur noch mit einer Sicherheitsabfrage nervt, wenn man wirklich etwas geändert hat.
                    Refining Linux: “[url=http://www.refining-linux.org/archives/65/Performing-push-backups-Part-1-rdiff-backup/]Performing Push Backups – Part 1: rdiff-backup[/url]”

                    Kommentar


                    • #25
                      Kann man da auch ein Demo-XML mit dazu packen? Standalone macht das Script ja nix
                      [COLOR="#F5F5FF"]--[/COLOR]
                      [COLOR="Gray"][SIZE="6"][FONT="Georgia"][B]^^ O.O[/B][/FONT] [/SIZE]
                      „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                      [URL="http://www.php.de/javascript-ajax-und-mehr/107400-draggable-sorttable-setattribute.html#post788799"][B]Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“[/B][/URL][/COLOR]
                      [COLOR="#F5F5FF"]
                      --[/COLOR]

                      Kommentar


                      • #26
                        Das installieren von userscripts.org hat funktioniert. Danke!

                        Kommentar


                        • #27
                          Wollte auch noch eine Beschreibung anbringen, wenn ich dazu Zeit und Muße finde.
                          Ein Beispiel-XML-Code müsste aber kurz und in Snippet-Form vorliegen, weil ich außer dem Skript keine Dateien hochladen kann. Ich müsste es also in die Meta-Beschreibung mit reinnehmen. Ich kann ja vorerst mal als Script-Homepage diesen Thread verlinken.
                          Refining Linux: “[url=http://www.refining-linux.org/archives/65/Performing-push-backups-Part-1-rdiff-backup/]Performing Push Backups – Part 1: rdiff-backup[/url]”

                          Kommentar


                          • #28
                            So, habe die Skript-Seite dort ein wenig aufgepeppt und ein HOWTO geschrieben: vBulletin Editor Mod for Greasemonkey

                            Bitte das Skript von dort nochmal installieren. Ich habe noch den Bug gefixt, dass trotz Umstellung auf deutsche Sprache der Benutzer-Skript-Menü-Eintrag immer noch auf Englisch war.
                            Refining Linux: “[url=http://www.refining-linux.org/archives/65/Performing-push-backups-Part-1-rdiff-backup/]Performing Push Backups – Part 1: rdiff-backup[/url]”

                            Kommentar


                            • #29
                              Perfekt
                              Super Tool

                              Jetzt fehlt nur noch das KI-Plugin das automatisch den Post analysiert und die passenden Snippets einfügt, kombiniert mit einem Scoring wie bei Spamassasin, das ab einem gewissen Wert dem User automatisch eine Bewertung verpasst
                              [URL="http://www.robo47.net"]robo47.net[/URL] - Blog, Codeschnipsel und mehr
                              | :arrow: [URL="http://www.robo47.net/blog/192-Caching-Libraries-and-Opcode-Caches-in-php-An-Overview"]Caching-Klassen und Opcode Caches in php[/URL] | :arrow: [URL="http://www.robo47.net/components"]Robo47 Components - PHP Library extending Zend Framework[/URL]

                              Kommentar


                              • #30

                                Mach doch. Schreibe dir deinen eigenen Control Handler. Das Skript ist gut erweiterbar.
                                Ich schreibe gerade ein wenig Dokumentation. Die Control Handler kommen als nächstes. Hier eine Übersicht der bisherigen Dokumentation: Discuss vBulletin Editor Mod &ndash; Userscripts.org
                                Refining Linux: “[url=http://www.refining-linux.org/archives/65/Performing-push-backups-Part-1-rdiff-backup/]Performing Push Backups – Part 1: rdiff-backup[/url]”

                                Kommentar

                                Lädt...
                                X