Why is my svg image not found while the url is correct? - html

I'm using https://identicon-api.herokuapp.com/ to embed identicons in my page. You can choose either SVG or PNG. PNG works just fine, but for performance reasons, I want to use SVG. But when I use SVGs, the image isn't found, and the alt-text is displayed.
Nevertheless, the URL is valid, and when I open the image in a new tab, it's rendered correctly.
<img
v-if="iconsenabled"
style="max-width:1.75em"
:src="'https://identicon-api.herokuapp.com/'+e.author+'/2000?format=svg'"
:alt="e.author+`'s identcon.`"
:title="e.author+`'s identicon. Toggle 'show icons' to see the name instead`"
/>
(BTW, Yes, I'm using Vue, but that doesn't affect anything)

The SVG has an incorrect MIME type set by the server. <img> requires the MIME type to be image/svg+xml, but https://identicon-api.herokuapp.com/ currently sets it to text/html, which causes a loading error:
For reference, here's a sample SVG with the proper MIME type that renders correctly in an <img>:
<img src="https://upload.wikimedia.org/wikipedia/commons/4/42/Sample-image.svg" width="200">
As a workaround, you could fetch the SVG, convert it to a base64 string, and use that as a data URL:
<img :src="'data:image/svg+xml;base64,' + __SVG_BASE64__">
Example:
new Vue({
el: '#app',
data: () => ({
myImgUrl: ''
}),
mounted() {
fetch('https://identicon-api.herokuapp.com/tony19/2000?format=svg')
.then(resp => resp.text())
.then(text => this.myImgUrl = 'data:image/svg+xml;base64,' + btoa(text))
}
})
<script src="https://unpkg.com/vue#2.6.12"></script>
<div id="app">
<img :src="myImgUrl" width="200" height="200">
</div>

Related

How to use Base64 Encoded Image as img tag's source?

now, I am make thumbnail pages using BASE64.
I store Image on server, and call them back as Base64 on client.
I want use these Base 64 encoded Imgs as src.
It it work well
. but, I got an err like that
GET http://localhost:8080/%7B%7Bitem.THUMBNAIL%7D%7D 404
what is problem? and it is proper way to use base64 as src without any convert?
here is my Source
Script
$http.get( "app/dashboard/recentWithInfo").then( function( rtn) {
rtn.data.map( item => {
if( item.THUMBNAIL){
item.THUMBNAIL = "data:image/png;base64," +item.THUMBNAIL.body;
}
})
$scope.items = rtn.data;
});
HTML
<img class="block-thumbnail-img" ng-if="item.THUMBNAIL != null" src="{{item.THUMBNAIL}}">
<h2 ng-if="item.THUMBNAIL == null" style="color:#ccc"> No THUMBNAIL</h2>
Additionally, I use Springboot and AngularJS.
Thanks in advance!
Yes you can use base64 images but make your the images are small and less in no.. below is a basic code where base64 images are called into html pages and rendered
<div>
<p>Taken from wikpedia</p>
<img src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />
</div>
check the fiddle http://jsfiddle.net/hpP45/

How to set filename for base64 rendered pdf using object tag?

Well I am using the following code to render a PDF that is returned from a webservice as base64 string.
<html>
<object data="data:application/pdf;base64,{!pdfStampingResponse.pdfBase64}" type="application/pdf" width="100%" class="internal">
<param name="view" value="fitH" />
</object>
</html>
This works well but I want to set the download filename when user tries to save the file. Somehow I am unable to find a working solution. Any idea how to do this ?
please try this
const FILE_NAME = 'myfile.pdf';
const file_header = ';headers=filename';
fetch('https:your-url/myfile.pdf?dl=0').then(r => r.blob())
.then(blob=>{
const f = new FileReader();
f.onload = () => myPdfViewer.src = f.result.replace(';', file_header + encodeURIComponent(FILE_NAME) + ';');
f.readAsDataURL(blob);
});
Then insert id myPdfViewer to an iframe.
I hope it can help.
You can use the following code syntax
<object data="data/test.pdf" type="application/pdf" width="300" height="200">
alt : test.pdf
</object>
Found this here.
Hope it helps.
Use download="yourfilename" in anchor tag.
The download attribute specifies that the target will be downloaded when a user clicks on the hyperlink.
PS:This attribute is only used if the href attribute is set.
Is there any way around this so that I can control the name?
No. You cannot control the name of a file stored at user local filesystem.
See here: https://stackoverflow.com/a/44061387/9913319

