I am currently using Jawr to compress and bundle my css, javascript and image files.
Jawr is currently converting all of the url() links in my css files, regardless whether they are images or not. For example:
#font-face {
font-family: 'NothingYouCouldSay';
src: url('../fonts/NothingYouCouldSay.eot') format('eot');
src: local("☺"), url('../fonts/NothingYouCouldSay.woff') format('woff'), url("../fonts/NothingYouCouldSay.otf") format("opentype"), url('../fonts/NothingYouCouldSay.ttf') format('truetype'), url('../fonts/NothingYouCouldSay.svg') format('svg');
font-weight: normal;
font-style: normal;
}
Jawr is converting all of the url() values, but then the resources cannot be found when the webserver is running, as I have configured the image servlet to listen only for *.png & *.jpg.
#font-face {
font-family: 'NothingYouCouldSay';
src: url('../../../cb1130234589/resources/fonts/NothingYouCouldSay.eot') format('eot');
src: local("☺"), url('../../../cb1130234589/resources/fonts/NothingYouCouldSay.woff') format('woff'), url("../../../cb1130234589/resources/fonts/NothingYouCouldSay.otf") format("opentype"), url('../../../cb1130234589/resources/fonts/NothingYouCouldSay.ttf') format('truetype'), url('../../../cb1130234589/resources/fonts/NothingYouCouldSay.svg') format('svg');
font-weight: normal;
font-style: normal;
}
If I add *.woff to the image servlet mapping, then the servlet complains that the mime type of the file is not understood.
Is there any way I can get Jawr to not process these particular particular URLs?
So, after trying a few different ideas, I ended up writing my own custom post processor to handle this. I reuse as much of the existing Jawr code as possible, which means it may be quite brittle if Jawr changes it's underlying code.
Anyway, here's what I wrote:
package com.bullethq.jawr.postprocessor;
import net.jawr.web.resource.FileNameUtils;
import net.jawr.web.resource.bundle.factory.util.PathNormalizer;
import net.jawr.web.resource.bundle.postprocess.BundleProcessingStatus;
import net.jawr.web.resource.bundle.postprocess.impl.CSSURLPathRewriterPostProcessor;
import net.jawr.web.resource.bundle.postprocess.impl.PostProcessorCssImageUrlRewriter;
import java.io.IOException;
public class CustomCssUrlPathRewriterPostProcessor extends CSSURLPathRewriterPostProcessor {
public static final String CUSTOM_URL_PATH_REWRITER = "customcsspathrewriter";
public CustomCssUrlPathRewriterPostProcessor() {
super(CUSTOM_URL_PATH_REWRITER);
}
// ========================================================================
// ========================================================================
// ========================================================================
#Override
protected PostProcessorCssImageUrlRewriter createImageUrlRewriter(BundleProcessingStatus status) {
return new CustomPostProcessorCssImageUrlRewriter(status);
}
// ========================================================================
// ========================================================================
// ========================================================================
public class CustomPostProcessorCssImageUrlRewriter extends PostProcessorCssImageUrlRewriter {
public CustomPostProcessorCssImageUrlRewriter(BundleProcessingStatus status) {
super(status);
}
// ========================================================================
// ========================================================================
// ========================================================================
#Override
protected String getUrlPath(String match, String originalPath, String newCssPath) throws IOException {
String url = match.substring(match.indexOf('(') + 1, match.lastIndexOf(')')).trim();
// Remove any quotes if necessary.
String quoteStr = "";
if (url.startsWith("'") || url.startsWith("\"")) {
quoteStr = String.valueOf(url.charAt(0));
url = url.substring(1, url.length() - 1);
}
// We now check if the url ends in a known image file extension
// If not, the url is ignored.
if (FileNameUtils.hasImageExtension(url)) {
return super.getUrlPath(match, originalPath, newCssPath);
} else {
// We need to rewrite the path, as any relative URLs will
// not resolve correctly if Jawr has changed the CSS path.
url = PathNormalizer.concatWebPath(originalPath, url);
url = PathNormalizer.getRelativeWebPath(PathNormalizer.getParentPath(newCssPath), url);
return "url(" + quoteStr + url + quoteStr + ")";
}
}
}
}
And then, you need to configure Jawr to use this custom post processor in jawr.properties:
jawr.custom.postprocessors.customcsspathrewriter.class=com.bullethq.jawr.postprocessor.CustomCssUrlPathRewriterPostProcessor
jawr.css.bundle.factory.filepostprocessors=customcsspathrewriter
Related
I want to display the images stored in database.
The database stores the path of the image. I want to retrieve the image using angular. How can i do that?
You need create a service to call API to get image URL ( i assume image stored in JSON file)
#Injectable()
export class ConfigService {
constructor(private http: HttpClient) { }
getData() {
return this.http.get('/assets/config.json');
}
}
Create component ts file to call service and return image url
export class AppComponent {
name = 'Test display image';
thumbnail: any;
constructor(private imageService: ConfigService, private sanitizer: DomSanitizer) { }
ngOnInit() {
this.imageService.getData()
.subscribe((baseImage : any) => {
let objectURL = baseImage.image;
this.thumbnail = objectURL;
});
}
}
Update HTML file to display image
<img width="100%" id="myimage" [src]='thumbnail' />
Demo: https://stackblitz.com/edit/display-imagepath-from-api
The Graph component is getting data (verified in console) but for some reason the page is still blank. I am not quit sure I understand how the map function works. This is the last piece I need to figure out to render this graph but for whatever reason I can't seem to get any graphics on the screen. The state of nodes in the console is:
{data: {action: [{action: "Changed", timestamp: 1499348050,…},…]}}
data:{action: [{action: "Changed", timestamp: 1499348050,…},…]}
action:[{action: "User Assist Changed", timestamp: 1499348050,…},…]
Graph Component:
import React, {Component} from 'react';
import * as d3 from "d3";
import {graphql} from 'react-apollo';
import getObjectsQuery from './Queries';
class Graph extends React.Component {
constructor(props) {
super(props);
this.state = { startTime:this.props.startTime,
endTime:this.props.endTime,
nodes:this.props.getObjectsQuery
}
//console.log('graph data:', this.props.data)
}
componentDidMount() {
console.log('nodes:', this.props.data)
this.force = d3.forceSimulation(this.props.data)
.force("charge",
d3.forceManyBody()
.strength(this.props.forceStrength)
)
.force("x", d3.forceX(this.props.width / 2))
.force("y", d3.forceY(this.props.height / 2));
this.force.on('tick', () => this.setState({nodes: this.props.data}));
console.log('setState:', this.props.data);
}
componentWillUnmount() {
this.force.stop();
}
render() {
// console.log('graph datas:', this.props.data)
return (
<svg width={this.props.width} height={this.props.height}>
{Object.keys(this.props.data).map((action, index) =>(
<circle r={action.action} cx={action.second} cy={action.obj} fill="red" key={index}/>
))}
</svg>
);
}//render
}//Component
export default graphql(getObjectsQuery,
{ options: (ownProps) => {
console.log(ownProps.startTime);
return ({ second: { startTime: ownProps.startTime,
endTime: ownProps.endTime
} })
} } )(Graph);
Graph.defaultProps = {
width: 300,
height: 300,
forceStrength: -10
};
If this.props.data.action is an array then it can be used directly in map:
{this.props.data.action.map((action,
but this.props.data.action (and even this.props.data?) can be undefined on start, first render
use some conditions in render to prevent errors, f.e.
{!this.props.data.loading && this.props.data.action.map((action,
Check if loading is present ... structure of props passed into component can be mapped differently by fn defined in config props property in graphql() (f.e. in case of conflict props names). Search for examples.
I am learning the Jersey web services, now I understood how GET and POST work :
#GET
#Produces("text/html")
public String getHandler() {
return "<h1>Get some REST!<h1>";
}
#POST
#Consumes("application/x-www-form-urlencoded")
#Produces("text/plain")
public String postHandler(String content) {
return content;
}
in Jersey Documentation for featching images it said :
#GET
#Path("/images/{image}")
#Produces("image/*")
public Response getImage(#PathParam("image") String image) {
if (!isSafeToOpenFile(image)) {
throw new IllegalArgumentException("Cannot open the image file.");
}
File f = new File(image);
if (!f.exists()) {
throw new WebApplicationException(404);
}
String mt = new MimetypesFileTypeMap().getContentType(f);
return Response.ok(f, mt).build();
}
I would appreciated if you can show me an example using the above code to fetch images from a folder in the server and post them in a html.
Thanks lot.
Here is a full example of a live gallery, based on REST services.
REST services (Jersey)
This service gives the content (filenames) of the image server directory (here C:\Temp\hotfolder).
// array of supported extensions
static final String[] EXTENSIONS = new String[] { "jpg", "jpeg", "gif", "png", "bmp" };
// filter to identify images based on their extensions
static final FilenameFilter IMAGE_FILTER = new FilenameFilter() {
#Override
public boolean accept(final File dir, final String name) {
for (final String ext : EXTENSIONS) {
if (name.endsWith("." + ext)) {
return (true);
}
}
return (false);
}
};
#GET
#Path("folderImages")
#Produces("text/json")
public Response getFolderImages(#QueryParam("lastknown") String lastknown)
{
//Gets the contents of the folder (reverse order : more recent first)
//see http://stackoverflow.com/questions/11300847/load-and-display-all-the-images-from-a-folder
File dir = new File("C:\\Temp\\hotfolder");
File [] files = dir.listFiles(IMAGE_FILTER);
Arrays.sort( files, new Comparator<File>() {
public int compare(File f1, File f2) {
if (f1.lastModified() > f2.lastModified()) {
return -1;
} else if (f1.lastModified() < f2.lastModified()) {
return +1;
} else {
return 0;
}
}
});
//Fills a list (from the more recent one, until the last known file)
ArrayList<String> newfiles = new ArrayList<String>();
for (File f : files)
{
if (lastknown!=null && f.getName().equals(lastknown))
break;
newfiles.add(f.getName());
}
//Answers the list as a JSON array (using google-gson, but could be done manually here)
return Response.status(Status.OK).entity(new Gson().toJson(newfiles)).type("text/json").build();
}
Also this is the image service, needed for rendering each image individually.
#GET
#Path("/images/{image}")
#Produces("image/*")
public Response getImage(#PathParam("image") String image) {
File f = new File("C:\\Temp\\hotfolder\\" + image);
if (!f.exists()) {
throw new WebApplicationException(404);
}
String mt = new MimetypesFileTypeMap().getContentType(f);
return Response.ok(f, mt).build();
}
gallery.html
Html, with a little help of JQuery. This HTML polls every 5 seconds, asking for service if there is new files (more recent) than the last file known. Et voilà!
You can notice we are using the jquery .prepend method to insert images dynamically at the beginning of the gallery div.
<html>
<head>
<title>Folder demo</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
<h1>Live gallery</h1>
<div id="gallery1" style="border:1px solid black;padding:10px;"></div>
<div id="info1"></div>
<script>
var counter = 0;
var lastknown = "";
function doPoll(){
$.get('rest/folderImages?lastknown='+lastknown, function(data) {
counter++;
$("#info1").html("<pre>Counter: " + counter + "<br>New files: " + data + "</pre>");
for (var i=data.length-1; i>=0; i--) {
$("#gallery1").prepend("<img src=\"rest/images/" + data[i] + "\" style=\"width:200px;height:200px\" />");
lastknown = data[i];
}
setTimeout(doPoll,5000);
});
}
$(document).ready( doPoll );
</script>
</body>
</html>
The Jersey example from documentation is clear enough to me. However, here is a simplified example without parameters (do simple to begin...)
#GET
#Path("/images/pet")
#Produces("image/*")
public Response getImage() {
File f = new File("C:\\\\Temp\\dog.jpg");
if (!f.exists()) {
throw new WebApplicationException(404);
}
String mt = new MimetypesFileTypeMap().getContentType(f);
return Response.ok(f, mt).build();
}
As my Jersey is configured as /rest/* path in the web.xml of the yourapp application, the image is accessible at the following address:
http://serverip:port/yourapp/rest/images/pet
You can try it directly this URL in the browser navigation bar (it is a REST image service, served as if it was a static image), or if you want it in a html page, you can use classic HTML:
<html>
<body>
<h1>Woof!</h1>
<img src="http://localhost:8080/myapp/rest/images/pet" />
</body>
</html>
Hope it helps.
EDIT
Okay that was too obvious. So you need to implement a method or service that gives the content of a directory with image file names in the given order you need (as a java List).
Using this List, you can build a html like this within a loop:
<html>
<body>
<h1>Several images</h1>
<img src="/yourapp/rest/images/last.jpg" /><br/>
<img src="/yourapp/rest/images/third.jpg" /><br/>
<img src="/yourapp/rest/images/second.jpg" /><br/>
<img src="/yourapp/rest/images/first.jpg" /><br/>
</body>
</html>
This is the result HTML you must output (in JSP or whatever you use). The REST service getImage() will be called automatically by the browser, once for each image.
Am I clear ?
Does anyone know how to use the "Controlled Embedded Browser" in SWT, which allows page manipulation? I can only find info on how to use the normal SWT browser, but I need to be able to interact with the loaded page. Thank you. Like this -
http://publib.boulder.ibm.com/infocenter/btt/v7r0/index.jsp?topic=%2Fcom.ibm.btt.application_presentation.doc_7.0%2Fdoc%2Freference%2Frichclient%2Fcontrolembededbrowser.html - but there is no instruction on how to initiate such a class.
Here is an example from Eclipse SWT snippets website
Also this post might give you some insight on this.
Using Java Objects in JavaScript in Eclipse SWT Browser Control
To expose Java Object from Eclipse to JavaScript, you need to create a class that extends BrowserFunction. The constructor of this class takes two arguments; the first one is Browser instance and second one is name of the the function that will be available in JavaScript code running the SWT browser control... ...
Code snippet
BrowserFunction:
import java.io.File;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.BrowserFunction;
public class ListFilesFunction extends BrowserFunction {
Browser browser = null;
String functionName = null;
public ListFilesFunction(Browser browser, String name) {
super(browser, name);
this.browser = browser;
this.functionName = name;
}
public Object function (Object[] args)
{
if (args.length == 0)
browser.execute("alert('Function " +
functionName + " requires one argument - parent folder path');");
File file = new File(args[0].toString());
if (!file.exists())
browser.execute("alert('Folder " + args[0] +
" does not exist');");
if (!file.isDirectory())
browser.execute("alert('Path " + args[0] + " must be a folder');");
return file.list();
}
}
associate this function with the browser control
public class View extends ViewPart
{
Browser browserCtl = null;
...
public void createPartControl(Composite parent) {
...
browserCtl = new Browser(parent, SWT.None);
new ListFilesFunction(browserCtl, "getFiles");
...
}
...
}
invoke this function from JavaScript:
<html>
<head>
<script type='text/javascript'>
files = getFiles("c:/");
for (i = 0; i < files.length; i++)
{
document.writeln(files[i] + "<br>");
}
</script>
</head>
<body>
</body>
</html>
im using Vaadin and trying to import jQuery and my own script. I have extended ApplicationServlet class and redefined this method
#Override
protected void writeAjaxPageHtmlHeader(BufferedWriter page, String title,
String themeUri, HttpServletRequest request) {
try {
super.writeAjaxPageHtmlHeader(page, title, themeUri, request);
page.write("\n<script type=\"text/javascript\" src=\"/VAADIN/themes/MyTheme/js/jquery-1.7.1.js\"></script>");
page.write("\n<script type=\"text/javascript\" src=\"/VAADIN/themes/MyTheme/js/script.js\"></script>");
System.out.println("Added jQuery and other scripts to page header.");
} catch (IOException e) {
e.printStackTrace();
}
}
and changed in web.xml servlet class to my own, but when i get it running my scripts don't work, so i open JavaScript Console and get this two messages:
Not allowed to load local resource: file:///VAADIN/themes/MyTheme/js/jquery-1.7.1.js
Not allowed to load local resource: file:///VAADIN/themes/MyTheme/js/script.js
Why is this happening, what can i do?
The themeUri parameter provides the URI of the theme in use, so try to use that in your src attributes:
page.write("\n<script type=\"text/javascript\" src=\"" + themeUri + "/js/jquery-1.7.1.js\"></script>");