Paste rich text into content-editable div and only keep bold and italics formatting

后端 未结 3 1311
礼貌的吻别
礼貌的吻别 2020-12-23 14:35

I want to paste some rich text which has different fonts, font sizes, font weights, etc. into a content-editable div and ONLY keep boldness and italics. Any ide

相关标签:
3条回答
  • 2020-12-23 15:14

    Let begin with your code :

    //on paste
    var text = (e.originalEvent || e).clipboardData.getData('text/plain')
    
    
    //html in clipboard are saved as Plain Unicode string , 
    
    getData('text/plain') //return data as string,
    
    //if MIME TYPE 'text/html' is used you will get data as html with style attributes
    
    // insert text
    
    document.execCommand('insertText', false, text);
    
    //this will simply insert the text to contenteditable div.
    
    //so there is no chance of knowing recieved text is bold / italics.
    

    (1) we must get data as html,to get style properties: fontWeight, fontStyle.

    (2) reduce html for needed style format,

    (3) append to contenteditable div.

    !important ::

    we depend on Clipboard API, to get data.

    it is not fully supported by newer browsers, please check links below:

    https://developer.mozilla.org/en-US/docs/Web/Reference/Events/paste

    http://caniuse.com/clipboard

    so in IE Browser it wont work as expected.

    the data format argument we pass in getData() is different in IE Browser:

    http://msdn.microsoft.com/en-us/library/ie/ms536436(v=vs.85).aspx

    so we get only plain string from getData() method, i checked in IE 9.0.8112.16421 ( not updated ) ,

    i am not aware of version IE 10, 11.

    I coded in a way, if getData("Html") supported in ie 10,11 code, requirements will get done.

    Code works : Like @Cristi did, get all html elements.

    iterate through them, instead of changing style attributes we use tags.

    tags for bold & tag for italics.

    Iterations are done asynchronously, because pasting large text content may hang browser.

    I had Tested in Chrome, Firefox.

    pasteArea.addEventListener('paste', function(e) {
    
        // prevent pasting text by default after event
        e.preventDefault(); 
    
        var clipboardData = {},
        rDataText,
        rDataHTML;
    
        clipboardData = e.clipboardData;
        rDataHTML = clipboardData.getData('text/html');
        rDataPText = clipboardData.getData('text/plain');
    
    
        if (rDataHTML && rDataHTML.trim().length != 0) {
    
            //Function Call to Handle HTML
    
            return false; // prevent returning text in clipboard
        }
    
        if (rDataPText && rDataPText.trim().length != 0) {
    
            //Function Call to Handle Plain String
    
            return false; // prevent returning text in clipboard
        }
    
    }, false);
    
    // Handle Plain Text
    function PlainTextHandler(pText) {
        // Remove Line breaks
        // append to contenteditable div - using range.insertNode()
        // document.execCommand();  had issue in ie9 so i didn't used it 
    }
    
    // Handle HTML
    function formatHtml(elem, complete) {
            var flag_italic = false;
            var flag_weight = false;
            var fontStyle;
            var fontWeight;
    
            if (elem.nodeType == 1) { // only pass html elements
    
                // get style in css 
                var CSSStyle = window.getComputedStyle(elem);
                fontStyle = CSSStyle.fontStyle;
                fontWeight = CSSStyle.fontWeight;
    
                // get style defined by inline
                var InlineStyle = elem.style;
                inlineFontStyle = InlineStyle['font-style'];
                inlineFontWeight = InlineStyle['font-weight'];
                if (inlineFontStyle && inlineFontStyle.trim() != '') fontStyle = inlineFontStyle;
                if (inlineFontWeight && inlineFontWeight.trim() != '') fontWeight = inlineFontWeight;
    
                // get style defined in MSword
                var msStyle = elem.getAttribute('style');
                if (/mso-bidi/.test(msStyle)) {
                    var MSStyleObj = {};
                    var styleStrArr = msStyle.split(";");
                    for (i = 0; i < styleStrArr.length; i++) {
                        var temp = styleStrArr[i].split(":");
                        MSStyleObj[temp[0]] = temp[1];
                    }
                    fontStyle = MSStyleObj['mso-bidi-font-style'];
                    fontWeight = MSStyleObj['mso-bidi-font-weight'];
                }
    
                if (fontStyle && fontStyle == 'italic') flag_italic = true; // flag true if italic
    
                if (fontWeight && (fontWeight == 'bold' || 600 <= (+fontWeight))) flag_weight = true;  // flag true if bold - 600 is semi bold
    
                // bold & italic are not applied via style
                // these styles are applied by appending contents in new tags string & bold
                if (flag_italic && flag_weight) {
                    var strong = document.createElement('strong');
                    var italic = document.createElement('i');
                    strong.appendChild(italic);
                    newtag = strong;
                } else {
                    if (flag_italic) {
                        newtag = document.createElement('i');
                    } else if (flag_weight) {
                        newtag = document.createElement('strong');
                    } else {
                        // remove un wanted attributes & element
                        var tagName = elem.tagName;
                        // strong are not skipped because, by creating new unwanted attributes will be removed
                        if (tagName == 'STRONG' || tagName == 'B') {
                            newtag = document.createElement('strong');
                        } else if (tagName == 'I') {
                            newtag = document.createElement('i');
                        } else {
                            newtag = document.createElement('span');
                        }
                    }
                }
    
                // content appended
                var elemHTML = elem.innerHTML;
                if (flag_italic && flag_weight) {
                    newtag.childNodes[0].innerHTML = elemHTML;
                } else {
                    newtag.innerHTML = elemHTML;
                }
    
                // curr element is replaced by new
                elem.parentNode.insertBefore(newtag, elem);
                elem.parentNode.removeChild(elem);
            }
            complete() // completed one iteration
        }
    

    Fiddle: http://jsfiddle.net/aslancods/d9cfF/7/

    0 讨论(0)
  • 2020-12-23 15:14

    I used this on my website for long time

    $(document).on('paste','#tesc', function() {
                     setTimeout(function() {
                            asd = strip_tags( $('#tesc').html(), '<b><b/><i></i>');
    
                            $('#tesc').html( asd );
                    },100);
    
            });
    
    function strip_tags (input, allowed) {
        /* http://kevin.vanzonneveld.net*/
    
        if ( input == undefined ) { return ''; }
    
        allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
        var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
            commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
        return input.replace(commentsAndPhpTags, '').replace(tags, function ($0, $1) {
            return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
        });
    }
    
    0 讨论(0)
  • 2020-12-23 15:16

    Here's a working demo: http://jsfiddle.net/SJR3H/7/

    $(document).ready(function(){
    
            $('[contenteditable]').on('paste',function(e) {
    
                e.preventDefault();
    
                var text = (e.originalEvent || e).clipboardData.getData('text/html') || prompt('Paste something..');
                var $result = $('<div></div>').append($(text));
    
                $(this).html($result.html());
    
                // replace all styles except bold and italic
                $.each($(this).find("*"), function(idx, val) {
    
                    var $item = $(val);
                    if ($item.length > 0){
                       var saveStyle = {
                            'font-weight': $item.css('font-weight'),
                            'font-style': $item.css('font-style')
                        };
                        $item.removeAttr('style')
                             .removeClass()
                             .css(saveStyle); 
                    }
                });
    
                // remove unnecesary tags (if paste from word)
                $(this).children('style').remove();
                $(this).children('meta').remove()
                $(this).children('link').remove();
    
            });
    
        });
    

    Later edit: http://jsfiddle.net/SJR3H/8/

    i added the following lines:

    $item.replaceWith(function(){
           return $("<span />", {html: $(this).html()});
    });
    

    It actually replaces all html tags with spans. There you can optionally choose to let some tags as they were in the original text (h1, p, etc), styling them as you desire.

    0 讨论(0)
提交回复
热议问题