ZK Textbox content containing <html> tag - zk

When I put the string '' into a ZK Textbox, that is
<textbox value="<html>" />
it causes a JavaScript error in the browser
Uncaught SyntaxError: Unexpected token ILLEGAL
and I can see in the developer tools of the browser that the generated JS code is really incomplete:
zkmx(
[0,'g2JQ_',{dt:'z_y20',cu:'\x2Fdtag',uu:'\x2Fdtag\x2Fzkau',ru:'\x2Fzul\x2Fcomponent\x2Fmenu.zul',style:'width\x3A100\x25\x3B',ct:true},[
...
['zul.inp.Textbox','g2JQp7',{id:'tb',$$0onBlur:true,$$0onSwipe:true,$$0onError:true,$$0onAfterSize:true,$$0onChanging:true,$$1onChange:true,$$1onSelection:true,$$0onFocus:true,width:'500px',style:'font-size:11px;',_value:'
</div>
How can I escape the content of the textbox so that I can display any HTML code in the textbox?
I tried
Replace '<' with '> but then > is displayed.
I also tried
<![CDATA[ <html></html>]]>
but then it was literally displayed, that is, also the
<![CDATA[
UPDATE
It is somehow due to the fact that we have JSPs containing several ZK pages.
And the exact content what causes problem is the closing HTML tag
</html>
The workaround is the following:
Events.echoEvent("onLater", txtDescription, txtDescription);
txtDescription.addEventListener("onLater", new EventListener<Event>() {
#Override
public void onEvent(Event event) throws Exception {
txtDescription.setValue("<html>...</html>");
}
});

Normally you should get values from your composer or viewmodel, and then this problem doesn't exist.
If you want to do it in the zul, you can make a parameter in zscript like this :
<zscript>
<![CDATA[
String a = "<html>";
]]>
</zscript>
<textbox value="${a}" />
Here I created a fiddle so you can test it.

Many time we have saved HTML code in database but when we are going to display that saved value in zk page it show HTML code as well with data .
To resolve this issue we have to use HTML escape there are plenty of way to fix this
You can do it on Java side as well zul page and here is simple way how you can achieve in the zul page
<html>
<![CDATA[
${vm.accessYourValue}
]]>
</html>

Related

How to use onclick method inside AEM component

Am having a AEM6 html component, am getting the values from dialog and using it inside the component via the .js file and using the return properties.
I could able to get the authored values but it is getting null or empty when am using it inside the onclick method. Please find below the code snippet below.
<div data-sly-unwrap data-sly-use.test="test.js"></div>
<a href="#" class="${test.testId}" id="${test.testId}" onClick="toggleDraw('${test.testId}')" >
The content I authored is getting displayed in class and Id, but it is not displaying in the onClick method.
Below is the Output am getting after authoring.
<a href="#" class="get-a-quote" id="get-a-quote" onClick="toggleDraw('')" >
Output I needed is :
<a href="#" class="get-a-quote" id="get-a-quote" onClick="toggleDraw('get-a-quote')" >
This should do the trick:
<a data-sly-test.variable123="toggleDraw('${test.testId}')" href="#" class="${test.testId}" id="${test.testId}" onclick="${variable123 # context='attribute'}" >
You need to put the function call in a variable because of the nested single quotes. And you need to manually set the context in this case. If "attribute" does some escaping you do not like, you could use "unsafe" - this will end in all escaping mechanisms being disabled. That might or might not be a security issue for your application.
HTH

XForms and restxq application

I am trying to create a simple interface, that will use XForms to display a button that say "Drop a Database". I then want to be able to invoke a RestXQ document called dropdatabase.xqm which is called when the button on the form is clicked. I am using BaseX. I saved my XForm in a file called onlydel.xml in the basex/webapp/static folder. I created my RestXQ program called dropdatabase.xqm and saved it to my basex/webapp folder. I have created a database called patients.
xforms: The contents of onlydel.xml is:
<?xml-stylesheet href="xsltforms/xsltforms.xsl" type="text/xsl"?>
<?xsltforms-options debug="yes"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<head>
<title>XFORMS IN XHTML</title>
<model xmlns="http://www.w3.org/2002/xforms" id="order-model">
<instance>
<soap xmlns="">
</soap>
</instance>
<submission action="/dropdatabase" method="post" id="s06"/>
</model>
</head>
<body>
<h2>DATABASE</h2>
<div style="float:center;">
<fieldset style="width:50%">
<xf:submit submission="s06"><xf:label>Drop A Database</xf:label></xf:submit>
</fieldset></div>
</body>
</html>
RestXQ :The contents of dropdatabase.xqm is:
module namespace _ = 'http://exquery.org/ns/restxq';
(:~
: Deletes the blog database and redirects the user to the main page.
:)
declare
%restxq:path("/dropdatabase")
%restxq:GET
function _:dropdatabase()
{
(db:drop("patients"))
};
When I run this I get the following error:
Stopped at /home/ubuntu/basex/webapp/dropdatabase.xqm, 10/13:
[XUST0001] StaticFunc expression: no updating expression allowed.
The help I need is:
Can I do something like this with the code I have written.
What is the reason for the error and a solution to eliminate the error too would be helpful
The error message seems quite clear to me: db:drop() is an updating expression and is hence not allowed at this point. You have to mark the function as an updating function by using the %updating annotation.

Tapestry 5 custom component in form - access during validation

A have problem with accessing my custom components (which are used as parts of the form).
Here is the story:
I have dynamic form which have few modes of work. Each mode can be selected and loaded into form body with AJAX. It looks like that (template):
<t:form t:id = "form">
<p class= "calcModeTitle">
${message:modeLabel}: <select t:id="modeSelect"
t:type="select"
t:model="modesModel"
t:value="selectedMode"
t:blankOption="NEVER"
t:encoder="modeEncoder"
t:zone = "modeZone"
/>
</p>
<div class="horizontal_tab">
<t:errors/>
</div>
<t:zone t:id="modeZone" id="modeZone" t:update="show">
<t:if test="showCompany">
<t:delegate to="block:companyBlock" />
</t:if>
<t:if test="showPersonal">
<t:delegate to="block:personalBlock" />
</t:if>
<t:if test="showMulti">
<t:delegate to="block:multiBlock" />
</t:if>
</t:zone>
<t:block id="companyBlock">
<t:modes.CompanyMode t:id="company"/>
</t:block>
<t:block id="personalBlock">
<t:modes.PersonalMode t:id="personal" />
</t:block>
<t:block id="multiBlock">
<t:modes.MultiMode t:id="multi" />
</t:block>
<div class="horizontal_tab">
<input type="submit" value="${message:submit_label}" class="submitButton thickBtn"/>
</div>
</t:form>
AJAX works pretty well and form changes accordingly the "modeSelect" state. But i run into problem when submitting the form. I have in class definition hooks for components placed as:
//----form elements
#Component(id = "form")
private Form form;
#InjectComponent
private CompanyMode company;
#InjectComponent
private PersonalMode personal;
#InjectComponent
private MultiMode multi;
where *Mode classes are my own components, containing form elements and input components. I planned to get access to them during validation, and check values supplied by user with form, but when I am trying to reach anything from them I've got nullPointerException - it seems that component are not initialized in my class definition of form. On the other hand form component is injected properly (I am able to write some error for example). I am a bit lost now. How to properly inject my components to class page containing the form?
Dynamic forms in tapestry are a bit complicated. Tapestry passes a t:formdata request parameter which contains the serialized form entities. This is then used serverside in the POST to re-hydrate initial form state. This must be kept up-to-date with what the client sees.
If you want to add dynamic content to a form via ajax, you will need to use the FormInjector. You might want to take a look at the source code for the AjaxFormLoop to see an example.
If you want to render hidden form fragments and make them visible based on clientside logic, you can use the FormFragment
From tapestry guide:
A block does not normally render; any component or contents you put
inside a block will not ordinarily be rendered. However, by injecting
the block you have precise control over when and if the content
renders.
Try to use here either "t:if" or "t:delegate".
Something like this:
<t:zone t:id="modeZone" id="modeZone" t:update="show">
<t:delegate to="myBlock" />
</t:zone>
<t:block t:id="companyBlock">
<t:modes.CompanyMode t:id="company"/>
</t:block>
<t:block t:id="personalBlock">
<t:modes.PersonalMode t:id="personal" />
</t:block>
<t:block t:id="multiBlock">
<t:modes.MultiMode t:id="multi" />
</t:block>
java:
#Inject
private Block companyBlock, personalBlock, multiBlock;
public Block getMyBlock(){
if (getShowCompany()) return companyBlock;
if (getShowPersonal()) return personalBlock;
return multiBlock;
}

Is the inputmode attribute valid (in HTML5 forms) or not?

I am getting validation errors with the inputmode attribute on text areas and text fields. The validator tells me Attribute inputmode not allowed on element input at this point but the HTML5 spec indicates that it is allowed.
Is there actually something wrong with this code, or is the validator at fault?
Here is a bare bones case which will produce exactly this kind of validation error (twice), in one case on an email input, and on the other on a textarea.
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<form method="post" action="contactme.php">
<label class='pas block'>
Your E-Mail:<br/>
<input type='email' name='email' required inputmode='latin' placeholder='your e-mail here' />
</label>
<label class='pas block'>
Your Message:<br/>
<textarea name='message' required inputmode='latin' placeholder='and your message here!'></textarea>
</label>
</form>
</body>
</html>
Also, see the chart about which attributes apply to the different input types here:
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#attr-input-type
The "inputmode" attribute applies only to "text" and "search".
UPDATE 2019-09-04: "inputmode" is now a global attribute (per WHATWG) and can be specified on any HTML element: https://html.spec.whatwg.org/multipage/dom.html#global-attributes
Another reference page for "inputmode":
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inputmode
On another note, "inputmode" is not a W3C HTML5 attribute, but it is a W3C HTML 5.1 attribute (at least at the time I'm writing this). UPDATE 2019-09-04: "inputmode" has been removed from HTML 5.2 and HTML 5.3.
The HTML5 spec says
The following content attributes must not be specified and do not apply to the element: accept, alt, checked, dirname, formaction, formenctype, formmethod, formnovalidate, formtarget, height, inputmode, max, min, src, step, and width.
It's under bookkeeping details at https://html.spec.whatwg.org/multipage/input.html#e-mail-state-(type=email)
Five years after the question was asked, some may wonder why some of the properties listed by #dsas doesn't trigger such errors, like enctype
The answer is simple support, while enctype for instance gained a wide support
inputmethod is supported only as of IE11 and Edge 14, for more infos click here

AJAXControlToolkit TabContainer - bug in dynamically adding/removing tabs?

I am using AjaxControlToolkit version 4.1.40412.0, .NET 4.0, VS2010
Using the TabContainer control I want to add/remove tabs dynamically, but it looks like all of my dynamic changes are not persistent. Here is my scenario: I start with a tabcontainer with 1 tabpanel (hardcoded, i.e. added at design time), then dynamically I add more tabpanels and hide the original tabpanel (run time). As expected I see only the new tabpanels on the page, however any time I try to select a different tab the whole control reverts back to its design time state, i.e. only shows the original tabpanel, which was supposed to be gone and the new tabpanels are nowhere to be found. What am I missing? I guess as a workaround I can add 50 or so tabs at design time and then dynamically hide/display rather than remove/add, but this seems clunky, sloppy and unnecessary.
Here is my code if you want to duplicate the issue:
ASPX
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="WebForm1.aspx.vb" Inherits="WebApplication1.WebForm1" %>
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>
<!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">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server"/>
<asp:TabContainer ID="tcMain" runat="server" AutoPostBack="true" ScrollBars="auto" >
<asp:TabPanel ID="tbTab0" runat="server" HeaderText="Tab0"/>
</asp:TabContainer>
</div>
</form>
</body>
</html>
ASPX.VB
Public Class WebForm1
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
For i As Integer = 0 To 3
Dim ol As New Label
ol.Text = i.ToString
Dim oT As New AjaxControlToolkit.TabPanel
oT.Controls.Add(ol)
oT.HeaderText = i.ToString
tcMain.Tabs.Add(oT)
Next
For i As Integer = 1 To tcMain.Tabs.Count
If tcMain.Tabs(tcMain.Tabs.Count - i).HeaderText = "Tab0" Then tcMain.Tabs.RemoveAt(tcMain.Tabs.Count - i)
Next
End If
End Sub
End Class
Note: If you comment out "If Not Page.IsPostBack Then" , i.e. run the code under it on every page load, the tabcontainer works as expected - I can select any tab without problems. In my real project this cannot be the solution though - I will be adding/removing tabs based on user input, so unless I keep a log of all changes ever made to the control I cannot load those changes every time the page loads.
You need to run your code in the page init or pre init, because by the page load, the page is already built along with the view state.