How do I create a printable Slate document? - palantir-foundry

Given that Slate documents by default do not appear when calling window.print() (or using the print/save as pdf option in chrome), and also that the optimal styling may differ when printed than when displayed in a web page, what are some good ways to create a "print version" of a Slate dashboard?
I'm also thinking of things like hiding sliders and search fields, adding classification watermarks, adjusting logo placement etc.

Slate is optimized for rapid application development. The underlying framework imposes few limitations on the configurability of layout our styling. As a result, Slate is unable to generically render all applications in a manner suitable for print media or export. Application developers will need to invest time on an app-by-app basis to support printing.
The first, best option is to consider why there is a requirement or request to print your app. Do your users simply need a way to preserve the view they've created and reference it later or use it during a presentation? In this case, consider using (or highlighting to your users to use) the built-in Get Shareable Link functionality. In View mode it's under the Action menu - in edit mode, you can use the Slate.saveView action and the Slate.viewSaved event to create these programmatically, then the Slate.loadView action to load a previously saved view.
This will create a unique url with an id that will, whenever the link is loaded, return all the page widgets to the state they were in when the link was generated. This means, for example, a set of input widgets will default to the inputs configured by the user and feed into the queries, etc.
In combination with the per-user storage cache, this makes it possible to build workflows to save a list of preview "views" for a given user and reload them in the future.
If you really must print or export, then you'll need to define additional media CSS styles to help your application render appropriately.
To start, you'll need to add at least this to the Global Styles:
#media print {
#page {
size: A4;
}
html, body {
height: 600mm !important;
}
}
You can read more about media CSS for printing in various articles like this or this.
Printing “responsive” applications or any application with complex styling or layout will be very difficult. In these cases, consider creating a “Print View” as a separate application that receives necessary inputs via URL parameters and generates a simplified view optimized for printing. This will increase the development cost and maintenance burden, but will result in satisfactory behavior.

If after applying the above Global Styles, the printout is still getting cut off, try using the "Print using system dialog" option in Chrome, which (at least on a Mac) will give the option to specify a Scale (screenshot). By scaling down from 100% you should be able to get the full Slate view to fit on the page.

Related

Reliable method of scraping page source i.e the tv at the beginning of each line?

When extracting data you can use CSS/xpaths. But is there a similar or reliable method of doing this in the page source.
www.amazon.com/Best-Sellers-Electronics-Televisions/zgbs/electronics/172659
You could get the page source and then parse using Regex but probably not be reliable if for instance the tv did not load on the page. I have looked up various solutions but I have yet to find one that mentions getting every tv at start of each line (1, 4, 7 etc,, in source) or using a reliable method e.g Css/xpaths in source of a page.
What would is the golden standard of reliable method of doing what I am after?
To get the page source you can use CURL if the page is rendered entirely on server side (most pages won't be), or headless chrome to get the actual DOM that will render in the browser (https://developers.google.com/web/updates/2017/04/headless-chrome).
For scraping the content, I've used cheerio (https://github.com/cheeriojs/cheerio) which will allow you to read in HTML to an object and then scrape your data off that using jQuery expressions. (Headless chrome allows you to execute JS on the pages you visit, so you don't necessarily need cheerio).
In your specific example you could get the TV on each line by combining the right class selectors to get the divs containing TV's, and using attribute selector with 'margin-left=0px' which would get first item on each line. That is obviously very much bound to structure of the page and will likely be broken by smallest of changes in the page source. (And not really any different from using xpaths. Still better than regex though)
With certain elements loading / not loading on the page (if that was what you meant by TV not being there), no golden solutions that I know of, except allowing sufficient time for the page to load and handling your scraper failing gracefully.

Way To Modify HTML Before Display using Cocoa Webkit for Internationalization