load image asynchronous

If I have an image tag like the following:
<img src="myimage.jpg" />
and if I add "async" to it:
<img async src="myimage.jpg" />
will the image load asynchronous?
The way to async load (lazy load) the content is to not set the 'src' attribute and then execute a script that loads the images once DOM-ready is launched.
<img data-lazysrc='http://www.amazingjokes.com/images/20140902-amazingjokes-title.png'/>
and with jQuery (or possible with plain JavaScript too) use below code (as suggested here):
<script>
function ReLoadImages(){
$('img[data-lazysrc]').each( function(){
//* set the img src from data-src
$( this ).attr( 'src', $( this ).attr( 'data-lazysrc' ) );
}
);
}
document.addEventListener('readystatechange', event => {
if (event.target.readyState === "interactive") { //or at "complete" if you want it to execute in the most last state of window.
ReLoadImages();
}
});
</script>
var img = new Image(),
url = "myimg.jpg",
container = document.getElementById("holder-div");
img.onload = function () { container.appendChild(img); };
img.src = url;
This would start loading an image as soon as you request it in-script, and whenever the image was done loading, it would grab and add the image to it.
There are lots of other ways of doing this...
This is just a dead-simple example of async loading of a single image.
But the moral is this:
For async loading to work, either load it in JavaScript and use the onload, or include the image tag on the page, without the src attribute (specify the width and height in HTML), and go back at some point, in JS, and set the image URL.
The modern way to do this is with the loading attribute for images and iframes.
Attribute: loading=lazy
This will defer loading of the content until the element reaches a calculated distance from the viewport (that just means, it's got quite likely that the user will scroll it into view).
<img src="defer.png" loading="lazy" alt="An Awesome Image" width="500" height="400">
Setting the attribute to lazy invokes the new behaviour.
This is already in Chromium since v76, but might not hit non-Chromium browsers until it goes through the usual specification shennanigans.
If you are going to defer loading using a script, it would be worth writing the image with the lazy attribute and polyfilling the behavior as opposed to working off of a class name, etc. That way, you can allow the native version to take over as it becomes available.
Forced Eager Loading
Automatic lazy loading may become a feature of lightweight browsing, in which case, you may want to do the inverse and force an image to load. You can use the same loading attribute with a value of eager to ask the browser to grab the image even if it might otherwise choose not to.
<img src="defer.png" loading="eager" alt="An Awesome Image" width="500" height="400">
Further reading
View the pull request for the WHATWG spec
Fallback JavaScript with notes about perhaps not using fallbacks
An alternate way to async load an image is by using Promise in javascript, which serves the purpose of doing things asynchronously.
function asyncImageLoader(url){
return new Promise( (resolve, reject) => {
var image = new Image()
image.src = url
image.onload = () => resolve(image)
image.onerror = () => reject(new Error('could not load image'))
})
}
// then use it like this
var image = asyncImageLoader(url)
image.then( res => {
console.log(res)
})
<img async src="myimage.jpg" />
The image tag doesnt supports any async attribute.
http://www.w3.org/TR/html5/embedded-content-0.html#the-img-element
While several other answers highlight ways to fetch images asynchronously, it may also be helpful to know that the <img /> tag supports an attribute that serves as a hint to the browser that may result in images being be decoded asynchronously. It doesn't appear to be supported by Internet Explorer.
<img src="myimage.jpg" decoding="async"/>
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Img#attr-decoding
https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decoding
https://github.com/whatwg/html/issues/1920
If you're using jQuery, I did something simple, yet effective, like this:
HTML
<div data-lazy-load-image="/Images/image-name.png" data-image-classname="pop-in"></div>
JavaScript
$(function () {
$("[data-lazy-load-image]").each(function (index, element) {
var img = new Image();
img.src = $(element).data("lazy-load-image");
if (typeof $(element).data("image-classname" !== "undefined"))
img.className = $(element).data("image-classname");
$(element).append(img);
});
});
CSS
#-webkit-keyframes pop-in {
0% { opacity: 0; -webkit-transform: scale(0.5); }
100% { opacity: 1; -webkit-transform: scale(1); }
}
#-moz-keyframes pop-in {
0% { opacity: 0; -moz-transform: scale(0.5); }
100% { opacity: 1; -moz-transform: scale(1); }
}
#keyframes pop-in {
0% { opacity: 0; transform: scale(0.5); }
100% { opacity: 1; transform: scale(1); }
}
You could extend this to include additional optional attributes for each image, but you get the idea.
This will wait until the DOM is ready, then dynamically (async) load the images into the element that you mark with the data-lazy-load-image attribute. I included the CSS to make the images "pop in" when they are loaded.
While #Norguard's example is quite simple and easy enought for an image or two, I have found echo.js pretty handy for lazy-loading, https://github.com/toddmotto/echo.
It does lazy-loading images with data-* attributes and comes with some neat other things too.
<img data-echo="img/photo.jpg">
<script src="dist/echo.js"></script>
<script>
echo.init();
</script>
I have used the following approach with jQuery.
First, don't use a "src" attribute in the image tag, but put your source into a different attribute, like this:
<img async-src="/mydirectory/myimage.jpg" />
Then, within the jQuery document-ready function, I use this code to copy the element's async-src to the element's actual src:
$("img[async-src]").each(function(index) {
$(this).attr("src", $(this).attr("async-src"));
});
Notes:
jQuery's .each function may process the tags in the sequence they are coded in the HTML/DOM, but image sizes and network issues may mean that images don't actually load sequentially. In other words, your third async-src image might visually appear onscreen before the first has finished loading.
If your page layout relies on the pixel dimensions of that image file — e.g. you're not defining the image's dimensions via tag attributes, CSS, or a parent element — then you may have to use a "src" attribute on the original file pointing to a blank white or clear GIF of the dimensions you want.
Finally, if you want to process some code after the async loading of the image — for example, to handle a fading effect or change a CSS tag relevant to the element — expand the jQuery like this:
$("img[async-src]").each(function(index) {
$(this).load(function() {
// code to run after loading
});
$(this).attr("src", $(this).attr("async-src"));
});
It might be too late of an answer but recently was facing the same issue and the "lighthouse" in the console suggested that I should follow what's mentioned here in the link:
enter link description here
Basically, I did the following as suggested and it works really well:
<script src="lazysizes.min.js" async></script>
<!-- Images End -->
</body>
You may download the lazysizes.min.js from https://raw.githubusercontent.com/aFarkas/lazysizes/gh-pages/lazysizes.min.js
and source it locally.
Then, add the class lazyload to images that should be lazy loaded. In addition, change the src attribute to data-src.
For example:
<img data-src="images/flower3.png" class="lazyload" alt="">
You may be wondering why it is necessary to change the src attribute to data-src. If this attribute is not changed, all the images will load immediately instead of being lazy-loaded. data-src is not an attribute that the browser recognizes, so when it encounters an image tag with this attribute, it doesn't load the image. In this case, that is a good thing, because it then allows the lazysizes script to decide when the image should be loaded, rather than the browser.
Visit the reference for better understanding.
Hopefully it'll be of help to someone :)
You can read more about lazyload attribute:
<img src="myimage.jpg" alt="some description" lazyload/> - with default values
or you can prioritize:
<img src="myimage.jpg" alt="some description" lazyload="1"/>
<img src="myimage.jpg" alt="some description" lazyload="2"/>

