find HTMLEditor cursor pointer for inserting image - html

as said in topic: JavaFX HTMLEditor - Insert image function
if want to insert image should add below tag to htmlText of htmlEditor
"<img src=\"" + getClass().getResource(PicName[i])) + "\" width=\"" + target.getImage().getWidth() + "\"height=\"" + target.getImage().getHeight() + "\">")
but if want to add image in cursor position how to do it?

You can achieve this in the following way
Use the ScenicView to explore the HTMLEditor
Get WebView inside HTMLEditor
Get WebEngine of that WebView
Run a JavaScript Code to Insert an image to the caret pos using WebEngine
How To Replace HTML using JS
Link to Original Post
function insertHtmlAtCursor(html) {
var range, node;
if (window.getSelection && window.getSelection().getRangeAt) {
range = window.getSelection().getRangeAt(0);
node = range.createContextualFragment(html);
range.insertNode(node);
} else if (document.selection && document.selection.createRange) {
document.selection.createRange().pasteHTML(html);
}
}
How to Execute JS Code Guide
Node webNode = htmlEditor.lookup(".web-view");
if (webNode instanceof WebView) {
WebView webView = (WebView) webNode;
WebEngine engine = webView.getEngine();
engine.executeScript("alert('helo')"); // add js code here
}

text fileds are have a linear datastructure and can have a sequential position and corresponding location in its view.
but for html view the displayed object location on screen to location in the text mapping is a bit difficult so thats why the html editor cant determine the cursor position
im working on some other workaround to insert image at given cursor position.
try to insert a dummy text as a placeholder like ###inserImage#### then replace it with the actual image tag <img src="file:\c:\testhtmleditor\sample01.jpg" />..

Let's try this piece of code
#FXML private HTMLEditor editor;
...
public void insertTextToCurrentFeatureCursorPosition(String text) {
WebView webView = (WebView) editor.lookup(".web-view");
WebPage webPage = Accessor.getPageFor(webView.getEngine());
webPage.executeCommand("insertHTML", text);
}
Where text is the HTML code which wraps the image

Related

Qt: Set background image on QTextDocument using HTML to generate pdf file

