How to cache svg (embedded as <object>), in browser - html

I have an angular2 application which consists of multiple components, which embeds ( param) different small svg files in its templates. The reason for this choice is that I need to interact with the svg and manipulate the inner DOM of the svg files. Also I want to refer to an svg file, and not use inline svg multiple places in the template, its cleaner in the component template.
My problem is that these svg files is not being cached in the browser, and when loading a page whith multiple components (which renders these svg files), I notice some small delay before the page is finished loading.
This is far from optimal, and Im considering going back to inline svg if I cant solve this issue.
My goal is to be able to have the components template point to an svg file, and when this component is loaded for the first time, it will not be sent from the server, but retrieved from browser cache. Hopefully this will solve the delayed loading issue I have.
I have allready tried defining an cache.manifest file in the root of my application (which defines the different svgs to be cached), but when the component loads, the server is still sending the svgs (and param.js) each time a component load.!
This is how I have structured one of the component template, which consists of the svg symbol, and when I click the svg symbol, I open a popup which should contain the same symbol:
<div>
<!--Header-->
<div>{{ name }}</div>
<!--Actual svg symbol Object-param style-->
<div class="symbolIcon"(mouseup)="onMouseUp()" (mousedown)="onMouseDown()" >
<object type="image/svg+xml" data="app/mySymbol.svg" >
<param name='Activate' value={{activate}} />
<param name='Status' value={{status}} />
</object>
</div>
</div>
<!--Placeholder for Popup-->
<modal-popup *ngIf="loadPopup" (command)="popupCmd($event);">
<!--Symbol to be placed on Popup (same as in template above)-->
<div class="modal-startstop-symbol">
<!--Place content here...injected into "ng-content" in child-->
<object type="image/svg+xml" data="app/mySymbol.svg" >
<param name='Activate' value={{activate}} />
<param name='Status' value={{status}} />
</object>
</div>
</modal-popup >

Related

Images aren't rendering when Blazor variable bound to style in <image> tag

I'm playing around with a basic Dot-Net web assembly application. In the application I'm displaying two images using two different image tags image and img. The size of the image is bound to a private variable Size. I've noticed a problem where images do not render in a specific scenario using the image tag.
Replication:
dotnet new blazorwasm
I downloaded the SVG from: Bootstrap icons, then I placed the SVG file in "wwwroot/Media/".
In index.razor I've updated the code as follows:
#page "/"
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<img src="Media/search.svg" alt="Bootstrap" width="#Size" height="#Size">
<image src="Media/search.svg" alt="Bootstrap" width="#Size" height="#Size"/>
#code
{
private static string Size => "75";
}
The result of running the above code shows only one image displaying
Through process of elimination, the image defined using the image tag is the problem here. If you tweak the code to use hardcoded values i.e.
<image src="Media/search.svg" alt="Bootstrap" width="75" height="75"/>
then the code works again as expected.
I'm aware that <image> is deprecated, but I'd like to understand if the reason the binding breaks the image displaying is due to the deprecation or something else?
Update
The generated HTML using the template is
<!--!--><div class="top-row px-4" b-vv8m6rf2se="">About</div>
<article class="content px-4" b-vv8m6rf2se=""><!--!--><!--!--><!--!--><!--!-->
<!--!--><h1 tabindex="-1">Hello, world!</h1>
Welcome to your new app.
<img src="Media/search.svg" alt="Bootstrap" width="75" height="75">
<image src="Media/search.svg" alt="Bootstrap" width="75" height="75"></image></article>
An interesting find, although of course not of any practical value, just use <img>.
I could easily reproduce this with a jpg image so it's not about svg.
Now for a speculative answer:
Blazor treats <image> like any other tag and the generated HTML looks like expected. But according to this answer,
The HTML5 parsing spec requires that the tag is mapped to the img element at the tree construction stage
This makes me think that when the complete tag is rendered just once it works fine, handling is up to the browser.
But after Blazor has filled in the #Size it will try to update the HTML it generated earlier. If the Browser really changed <image> to <img> internally then the JS Bridge will have trouble finding the element again and the updates fail.

Make <img> use cached result in multiple instances of Angular component

