Using d3 data properties to set inner HTML to an img link - image

I'd like to be able to pass in an img src to inner html in a web application I'm building.
Here's an example of one item in my data:
{"ArtistImage": "https://photos.bandsintown.com/thumb/8697643.jpeg", "Address": "7000 Coliseum Wy, Oakland, CA 94621", "Artist": "Shawn Mendes"}
And the HTML I'm trying to insert the image:
<li>
<a id="test" href="#">Image</a>
</li>
And the JavaScript to dynamically change the inner HTML based on which data point I'm hovering over.
d3.selectAll(".events")
.on("mouseover", function(d) {
document.getElementById("test").innerHTML = "<img src=\"d.ArtistImage\" width=\"400px\" height=\"150px\">";
})
But it's reading a 404 error, image not found. How to I get this bit of JavaScript to pass the link in d.ArtistImage as a string to the inner HTML?

When you do this...
"<img src=\"d.ArtistImage\" width=\"400px\" height=\"150px\">"
... you are saying that the src of that image is literally d.ArtistImage, which is clearly incorrect.
You can do it easily with template literals. Or simply concatenating the strings:
"<img src='" + d.ArtistImage + "' width='400px' height='150px'>"
Finally, you don't need to use document.getElementById in a D3 code. One could argue that document.getElementById is faster than a D3 selection (which internally uses document.querySelector), but the difference is not significant and, what's more important, this is not idiomatic. Just use a D3 selection with html, which uses innerHTML internally:
d3.selectAll(".events").on("mouseover", function(d) {
d3.select("#test").html("<img src='" + d.ArtistImage + "' width='400px' height='150px'>");
})

Related

EditorJS : Sanitze HTML in client the best way

I'm using editorJS with Strapi (back) and NextJS (front).
Acutally, I sanitize the data directly in the frontend with a custom parser.
It's working fine, but I've got an issue when I paste content from Word, it adds a span with some style tag.
This is the part when I transform the data from editorJS to a paragraph block
paragraph: function (e) {
return "<p>" + e.data.text + "</p>";
},
//e.data.text = <span style="font-size:11pt;font-family:Arial;>Example</span>
I want to get rid of all the style. What's the best method ?
Should I sanitize the HTML in the strapi or keep it like this in the front app ?

How can I couch the CKEditor inline output in custom surrounding HTML with custom CSS files?

So let's say that I have the following source in the CKEditor:
<p>This is my <b>description</b> content.</p>
When this is saved. I know that it will go into a content block on my web site, something like the following:
<html>
<head>
<link href="//styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="content">
<div id="heading">{{ heading }}</div>
<div id="description">{{ description }}</div>
</div>
</body>
</html>
And let's say that the file styles.css has the following rule:
#description p {
text-indent: 15px;
}
#description b {
font-size: larger;
}
What I would like to do is to be able to see, as I'm typing, what things are going to look like on the site. Now I'm sure this could be done piecemeal by inserting these styles into the editor manually, but that's not going to work, as our site styles are considerably more complex and vary depending on which site we are on. What I need to be able to do is surround what's in the editor with the tags below, so that what's in the CSS file will naturally take effect in the editor display, giving our editors a realistic expectation of what they will see once their stories are up on the site.
In short, I need something like this:
cke.before_code = '<html><head><link href="//styles.css" rel="stylesheet" type="text/css"></head><body><div id="content"><div id="description">';
cke.after_code = '</div></div></body></html>';
And then I would expect the output that would be seen to be this:
before_code + "whatever the editor is typing presently" + after_code
Hopefully all that's clear. If anyone has any tips as to how this might be accomplished, would much appreciate any pointers.
I was not able to find a way to integrate html / styling in the way that I had asked for above. And given the radio silence on this issue, I suspect that what I've asked for here may not be possible. I did, however, figure out a way to achieve the next best thing using the preview button. Depending on the item our editors are editing, clicking the preview button will now show an instant preview for that particular item, styled as if it were live on our sites. Here's a step-by-step for those interested.
First, assume we have the following to start:
CKEDITOR.replace('editor', config);
Second, We'll want to add the following to the config and place it before the line above so that the event is registered to the editor:
Object.assign(config, {
on: {
contentPreview: function(e) {
let match = e.data.dataValue.match(/<body[^>]*>((?:.|\s)*)<\/body>/),
before = '' +
'<html>' +
'<head>' +
'</head>' +
'<body>',
content = match[1],
after = '' +
'</body>' +
'</html>;
e.data.dataValue = before + content + after;
}
}
});
content will now contain whatever the user has entered in the editor. And by adding before, content, and after together, we end up with the web page that will be presented in the preview. Only now, the page is under our control, and we can make adjustments based on what page the editor is viewing, other fields on the page, and so on, and we can add in links to our site's live styles.
Let's say that I now want to add in Bootstrap and a link to my site's styling. And let's say I want to surround content with one type of container if an editor is working on a blog and another if he is working on a news story. In this case, I might do something like this:
Object.assign(config, {
on: {
contentPreview: function(e) {
let match = e.data.dataValue.match(/<body[^>]*>((?:.|\s)*)<\/body>/),
before = '' +
'<html>' +
'<head>' +
'<link href="//stackpath.bootstrapcdn.com/bootstrap/4.5.6/css/bootstrap.min.css" rel="stylesheet" type="text/css">' +
'<link href="//mylivesite.com/styles.css" rel="stylesheet" type="text/css">' +
'<script src="//mylivesite.com/scripts.js"></' + 'script>' +
'</head>' +
'<body>',
content = match[1],
after = '' +
'</body>' +
'</html>;
if (location.pathname.indexOf('blog') > -1)
content = '' +
'<div class="row blog">' +
'<div class="col-sm-8">' + content + '</div>' +
'<div class="col-sm-4">Blog Right Column Content</div>' +
'</div>';
else
content = '' +
'<div class="row news">' +
'<div class="col-sm-8">' + content + '</div>' +
'<div class="col-sm-4">News Right Column Content</div>' +
'</div>';
e.data.dataValue = before + content + after;
}
}
});
Now when the preview opens, it will have all the styling from the live site as well as bootstrap columns, so the editor can play with the browser and see how everything will look at various dimensions.
In a sense then, this is superior to just seeing styles in the editor as you type (although that still would be nice), since it allows editors to get a sense of what the content will look like in the context of the page on which it appears after styles have loaded and scripts executed. And if content will appear differently based upon which options the editor has selected, you can build the preview page dynamically based on those values prior to presenting the preview.
This was the solution I ended up with, and my people were very pleased with it, so I thought I would share.