i am wrapping my head in this problem for a few time.
I need to create a report by creating a pdf file with some data on it.
So my plan was to instead of using the QTextCursor, i use HTML + CSS to create the content in my pdf file.
Unfortunately I can't go with the QWebEngine widgets solution because I am compiling into MinGW and setting the MVSC 2017 environment is a huge mess.
Sadly i have to go with the QTextDocument and his HTML subset support.
My problem is I can't put a background image in my pdf file.
I want to put this image as a background image:
What make me crazy is that I use the css property to display a background image in my pdf file.
background-image: url(:/images/blue-gradient-background.jpg);
And it seems that Qt is taking this into account but it still don't display the background.
Have a look:
The first pdf file don't contain the css property background image on the html content but the second does and you can see that the size of the file is bigger so it has considered the css property.
But it hasn't displayed the background:
On the left is the first file and on the right is the second file with the css property.
I use a html file in the ressource to generate the report :
<!DOCTYPE html>
<html>
<style>
body {
background-image: url(:/images/blue-gradient-background.jpg);
}
h1 {
color: blue;
}
#table-content {
}
#table-content table {
margin: 1em
}
</style>
<body>
<div align="center"><h1>[title-template]</h1></div>
<div align="center" id="table-content">[table-template]</div>
</body>
</html>
This html file is open and read in the constructor of the class:
FileEditor::FileEditor()
{
QFile htmlTemplate(":/html/report.html");
if (htmlTemplate.open(QIODevice::ReadOnly | QIODevice::Text))
{
QTextStream in(&htmlTemplate);
m_reportPageHTMLTemplate = in.readAll();
}
}
Then i use a custom class with this function that use QPrinter and QPainter to write the data:
void FileEditor::writeReportPdfFile(const QString &i_path, const S12xConf &i_s12xConf, const S12xData &i_s12xData, const BenchTestData &i_benchTestData)
{
QDir directory(i_path); // we create a QDir with the path
if (!directory.exists()) // if the directory does not exist then
{
directory.mkpath("."); // we create the path
}
QString fileName = getCurrentHourDate() + "_S12xNG_Test_Report.pdf";
QPrinter pdfPrinter(QPrinter::HighResolution);
pdfPrinter.setOutputFormat(QPrinter::PdfFormat);
pdfPrinter.setPageSize(QPageSize(QPageSize::A4));
pdfPrinter.setOutputFileName(i_path + "/" + fileName);
pdfPrinter.setFullPage(true);
QPainter painter(&pdfPrinter);
painter.setBackgroundMode(Qt::OpaqueMode);
QTextDocument measuresDoc;
QTextDocument averagesDoc;
QTextDocument inOutDoc;
measuresDoc.documentLayout()->setPaintDevice(&pdfPrinter);
measuresDoc.setPageSize(pdfPrinter.pageRect().size());
averagesDoc.documentLayout()->setPaintDevice(&pdfPrinter);
averagesDoc.setPageSize(pdfPrinter.pageRect().size());
inOutDoc.documentLayout()->setPaintDevice(&pdfPrinter);
inOutDoc.setPageSize(pdfPrinter.pageRect().size());
setMeasuresTextDocument(&measuresDoc);
setAveragesTextDocument(&averagesDoc);
setInputsOutputsTextDocument(&inOutDoc);
measuresDoc.drawContents(&painter); // We print TextDocument of the Measures into the document
pdfPrinter.newPage(); // We inject the current page and continue printing on new page
averagesDoc.drawContents(&painter); // We print the TextDocument of the Averages into the document
pdfPrinter.newPage(); // We inject the current page and continue printing on new page
inOutDoc.drawContents(&painter); // We print the TextDocument of the Inputs/Outputs into the document
measuresDoc.undo();
averagesDoc.undo();
inOutDoc.undo();
}
Here is the function to add the html data into the measures QTextDocument:
void FileEditor::setMeasuresTextDocument(QTextDocument *o_measuresDoc)
{
QString htmlContent = m_reportPageHTMLTemplate;
htmlContent.replace("[title-template]","I. Measures Data");
o_measuresDoc->setHtml(htmlContent);
}
So what i am doing wrong?
Thanks in advance for your responses.
I have found the answer!
it is about the drawContents method of QTextDocument.
There is a second parameter that you need to add in order to see the background image in your document.
It's the a QRectF object that represend the size of the rect that the background image will be clipped into.
void QTextDocument::drawContents(QPainter *p, const QRectF &rect = QRectF())
Draws the content of the document with painter p, clipped to rect. If rect is a null rectangle (default) then the document is painted unclipped.
So what I did is:
easuresDoc.drawContents(&painter, pdfPrinter.paperRect()); // We print TextDocument of the Measures into the document
pdfPrinter.newPage(); // We inject the current page and continue printing on new page
averagesDoc.drawContents(&painter, pdfPrinter.paperRect()); // We print the TextDocument of the Averages into the document
pdfPrinter.newPage(); // We inject the current page and continue printing on new page
inOutDoc.drawContents(&painter, pdfPrinter.paperRect()); // We print the TextDocument of the Inputs/Outputs into the document
pdfPrinter.paperRect is the rectangle of the page without the margin.
Also if you want the background image to be printed scaled with no repeat than you need to put the printer into QPrinter::PrinterResolution
QPrinter pdfPrinter(QPrinter::PrinterResolution);

element.addEventListener not adding listener

So I have an array of strings that will turn into buttons,
//At start
function acceptSuggestion() {
console.log(`clicked`)
console.log(this.textContent);
}
//Else where
suggestions.couldBe.innerHTML = ``;
list.suggestions.forEach(function (item) {
let button = document.createElement(`button`);
button.textContent = item;
button.addEventListener(`click`, acceptSuggestion);//before append
button.style = `text-align:center; width:50%`;
suggestions.couldBe.appendChild(button);
button.addEventListener(`click`, acceptSuggestion);//after append
suggestions.couldBe.innerHTML+=`<br>`;
});
It creates the buttons fine
But clicking them does nothing.
Why is this? I know I have the event right cuz of this: https://www.w3schools.com/js/js_htmldom_eventlistener.asp
If it matters, I am using electron.js to create an webpage like application, and not a browser.
The reason this is happening is because of this line:
suggestions.couldBe.innerHTML+="<br>";
What is happening is your Browser element is generating all new fresh HTML each loop because of the += on the innerHTML.
Basically in pseudo code:
var temp = suggestions.couldBe.innerHTML + "<br>;
suggestions.couldBe.innerHTML = temp;
This causes your element that was added via the suggestions.couldBe.appendChild(button); to be converted to html, then re-parsed and all new elements created from HTML each iteration of the loop. Because your Button event handler was created in JS; it is lost when it recreated the button from the HTML version.
You want to do this either all via JS; not mixing it. So my suggestion would be to change this line:
suggestions.couldBe.innerHTML+="<br>";
to
suggestions.couldBe.appendChild(document.createElement('br'));

Flex 4 TextArea: automatic character escaping in HTML/TextFlow links

