cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
JMP is taking Discovery online, April 16 and 18. Register today and join us for interactive sessions featuring popular presentation topics, networking, and discussions with the experts.
Submit your abstract to the call for content for Discovery Summit Americas by April 23. Selected abstracts will be presented at Discovery Summit, Oct. 21- 24.
Craige_Hales
Super User
Create HTML table from JSL

Recently I needed to do some web scraping to figure out parts availability. I used JMP to sift through the data and make a web page. This JSL is a simplified version of that web page generator. It creates an HTML directory in your computer's $TEMP space and adds some graphics using JMP's maps. At the same time, it builds a data table with links to the images.

Clicking the link in the data table opens another window; the table is moved back in front for this illustration.Clicking the link in the data table opens another window; the table is moved back in front for this illustration.

To make a web page that looks pretty, I went to a randomly selected online table generating site, did some color customizations, and grabbed the sample CSS and HTML to paste into the JSL. After a few minutes of studying, I cut it apart so the repetitive table body lines can be created from JSL. You can run the JSL unchanged and it will open a browser to the file-based site in your temp directory, or you can see it here.

// example web page creation
// step 0: make a place to keep the web site
htmlDir = "$temp/html/";
Delete Directory( htmlDir );
Create Directory( htmlDir );

// step 1, build a JMP table, pictures, links.
positions = {{"North Carolina", -84, -76, 33.5, 37}, {"Virginia", -83.4, -75.3, 36.1, 39.7}, {"Kentucky", -89.8, -81.4, 36, 39.6}, {"Tennessee", -90,-81.6, 34.2, 37.8}};
maps = {Images( "Detailed Earth" ), Images( "NASA server" ), Images( "Street Map Service", "Mapbox Light", "" )};
copyright = {"", "", "© Mapbox © OpenStreetMap"};
maptype = Function( {i}, Regex( Char( maps[i] ), "\!"([^\!"]*)", "\1" ) );//  text between the first two quotation marks - just the quoted string part

dtBC = Open( "$sample_data/big class.jmp" ); // not using the data in the maps, just need to open graph builder with a table

// this expression will be used in loops below to make graphs by substituting _backgroundimage_() and by using variables iPos and iMap
gbExpr = Expr(
	dtBC << Graph Builder( Size( 840 * 2, 411 * 2 ), Show Control Panel( 0 ), Show Legend( 0 ), Variables( X( :weight ), Y( :height ) ),
		Elements( Points( X, Y, Legend( 3 ) ), Smoother( X, Y, Legend( 4 ) ) ),
		SendToReport(
			Dispatch( {}, "Graph Builder", OutlineBox, {Set Title( "" ), Image Export Display( Normal )} ),
			Dispatch( {}, "weight", ScaleBox,
				{Scale( "Geodesic", {Compact Map( {Region( "United States" ), Alaska( 1 ), Hawaii( 1 ), Puerto Rico( 1 )} )} ), Format( "Best", 9 ),
				Min( positions[iPos][2] ), Max( positions[iPos][3] ), Inc( 2 ), Minor Ticks( 1 ), Label Row(
					{Show Major Labels( 0 ), Show Major Ticks( 0 ), Show Minor Ticks( 0 )}
				)}
			),
			Dispatch( {}, "height", ScaleBox,
				{Scale( "Geodesic", {Compact Map( {Region( "United States" ), Alaska( 1 ), Hawaii( 1 ), Puerto Rico( 1 )} )} ),
				Min( positions[iPos][4] ), Max( positions[iPos][5] ), Inc( 0.5 ), Minor Ticks( 0 ), Label Row(
					{Show Major Labels( 0 ), Show Major Ticks( 0 ), Show Minor Ticks( 0 )} )} ),
			Dispatch( {}, "graph title", TextEditBox, {Set Text( positions[iPos][1] )} ),
			Dispatch( {}, "X title", TextEditBox, {Set Text( copyright[iMap] )} ),
			Dispatch( {}, "Y title", TextEditBox, {Set Text( "" )} ),
			Dispatch( {}, "Graph Builder", FrameBox,
				{Background Color( 60 ), Background Map( _backgroundimage_(), Boundaries( "US States" ) ), DispatchSeg( MapSeg( 1 ),
					{Clip Shape( Boundaries( "US States", ID( positions[iPos][1] ) ) )} )} )
		)
	)
);

// open a new table. Give it clickable columns within JMP.

dt = New Table( "places",
	addrows( N Items( positions ) ),
	New Column( "name", character ),
	New Column( maptype( 1 ),
		Character,
		"Nominal",
		Set Property(
			"Event Handler",
			Event Handler(
				Click( JSL Quote(Function( {thisTable, thisColumn, iRow}, {  },Web( Char( thisTable:thisColumn[ iRow ] ) ); );) ),
				Tip( JSL Quote(Function( {thisTable, thisColumn, iRow}, {  },"Open " || Char( thisTable:thisColumn[ iRow ] ) || " in browser."; );) ),
				Color( JSL Quote(Function( {thisTable, thisColumn, iRow}, {  },RGBColor("link"); );) )
			)
		)
	),
	New Column( maptype( 2 ),
		Character,
		"Nominal",
		Set Property(
			"Event Handler",
			Event Handler(
				Click( JSL Quote(Function( {thisTable, thisColumn, iRow}, {  },Web( Char( thisTable:thisColumn[ iRow ] ) ); );) ),
				Tip( JSL Quote(Function( {thisTable, thisColumn, iRow}, {  },"Open " || Char( thisTable:thisColumn[ iRow ] ) || " in browser."; );) ),
				Color( JSL Quote(Function( {thisTable, thisColumn, iRow}, {  },RGBColor("link"); );) )
			)
		)
	),
	New Column( maptype( 3 ),
		Character,
		"Nominal",
		Set Property(
			"Event Handler",
			Event Handler(
				Click( JSL Quote(Function( {thisTable, thisColumn, iRow}, {  },Web( Char( thisTable:thisColumn[ iRow ] ) ); );) ),
				Tip( JSL Quote(Function( {thisTable, thisColumn, iRow}, {  },"Open " || Char( thisTable:thisColumn[ iRow ] ) || " in browser."; );) ),
				Color( JSL Quote(Function( {thisTable, thisColumn, iRow}, {  },RGBColor("link"); );) )
			)
		)
	)
);

// loop over states and map types to fill in the table

For( iPos = 1, iPos <= N Items( positions ), iPos += 1,
	dt:name[iPos] = positions[iPos][1];
	For( iMap = 1, iMap <= N Items( maps ), iMap += 1,
		gb = Eval( Substitute( Name Expr( gbExpr ), Expr( _backgroundimage_() ), maps[iMap] ) );
		img = gb << getpicture;
		path = htmlDir || Regex( positions[iPos][1] || maptype( iMap ), " ", "", globalreplace ) || ".jpg";
		img << savepicture( path, "jpg" );
		Column( dt, maptype( iMap ) )[iPos] = path;
		gb << closewindow;
	);
);

// at this point, the data table has clickable links. But there is no option to save it as HTML.
// visit https://www.tablesgenerator.com/html_tables to make a style sheet for a table of 4 columns, paste it here.
// mostly we need the style sheet, but we also need to see how the styles connect to the html elements.
// carve it up into snips of JSL that can be reused:

style =
"\[
<style type="text/css">
.tg  {border:none;border-collapse:collapse;border-color:#9ABAD9;border-spacing:0;}
.tg td{background-color:#EBF5FF;border-color:#9ABAD9;border-style:solid;border-width:0px;color:#444;
  font-family:Arial, sans-serif;font-size:14px;overflow:hidden;padding:10px 5px;word-break:normal;}
.tg th{background-color:#409cff;border-color:#9ABAD9;border-style:solid;border-width:0px;color:#fff;
  font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}
.tg .tg-phtq{background-color:#D2E4FC;border-color:inherit;text-align:left;vertical-align:top}
.tg .tg-0pky{border-color:inherit;text-align:left;vertical-align:top}
.tg .tg-f8tv{border-color:inherit;font-style:italic;text-align:left;vertical-align:top}
.tg .tg-6gib{background-color:#D2E4FC;border-color:inherit;font-weight:bold;text-align:left;vertical-align:top}
.tg .tg-fymr{border-color:inherit;font-weight:bold;text-align:left;vertical-align:top}
</style>
]\";
header =
"\[
<table class="tg">
<thead>
  <tr>
    <th class="tg-0pky">State</th>
    <th class="tg-f8tv">Detailed Earth</th>
    <th class="tg-f8tv">NASA Server</th>
    <th class="tg-f8tv">StreetMap Service</th>
  </tr>
</thead>
<tbody>
]\";
evenrow =
"\[
  <tr>
    <td class="tg-6gib">^dt:name[row()]^</td>
    <td class="tg-phtq">^detail_earth^</td>
    <td class="tg-phtq">^nasa_server^</td>
    <td class="tg-phtq">^streetmap_service^</td>
  </tr>
]\";
oddrow =
"\[  
  <tr>
    <td class="tg-fymr">^dt:name[row()]^</td>
    <td class="tg-0pky">^detail_earth^</td>
    <td class="tg-0pky">^nasa_server^</td>
    <td class="tg-0pky">^streetmap_service^</td>
  </tr>
]\";
trailer = "\[ 
</tbody>
</table>
]\";

