How to load TinyMCE Editor through WebView within jar? - jar

In my JavaFX project, I am trying to integrate the TinyMCE editor as a HTML rich text editor via WebView. Here is a demo app:
package tinydemo;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class TinyDemo extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Demo");
WebView webView = new WebView();
webView.getEngine().load(TinyDemo.class.getResource("simple.html").toExternalForm());
StackPane root = new StackPane();
root.getChildren().add(webView);
primaryStage.setScene(new Scene(root, 500, 400));
primaryStage.show();
}
}
I am using Netbeans IDE, the package view is:
The content of simple.html :
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Simple theme example</title>
<script type='text/javascript' src='jquery-1.5.2.min.js'></script>
<script type="text/javascript" src="tiny_mce/tiny_mce.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var wewe = document.getElementById('wewe');
wewe.innerHTML += '<br/>protocol: '+ document.location.protocol;
tinyMCE.init({
mode : "textareas",
theme : "simple"
});
});
</script>
</head>
<body>
<div id="wewe"></div>
<h3>Simple theme example</h3>
<textarea id="elm1" name="elm1" rows="15" cols="80" style="width: 80%">
This is some example text that you can edit inside the <strong>TinyMCE editor</strong>.
</textarea>
<script type="text/javascript">
if (document.location.protocol == 'file:') {
alert("The examples might not work properly on the local file system due to security settings in your browser. Please use a real webserver.");
}
</script>
</body>
</html>
Now, when I run the app from Netbeans, the TinyMCE editor loads successifully with the file protocol detected.
However, when I run the generated TinyDemo.jar from the command line under the folder dist, I get this:
Where TinyMCE editor is failed to load. I think the problem is absolute/relative path references of TinyMCE within jar, but could not resolve it. Any help is appreciated. Thanks.

According to this forum discussion thread relative resource loading currently only works correctly in the 2.1 developer preview of JavaFX and not in the 2.0GA version.
If, after upgrading to the 2.1 preview version of JavaFX, loading resources from a jar still doesn't work, then you could deploy TinyMCE on the classpath but outside of the packaged jar so that it is loaded using (for example) the file or http protcols rather than the jar protocol. Or you can develop a custom protocol handler which loads resources from the jar as discussed in the referenced thread.

Related

Spring Boot + Thymeleaf css is not applied to template