I'm using the Spark's TextArea that contains links like this:
#hashtag
As you can see, this is a link to the Twitter search page for the specific hashtag. The hash-sign must be escaped in the query string. But, I have a problem here: when I click the link, the '%' symbol gets escaped automatically and the URL becomes corrupted (...search?q=%2523hashtag). Can I turn off this automatic escaping?
The '#' sign, if used in the URL, does not become escaped, and therefore the Twitter page does not open correctly in this case. So I cannot use neither '#' nor '%23' in the URL.
I would appreciate any solution for this.
Thank you.
Ok... so far, I couldn't find a way to turn off the automatic escaping of the URL when it's clicked. But I've found the workaround instead.
Basically, I add a custom click handler to all the link elements inside the TextFlow and open the links manually when clicked (instead of a built-in TLF behavior). Like this:
public function addLinkHandler( textFlowOrGroupElement: FlowGroupElement ): void
{
// scan the flow elements
for ( var f1: int = 0; f1 < textFlowOrGroupElement.numChildren; f1 ++ ) {
// found element
var curFlowGroupElement: FlowElement = textFlowOrGroupElement.getChildAt( f1 );
// if this is the link element, add the click event listener
if ( curFlowGroupElement is LinkElement ) {
( curFlowGroupElement as LinkElement ).addEventListener( FlowElementMouseEvent.CLICK, onLinkClick );
}
// if this is another flow group
else if ( curFlowGroupElement is FlowGroupElement ) {
// scan this group in turn, recursively
addLinkHandler( curFlowGroupElement as FlowGroupElement );
}
}
}
and here is the click handler for the links:
public function onLinkClick( e: FlowElementMouseEvent ): void
{
e.stopImmediatePropagation();
e.preventDefault();
var linkElement: LinkElement = e.flowElement as LinkElement;
navigateToURL( new URLRequest( linkElement.href ), '_blank' );
}
So in the end to make the Twitter-hashtag links work correctly in the TextArea, I do this:
addLinkHandler( textArea.textFlow );
P.S. The algorithm of adding the click handlers is based on this post, but optimized.

LibTiff.NET append mode bug?

