I need to create a code to change an example text to a user-defined value when the user types in an input field (Similar to the preview field when writing a question on Stack Overflow).
This needs to be achieved without the use of HTML5 or Flash as the users will be running IE8, not all will have Flash plug-ins installed.
As such I have started by looking at DHTML to achieve the desired effect. Currently I can change the example text when a user types in the input field but only to a pre-defined value ("Example" in the code below), how should I edit this code to display the user-defined value?
JS
function changetext(id)
{
id.innerHTML="Example";
}
HTML
<form>
Content:<input type="text" id="input" onkeyup="changetext(preview)" />
</form>
<p id="preview">No content found</p>
You need to have something like this in the function:
function changetext(id){
var info = document.getElementById('input').value();
id.innerHTML = info;
}
This js is not fully correct. I would highly recommend you start using a javascript library like jQuery. It makes this a menial task.
Edited:
jQuery will work in IE8 just fine. in jQuery you will not need to attach js to your input. The code would look like this.
$('#input').click(function(){
$('#preview).html(this.val());
});
It is a lot cleaner and doesnt have js in the html.
Related
I've tried the following to format a date in the locale of the browser:
<script>document.write((new Date(2021, 4, 14)).toLocaleString().split(",")[0])</script>
However, based on this question Document.write clears page it seems like it is writing after the document stream is closed, thereby opening a new stream and replacing the content on my page.
Using htmx is there a recommended way of formatting dates to the browser locale?
Is there an htmx tag that allows me to execute this javascript safely?
This is the html I'm using to invoke htmx:
<div hx-get="/open_orders"
hx-trigger="load"
hx-target="this"
hx-swap="outerHTML">
<img class="htmx-indicator"
src="[[=URL('static', 'images/spinner.gif')]]"
height="20"/>
</div>
-Jim
As you mentioned, document.write() does not play well with htmx. This is true for most front-end libraries/toolkits/frameworks that want to control what is displayed in the browser window.
Instead, there are a number of ways you could do this instead:
Try rendering the time on your server and simply displaying the value via htmx. This library works best when you put the server in charge whenever you can. I would recommend starting with this, if you can, instead of rendering a date via Javascript.
If you really need to update this information on the browser (for instance, to update the display as the data changes, write to a specific DOM element instead:
<span id="time"> </span>
<script>
document.getElementById('time').innerHTML = currentTime();
</script>
You can also hook in to a wide range of events that htmx triggers. This works well if you want to update information on the browser whenever htmx does something -- for instance, you can update the date/time displayed whenever htmx loads a new html fragment into the DOM.
I am perfectly aware that I can sanitize innerHTML-bound data using:
<div innerhtml.bind="someData | sanitizeHTML"></div>
However, based on my observations, this sanitization only removes <script> tags. It doesn't protect the user from event-driven content such as:
"Hi! I am some HTML-formatted data from the server! <button onclick="getRekt();">Click me for butterflies!</button>"
Is there a better way to prevent ANY type of javascript or event callbacks from being rendered on the element?
The sanatizeHTML value converter is a very simple sanitizer, and only remove the scripts tags. See the code here.
You can create your own value converter with a more complex santizer. Check this answer for more details about how to sanitize html in a browser.
But don't forget to never trust the browser, if you can it's better to sanitize the html in the server side before to send it to the browser to display it.
In my Grails project I'm using the PDF plugin to generate PDFs from gsp page.
It works well, but I would like to add more functionalities to users, so I would like to allow user to edit the PDF basic template (defined in a gsp page), in particular I would like to allow the editing of the text inside the template and store it somewhere.
Anybody knows how could it be done?
If you only want to change the text, you could store the edited text in a database with the user id and loading it into the gsp page instead of the standard text.
If you also want to change the style of the page you could try to store the whole gsp page in the database and let the user editing it with an HTML Editor.
that's how i would start with, maybe someone has an better idea
The underlying components of the pdf plugin don't strictly require a .gsp file. It simply uses .gsps rendered as strings and feeds those into the flyingsaucer lib. So you could use a WYSIWYG type editor to allow users to create html snippets, save those strings somehow and then feed those though to the flyingsaucer libs yourself. just look into the included service methods of the plugin for an example. That might sound scary, but it really isn't very complicated.
You might want to wrap the user generated content with some of your own HTML markup for sanity and styling purposes of course, but the idea you are going for is entirely doable.
You could have a GSP that behaves of two different ways. First of all the GSP will be rendered in a Editable state. In this state the user could do some edits in some parts of the GSP. After that, the GSP will be rendered in a Preview state, where user could check the modifications that he has done in the previous step (nothing can be edited in this state). Finally, the GSP will be rendered as a PDF (using Grails Rendering Plugin).
Note that user will not edit the GSP itself. You need to allow him to edit through HTML elements as Text Areas, for instance. In this case we're using an WYSWYG editor. This editor allows the user to put text as Bold, Italic, etc.
Therefore, the most important step of this solution is to distinguish the two states in the same GSP. To do that you can use a boolean variable (called editing, for instance). This variable, if true, will render the GSP with the elements that will allow him to perform changes in the document. For other side, if the editing variable is false, the GSP will be rendered just with texts, not allowing any kind of editing.
The user could Check or Uncheck checkboxes (to show or hide some part of the document) and write or change texts in the Text Areas elements.
Below I'll show how this solution works.
GSP
The GSP is a template GSP and is called _quote.gsp
The piece of code below shows the use of the editing variable. Note that if editing = true, then a textarea is rendered and user can edit the text. There is a standard text that can be changed.
The post variable keeps what user has done after the editing phase. We use JQuery serialize to get all paramaters and pass it to a Grails Controller.
<p>
<g:if test="${editing}">
<pgs:textArea html="true" autosize="true" name="fraseInicial" rows="2" cols="80">
${post?.fraseInicial?post.fraseInicial:"Conforme sua solicitação, a empresa tem a satisfação de informar-lhe os métodos e preços."}
</pgs:textArea>
</g:if>
<g:else>
${post.fraseInicial}
</g:else>
</p>
pgs:textArea is a specific taglib of this system and is used to render a WYSWYG editor, you can replace it for a simple TextArea HTML element.
An example with checkbox:
<g:if test="${editing || post.temPrazoAnalise}">
<h1>
Teste teste
</h1>
<g:if test="${editing}"><g:checkBox name="temPrazoAnalise" value="${!post?true:post?.temPrazoAnalise == null?false:true}"/></g:if>
<g:if test="${editing || post.temPrazoAnalise}">
<p>Teste teste teste </p>
</g:if>
</g:if>
Controller
The previewQuote() is called from an AJAX call that serializes (via JQuery) all parameters of GSP.
The back() action allows the user to back to the editing state from the preview state. This is the reason why we set session["paramsReport"] = params inside previewQuote(). Doing this way it's possible to use session["paramsReport"] inside back() and restore the values changed by the user.
def editQuote() {
def quote = Quote.get(params.id)
render(template: "/quote/report/quote", model: [editing:true, quote:quote])
}
def previewQuote() {
Quote quote = Quote.get(params.id)
session["paramsReport"] = params
render(template: "/quote/report/quote", model: [quote:quote, post:params])
}
def back() {
def quote = Quote.get(params.id)
if (session["paramsReport"]) {
render(template: "/quote/report/quote", model: [editing:true, post:session["paramsReport"], quote:quote])
}
}
def generateQuote() {
Quote quote = Quote.get(params.id)
def f = new File(grailsApplication.mainContext.servletContext.getRealPath("/app/temp/${quote.code}.pdf"))
if (f.exists())
f.delete()
f.withOutputStream { os ->
pdfRenderingService.render([template: '/quote/report/quote', model: [quote:this, post:session["paramsReport"], pdf:true]], os)
}
}
This solution was developed by wanderson-santos (https://stackoverflow.com/users/128857/wanderson-santos) and me.
I hope you understand the overall idea of the solution. I understand that could be a bit complicated at a first view. Anyway, is a solution that allows flexibility for this kind of requirement (i.e. allow the user to customize a report before the PDF is generated).
I'm building a google-style text box that auto-completes typed text.
Using typeahead with typeahead.js-bootstrap.css:
$(document).ready(function() {
$('#op1').typeahead({
remote: '/search/%QUERY',
});
});
<input type="text" id="op1">
it worked but there are two problems:
I could not customize it. Whenever I make any significant style changes, or use bootstrap's form-control class for input element: the text box gets completely messed up.
The auto-completed ("hint") text was written above the typed text so I whatever color I set for the hint was the color of the entire text! I tried giving the hint a negative z-order but then it was not displayed at all.
I've tried Typeahead AND Select2 auto-completion libraries with my Bootstrap 3 template, and so far the only thing I was able to work out-of-the-box without completely ruining the layout was the above code
If anyone can solve these problems, or otherwise recommend a full CSS + JS typeahead solution for Bootstrap3, I'd be grateful :)
It gives you completely easy way to customise the look with formatresults. You can even write full html view for your results. and to customise the look of input box apply a class to the wrapper for your search box and override select2 rendered css(load the page and check from browser that from where that style is coming).
http://ivaynberg.github.io/select2/
I made a full featured customised search with this.
There is now a fork available for select2 that supports Bootstrap 3.
http://fk.github.io/select2-bootstrap-css/
https://github.com/fk/select2-bootstrap-css#readme
I am able to create a simple pdf using iText api inside a struts action class.
The data that should be passed into the pdf is generated on screen based on user search parameters.
What I am wondering is how I can pass the data into the struts action so it can be displayed in the pdf?
Thanks in advance.
Similar question is already here. You just need to transfer everything that is on the page to struts action. I would do it like so:
JSP:
<div id="content">
wrap everything generated in here
</div>
<html:hidden styleId="hiddenHtml" name="hiddenHtml"/>
<html:submit onclick="setContentAsParam();">Export PDF</html:submit>
JS:
function setContentAsParam() {
document.getElementById('hiddenHtml').value = document.getElementById('content').innerHTML
}
This will set all the HTML to a action class property hiddenHtml. Get back if anything won't work, I wrote this out of my head without a test :)