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

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.

Related

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.

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

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'>");
})

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.

Laravel file manager standalone iframe to input

I don't know how can't I find any examples on this, like no one used it before..
I want to open file manager in iframe and on images click to insert image url to input. Their example opens new window...
I am using laravel file manager standalone button to change avatar image but by their docs I can do it like this:
<div class="input-group">
<span class="input-group-btn">
<a id="lfm" data-input="thumbnail" data-preview="holder" class="btn btn-primary">
<i class="fa fa-picture-o"></i> Choose
</a>
</span>
<input id="thumbnail" class="form-control" type="text" name="filepath">
</div>
<img id="holder" style="margin-top:15px;max-height:100px;">
And calling $('#lfm').filemanager('image');
Which works but it opens new window because this is .filemanager()
(function( $ ){
$.fn.filemanager = function(type, options) {
type = type || 'file';
this.on('click', function(e) {
var route_prefix = (options && options.prefix) ? options.prefix : '/laravel-filemanager';
localStorage.setItem('target_input', $(this).data('input'));
localStorage.setItem('target_preview', $(this).data('preview'));
window.open(route_prefix + '?type=' + type, 'FileManager', 'width=900,height=600');
window.SetUrl = function (url, file_path) {
//set the value of the desired input to image url
var target_input = $('#' + localStorage.getItem('target_input'));
target_input.val(file_path).trigger('change');
//set or change the preview image src
var target_preview = $('#' + localStorage.getItem('target_preview'));
target_preview.attr('src', url).trigger('change');
};
return false;
});
}
})(jQuery);
Now changing:
window.open(route_prefix + '?type=' + type, 'FileManager', 'width=900,height=600');
To:
$('iframe').attr('src', route_prefix + '?type=' + type);
Will append filemanager to iframe as I want but when I click on image inside iframe it opens image in new tab as it is setting new url but skipping the script?
I think that I could get image url if it was opening in iframe but it is not...
Do you maybe know how to do this?
Thanks
I found out answer for my needs, not finished one tho but it works as needed:
Open up script.js from vendor/..../js folder and change useFIle function if/else statement where it looks up are you using any editor (cke,mce,etc..) and if not it just opens image in new window.
I remove that option and added this:
// parent.document.getElementById(field_name).value = url;
var target_input = parent.document.getElementById(localStorage.getItem('target_input'));
target_input.value = url;
//set or change the preview image src
var target_preview = parent.document.getElementById(localStorage.getItem('target_preview'));
target_preview.src = url;
From my question you can see jquery-plugin for opening laravel-filemanager into iframe and adding elements to localstorage.
I used that elements from localstorage in iframe to append url in input and display image in holder.
Now I will change this a little bit, since I wan't to leave this script as it is for full manager page on that url. I will just add another field as uri to be able to say this url is opened by iframe and use someOtherFUnction instead of useFile function by default.

How to refresh only a image of a whole page, when the imagename is variabel?

This is my puzzle i'm struggeling with:
I have a website with a certain amount of images, and i'd like the images to be refreshed each say 20 seconds,
this is the code I wrote so far for that:
<IMG src="imgcam/mostasquare_1.jpg" border="1" name="refresh" id="img1">
<IMG src="imgcam/mriehelbypass_1.jpg" border="1" name="refresh" id="img2">
<SCRIPT language="JavaScript" type="text/javascript">
var t = 35 // Interval in Seconds
images = new Array('../imgcam/mostasquare_1.jpg','../imgcam/mriehelbypass_1.jpg'); //URLs of the Images
function Start() {
tmp = new Date();
tmp = "?"+tmp.getTime();
for (i=1;i<image.length;i++){
document.getElementById("img"+i).src = images[i]+tmp;
}
setTimeout("Start()", t*1000)
}
Start();
</SCRIPT>
And solely this works great,
But, here is the catch:
I also would like to force the browser to refresh/download all images when opening the page.
so therefor I appended a querystring with a random number (or time, or version, etc).
so that resulted in:
<img src="mostasquare_1.jpg80123123" alt="image1" />
However,
because I added the random number, the array has got the wrong values
how can I tackle this specific "catch22" problem?
bonus points: i'd also like to show a little text on top of the image(s) (floating with css or so?) which shows when the last refresh of the image took place.
Here you can find an example using jquery: http://codepen.io/anon/pen/waGbQg
You can keep original path inside a data-attribute and update src starting from it in this way:
$this.attr("src", $this.attr("data-original-image") + "?" + d.getTime());

Resources