I've started using LibTiff.NET for writing tiff IPTC tags lately and discovered strange behavior on some files that i have here. I'm using sample code that ships with LibTiff.NET binaries, and it works fine with most of the images, but some files are having image data corruption after these lines:
class Program
{
private const TiffTag TIFFTAG_GDAL_METADATA = (TiffTag)42112;
private static Tiff.TiffExtendProc m_parentExtender;
public static void TagExtender(Tiff tif)
{
TiffFieldInfo[] tiffFieldInfo =
{
new TiffFieldInfo(TIFFTAG_GDAL_METADATA, -1, -1, TiffType.ASCII,
FieldBit.Custom, true, false, "GDALMetadata"),
};
tif.MergeFieldInfo(tiffFieldInfo, tiffFieldInfo.Length);
if (m_parentExtender != null)
m_parentExtender(tif);
}
public static void Main(string[] args)
{
// Register the extender callback
// It's a good idea to keep track of the previous tag extender (if any) so that we can call it
// from our extender allowing a chain of customizations to take effect.
m_parentExtender = Tiff.SetTagExtender(TagExtender);
string destFile = #"d:\00000641(tiffed).tif";
File.Copy(#"d:\00000641.tif", destFile);
//Console.WriteLine("Hello World!");
// TODO: Implement Functionality Here
using (Tiff image = Tiff.Open(destFile, "a"))
{
// we should rewind to first directory (first image) because of append mode
image.SetDirectory(0);
// set the custom tag
string value = "<GDALMetadata>\n<Item name=\"IMG_GUID\">" +
"817C0168-0688-45CD-B799-CF8C4DE9AB2B</Item>\n<Item" +
" name=\"LAYER_TYPE\" sample=\"0\">athematic</Item>\n</GDALMetadata>";
image.SetField(TIFFTAG_GDAL_METADATA, value);
// rewrites directory saving new tag
image.CheckpointDirectory();
}
// restore previous tag extender
Tiff.SetTagExtender(m_parentExtender);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
After opening i see mostly blank white image or multiple black and white lines instead of text that have been written there (i don't need to read\write tags to produce this behavior). I noticed this happens when image already has a custom tag (console window alerts about it) or one of tags have got 'bad value' (console window in this case says 'vsetfield:%pathToTiffFile%: bad value 0 for "%TagName%" tag').
Original image: http://dl.dropbox.com/u/1476402/00000641.tif
Image after LibTiff.NET: http://dl.dropbox.com/u/1476402/00000641%28tiffed%29.tif
I would be grateful for any help provided.
You probably should not use CheckpointDirectory method for files opened in append mode. Try using RewriteDirectory method instead.
It will rewrite the directory, but instead of place it at it's old
location (as WriteDirectory() would) it will place them at the end of
the file, correcting the pointer from the preceeding directory or file
header to point to it's new location. This is particularly important
in cases where the size of the directory and pointed to data has
grown, so it won’t fit in the space available at the old location.
Note that this will result in the loss of the previously used
directory space.

printing just canvas element on a page

im a little stuck using the canvas element in html5, have scoured the net looking for a workable solution but to no avail!
the main issue is that I want to click a button and send just the canvas element on the page to the printer.
i have tried using toDataUrl() - but this just seems to be resulting in a blank white image which has none of the canvas content!
the other issue i am experiencing is that attempting to initiate any javascript functions using "onClick" attached to a form button seems to be being tempermental at best!
here is my current attempt - this works in the sense that it does open a new window and attempt to send it to printer and it does create a base64 string (tested this using the "dataUrl" output on the second lowest document.write line) but as previously mentioned the image appears to be completely blank! (the canvas itself is definitely filled, both with an imported image and some text)
function printCanv()
{
var dataUrl = document.getElementById('copy').toDataURL(); //attempt to save base64 string to server using this var
document.getElementById('testBox').value = dataUrl; //load data into textarea
//attempt open window and add canvas etc
win = window.open();
self.focus();
win.document.open();
win.document.write('<'+'html'+'><'+'head'+'><'+'style'+'>');
win.document.write('body, td { font-family: Verdana; font-size: 10pt;}');
win.document.write('<'+'/'+'style'+'><'+'/'+'head'+'><'+'body'+'>');
((image code is here but site will not let me post it for some reason?))
win.document.write(dataUrl);
win.document.write('<'+'/'+'body'+'><'+'/'+'html'+'>');
win.document.close();
win.print();
win.close();
}
note: the code from "win = window.open()" onwards is currently taken from a tutorial and not my own work!
it is currently being called using <body onload="printCanv";"> - for some reason I could not get this to work at all using a button (little chunk of code below is my attempt which seemed to fail)
<input type="button" id="test" value="click me" onClick="printCanv();"> </input>
apologies is this help request is all over the place! i haven't posted to a site like this before and it didn't like me posting some html/script!
thanks in advance for any help you may be able to offer :)
Edit: draw function:
function copydraw() { //function called "copydraw" (could be anything)
var testimage3 = document.getElementById('copy').getContext('2d'); //declare variable for canvas overall (inc paths)
var img3 = new Image(); //declare image variable called "img3"
var testVar = document.getElementById('userIn').value; //take value from userin box. only updating on browser refresh?
img3.onload = function(){ //when image has loaded (img.onload) run this function
testimage3.drawImage(img3,0,0); //draw "img" to testimage
testimage3.font = "30pt 'Arial'"; //font method varies font attrib (weight, size, face)
testimage3.fillStyle = "#000000"; //sets fill color
testimage3.fillText(testVar, 310, 360); //filltext method draws text (xup ydown)
}
img3.src = 'images/liecakeA4.jpg'; //source of image
}
This function works perfectly, it draws the object and adds text from the variable, but for some reason it seems to be preventing me from outputting it as an image. I'm really confused!
I'm not sure exactly what's wrong with your code, I suspect in your current version calling printCanv in the body load event will mean you're trying to print the canvas before it's drawn. Running it off the button should work better, I'm not sure why that wasn't working for you as there's no reason in principle why it shouldn't work.
To arrive at a working version I've modified your code slightly:
function printCanvas(el) {
var dataUrl = document.getElementById(el).toDataURL(); //attempt to save base64 string to server using this var
var windowContent = '<!DOCTYPE html>';
windowContent += '<html>'
windowContent += '<head><title>Print canvas</title></head>';
windowContent += '<body>'
windowContent += '<img src="' + dataUrl + '">';
windowContent += '</body>';
windowContent += '</html>';
var printWin = window.open('','','width=340,height=260');
printWin.document.open();
printWin.document.write(windowContent);
printWin.document.close();
printWin.focus();
printWin.print();
printWin.close();
}
This works for me in the Firefox 4.0 nightly.
One addition to the accepted-best-answer: It doesnt work here with Chrome 17.0.942.0 winvista, because the print-preview-dlg is shown within the website itself and printWin.close() will close the dlg too.
So printWin.close() must be delayed or initiated by the user, but those are no good solutions.
It would be best, if chrome printdlg could have a callback, sth. one knows, printing is done, and can close the window. If this is possible is another question.