AngularJS ng-href and svg xlink

I'd like some input on using xml namespaced attributes with angular.
The problem is angular comes with a couple of directives to handle writing attributes such as href and src when angular has parsed the expresssions (otherwise the browser will try to load {{mymodel.myimage}} as a url)
https://github.com/angular/angular.js/blob/master/src/ng/directive/booleanAttrs.js#L329
The problem I'm facing is that I'm using angular to output svg together with D3 and since angular doesn't have a way to output xlink:href I was stuck.
I created a custom directive that outputs xlink:href
app.directive('ngXlinkHref', function () {
return {
priority: 99,
restrict: 'A',
link: function (scope, element, attr) {
var attrName = 'xlink:href';
attr.$observe('ngXlinkHref', function (value) {
if (!value)
return;
attr.$set(attrName, value);
});
}
};
});
Full demo: http://plnkr.co/edit/cMhGRh
But it seems that if I don't manually add xlink:href to the element, the svg image will not render.
Any suggestions on how to best handle xml namespaces / svg together with angular would be greatly appreciated.
You can use ng-attr-<some attribute>
ng-attr-xlink:href="{{xxx}}" works for me.
Note that you also need an empty xlink:href="" as initial value. – Derek Hsu
If, like me, you're looking for a way to add images to svg, you can do so adding:
xlink:href="" ng-href="{{ foo }}"
Example:
http://jsbin.com/sigoleya/1/edit?html,js,output
Where I found the solution:
https://github.com/angular/angular.js/issues/7697
I ran into a similar problem when trying to output a value for xlink:href that's tied to the model. Based on the user's chosen <option> in a <select> control, I was trying to show a dynamic SVG icon via the xlink:href attribute of the <use> element.
I found a thread about this in the GitHub Issues for AngularJS. Based on the discussion there, it appears that because a viable workaround exists, they've effectively tabled a fix by moving it to the Backlog milestone.
What ultimately worked for me was inspired by this JSBin:
http://jsbin.com/sigoleya/1/edit?html,js,output
Here's the code I used in my template:
<svg class="icon" data-ng-class="category.iconName">
<use xlink:href="" data-ng-href="{{'#' + category.iconName}}">
</svg>
Given a category.iconName of icon-music, for example, Angular sets the xlink:href dynamically to #icon-music, which references the <svg id="icon-music"> element further up on the same page.
As others have noted, what's key is setting a blank xlink:href="" attribute on the element where you call the ngHref directive. Attribute order does not seem to matter. Using ng-attr-xlink:href="{{xxx}}" (as mentioned in Derek Hsu's answer) did not work for me.
All of this assumes Angular 1.3.36.
I solved the same problem with the following modules:
Module for SVGs:
var app = angular.module('Svgs', []);
angular.forEach([
{ ngAttrName: 'ngXlinkHref', attrName: 'xlink:href' },
{ ngAttrName: 'ngWidth', attrName: 'width' },
{ ngAttrName: 'ngHeight', attrName: 'height' }
], function (pair) {
var ngAttrName = pair.ngAttrName;
var attrName = pair.attrName;
app.directive(ngAttrName, function (IeHelperSrv) {
return {
priority: 99,
link: function (scope, element, attrs) {
attrs.$observe(ngAttrName, function (value) {
if (!value) return;
attrs.$set(attrName, value);
if (IeHelperSrv.isIE) element.prop(attrName, value);
});
}
};
});
});
Module for IE detection:
angular.module('IeHelper', []).factory('IeHelperSrv', function () {
return {
isIE: checkForIE.isIE,
}
});
var checkForIE = {
init: function () {
this.isIE = (navigator.userAgent.indexOf('MSIE') != -1);
}
};
checkForIE.init();
HTML:
<!-- image has initial fake source, width and height to force it to render -->
<image xlink:href="~/Content/Empty.png" width="1" height="1"
ng-xlink-href="{{item.imageSrc}}"
ng-width="{{item.width}}" ng-height="{{item.height}}"
ng-cloak
/>
For anyone else having this problem due to Angular/Angular UI Router in HTML5 mode, I came up with a straightforward fix to enable svg sprite icons to work with their xlink:href attribute and the tag.
Gist is here: https://gist.github.com/planetflash/4d9d66e924aae95f7618c03f2aabd4a3
app.run(['$rootScope', '$window', function($rootScope, $window){
$rootScope.$on('$locationChangeSuccess', function(event){
$rootScope.absurl = $window.location.href;
});
<svg><use xlink:href="{{absurl+'#svgvID'}}"></use></svg>
I ran into this problem where I was using Ajax to load the svg spritesheet onto the page. If I had a on the page before the spritesheet was loaded, it would fail and would not resolve once the spritesheet was avaialble. Any added to the dom after the spritesheet was loaded were fine. I had to delay putting the items in the dom until after the spritesheet finished loading.
This only affected IOS. All other browsers didn't care about the order.
This took me more time than I would've wanted. Around 20-30 minutes.
If I understand correctly, any failed loading on image element will render that element useless in the future. I believe it's something similiar #GeekyMonkey is saying. If angular binding system has set xlink:href initially to null, Image element wont work anymore, even if we have valid value in the future.
Here is solution, notice how I have wrapped image element inside g element, using ng-if directive. That makes sure we will bind against image only when a correct value is available.
<g ng-if="vm.svgMap.background != null">
<image
ng-attr-xlink:href="{{vm.svgMap.background.image | trusted}}"
ng-attr-width="{{vm.svgMap.background.width}}"
ng-attr-height="{{vm.svgMap.background.width}}"
xlink:href=""
width="1"
height="1"
x="0"
y="0"></image>
</g>
As others said, the order of attributes are important as well. To ensure that angularJS allows us to bind image element, we'll also have to trust that resource, I've done it through filter (it's the one in xlink:href attribute):
(function() {
'use strict';
angular.module('myTool').filter('trusted', TrustedFilter);
function TrustedFilter($sce) {
return function(url) {
return $sce.trustAsResourceUrl(url);
};
};
}());

Image tags returned by KCfinder are incomplete on CKeditor

Image tags returned by KCfinder are incomplete on CKeditor and not displayed/saved correctly. Note that i am using an inline CKEditor and KCFinder for image upload.
Here are the integration codes:
ckeditor/config.js
config.filebrowserBrowseUrl = base_url+'/js/kcfinder/browse.php?type=files';
config.filebrowserImageBrowseUrl = base_url+'/js/kcfinder/browse.php?type=images';
config.filebrowserFlashBrowseUrl = base_url+'/js/kcfinder/browse.php?type=flash';
config.filebrowserUploadUrl = base_url+'/js/kcfinder/upload.php?type=files';
config.filebrowserImageUploadUrl = base_url+'/js/kcfinder/upload.php?type=images';
config.filebrowserFlashUploadUrl = base_url+'/js/kcfinder/upload.php?type=flash';
On page HTML
<div id="page_body" contenteditable="true" class="full">...</div>
On page JS
<script type="text/javascript">
CKEDITOR.disableAutoInline = true;
var editor = CKEDITOR.inline( 'page_body', {
on: {
focus: function(event){
var data = event.editor.getData();
alert(data);
},
blur: function( event ) {
var data = event.editor.getData();
var page_id = <?php echo $this->uri->segment(3) ?>;
var page_link =$("#page_link").val();
$.ajax({
type: 'POST',
url: '<?php echo site_url('admin/dashboard/ajaxChangePageData') ?>',
data: { page_id: page_id, page_body: data,page_link:page_link },
beforeSend:function(){},
success:function(data){},
error:function(){ alert("Error"); }
});
}
}
} );
</script>
Strange is that i can browse the server/upload without any error with KCFinder i can even select an image from the server and the image is shown successfully in the content. but the code width height info are not present after a reload. I figured that the html created for the image was incomplete
in source mode i see-
<img alt="" src="/gchalk/content/images/333(1).jpg" 300px; height: 224px;" />
The situation just gets worse if for the second time i make some changes to the div say add some text. The image is lost and its treated as text, the above piece of code is shown as
in source mode-
<img alt="" data-cke-saved-src="/gchalk/content/images/333(1).jpg" src="/gchalk/content/images/333(1).jpg" 300px;="" height:="" 224px;"="">
and it appears on browser/editor as -
<img alt="" data-cke-saved-src="/gchalk/content/images/333(1).jpg" src="/gchalk/content/images/333(1).jpg" 300px;="" height:="" 224px;"="">
I am tearing my hair for a day and cant find a way around. Please help me out to figure how to solve it.
Oh, and for the record the text is saved in MySQL as "TEXT" through the ajax post i am pretty sure its not a problem but still just saying!
I notice the image tag gets messed up in the default ckeditor(not inline) too.
Things that could effect the output of your code :
1- Magic Quotes when using PDO. if they are ON, turn them OFF in you php.ini! they are deprecated. Why am I telling you this? will because in your source mode you had 300px; height: 224px;" when you stored it and displayed it you had 300px;="" height:="" 224px;"=""
2- your CKeditor package. Try to download and reupload your Ckeditor (Update it to the last version if possible)
other than that, I do not see anything wrong with the code you have provided. Good luck!