I have an Angular component called folder-browser which serves as a folder browser. It displays the folders in a vertical list, and when a folder is opened it displays folders within that folder if there are any:
Here is the HTML for this:
<div *ngFor="let element of folders">
<div class="folder" (click)="selectFolder(element)" [ngClass]="{'selected': checkSelected(element)}">
<div class="chevron-container">
<img class="chevron-icon" src="{{getChevronIcon(element)}}">
</div>
<img class="folder-icon" src="{{folderIcon}}" />
<span class="folder-name">{{element.name}}</span>
</div>
<div class="sub-folders" *ngIf="element.expanded">
<folder-browser [folders]="element.children"></folder-browser>
</div>
</div>
My question is about the two <img> elements (there are three distinct SVGs—the chevron img element uses either a down chevron or a right chevron). As you can see, these img elements are used many times; not only are they inside an *ngFor div, this folder-browser component is used recursively to display subfolders.
The src of these img elements points to a CDN. Looking at the network tab of Chrome dev tools, I can see that each folder-browser component that is initialized makes three calls to the CDN for the three image types. Additionally, every time a folder is opened and closed (which switches the chevron between facing down and right), the down and right chevron SVGs are loaded from the CDN.
Since there are only three different SVGs being used, I would like the browser to only load each one once and then use the cached image for each subsequent img element. This seems to happen to some extent, since only one request is made per image type when the component is initialized as opposed to however many folders are in the *ngIf. However, when initializing a new instance of the same component it would be nice if it would use the cached images since they are the same.
Is there a built-in way to do this?

object tag with svg populated with entire webpage

I'm trying to include an svg icon into my personal portfolio with the object tag(need to be animated). This is what happens when I do so:
Entire webpage populated within object tag for some reason.
My entire webpage gets shoved inside the object tag. I'm using Vuejs, here is a snippet of my template:
<template>
<div>
<p>Landing Page</p>
<object
type="image/svg+xml"
data="public/Images/logo/logo.svg"
/>
</div>
</template>
Any idea why this behaviour is occuring?
You could include your svg as an image instead
<img src="public/Images/logo/test.svg" />

TYPO3 DCE (Fluid): How to generate an SVG Object instead of an image tag?

Our TYPO3 users (editors) need to exchange / update SVG files to the TYPO3 website. The svg files are clickable, hence the <img> html tag does not work for them. We decided in favour of the <object> tag, with <img> fallback (Do I use <img>, <object>, or <embed> for SVG files?).
The Fluid code for the fronted is easy for generating normal img tags:
<f:layout name="Default" />
<f:section name="main">
<div class="container">
<f:for each="{dce:fal(field:'image1', contentObject:contentObject)}" as="fileReference" iteration="iterator">
<f:if condition="{iterator.isFirst}">
<f:image src="{fileReference.uid}" alt="" treatIdAsReference="1" />
</f:if>
</f:for>
</div>
</f:section>
However, according to FluidTYPO3 vhs ViewHelper for SVG Images?, I might be able to use fluid code like this:
<img src="{f:uri.image(src: 'uploads/tx_myext/{imgIcon}')}">
which, adapted to object, would be:
<object data="{f:uri.image(src: 'xxx')}" type="image/svg+xml">
<img src="{f:uri.image(src: 'xxx')}">
</object>
Unfortunately, I have no idea what to provide as src. {fileReference.uid} only inserts the unique id of the file (a number).
How can I convert the file id to the relative or absolute URI of the picture?
I think the viewhelper attribute treatIdAsReference is what you are looking for.
f:image as well as f:uri:image can handle Files and FileReferences.
It looks like you have a FileReference, so you should add the attribute with value 1
Here is an example with inline notation:
{f:uri.image(src: '{fileReference.uid}', treatIdAsReference:'1')}
The result of this is the path to your file, it can be used in regular HTML-Tags.

How to upload image in selenium webdriver.. element is not visible

ff.findElementByxpath(//object[# id='slPlugin2']).click();
is not recognizing the element.
And also suggest me the way to upload media through webdriver
<table class="imgTable photoTable" cellspacing="0">
<div id="fileUploadControl404" class="fileUpload t-toolbar t-grid-toolbar t-grid-top">
<object id="slPlugin2" width="117" height="32" data="data:application/x-silverlight," type="application/x-silverlight">
<param value="/LMM/ClientBin/FileUpload.xap" name="source">
<param value="Url =https://lmmwipqa.blob.core.windows.net/uploads?se=2013-12-28T07%3A18%3A43Z&sr=c&sp=w&sig=fxuPdwl4huKRISO%2BCPdZIQxh0i5cdnGjWKO8okj2O34%3D, Parent =fileUploadControl404, Caption =Add Photo" name="initParams">
</object>
</div>
//object[# id='slPlugin2']
The above parameter should be within double quotes,i.e., a string should be passed as parameter to findElementByXPath().
The required statement can be rewritten as follows :
ff.findElementByXPath("//object[#id='slPlugin2']").click();
With respect to clicking on invisible elements, the following statement can be used :
(Note : This assumes the page has jQuery on it)
((JavascriptExecutor)driver).executeScript("$('selector_of_element').click();");
For file upload you can refer this.
I think, ff.findElementById("slPlugin2") would be more shorter way to find the element,
but, anyway unfortunatelly, WebDriver will be not be able to handle the elements
inside the Silverlight embeded app.
I'd recomend to get the parent div: ff.findElementById("fileUploadControl404")
Get its coordinates with .getLocation();
Use Java Robot
or Sikuli in order to manipulate the embeded control.