Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I replace plain text image URLs in textnodes with img elements using JavaScript?

I'm a complete newbie to JavaScript, and I'm trying to make a Greasemonkey script that replaces image links with the actual image (as well as do other stuff that I'll do later on).

So I thought I could use the following.

var imagelinks = [
    "http*://*/*.jpg",
    "http*://*/*.png",
    "http*://*/*.gif"
];

All I am trying to do is using JavasScript (and/or jQuery), replace raw URL text within a "post-list-content-element" element with the image that that URL links to. In this example I want to replace that URL with the actual image.

like image 295
Alex Avatar asked Jan 19 '23 01:01

Alex


2 Answers

Thanks for adding the example link to your question, it really helped. I've removed my previous confused efforts.

var items = document.getElementsByClassName('post-list-content-element');
[].forEach.call(items, function(item){
    item.innerHTML = item.innerHTML.replace(
            /http?:\/\/\S*?\.(jpg|png|gif)/g,
            '<img src=$&>');
});

A caveat: this assumes that there are no actual images already within your post-list-content-element divs.

Okay, here's a more general purpose version that only replaces within textnodes. I'll leave you to iron out the bugs :-)

var replaceInChildTextNodes = (function(){

    var eachChild, splits;

    eachChild = function(node, f){
        var children, parent = node;
        children = [].slice.apply(parent.childNodes);
        children.forEach(function(child){
            f(child, parent);
            eachChild(child, f);
        });
    };

    splits = function(s, regexp){
        var nonmatches=[], matches=[], i=0, j=0;
        while((match = regexp.exec(s))){
            j = match.index;
            nonmatches.push(s.substr(i, j-i));
            matches.push(match[0]);
            i = j + match[0].length;
            if(!regexp.global)
                break;
        }
        nonmatches.push(s.substr(i));
        return {nonmatches: nonmatches, matches: matches};
    };

    return function(nodes, regexp, replacer){
        [].forEach.call(nodes, function(node){
            eachChild(node, function(childNode, parent){
                var match, i=0, j=0, split, newNodes=[];
                if(childNode.nodeName === '#text'){
                    split = splits(childNode.nodeValue, regexp);
                    if(split.matches.length === 0)
                        return;
                    newNodes = [];
                    split.nonmatches.forEach(function(text, i){
                        if(text !== '')
                            newNodes.push(document.createTextNode(text));
                        if(split.matches[i])
                            newNodes.push(replacer(split.matches[i]));
                    });
                    newNodes.forEach(function(newNode){
                        parent.insertBefore(newNode, childNode);
                    });
                    parent.removeChild(childNode);
                }
            });
        });
    };
}());

Usage:

var parents = document.getElementsByClassName('post-list-content-element');
replaceInChildTextNodes(parents, /http?:\/\/\S*?\.(jpg|png|gif)/g, function(text){
    var img = document.createElement('img');
    img.src = text;
    return img;
});

It doesn't use String#split, so you don't need to worry about capturing groups in the regexp, and it respects the g flag.

Caveat: not cross-browser.

like image 181
14 revs Avatar answered Jan 29 '23 20:01

14 revs


Try this:

// ==UserScript==
// @name          your script
// @require       http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js
// ==/UserScript==
var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|].(gif|jpg|png))/ig;
$(".post-list-content-element").each(function(){
    $(this).html($(this).text().replace(exp,"<img src='$1' \\>"))
});
like image 23
Julien Bourdon Avatar answered Jan 29 '23 20:01

Julien Bourdon