I am evaluating Thymeleaf and Flying Saucer for pdf generation from templates, and I am having a problem with applying css to my Thymeleaf template. I already read the relevant questions & answers here, here, and here; but none of the suggested solutions fixed my problem.
This is how my resources folder looks like:
So I am using the default directories that Spring will look for. And that's how the head tag looks like in my template.html:
<head>
<title>Spring Boot and Thymeleaf Example</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="../static/css/style.css" th:href="#{/css/style.css}"/>
</head>
If I inline my css in template.html then the generated pdf file will be styled properly (so there shouldn't be a problem with how I generate the pdf). However, when I try to link to the css file as shown above the generated pdf is not styled (so the css is not applied).
Lastly, I can access my css file at http://localhost:8080/css/style.css, so there doesn't seem to be a problem with Spring serving the static content.
For completeness, this is how I generate the pdf:
private final SpringTemplateEngine templateEngine;
private final Log log;
#Autowired
public PdfGenerator(SpringTemplateEngine templateEngine) {
this.templateEngine = templateEngine;
log = LogFactory.getLog(getClass());
}
public void generate(HttpServletRequest servletRequest, HttpServletResponse servletResponse, ServletContext servletContext) {
// Parse the pdf template with Thymeleaf
Locale locale = getLocale(servletRequest);
WebContext context = new WebContext(servletRequest, servletResponse, servletContext, locale);
context.setVariable("user", buildDummyUser());
context.setVariable("discounts", buildDummyDiscounts());
String html = templateEngine.process("template", context);
// Create the pdf with Flying Saucer
try (OutputStream outputStream = new FileOutputStream("generated.pdf")) {
ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(html);
renderer.layout();
renderer.createPDF(outputStream);
} catch (IOException | DocumentException e) {
log.error("Error while generating pdf", e);
}
}
I am using WebContext instead of Context because I was getting the following error with Context:
org.thymeleaf.exceptions.TemplateProcessingException: Link base "/css/style.css" cannot be context relative (/...) unless the context used for executing the engine implements the org.thymeleaf.context.IWebContext interface
What am I missing here, why is my style.css not applied to template.html?
I had same problems and I was also trying to use thymeleaf template resolver for pdf generation. I did lots research on thymeleaf and spring framework, I tried WebContext, I tried HttpServletRequest, I tried some of Spring Thymeleaf integration solutions it was not working either. So I think it was not syntax error, and I finally end up with using absolute path instead of relative.
Url for reference
Here the reason with my assumption, lets say our resources are served on localhost:8080/myapp/css/style.css. And the relative path to request resource is really ups to what context it relatives to.
For eaxmple a normal thymeleaf model Veiw, which return as html pages on browser for client, so the context in that case would be the request hostname, port and application context(eg: localhost:8080/myapp). And relative path will be based on that. So if relative path is /css/style.css, context + relative path will result to be localhost:8080/myapp/css/style.css
Unlike web context, in our case, offline template is on server backend, so the context I assume would be the server running context, which would be the local server path + appcontext(eg: D:/myServer/apps/myapp), relative path /css/style.css on this would be D:/myServer/apps/myapp/css/style.css, this is not make sense. In order to use static resources, I have to pass it's absolute path.
I started use :
<link rel="stylesheet" type="text/css" th:href="#{http://localhost:8080/myapp/css/style.css}"/>
It's working fine but what if there are multiple host names or server is running on a proxy, then this is going to be a hard coded solution. It's better to know what is the real base url the user is requesting. So we can't really get rid off HttpSevletRequest.
Here is my code:
1.Config resource handler:
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/css/**")
.addResourceLocations("classpath:/css/")
.setCachePeriod(31556926);
}
Get base url from HttpServletRequest, you can inject it in method or autowired in your service class, or get from RequestContextHolder. I write this in my Service class:
private static String getCurrentBaseUrl() {
ServletRequestAttributes sra = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest req = sra.getRequest();
return req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + req.getContextPath();
}
This is the place I use template engine in my class:
Context context = new Context();
context.setVariable("variales", variables);
context.setVariable("baseUrl", getCurrentBaseUrl());
String content = springTemplateEngine.process("myTemplate",context);
In my template, I use absolute css url like this:
<link type="stylesheet" th:src="#{|${baseUrl}/css/style.css|}" />
Syntax looks fine so the problem is not with the syntax.
Also you cannot use #{...} syntax without an IWebContext interface so You are getting this exception.
I had a similar problem - my css was not applied to my template page.
My problem was that the css file was in css sass format
.table
margin: 0 0 40px 0
when I convert it to the normal css format like
.table {
margin: 0 0 40px 0;
}
it worked
I solved this problem by changing the path structure in href. I had the same directory structure as you (html files are in templates doc, css files are in static doc).
<head>
<title>Spring Boot and Thymeleaf Example</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="/css/style.css"/>
</head>
It might help you to apply css to your html page.
I found a lazy man's way of taking care of this. It works, with a very simple approach. The 'inserted' fragment is just a CSS style tag in the body of a simple HTML document. I place this in the HEAD of my target file, right where I would have put the LINK REL tag:
<th:block th:insert="std-reports/std-reports-css-fragment.html :: style"></th:block>

JxBrowser onStartLoadingFrame Data Passing Issue

I am currently using JxBrowser 6.19.1 and I would like to ask if it is possible to set a variable value when I first start loading a page, by using onStartLoadingFrame. Then I am going to use that data in the page.
For example:
final JFrame frame = new JFrame("Hello World!");
final Browser browser = new Browser();
BrowserView view = new BrowserView(browser);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(view, BorderLayout.CENTER);
frame.setSize(400, 300);
frame.setVisible(true);
browser.addLoadListener(new LoadAdapter() {
#Override
public void onStartLoadingFrame(StartLoadingEvent event) {
browser.executeJavaScriptAndReturnValue("var data = 1"); // does not work every single time, real question
}
});
browser.loadURL("echo.html");
where my echo.html will be something like this:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<h1>Echo Page</h1>
<script>
alert(data);
</script>
</body>
The question comes, sometimes it prompt the alert, sometimes doesn't. Does anyone know why? (Due to Multitheading?) Is that any work around for this?
Hope someone can help me with that. Thanks.
If you need to execute some JavaScript code before any other JavaScript on the loaded web page is executed, then you should use the onScriptContextCreated JavaScript context event as shown below:
browser.addScriptContextListener(new ScriptContextAdapter() {
#Override
public void onScriptContextCreated(ScriptContextEvent event) {
event.getBrowser().executeJavaScript("var data = 1");
}
});
In this case, the data JavaScript variable will be set properly, and the script on the web page will always work as expected.

Unable to get unique id for element error with GUI extension popup

I'm building a GUI extension that includes a popup that is opened on the click of a new button in the ribbon bar. The popup includes a dropdown that is dynamically populated with some information gathered from the system using the Core Service. At least that's the idea. I am able to get the button to appear, and it opens the popup, but as soon as I start with the javascript for the popup I get an error Unable to get unique id for element and the CME doesn't finish loading. Here's what I have so far:
Popup ASPX
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="SwitchUserPopup.aspx.cs" Inherits="SwitchUser.Popups.SwitchUserPopup" %>
<%# Import Namespace="Tridion.Web.UI.Core" %>
<%# Import Namespace="Tridion.Web.UI" %>
<%# Import Namespace="System.Web" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="http://www.sdltridion.com/web/ui/controls">
<head runat="server">
<title>Select User</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>Select User</h1>
<c:dropdown id="SwitchUserDropdown" runat="server" nullable="false"/>
</div>
</form>
</body>
</html>
Popup ASPX Code
namespace SwitchUser.Popups
{
[ControlResourcesDependency(new [] { typeof(Popup),
typeof(Tridion.Web.UI.Controls.Button),
typeof(Stack),
typeof(Dropdown),
typeof(List) })]
[ControlResources("SwitchUser.Resources")]
public partial class SwitchUserPopup : TridionPage
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
TridionManager tm = new TridionManager();
tm.Editor = "SwitchUser";
System.Web.UI.HtmlControls.HtmlGenericControl dep =
new System.Web.UI.HtmlControls.HtmlGenericControl("dependency");
dep.InnerText = "Tridion.Web.UI.Editors.CME";
tm.dependencies.Add(dep);
System.Web.UI.HtmlControls.HtmlGenericControl dep2 =
new System.Web.UI.HtmlControls.HtmlGenericControl("dependency");
dep2.InnerText = "Tridion.Web.UI.Editors.CME.commands";
tm.dependencies.Add(dep2);
//Add them to the Head section
this.Header.Controls.Add(tm); //At(0, tm);
}
}
}
Popup JS
Type.registerNamespace("SwitchUser.Popups");
SwitchUser.Popups.SwitchUser = function (element) {
Type.enableInterface(this, "SwitchUser.Popups.SwitchUser");
this.addInterface("Tridion.Cme.View");
};
SwitchUser.Popups.SwitchUser.prototype.initialize = function () {
$log.message("Initializing Switch User popup...");
this.callBase("Tridion.Cme.View", "initialize");
var p = this.properties;
var c = p.controls;
c.UserDropdown = $controls.getControl($("#SwitchUserDropdown"), "Tridion.Controls.Dropdown");
};
$display.registerView(SwitchUser.Popups.SwitchUser);
The extension is configured correctly in System.config - I can see the log message in the javascript console. However, I also see this Unable to get unique id for element error with the following additional information:
anonymous(object{..})
WebRequest.completed(object{..})
Net.loadFile$onComplete(object{..})
Net.loadFile$onOperationCompleted()
Xml.loadXmlDocuments$onSuccess(array1)
Xml.loadXmlDocument$onSuccess(array1)
Dropdown.setup$filesLoaded(object{..})
setupDone()
anonymous(function: DisplayController$start())
DisplayController.start()
anonymous()
anonymous(undefined, "Tridion.Controls.Dropdown")
Tridion.Assert$raiseError("Unable to get unique id for element.")
From that logged info it seems that the problem is the dropdown. If I comment out the line in my JS that registers the view then I don't get the error, but I also don't get the log message so I suspect that this is a mandatory call. Can anyone shed any light on why this might be happening? I've been using the Example PowerTool code as a reference, and I believe I've replicated what is there...
Update
I tried to step through the code - I found a suitable line and placed a breakpoint there. Then I reloaded the CME and suddenly my breakpoint was on a line that had no relevance to my code, and I couldn't find anything related to my code. However, according to the console it is still being executed.
So, instead I put log messages in my initialize method as follows:
SwitchUser.Popups.SwitchUser.prototype.initialize = function () {
$log.message("Initializing Switch User popup...");
this.callBase("Tridion.Cme.View", "initialize");
$log.message("Tridion.Cme.View callBase done");
var p = this.properties;
var c = p.controls;
$log.message("Set properties and controls");
c.UserDropdown = $controls.getControl($("#SwitchUserDropdown"), "Tridion.Controls.Dropdown");
$log.message("Got UserDropdown control");
};
I can see in the console that it logs as far as Set properties and controls and then I get the error.
I put a breakpoint in the getControl method and was able to determine why I was getting the error. $("#SwitchUserDropdown") was not finding anything so when the code below was running it threw the error:
var id = Tridion.Utils.Dom.getUniqueID(element);
if (id)
{
var control = instances[id];
if (!control)
{
control = instances[id] = new ctor(element, settings);
if (Tridion.Type.isFunction(control.initialize))
{
control.initialize();
}
}
}
else
{
Tridion.Utils.Assert.raiseError("Unable to get unique id for element.");
}
return control;
It seems obvious now that I know why it was happening that the code was running at the wrong time. I believe it shouldn't run when the CME loads, but only when the popup is opened. This leads me to look at the configuration of the resources in my Editor config file. I had previously grouped my popup's JS with other resources associated with the ribbon toolbar button. By placing the popup specific resources in their own resource group I was able to stop the error and successfully get the control.

Add a custom class to a project in webmatrix

im new in asp.net and im trying to add a custom class to my proyect.
i created a file called Test.cs
public class Test
{
public string sayHello()
{
return "Hello World";
}
}
and in my Default.cshtml :
Test example = new Test();
#example.sayHello();
But i get a error trying to load Test class... I need to include something with "using"? I need to compile with visual studio to create custom classes? or i miss something?
Thanks for help guys.
You must create a new dir named "App_Code" in the root of your site and move your Test.cs in it.
Then, this Default.cshtml works:
#{
Test example = new Test();
var message = example.sayHello();
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<p>#message</p>
</body>
</html>

Can't display text after displaying image in servlet?

I wrote a servlet which takes the name of a image from the client and displays it to client by converting it to byte array.after displaying the image now when i am trying to print some text i m not able to do so.it simply doesn't print the text even after using PrintWriter.
I am using jboss application server to deploy it.
here is the servlet-Image.java:
package javaserv.image;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.swing.ImageIcon;
public class Image extends HttpServlet {
private static final long serialVersionUID = 1L;
public Image()
{
super();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String imagename = request.getParameter("imagename");
File fileimage = new File("C:/langs/projects/javaserv/"+imagename+".jpg");
byte [] imagearray;
imagearray = new byte[(int)fileimage.length ()];
FileInputStream fis = new FileInputStream (fileimage);
fis.read (imagearray);
response.setContentType("image/jpeg");
response.setContentLength((int)fileimage.length ());
ServletOutputStream out = response.getOutputStream();
int i=0;
while(i<imagearray.length)
{
out.write(imagearray[i]);
++i;
}
out.flush();
out.close();
out = response.getOutputStream();
response.setContentType("text/html");
out.println("<html><body>");
out.println("here is your image");
out.println("<p>");
out.println("</html></body>");
out.close();
}
}
"imagename" is the name of the image entered by client
You can either write your JPEG to the out, or the HTML, not both.
Your code writes the JPEG to the output, closes the output stream, then tries to open it again to write some HTML.
If you want to display a synamic image on a HTML page, you should be using a servlet for the image, and a JSP page for the HTML.
You basically need to let the client fire two HTTP requests. One to the HTML which in turn contains an <img> element which let the webbrowser automagically send another HTTP request to the image file.
First create a HTML page like follows:
<!DOCTYPE html>
<html lang="en">
<head>
<title>An image</title>
</head>
<body>
<p>Here is your image</p>
<p><img src="images?imagename=foo.gif"></p>
</body>
</html>
Where I assume that your image servlet is listening on an url-pattern of /images. Finally just give the enduser the URL to the HTML page (can also be a JSP page by the way) instead of the URL to the image. The enduser will then retrieve a HTML page with some text and an image.
That said, your imageservlet is honestly said pretty poor written in terms of speed, memory efficiency and resource handling. I'd suggest to have a look for this basic example how to do it properly.
You can inline the image, then the browser only does one request.
<img src="data:image/png;base64,....

Resources