I am trying to implement pdf generating into my web application so i decided to use pdfMake for this.
however, after importing everything needed...
import * as pdfMake from 'pdfmake/build/pdfmake';
import * as pdfFonts from 'pdfmake/build/vfs_fonts';
(pdfMake as any).vfs = pdfFonts.pdfMake.vfs;
my pdf generating function :
generatePDF() {
let docDefinition = {
header: 'C#Corner PDF Header',
content: 'Sample PDF generated with Angular and PDFMake for C#Corner Blog'
};
pdfMake.createPdf(docDefinition).open();
}
my button code :
<button class="botright" (click)="generatePDF()" mat-raised-button >Téléchargez le bordereau de prise en charge <mat-icon>picture_as_pdf</mat-icon></button>
...clicking the button i assigned to open the pdf only opens a blank web page
You can check the errors raised in the browser's console but if I have to guess, I'd say it's most likely caused by the wrong format of the 'content' variable, declared as an string here instead of an array :
example from pdfmake's playground :
var documentDefinition = {
content: [
'First paragraph',
'Another paragraph, this time a little bit longer to make sure,
this line will be divided into at least two lines'
]
}
Every browser can behave differently to a command such as open Modern Browser security should consider it as a pop-up request thus block or blank such viral activity.
a different effect
another may allow a new browsing window not a tab
Related
I am working on an application where user can add comments to certain fields. these comments can also be links. So, as a user I want to be able to click on those links rather than copy pasting them in a new tab.
If a normal web link ([http://|http:]... or [https://|https:]...) occurs in a comment/attribute value, it should be presented as a clickable link.
Multiple links may occur in the same comment/attribute value.
Clicking on a link opens a new browser tab that calls up this link.
This is how the formControl is being managed. I think i can identify multiply links with the help of regex but how do I make them clickable as well?
Thanks for answering and helping in advance.
this.formControl = new FormControl('', [this.params.customValidations(this.params)]);
this.formControl.valueChanges.subscribe(() => {
this.sendStatusToServices();
});
Outside the form editor/input (most likely what you're looking for)
Either before saving the value of the Form Field to the Database, or editing the received body from the database just before presenting to the user, you can use Regex to replace links with anchor tags.
function replaceURLWithHTMLLinks(text) {
var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&##\/%?=~_|!:,.;]*[-A-Z0-9+&##\/%=~_|])/ig;
return text.replace(exp,"<a href='$1'>$1</a>");
}
Rich text editor
If however, you're trying to enable links INSIDE the form input (like WordPress's text editor), that's going to be a bit more difficult. You'll need a <textarea> to enable custom HTML elements. Then you need to detect when the user has typed a URL, so you can call replaceURLWithHTMLLinks(). Honestly, you should just use a package. There's several good one out there.
Angular Rich Text Editor - A WYSIWYG Markdown Editor, by SyncFusion
NgxEditor, by sibiraj-s
typester-editor
Hope this helps
Using a regex approach and a pipe I was able to come up with something like below.
What I'm doing is replacing the links with hyperlink tags using a proper regex.
url replacement regex is taken from here
Supports multiple links within same comment.
Here is the sample pipe code
#Pipe({
name: 'comment'
})
export class CommentPipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer){}
transform(value: any, args?: any): any {
const replacedValue = this.linkify(value);
return this.sanitizer.bypassSecurityTrustHtml(replacedValue)
}
// https://stackoverflow.com/questions/37684/how-to-replace-plain-urls-with-links#21925491
// this method is taken from above answer
linkify(inputText: string) {
var replacedText, replacePattern1, replacePattern2, replacePattern3;
//URLs starting with http://, https://, or ftp://
replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&##\/%?=~_|!:,.;]*[-A-Z0-9+&##\/%=~_|])/gim;
replacedText = inputText.replace(replacePattern1, '$1');
//URLs starting with "www." (without // before it, or it'd re-link the ones done above).
replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
replacedText = replacedText.replace(replacePattern2, '$1$2');
//Change email addresses to mailto:: links.
replacePattern3 = /(([a-zA-Z0-9\-\_\.])+#[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim;
replacedText = replacedText.replace(replacePattern3, '$1');
return replacedText;
}
}
Here is the completed stackblitz
If you want links within Input itself you might want to try different approach
Note: This is about JavaFX WebView, not Android WebView (i. e. I have seen "Android Webview Anchor Link (Jump link) not working").
I display a generated HTML page inside a javafx.scene.web.WebView that contains anchors and links to those anchors like this:
<p>Jump to Introduction</p>
some text ...
<h1 id="introduction">Introduction</h1>
more text ...
I use this code to load the HTML into the WebView:
public void go(String location) {
try {
// read the content into a String ...
String html = NetUtil.readContent(new URL(location), StandardCharsets.UTF_8);
// ... and use loadContent()
webview.getEngine().loadContent(html);
} catch (IOException e) {
LOG.error(e);
}
}
Everything is rendered correctly, but if I click on the link named "Introduction", nothing happens.
The HTML however is correct, which I checked by instead using this code:
public void go(String location) {
// use load() to directly load the URL
webview.getEngine().load(location);
}
Now, everything worls fine.
The problem seems to be somehow because the document URL of the WebView is null when using loadContent(), but since it's a readonly property, I have no idea how to make it work.
I need to use loadContent(), because the HTML is generated on the fly, and if possible in any way, I don't want to have to write it out to a file just to make anchor links working. Is there a way to fix this?
EDIT
I filed a bug for JavaFX.
It's probably another WebEngine bug. A lot of that code is just a native libraries wrapped in api, so we can't modify it in runtime to fix some disabilities.
If you are able to change the structure of generated file you can implement scrolling to element in js:
<script>
function scrollTo(elementId) {
document.getElementById(elementId).scrollIntoView();
}
</script>
<a href='#' onclick=scrollTo('CX')>Jump to Chapter X</a>
<h2 id="CX">Chapter X</h2>
If you can't change the structure, there is some steps that I've made to try to fix it and some suggestions - at first I've set value of location by reflections after loadContent for sure:
Field locationField = WebEngine.class.getDeclaredField("location");
locationField.setAccessible(true);
ReadOnlyStringWrapper location = (ReadOnlyStringWrapper) locationField.get(engine);
location.set("local");
But in fact, keeping state of actual location is just an information for you and manipulating this changes nothing. I've also found a way to set url from js (just a long shot, we don't have any specific details why it's not working):
window.history.pushState("generated", "generated", '/generated');
Of course we can't because of:
SecurityError: DOM Exception 18: An attempt was made to break through the security policy of the user agent.
I think you should forget about loadContent(). You said that you didn't want to write generated content to file. A little dirty hack but really helpful for you could be wrapped http server on random and unused port in your application. You don't even need external libraries because Java has simple utilities like that:
HttpServer server = HttpServer.create(new InetSocketAddress(25000), 0);
server.createContext("/generated", httpExchange -> {
String content = getContent();
httpExchange.sendResponseHeaders(200, content.length());
OutputStream os = httpExchange.getResponseBody();
os.write(content.getBytes());
os.close();
});
server.setExecutor(null);
server.start();
You can also use another browser to display your page, e.g. JCEF (Java Chromium Embedded Framework).
We have a component that contains a background image. Our front-end guy needs it to be loaded through CSS (i.e. background: url(/*path here*/)...). The following is a possible solution we came up with:
#string src = // Get image path from Sitecore().Field("Picture");
<div style="background: url(#src) left top no-repeat;"> ... </div>
However, there are two problems with this approach:
It makes it very difficult for the content editor to swap out the image. They will have to manually change it through edit item.
It feels like a hack/workaround.
So the question is as follows: Is there a way to edit the CSS of an element through Razor/Sitecore? Specifically, the background: field.
I had a similar case and I used :
<footer class="layout_footer" style="background-color: #Model.BackgroundColor">
on view rendering (cshtml file)
And on the model we have :
public string BackgroundColor
{
get
{
Sitecore.Data.Fields.ImageField imgField =((Sitecore.Data.Fields.ImageField)item.Fields["BackgroundImage"]);
return Sitecore.Resources.Media.MediaManager.GetMediaUrl(imgField.MediaItem);
}
}
For editing this field in page editor you can use Sitecore Field Editor from a command : http://blog.istern.dk/2012/05/21/running-sitecore-field-editor-from-a-command/
Check for edit mode, and display in edit mode a editable field. Also create a Custom Experience Button from the Field Editor Button Type. You can also display. See User friendly developing with the Sitecore Experience Editor
#string src = // Get image path from Sitecore().Field("Picture");
<div style="background: url(#src) left top no-repeat;">
#if (IsInEditingMode)
{
<h3>Backgroiund Picture: #Editable(m => m.Picture)</h3>
}
</div>
There is no Sitecore extension method which will do this out of the box (i.e. #Html.Sitecore().Field("fieldName") will not work here as it would render the entire image tag (also a load of other non-image markup in page editor mode) as you probably know.
The method that #sitecore climber mentions is useful for controller renderings (or view renderings with a custom RenderingModel). If you want to stick with simple view renderings (i.e. not create a RenderingModel) then you could create a Html extension method which can be re-used on any view rendering. This could be something like the following:
public string ImageFieldSrc(this SitecoreHelper sitecoreHelper, string fieldName, Item item = null)
{
if (item == null) {
item = sitecoreHelper.CurrentItem;
}
var imageField = new ImageField(item.Fields[fieldName]);
var mediaItem = imageField.MediaItem;
var mediaUrl = MediaManager.GetMediaUrl(mediaItem);
mediaUrl = HashingUtils.ProtectAssetUrl(mediaUrl); //if you want to use media request protection (adding the hash onto the end of the URL, use this line
return mediaUrl;
}
It's worth noting that if you are using Sitecore 7.5 or above there is a feature to protect media URLs with a hash to prevent malicious DoS type attacks described in this blog post by Adam Najmanowicz.
In summary; if you are using Sitecore 7.5+ and you use media hashing then you will need to call HashingUtils.ProtectAssetUrl on the media URL if it is to respect size parameters.
The problem is that the JpGraph is not displayed correctly on my web-page. The strange thing is that if I run the above code in isolation, then it works. But if I insert it in my main code, it fails producing the above-shown message.
P.S. I'm using 'ob_start();', but it does not solve the problem.
// A new graph with automatic size
$graph = new GanttGraph (0,0, "auto");
// A new activity on row '0'
$activity = new GanttBar (0,"Project", "2001-12-21", "2002-02-20");
$graph->Add( $activity);
// Display the Gantt chart
$graph->Stroke();
?>
</div>
JpGraph Error: HTTP headers have already been sent.
Caused by output from file index.php at line 85.
Explanation:
HTTP headers have already been sent back to the browser indicating the data as text before the library got a chance to send it's image HTTP header to this browser. This makes it impossible for the library to send back image data to the browser (since that would be interpretated as text by the browser and show up as junk text).
Most likely you have some text in your script before the call to Graph::Stroke(). If this texts gets sent back to the browser the browser will assume that all data is plain text. Look for any text, even spaces and newlines, that might have been sent back to the browser.
For example it is a common mistake to leave a blank line before the opening "<?php".
JpGraphs can't exist in files with html. They have to be in a pure php file. To get around this, I created a seperate file that generates the graph, and made the whole thing a function. At the end, change
$graph->Stroke();
to
$graph->Stroke(".<filepaht>.jpg");
Then, in your index.php page, reference the image file.
So, what it looks like you need is,
createjpgraph.php:
<?php
function GenGraph (<input variables>) {
// A new graph with automatic size
$graph = new GanttGraph (0,0, "auto");
// A new activity on row '0'
$activity = new GanttBar (0,"Project", "2001-12-21", "2002-02-20");
$graph->Add( $activity);
// Display the Gantt chart
$graph->Stroke("./foler/file.jpg");
}
?>
index.php:
...
<div>
...
<?php
include 'createjpgraph.php';
GenerateGraph(<variables>);
?>
<img src=\"./folder/file.jpg\" />
</div>
Hope this works for you.
You can even do it in the same html document - first writing the graph to a file, then displaying it ...
//Code generating your graph here ...
// Finally output the image to a file
$graph->Stroke("/var/www/html/tmp/out.jpg");
//end of php code
?>
<!-- now include the newly generated image in the HTML -->
<img src="/tmp/out.jpg">
</body>
</html>
It is seem that the jpeg file that is being created by the function cannot be over written in my case...
to do overwrite it..
I changed my JPGraph file gd_image.inc.php .. you have to comment out the line
that says JpGraphError::RaiseL(25111,$aStrokeFileName)
I have a scenario that I get an string with html data, this is not just html data it's an email (outlook) saved as an html file and dropped in the string.
Now this string needs to be formatted to an html document and should be a clickable link in a datagrid. So when I click on the link, the HTML document should pop-up and should gave me a nice HTML page that is readable for the normal users. I hope it's a bit clear what I want o_0.
I don't know where to start.
You can download the example html from here: http://www.mediafire.com/?b2gfwymw70ynxir
Thanks!
---edit
Hopefully I can explain it a little bit better. I need to create an link and when they click on it they get an HTML page.
The string variable has HTML data in it, to be precise, the source data of the HTML example above.
example:
public var html:String = source_code_of_example_file;
The entire source code of the HTML page is in my variable html. Now I need to make this an link and when they click on it, they will get the html page (as pop-up) on the fly.
You can use the htmlText property and then specify a CSS to perform the proper formatting:
<mx:TextArea id="resourceText" height="100%" width="100%"
styleName="resourceText" editable="false"
styleSheet="{resourceStyleSheet}" htmlText="{html}"/>
To read in the style sheet I declare it in the model:
public var resourceStyleSheet : StyleSheet;
It gets read in from an external file:
private function loadCSS():void {
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, cssCompleteHandler);
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
try {
urlLoader.load(new URLRequest("folder/base-html.css"));
} catch (error:Error) {
Alert.show("Unable to load requested document.");
}
}
private function cssCompleteHandler(event:Event):void {
// Convert text to style sheet.
var styleSheet:StyleSheet = new StyleSheet();
styleSheet.parseCSS(URLLoader(event.currentTarget).data);
// Set the style sheet.
model.resourceStyleSheet = styleSheet;
}
private function ioErrorHandler(event:IOErrorEvent):void {
trace("ioErrorHandler: " + event);
}
This will get it into the model, but then make sure resourceStyleSheet is bindable when you use it (I actually set a bindable variable on the view that I set to the model value.
It's not really clear what you want to do.
If your problem is you need to show HTML formatted text in flex there is a component which can do this
http://code.google.com/p/flex-iframe/
-- update after edit
If your intention is to open a html popup once the user clicks on the link you could use ExternalInterface to call a javascript function to do this.
Hope it Helps
There is no easy way to display HTML in a flex web application(this is a web application, right?). Like Xavi Colomer said you can use the Flex Iframe but is terribly slow, it requires you to change the display mode for your swf to opaque and this can cause more problems, depending on your application.
You could open a new page in the browser that will be used to display the HTML. Something like:
http://www.yourcooldomain.com/bla/displayTheHtml.php?oneTimeId=jhsfg765437gro734
More info on how to do this from flex here.
On the other side(server) I assume that you keep this html messages on a database(?) so displaying them using php(or whatever you are using :P) should be easy.
If you are gonna choose this path be careful about the security: oneTimeId in
displayTheHtml.php?oneTimeId=jhsfg765437gro734
should really be an one tyme only id.