MailChimp API - dynamic content - mc:repeatable + mc:edit

My email template has some intro text followed by a repeatable block [a picture + a button].
I would like to repeat this block some X times and each time have picture link and button link updated with new links.
Currently I am using this payload to edit one block, and it is working as intended. I have used this SO answer as a guideline.
var data = {
'template': {
'id': template_id,
'sections': {
'editbutton': '<a class="mcnButton " title="Get Profile" href="' + button1 + '" target="_blank" style="font-weight: bold;letter-spacing: normal;line-height: 100%;text-align: center;text-decoration: none;color: #FFFFFF;">GET DATA</a>',
'editimage': '<img alt="" src="' + image1 + '" width="564" style="max-width:564px; padding-bottom: 0; display: inline !important; vertical-align: bottom;" class="mcnImage">'
}
}
};
What I am struggling is repeating this block and updating image and button link.
I am working in Google Apps Script but I guess the problem is independence of language.
Any help would be appreciated.
Thanks.
I do not think you need to use the mc:repeatable or the mc:variant at all. Use the single mc:edit="editbutton_and_editimage_items_list" MailChimp tag. Put there dynamically generated HTML <ul><li> list with your actual data via sections part of the payload you sent to the API.
E.g. your sections.editbutton_and_editimage_items_list JSON item in your var data = {..} object above would look like:
<ul>
<li>
<a class="mcnButton " href="' + button1 + '" style="...">GET DATA</a></li>
<img alt="" src="' + image1 + '" width="564" style="..." class="mcnImage">
</li>
<!-- Repeat the LI with different data as needed --!>
</ul>
After you successfully set the template content of your yet-not-sent campaign with the data above, use the API to send the campaign.

Is it possible to turn all html images into links via javascript?

I want to turn every <img> into a link to itself (the file) via an external js file.
My thought process was that I could target all img elements, then grab the image src and place a link to it around the img element.
for example:
Turning this:
<img width="281" vspace="7" hspace="5" height="215" align="left" alt="img1" src="cits/images/image001.jpg"></img>
Into this:
<a href="cits/images/image001.jpg" target="_blank">
<img width="281" vspace="7" hspace="5" height="215" align="left" alt="img1" src="cits/images/image001.jpg"></img>
</a>
It looks like I can grab the img src as a variable as well as find the img element, but I'm not sure how I could go about adding the link around the img.
Grab all your images.
var images = document.getElementsByTagName('img');
Write a function that replaces the outerHTML of an image with new markup, including a link pointing to the src attribute of the image, which includes the old outerHTML of the image.
function makeLink(image){
image.outerHTML = '<a target="_blank" href="' + image.src + '">' + image.outerHTML + '</a>';
}
Loop through your images, and submit each one to the makeLink function.
for(var i = 0, l = images.length; i < l; ++i){
makeLink(images[i]);
};
Just in case you are using jQuery
$('img').each(function(ix, image){
$(image).wrap('<a target="_blank" href="' + $(image).attr('src') + '"></a>');
})
If you're willing to use jQuery, the code is very simple:
$("img").each(function () {
$(this).wrap($("<a target='_blank'/>").attr("href", $(this).attr("src"));
});
Otherwise you're gonna have to look into a raw JavaScript solution, which is a bit more elaborate. See #Barney's answer.

Images with razor asp.net mvc inside JS

I need to dynamically insert an image in my JS code. In my Razor template I have:
#section Includes {
<script type="text/javascript">
var imgPath = "#Url.Content("~/Content/img/")";
alert(imgPath);
</script>
}
Then in my JS I have:
insertImg = "";
if (response[i].someFlag == 'Y') {
insertImg = "<img src=\"" + imgPath + "/imgToInsert.gif\" width=\"6px\" height=\"10px\" />";
}
But it doesn't work - it will not find the image. The image is stored in /Content/img folder...
What am I doing wrong? I am guessing it is because it is mapping the image from Js script..looks like I will have to hardcode it?
Alert or console.log the following to see if there are too many slashes
" + imgPath + "/imgToInsert.gif"
It might be advantageous to use the MVC TagBuilder Class to build your image tags instead of using a string concatenations. Lets you build tags dynamically and makes sure they are well-formed. Most likely your tag is not well-formed.

Resources