How to print contents of an HTML element in MacGap? - objective-c

I'm creating a WebView app with MacGap2 and I'd like to be able to print the contents of an HTML element (with a print preview like you would see in Safari/Preview/etc).
I've been looking at WebUIDelegate's webView:printFrameView as well as Printing Entire Contents of WebView in Cocoa, Not Just Displayed - but I'm having a hard time putting it all together as I'm new to Objective-C/Cocoa.
If I wanted a method like this (options not necessary if print preview works):
MacGap.print([HTMLelement], [options]);
// Example usage
var el = document.getElementById('view');
// Or if not element, send as HTML string? (with inline CSS)
// el = el.innerHTML;
MacGap.print(el, { printBackgrounds: true, landscape: false });
What would I need to add to my MacGap Classes/Commands?
App.h:
- (void) print:(NSString*)printString;
App.m:
- (void) print:(NSString*)printString {
// ???
}

I dont have experience with MacGap2 and I tested this on a uiwebview not a webview, but I think it should still work to get the html string from the webview.
- (void) print:(NSString*)printString
{
NSString * pstrViewHTML= [myWebView stringByEvaluatingJavaScriptFromString:#"function getView(){return document.getElementById('view');} getView();"];
// Do something with html string.
}

Related

iOS: How can I find one specific tag in a HTML page

I am parsing a website and want to read out one specific HTML part of that website. I am looking for one (and one only) <frame> tag:
<frame scrolling="auto" ... src=”I need this text">
So I need basically only the text in src="". But how can I do this as simple as possible? So far I tried to analyze the string by:
NSString *html = [self.webview stringByEvaluatingJavaScriptFromString: #"document.body.innerHTML"];
But html stays empty and I wouldn't know how to continue. So how can I make this as simple as possible using my webview?
Something like this might work:
document.addEventListener("DOMContentLoaded", function() {
var allFrames = document.querySelectorAll("frame");
if (allFrames.length) {
var src = allFrames[0].src;
console.log(src);
var request = new XMLHttpRequest();
request.open("GET", "my-app://localhost/?src=" + encodeURIComponent(src));
request.send(null);
} else {
console.log("no frames on the page " + location.href);
}
});
Run this code using stringByEvaluatingJavaScriptFromString from the webViewDidFinishLoad callback, and handle the output data from the script using shouldStartLoadWithRequest callback.
You see the log and debug the script using Safari Web Inspector (for both simulator and device).

HTML string to PDF conversion

I need to create various reports in PDF format and email it to specific person. I managed to load HTML template into string and am replacing certain "custom markers" with real data. At the end I have a fulle viewable HTML file. This file must now be printed into PDF format which I am able todo after following this link : https://www.appcoda.com/pdf-generation-ios/. My problem is that I do not understand how to determine the number of pages from the HTML file as the pdf renderer requires creating page-by-page.
I know this is an old thread, I would like to leave this answer here. I also used the same tutorial you've mention and here's what I did to make multiple pages. Just modify the drawPDFUsingPrintPageRenderer method like this:
func drawPDFUsingPrintPageRenderer(printPageRenderer: UIPrintPageRenderer) -> NSData! {
let data = NSMutableData()
UIGraphicsBeginPDFContextToData(data, CGRect.zero, nil)
printPageRenderer.prepare(forDrawingPages: NSMakeRange(0, printPageRenderer.numberOfPages))
let bounds = UIGraphicsGetPDFContextBounds()
for i in 0...(printPageRenderer.numberOfPages - 1) {
UIGraphicsBeginPDFPage()
printPageRenderer.drawPage(at: i, in: bounds)
}
UIGraphicsEndPDFContext()
return data
}
In your custom PrintPageRenderer you can access the numberOfPages to have the total count of the pages

How to hide the iOS 8 Today Widget when there is nothing to display?

I'm using the today widget for iOS8 to display information relevant to the current day. The problem is I don't want to display the widget/section at all if there are no relevant messages to show.
I know it must be possible as the BA app does it (it only shows the widget when there is a flight, the rest of the time its not visible at all). I just cant figure out a way to achieve this behaviour.
Does anyone know how this can be done?
I found the way to do this is using the NCWidgetController. This allows you to easily specify when the today widget should be displayed based on whatever criteria you see fit.
Simply add the following into your viewDidLoad method (or anywhere that will be called when the widget reloads) in the today widget view controller and it will work:
BOOL hasDataToDisplay = NO;
NCWidgetController *widgetController = [NCWidgetController widgetController];
[widgetController setHasContent:hasDataToDisplay forWidgetWithBundleIdentifier:#"com.my-company.my-app.my-widget"];
Apple Docs: https://developer.apple.com/library/ios/documentation/NotificationCenter/Reference/NCWidgetController_Class/index.html#//apple_ref/occ/cl/NCWidgetController
WARNING: The NCWidgetController cannot be reset from the widget itself once you have set there is no content to display. In other words once you set it to NO then there is no going back unless you trigger it from the parent/containing app.
In the widget's ViewController's viewDidLoad method add the following:
BOOL DisplayWidget = NO;
[[NCWidgetController widgetController] setHasContent:DisplayWidget
forWidgetWithBundleIdentifier:#"<widget's bunder identifier>"];
This will disable the widget from showing.
To enable it again, you must do that from the containing app using the same line passing YES to setHasContent parameter. Make sure to add the necessary imports to the containing app in the ViewController which will re-enable the widget:
#import <NotificationCenter/NotificationCenter.h>
#interface ViewController () <NCWidgetProviding> {...}
[Check out page 41 of the documentations for widgets
https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensibilityPG.pdf ]
The approach which I used, though not perfect and has a small remnant in Notification Center, but worked for me:
In viewDidLoad() set preferred content size height to 1:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view from its nib.
preferredContentSize = CGSizeMake(0, 1)
view.setNeedsLayout()
}
then when widget updates, gets real height and set it:
var data: NSData?
func updateData() {
// fetch data
if let data = data {
let viewHeight: CGFloat
// UI preperation and initialize viewHeight var
preferredContentSize = CGSizeMake(0, viewHeight);
} else {
preferredContentSize = CGSizeMake(0, 1);
}
}
func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)) {
// Perform any setup necessary in order to update the view.
// If an error is encountered, use NCUpdateResult.Failed
// If there's no update required, use NCUpdateResult.NoData
// If there's an update, use NCUpdateResult.NewData
updateData()
completionHandler(data != nil ? NCUpdateResult.NewData : NCUpdateResult.NoData)
}
It is better use
+ (instancetype)widgetController
then call
- (void)setHasContent:(BOOL)flag forWidgetWithBundleIdentifier:(NSString *)bundleID

TCPDF with FPDI templates and THEAD

I have a html table with THEAD output with writeHTML which should be displayed on every page at the top of the table. It works but when I use a template loaded by FPDI the head is white and disappears on the second page and further. I can mark the head field with the mouse but the appear white. The border only appears as a little point on the left.
I already tried to add $this->setPageMark() to the addPage method. But its still the same issue.
public function AddPage($orientation = '', $format = ''){
parent::AddPage($orientation, $format);
if($this->template != null){
$this->useTemplate($this->template);
$this->setPageMark();
}
}
you need to enable page breaks at the beginning which is causing the issue you are having;
this is a sample code snippet ;
require_once('tcpdf/tcpdf.php'); //main code
require_once('tcpdf/fpdi.php'); //read existing pdf and sends to fpdf
$pdf = new FPDI();
$pdf->setPrintHeader(false); //no header
$pdf->setPrintFooter(false);//no footer
$pdf->SetAutoPageBreak(FALSE, 0); // set auto page breaks
//loop starts here
{
$pdf->setSourceFile($page_background); //set page
$templateId = $pdf->importPage(1); //we only need the first page
$pdf->useTemplate($templateId); //use the imported page
//your write html code and any other tcpdf related code comes here
}
$pdf->Output(outcome.pdf, 'I'); //use F instead of I to show generated pdf.

How to add a note on UIwebview

I would like to implement a function like adding a note of a selected text on UIWebview as iBooks and Amazon Kindle does.
I already created UIMenuItem. But, I dont know how to implement the method for this. Could anybody help in this regard?
I dont know what functionality is used to implement in this method. Thanks.
- (void)Note:(id)sender {
NSString *selection = [webView stringByEvaluatingJavaScriptFromString:#"window.getSelection().toString()"];
}
The JavaScript in question is designed to give you the text that is highlighted within your selection.
I'm not sure that running toString on an element will return the correct information though. The following method will return the highlighted text and save it into a variable.
function getHighlightedString() {
var text = window.getSelection();
myAnchorOffset = text.anchorOffset;
myFocusOffset = text.focusOffset;
myHighlightLength=myFocusOffset-myAnchorOffset;
if(myHighlightLength<0)
{
myHighlightLength*=-1;
temp = myAnchorOffset;
myAnchorOffset = myFocusOffset;
myFocusOffset = temp;
}
selectedText = text.anchorNode.textContent.substr(myAnchorOffset, myFocusOffset - myAnchorOffset);
}
when you have this method loaded into the webview
NSString myHighlightedText = [webView stringByEvaluatingJavaScriptFromString:#"getHighlightedString()"];