javascriptejshexo

How can I modify the type(ld+json) value with javascript in html label?


I'm using javascript to modify the "application/ld+json" in html script label, but I cannot select the json value and change it with raw js.

hexo 3.9
os: Linux 4.4.0-18362-Microsoft linux x64
node: 13.0.1

<script id="myjsonid" type="application/ld+json">
    {
        "@context": "https://schema.org",
        "@type": "BlogPosting",
        "mainEntityOfPage": "<%- config.url + url_for(path) %>",
        "headline": "<%- page.title %>",
        "datePublished": "<%= page.date %>",
        "dateModified": "<%= page.updated %>",
        "image": "<%= page.thumbnail %>",
        "author": {
            "@type": "Person",
            "name": "<%= config.author %>",
            "image": {
                "@type": "ImageObject",
                "url": "<%= theme.img.avatar %>"
            },
            "description": "<%- theme.uiux.slogan %>"
        },
        "publisher": {
            "@type": "Organization",
            "name": "<%= config.title %>",
            "logo": {
                "@type": "ImageObject",
                "url": "<%= theme.head.high_res_favicon %>"
            }
        },
        "keywords": "<% if(page.tags && page.tags.each) { page.tags.each(function(tag) { %><%- tag.name + ',' %><% })} %><%= theme.head.keywords %>",
        "description": "<% if(page.description) { %><%= page.description %><% } else if(page.excerpt){ %><%= strip_html(page.excerpt).replace(/^s*/, '').replace(/s*$/, '') %><% } else if (config.description){ %><%= config.description %><% } %>"
    }
</script>
<script>
    roundsum = Math.round(Math.random()*"<%= theme.thumbnail.random_amount %>"+1);
    testvar = document.getElementById("myjsonid");
</script>

now I don't know what to do, do i miss some api documents?


Solution

  • firstChild is giving you a Text node with the text of the script. You can use its nodeValue property (spec, MDN) both to get and set the text:

    const script = document.getElementById("myjsonid");
    script.firstChild.nodeValue = '{"foo": 1}'; // Completely replace it
    console.log(script.firstChild.nodeValue);
    

    Live Example:

    const script = document.getElementById("myjsonid");
    script.firstChild.nodeValue = '{"foo": 1}'; // Completely replace it
    console.log(script.firstChild.nodeValue);
    <script id="myjsonid" type="application/ld+json">
        {
            "@context": "https://schema.org",
            "@type": "BlogPosting",
            "mainEntityOfPage": "<%- config.url + url_for(path) %>",
            "headline": "<%- page.title %>",
            "datePublished": "<%= page.date %>",
            "dateModified": "<%= page.updated %>",
            "image": "<%= page.thumbnail %>",
            "author": {
                "@type": "Person",
                "name": "<%= config.author %>",
                "image": {
                    "@type": "ImageObject",
                    "url": "<%= theme.img.avatar %>"
                },
                "description": "<%- theme.uiux.slogan %>"
            },
            "publisher": {
                "@type": "Organization",
                "name": "<%= config.title %>",
                "logo": {
                    "@type": "ImageObject",
                    "url": "<%= theme.head.high_res_favicon %>"
                }
            },
            "keywords": "<% if(page.tags && page.tags.each) { page.tags.each(function(tag) { %><%- tag.name + ',' %><% })} %><%= theme.head.keywords %>",
            "description": "<% if(page.description) { %><%= page.description %><% } else if(page.excerpt){ %><%= strip_html(page.excerpt).replace(/^s*/, '').replace(/s*$/, '') %><% } else if (config.description){ %><%= config.description %><% } %>"
        }
    </script>

    You could also use textContent (spec, MDN) or innerText (spec, MDN) on the script element itself:

    const script = document.getElementById("myjsonid");
    script.firstChild.nodeValue = '{}'; // Completely replace it
    console.log(script.firstChild.nodeValue);
    

    Live Example:

    const script = document.getElementById("myjsonid");
    script.textContent = '{"foo": 1}'; // Completely replace it
    console.log(script.firstChild.nodeValue);
    script.innerText = '{"foo": 2}'; // Completely replace it
    console.log(script.firstChild.nodeValue);
    <script id="myjsonid" type="application/ld+json">
        {
            "@context": "https://schema.org",
            "@type": "BlogPosting",
            "mainEntityOfPage": "<%- config.url + url_for(path) %>",
            "headline": "<%- page.title %>",
            "datePublished": "<%= page.date %>",
            "dateModified": "<%= page.updated %>",
            "image": "<%= page.thumbnail %>",
            "author": {
                "@type": "Person",
                "name": "<%= config.author %>",
                "image": {
                    "@type": "ImageObject",
                    "url": "<%= theme.img.avatar %>"
                },
                "description": "<%- theme.uiux.slogan %>"
            },
            "publisher": {
                "@type": "Organization",
                "name": "<%= config.title %>",
                "logo": {
                    "@type": "ImageObject",
                    "url": "<%= theme.head.high_res_favicon %>"
                }
            },
            "keywords": "<% if(page.tags && page.tags.each) { page.tags.each(function(tag) { %><%- tag.name + ',' %><% })} %><%= theme.head.keywords %>",
            "description": "<% if(page.description) { %><%= page.description %><% } else if(page.excerpt){ %><%= strip_html(page.excerpt).replace(/^s*/, '').replace(/s*$/, '') %><% } else if (config.description){ %><%= config.description %><% } %>"
        }
    </script>


    In a comment you've said you want to change one specific part of the structure. To do that, use JSON.parse on the string to get an object tree for the JSON, make your change in that tree, and then use JSON.stringify to get a JSON string to write back to the script element:

    const script = document.getElementById("myjsonid");
    const obj = JSON.parse(script.firstChild.nodeValue);
    obj.image = "***THIS IS THE UPDATE***";
    script.firstChild.nodeValue = JSON.stringify(obj);
    console.log(script.firstChild.nodeValue);
    

    Live Example:

    const script = document.getElementById("myjsonid");
    const obj = JSON.parse(script.firstChild.nodeValue);
    obj.image = "***THIS IS THE UPDATE***";
    script.firstChild.nodeValue = JSON.stringify(obj);
    console.log(script.firstChild.nodeValue);
    <script id="myjsonid" type="application/ld+json">
        {
            "@context": "https://schema.org",
            "@type": "BlogPosting",
            "mainEntityOfPage": "<%- config.url + url_for(path) %>",
            "headline": "<%- page.title %>",
            "datePublished": "<%= page.date %>",
            "dateModified": "<%= page.updated %>",
            "image": "<%= page.thumbnail %>",
            "author": {
                "@type": "Person",
                "name": "<%= config.author %>",
                "image": {
                    "@type": "ImageObject",
                    "url": "<%= theme.img.avatar %>"
                },
                "description": "<%- theme.uiux.slogan %>"
            },
            "publisher": {
                "@type": "Organization",
                "name": "<%= config.title %>",
                "logo": {
                    "@type": "ImageObject",
                    "url": "<%= theme.head.high_res_favicon %>"
                }
            },
            "keywords": "<% if(page.tags && page.tags.each) { page.tags.each(function(tag) { %><%- tag.name + ',' %><% })} %><%= theme.head.keywords %>",
            "description": "<% if(page.description) { %><%= page.description %><% } else if(page.excerpt){ %><%= strip_html(page.excerpt).replace(/^s*/, '').replace(/s*$/, '') %><% } else if (config.description){ %><%= config.description %><% } %>"
        }
    </script>