In Objective C to build a Mac OSX (Cocoa) application, I'm using the native Webkit widget to display local files with the file:// URL, pulling from this folder:
MyApp.app/Contents/Resources/lang/en/html
This is all well and good until I start to need a German version. That means I have to copy en/html as de/html, then have someone replace the wording in the HTML (and some in the Javascript (like with modal dialogs)) with German phrasing. That's quite a lot of work!
Okay, that might seem doable until this creates a headache where I have to constantly maintain multiple versions of the html folder for each of the languages I need to support.
Then the thought came to me...
Why not just replace the phrasing with template tags like %CONTINUE%
and then, before the page is rendered, intercept it and swap it out
with strings pulled from a language plist file?
Through some API with this widget, is it possible to intercept HTML before it is rendered and replace text?
If it is possible, would it be noticeably slow such that it wouldn't be worth it?
Or, do you recommend I do a strategy where I build a generator that I keep on my workstation which builds each of the HTML folders for me from a main template, and then I deploy those already completed with my setup application once I determine the user's language from the setup application?
Through a lot of experimentation, I found an ugly way to do templating. Like I said, it's not desirable and has some side effects:
You'll see a flash on the first window load. On first load of the application window that has the WebKit widget, you'll want to hide the window until the second time the page content is displayed. I guess you'll have to use a property for that.
When you navigate, each page loads twice. It's almost not noticeable, but not good enough for good development.
I found an odd quirk with Bootstrap CSS where it made my table grid rows very large and didn't apply CSS properly for some strange reason. I might be able to tweak the CSS to fix that.
Unfortunately, I found no other event I could intercept on this except didFinishLoadForFrame. However, by then, the page has already downloaded and rendered at least once for a microsecond. It would be great to intercept some event before then, where I have the full HTML, and do the swap there before display. I didn't find such an event. However, if someone finds such an event -- that would probably make this a great templating solution.
- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
{
DOMHTMLElement * htmlNode =
(DOMHTMLElement *) [[[frame DOMDocument] getElementsByTagName: #"html"] item: 0];
NSString *s = [htmlNode outerHTML];
if ([s containsString:#"<!-- processed -->"]) {
return;
}
NSURL *oBaseURL = [[[frame dataSource] request] URL];
s = [s stringByReplacingOccurrencesOfString:#"%EXAMPLE%" withString:#"ZZZ"];
s = [s stringByReplacingOccurrencesOfString:#"</head>" withString:#"<!-- processed -->\n</head>"];
[frame loadHTMLString:s baseURL:oBaseURL];
}
The above will look at HTML that contains %EXAMPLE% and replace it with ZZZ.
In the end, I realized that this is inefficient because of page flash, and, on long bits of text that need a lot of replacing, may have some quite noticeable delay. The better way is to create a compile time generator. This would be to make one HTML folder with %PARAMETERIZED_TAGS% inside instead of English text. Then, create a "Run Script" in your "Build Phase" that runs some program/script you create in whatever language you want that generates each HTML folder from all the available lang-XX.plist files you have in a directory, where XX is a language code like 'en', 'de', etc. It reads the HTML file, finds the parameterized tag match in the lang-XX.plist file, and replaces that text with the text for that language. That way, after compilation, you have several HTML folders for each language, already using your translated strings. This is efficient because then it allows you to have one single HTML folder where you handle your code, and don't have to do the extremely tedious process of creating each HTML folder in each language, nor have to maintain that mess. The compile time generator would do that for you. However -- you'll have to build that compile time generator.

Can Go capture a click event in an HTML document it is serving?

I am writing a program for managing an inventory. It serves up html based on records from a postresql database, or writes to the database using html forms.
Different functions (adding records, searching, etc.) are accessible using <a></a> tags or form submits, which in turn call functions using http.HandleFunc(), functions then generate queries, parse results and render these to html templates.
The search function renders query results to an html table. To keep the search results page ideally usable and uncluttered I intent to provide only the most relevant information there. However, since there are many more details stored in the database, I need a way to access that information too. In order to do that I wanted to have each table row clickable, displaying the details of the selected record in a status area at the bottom or side of the page for instance.
I could try to follow the pattern that works for running the other functions, that is use <a></a> tags and http.HandleFunc() to render new content but this isn't exactly what I want for a couple of reasons.
First: There should be no need to navigate away from the search result page to view the additional details; there are not so many details that a single record's full data should not be able to be rendered on the same page as the search results.
Second: I want the whole row clickable, not merely the text within a table cell, which is what the <a></a> tags get me.
Using the id returned from the database in an attribute, as in <div id="search-result-row-id-{{.ID}}"></div> I am able to work with individual records but I have yet to find a way to then capture a click in Go.
Before I run off and write this in javascript, does anyone know of a way to do this strictly in Go? I am not particularly adverse to using the tried-and-true js methods but I am curious to see if it could be done without it.
does anyone know of a way to do this strictly in Go?
As others have indicated in the comments, no, Go cannot capture the event in the browser.
For that you will need to use some JavaScript to send to the server (where Go runs) the web request for more information.
You could also push all the required information to the browser when you first serve the page and hide/show it based on CSS/JavaScript event but again, that's just regular web development and nothing to do with Go.

Changing variable dynamically (at runtime) via LESS and CSS?

#myThemeBackground = #ddd;
div#box1 { background: #myThemeBackground; }
I'm using LESS in order to use variables for my css. It works fine, but I'm wondering if there's a way for me to change the "myThemeBackground" dynamically at runtime via javascript or something.
So say if the user chooses a custom color for the background I'd like the entire skin to change.
Note: this is for dynamically theming/skinning an application where the user chooses the color for the background for example and then the whole app changes (without a page refresh)
You can modify Less variables on the fly using the modifyVars method:
less.modifyVars({ myThemeBackground : '#000' });
I usually grab the CSS generated by LESS and include that in a file to optimize the web page loading speed. In fact, I use LESS.app for Mac to generate my CSS.
To my knowledge, part of the solution would involve including less.js file to your page. This in turn means that generating the style of the page would be slow and the caching might cause you some trouble too...
I would humbly suggest generating multiple CSS stylesheets with LESS and include these files when needed with JavaScript.
The only solution I can think of is to change the text you render with less.js, with:
less.refreshStyles()
Change the text in the file or in the less snippet of styling.
Read more about it here:
Load less.js rules dynamically

How can I switch easily between an Ajax-based website and a basic HTML website?

I have a website ( based on JSP/Servlets, using the MVC pattern), and I want to support Ajax-based website and basic HTML-based website. website visitors should be able to change the surfing mode from Ajax to basic HTML and vice versa, - as it applies in Google-mail.
The questions:
What is the best way to achieve this goal easily?
Should I design two views for each page?
I use jQuery and JSON as the result of this answer.
You need Unobtrusive JavaScript, which is part of progressive enhancement.
First, start creating a fully functional web application without any line of JavaScript. Once you got it to work, then start writing JavaScript code which "takes over" the raw HTML work without changing any line of HTML/CSS. In the server side code you need to add logic which recognizes whether the request has been fired by JavaScript or not and return response accordingly. You can test both cases by en/disabling JavaScript in the web browser. In Firefox it's easy with Web Developer Toolbar.
For example, you have a list of mails with all HTML links which should show the mail body:
Message title
Without JavaScript, this would fire a HTTP request to the servlet which loads the mail identified by 1, forwards the request to a JSP which hides the message list in the view and shows the mail in the view.
With JavaScript/jQuery, you need to write code which does exactly the same with help of Ajax, e.g.:
$('a.show').click(function() {
$.getJSON(this.href, callbackFunctionWhichHidesListAndShowsMail);
return false;
});
In the server side you have to distinguish between normal requests and ajax requests so that you can return response accordingly.
boolean ajax = "XMLHttpRequest".equals(request.getHeader("x-requested-with"));
// ...
if (ajax) {
writeJson(response, mail);
} else {
request.setAttribute("mail", mail);
request.getRequestDispatcher("/WEB-INF/mail.jsp").forward(request, response);
}
Finally, to give the user an option to switch between the modes manually, you have to set a cookie or preferably (since cookies are disableable) pass some information in URL (pathinfo or request parameter) which forces the server to disable emitting the <script> lines.
Think of the HTML version as the foundation. Build this first.
Then overlay the additional Ajax functionality as an optional layer on top of this, intercepting the default HTML behaviours as necessary. There isn't any need for two views, just a single view that gradually adds enhanced functionality depending on available technology and/or user preference.
You are quite sensibly attempting progressive enhancement. There is an excellent article, A List Apart: Understanding Progressive Enhancement, which I must give credit to this Stack Overflow answer for; Graceful degradation - when to consider.
I consider graceful degradation to be the more negative way of looking at the problem of supporting different browser capabilities; What is the difference between progressive enhancement and graceful degradation?