cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
The Discovery Summit 2025 Call for Content is open! Submit an abstract today to present at our premier analytics conference.
See how to use to use Text Explorer to glean valuable information from text data at April 25 webinar.
Choose Language Hide Translation Bar
View Original Published Thread

Craige_Hales
Super User
HTML with Embedded Images

This is NOT for saving interactive HTML. SaveInteractiveHTML already does this. You should probably use it instead.

When JMP saves HTML with graphics, it creates a directory named gfx to hold the images. The gfx directory will hold images for all the HTML files that are saved in the same parent directory. If you send the HTML to someone, they only need the files for that HTML, and they need to put the gfx directory and the HTML in the same location. It works pretty well if you have a server where you can put them, but not so good if you email them.

This example JSL will embed the images into the HTML using a Data URL (formerly known as a Data URI). The gfx is not needed after conversion because the pictures are moved into the HTML.

@ihnleung

// https://community.jmp.com/t5/Discussions/Distribution-plots-not-showing-in-Journal-saved-as-html/m-p/475041#M71971
// asked about emailing html reports. This code is an example of how the external
// images in the gfx folder can be converted into embedded URI data.
// most browsers should support this; it makes the html bigger, of course, but
// doesn't need the images in a shared directory.
workdir = "$temp/deleteme/";// careful! this dir is deleted ...
Delete Directory( workdir );// BANG!
Create Directory( workdir );// create empty dir
//
// make a journal with some reports and save it as html with external images in the gfx dir
//
dt = Open( "$sample_data/big class.jmp" );
bv = dt << Bivariate( Y( :weight ), X( :height ), Fit Line );
bv << journal;
bv << closewindow;
ow = dt << Oneway( Y( :height ), X( :sex ), Means( 1 ), Mean Diamonds( 1 ) );
ow << journal;
ow << closewindow;
Close( dt, nosave );
Current Journal() << savehtml( workdir || "x.html" );
Current Journal() << closewindow;
//
// load the html just saved above and embed the images in the gfx directory
//
html = Load Text File( workdir || "x.html" );// get the journal's html
snips = {}; // collect the snipped up html here
rc = Pat Match(// loop through the html, snipping it up into 'not file' and 'file' sections
    html, // the html that needs the files converted into URI (inline pictures)
    Pat Repeat(
        Pat Arb() >> txt // txt holds a snip of html that is not a picture file name
        + // text before a filename, above, is followed by a filename (or the end), below
        (
            ("> file + "\!"") // file holds a picture name
        | // alternative at the end, there is no filename
            Pat R Pos( 0 ) >> file // made it to the end of the text, file is "" in this case
        ) + //
        Pat Test( //
            Insert Into( snips, txt ); // first snip
            If( file != "", // second snip, except not at the end
                Insert Into( // replace the snipped part with embedded data
                    snips, // https://stackoverflow.com/questions/6826390/how-to-convert-image-to-data-uri-for-html-with-c
                    "
Looks like the JSL might get mangled( & colon ; instead of : ) because of the html inside of html...the attached file might work better.

This post originally written in German and has been translated for your convenience. When you reply, it will also be translated back to German.

Comments
jthi
Super User

When I want to have reports without gfx folders I have usually created interacative html and then break it on purpose, but this will add a lot of unnecessary text to .html which isn't needed (it might look a bit prettier, but usually I don't need it). I have done something a bit similar when sending JMP reports with powershell using Send-MailMessage with embedded images (I modified the parts of html with <img> with cid:).

 

Inspired by this post I wrote code which tries to avoid creation of gfx folder. Most likely this isn't as robust as different platforms will most likely have some weirdness when using << get html. I haven't (yet...) learned how to use Pat Match, so I used Munger() and some other things to replace correct characters. Script will also save different kinds of interactive html reports to see how large they are when compared to embedded images.

 

Script:

View more...
Names Default To Here(1);

dt = Open("$sample_data/big class.jmp", invisible);

workdir = "$temp/deleteme/";// careful! this dir is deleted ...

If(!Directory Exists(workdir),
	Create Directory(workdir);
);

nw = New Window("Report Window",
	H List Box(
		dt << Bivariate(Y(:weight), X(:height), Fit Line),
		dt << Oneway(Y(:height), X(:sex), Means(1), Mean Diamonds(1)),
		dt << Graph Builder(
			Show Control Panel(0),
			Variables(X(:Sex), Y(:Height), Group X(:Age)),
			Elements(Box Plot(X, Y))
		),
		dt << get as report
	)
);

// For some reason Oneway does create distribution plot twice. Using journal avoids this...
// New Window("", H List Box(pic_boxes[4], pic_boxes[5]));

// using journal conversion will partially break some interactivity, so save them before
nw << Save Interactive HTML(workdir || "test_interactive.html");
nw << Save Interactive HTML(workdir || "test_interactive_static.html", 1); // isStatic

nw << Journal Window;
nw << Close Window;
nw = Current Journal();
nw << Set Window Title("Journaled New Window");
Main Menu("Edit:Lock Journal", nw << Get Window Title);

// get html string from journal
html_str = nw << Get html;
// use xpath to get references to all pictureboxes
pic_boxes = nw << XPath("//PictureBox"); // for some reason in this case, last picturebox is found twice

// in basic html pictureboxes will be replaced by Picture Ignored string
pic_ignored_count = N Items(Words(Substitute(html_str, "Picture ignored", "¤"), "¤")) - 1; // only works if there are no ¤ in string
pics = pic_boxes << get picture;

For Each({cur_pic, idx}, pics,
	{w, h} = cur_pic << get size;
	base64compressed_str = Arg(Arg(parse(Char(cur_pic)), 1), 1);
	base64_str = Encode64 Blob(Gzip Uncompress(Char To Blob(base64compressed_str, "base64compressed")));
	// clean some <br> to make nicer looking html
	html_str = Munger(html_str, idx, "<br>\!NPicture ignored<br>\!N<br>", Eval Insert("<img src=\!"data&colon;image/png;base64,^base64_str^\!" width=^w^ height=^h^>"));	
);

// change background color to something a bit less blinding than white
// some grayish ones with names: gainsboro, whitesmoke, oldlace, silver, darkgray. https://www.w3.org/wiki/CSS/Properties/color/keywords
// for JMP's WHITE THEME color use rgb(248,248,248)
// for JMP's GRAY  THEME color use rgb(219,224,227), most likely not the best idea, as some fonts and other backgrounds should also be changed
Substitute Into(html_str, "body { ", "body { background-color:whitesmoke;,"); 

nw << Save Interactive HTML(workdir || "test_interactive_journal.html");
nw << Save Interactive HTML(workdir || "test_interactive_static_journal.html", 1); // isStatic
filename = Save Text File(workdir || "test_embedded.html", html_str); // save the embedded version
nw << Close Window;
Close(dt, nosave);

Open(workdir);