// use a picture for the link, include the 2-letter state name as text in the link

abrev=["North Carolina"=>"NC", "Virginia"=>"VA","Kentucky"=>"KY","Tennessee"=>"TN"];
pic = Function( {url, txt, abr},
	Eval Insert( "\[<img src="^url^" width="100" height="50" alt="^txt^" /><br>^abr^]\" )
);

// split the path name into overlapping txt and url parts
pat = Pat Arb() + "html/" + (Pat Break( "." ) >> txt + Pat Rem()) >> url; // url is the whole value, txt is just the remainder after "html/"
// url include .jpg extension. txt is for display and does not show extension

// assemble the html body text into a long string

bodytext = style || header;
For Each Row(
	dt,
	Pat Match( dt:"detailed earth"n[Row()], pat );
	detail_earth = Eval Insert( "\[<a href="^url^">^pic(url,txt,abrev[dt:name[row()]])^</a>]\" );
	Pat Match( dt:"nasa server"n[Row()], pat );
	nasa_server = Eval Insert( "\[<a href="^url^">^pic(url,txt,abrev[dt:name[row()]])^</a>]\" );
	Pat Match( dt:"street map service"n[Row()], pat );
	streetmap_service = Eval Insert( "\[<a href="^url^">^pic(url,txt,abrev[dt:name[row()]])^</a>]\" );
	bodytext ||= Eval Insert( If( Mod( Row(), 2 ) == 0, evenrow, oddrow ) );
);
bodytext ||= trailer;

bodytext ||= "\[<br><br><a href="https://community.jmp.com/t5/Uncharted/Create-HTML-table-from-JSL/ba-p/613288">More info</a><br>]\";

// wrap the rest of the web page around the body text

html = Eval Insert( "\[
<!DOCTYPE html>
<html>
  <head>
    <title>Pictures of States</title>
  </head>
  <body>
	^bodytext^
  </body>
</html>	
]\" );

// save and display

file = Save Text File( htmlDir || "states.html", html );
Web( file );

It is a picture of links, not actual links.It is a picture of links, not actual links.

Last Modified: Mar 16, 2023 8:14 PM