I want to use the publish/subscribe framework which is used internally by Strust2 jQuery plugin.
The user can select an account number from a list or type it in a textbox.
I want to publish an event when text box or select option changes. So the user can only type textbox OR select something from select box:
<s:textfield name="account" onblur="$.publish('accountChanged',this,event)"/>
<s:select name="accountList" list="destinationAccounts"
onblur="$.publish('accountChanged',this,event)"/>
Below is the js:
$.subscribe('accountChanged', function(event, data) {
alert("New data is: " + data.value);
if ( event.target.id=='account') {
//Do something
}
}
Here are issues:
The data.value only works for textbox, for select box the data.value is undefined.
I want to know which target received the event. event.target.id is not working! I think the event object is not a jQuery event object?
I reviewed the sample showcase application, but could not find any.
Am I calling $.publish method correctly? Are there better ways?
If you subscribe to topics keep the topic name unique for each tag that allows to separate handlers for the tag. The new event is created each time you publish the topic in the onblur event. The textfield handler for topic works as you described. The select tag doesn't work because wrong parameter passed as the data. The example of the working code
<s:textfield name="account" onblur="$(this).publish('accountChanged', this, event)"/>
<s:select name="accountList" list="{'list1', 'list2','list3'}" onblur="$(this).publish('accountListChanged', this, event)"/>
<script type="text/javascript">
$.subscribe('accountChanged', function(event, data) {
alert("accountChanged: " + data.value);
});
$.subscribe('accountListChanged', function(event, data) {
alert("accountListChanged: " + data.parentElement.value);
});
</script>
As you can see the data.value is undefined because data.parentElement.value should be used. event.target.id is not working because event.originalEvent.target.id should be used. The event object is a jQuery event, but originalEvent is DHTML object which is blur.
I don't know about your requirements, if you need to subscribe/publish events or use the original event handlers, I can't say what is better in this situation.
The below code solved my issue:
As I could not find any example of publish/subscribe framework, I hope below example will help others!
The jsp will be
You must call ${this).publish not $.publish
<s:textfield name="account" onblur="$(this).publish('destinationChanged', this, event)"/>
<s:select name="accountList" list="{'list1', 'list2','list3'}" onblur="$(this).publish('destinationChanged', this, event)" emptyOption="true"/>
<s:textfield name="destinationAccount" type="hidden" />
And the JS will be
$.subscribe('destinationChanged', function(event, data) {
//If user types in the textbox
//then get the value and make the select box shows an empty option
if( !!data.value){
destinationAccount= data.value;
$('#destinationKnownAccount').val($("#destinationKnownAccount option:first").val());
} else{
//The user selected an account from select box.
// So get the value from select box and clean textbox
destinationAccount= data.parentElement.value;
$('#destinationUnknownAccount').val('');
}
//Set the hidden box
$('#destinationAccount').val( destinationAccount);
});
As mentioned one can use event.originalEvent.target.id to find which target was selected.
Related
Say I have the following line in my JSP:
<form:checkboxes path="appliedPlayers" items="${suitablePlayers}" itemValue="id" itemLabel="displayName" />
I would like to disable the form-submit button when none of the checkboxes are checked. Something like:
$('#checkboxes').change(function() {
if (none_are_checked)
disableBtn();
});
Spring form tags does not support this. You can check the following link for supported attributes.
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/spring-form-tld.html#spring-form.tld.checkboxes
What can be done is, you can handle this scenario at the client side using jQuery(like you mentioned).
<script>
$(document).ready(function(){
$('input[name=players]').change(function() {
//alert('hello');
var checkedNum = $('input[name="players[]"]:checked').length;
if (!checkedNum) {
// User didn't check any checkboxes
disableBtn();
}
});
});
</script>
Explanation: in the above code snippet, when checkbox element changes then the registered function gets called which counts the number of selected checkbox elements. If zero then it enters if condition which is the requirement.
Note: above example assumes html attribute name value for checkboxes are players. You can change your jquery selectors appropriately if needed.
Credit:
https://stackoverflow.com/a/16161874/5039001
I want to pass a javascript variable to my servlet, where I need to use it.
In javascript, the variable count returns the rows of my table and I can show count in the jsp, using $('#counter').html(count); , but I cannot pass count's value to my servlet. I tried document.getElementById("hiddenField").value=count; but it doesn't work.
Javascript
<script>
var count = 3;
$(function() {
$('#counter').html(count);
$('#addButton').bind('click', function() {
count = document.getElementById("dataTable").getElementsByTagName("tr").length;
$('#counter').html(count);
});
$('#deleteButton').bind('click', function() {
count = document.getElementById("dataTable").getElementsByTagName("tr").length;
$('#counter').html(count);
});
});
document.getElementById("hiddenField").value=count; // ???
</script>
JSP
Count: <span id="counter"></span> <%-- it works --%>
<form method="post" action="newteamsubmit">
...
<input type="hidden" id="hiddenField" name ="countRows" />
<input type="submit" name ="button1" value=" Submit " />
<input type="submit" name = "button1" value=" Cancel " />
</form>
Servlet
String cr = request.getParameter("countRows"); //I' ve tried also to convert it
// to int, but that's not my problem, since I cannot pass the value as a start
I've spent many hours, trying to figure out how I can access a javascript variable in jsp, but I haven't found any solution.
Thanks in advance.
The count is computed each time the add button or the delete button are clicked. But you only set the hidden field value once, when the page is loaded (and its value is thus hard-coded to 3).
You must set it, as you're doing for the #counter element, in your click handlers:
$('#addButton').bind('click', function() {
count = document.getElementById("dataTable").getElementsByTagName("tr").length;
$('#counter').html(count);
$('#hiddenField').val(count);
});
$('#deleteButton').bind('click', function() {
count = document.getElementById("dataTable").getElementsByTagName("tr").length;
$('#counter').html(count);
$('#hiddenField').val(count);
});
Also note that you're repeating exactly the same code in two click handlers here. You should do that only once, for the two buttons:
$('#addButton, #deleteButton').bind('click', function() {
count = document.getElementById("dataTable").getElementsByTagName("tr").length;
$('#counter').html(count);
$('#hiddenField').val(count);
});
or even, since you're using jQuery:
$('#addButton, #deleteButton').bind('click', function() {
count = $("#dataTable tr").length;
$('#counter').html(count);
$('#hiddenField').val(count);
});
document.getElementById('hiddenField').value is not set because it is outside your document.ready. Put it inside your click handler.
Make sure of 2 things -
There is only one element with id "hiddenField" on your page.
Make sure that the following code
document.getElementById("hiddenField").value=count;
is after in the page.
Just make sure that js sets the hiddenField after the element has been loaded.
3. check for any JS errors using Javascript console.
Rest it looks good
The main issue here is that you are trying to access from the server, a variable that only exists at the client. To access that variable you have to send it from the client to the server using AJAX to trigger some form of API in the backend. REST, SOAP or XML-RPC are common technologies used for this sort of thing. The server side code is used for generating the UI and providing it with data from a database or such. Commonly the UI is generated only once, and then the client calls the server asking for more data in response to user actions, like clicking a button.
Imagine a table filled with information about books: title, author, publish date etc. This table can get quite large, and traditionally this table will be split up over several pages and possibly a dynamic filter. To save bandwidth and increase the user experience by not loading the entire page from scratch you can use AJAX to ask the server for just the relevant data. Doing so the page updates dynamically and smoothly for the user.
In your case, you can use this technique to update the server every time the user clicks the button.
If however you are really just looking to update a hidden field in a form with a value as the user performs actions, and the server wont do anything with it except show it you can just use javascript.
Remember also that the request variable contains the data you post to the server when you submit the form. The servlet will get the data after the client has posted it, which is after the JSP has generated the page. The sequence of the code execution is JSP -> Javascript -> Servlet.
Hope this helps!
You can use this way:
document.forms[0].countRows.value = counter
Hope this will help you
Here is the situation. I have a drop down menu. The option sin this drop down menu are being populated by fetching some values from the database. To do this following is what i have done.. :-
<select name="product_list" onchange="selectProduct(this.value)">
<option value="none">Select one</option>
<%
List<String> options = new ArrayList<String>();
DynamicCombo comboBox = new DynamicCombo();
options = comboBox.generateComboBox();
Collections.sort(options);
int tempVar = 0;
while (tempVar < options.size()) {
out.print("<option value=\"");
out.print(options.get(tempVar));
out.print("\">");
out.print(options.get(tempVar));
out.print("</option>");
tempVar++;
}
%>
</select>
DynamicCombo is a class that has a method called 'generateComboBox()'. This method simply returns an array list containing all the values that are fetched from the database, which is what i need to show in my drop down box in the front end (jsp page). On my jsp page i simply iterate through this list and print it as options appropriately.
This works absolutely fine.
Now i have another text box on my form, say 'textbox1'. Now the requirement is that this text box value should be updated depending on what the user has selected from the above drop down box.
So for example if the user selects 'prod1'(which is a primary key in the backend database table) option from the drop down box, then the corresponding value ( the product name) should be fetched from the database table and should be updated in the textbox named 'textbox1'.
The other thing is this entire thing is contained in a form which is supposed to be finally submitted to the servlet for further processing.
So how can i achieve this.
i figured out the solution to my own problem. It might not be the most elegant way of doing it, but it does the job pretty well.
So as per my requirement, what i exactly wanted to do was.... insert a value (that will be fetched from the database) into a text box on my form depending on what the user chooses from the drop down box that is already present on my form.
To achieve this, i went about and thought if some how i could nest a form withing my main form, it'd solve my issue. But i discovered that nesting of forms is not allowed. So the next option i thought of was to some how submit the same form without the user clicking on the submit button and also handle it appropriately as an 'incomplete' submit (in the sense that the form is still to be submitted manually by the user by clicking on the submit button) on the server.
So i simply made use of the 'onChange' event of a drop down box. I created an additional hidden field on my form.I wrote a simple javascript function that would simply set the value of the hidden field to the string-"partial Submit" and would submit my main form (say named 'form1') as :-
document.getElementById("hidden_id").setAttribute("value","partial submit");
form1.submit;
The function that does the above will be called whenever (and everytime) the onchange event of the drop down box gets fired.
When the user finally clicks on the submit button on the form to submit the finally completed form, then another javascript function is called that simply sets the value of the hidden field on the form to the string, "final submit" and would submit the form as :-
document.getElementById("hidden_id").setAttribute("value","final submit");
form1.submit;
Now on my server, i checked for the value of this hidden field as :-
if(request.getParameter("hidden_id").equals("partial Submit"))
{
// make a database connection, pass the value user selected from the drop down box
// to a prepared statement that does the query for getting the 'productName' from
// the database, collect the returned string in a variable and set a
// request attribute with this returned value. This value can simply be used in the
// jsp to fill in the value part of the textbox1.
}
else
{
if(request.getParameter("hidden_id").equals("final Submit"))
{
// do the rest of the final processing that needs to be done when user finally
// submits the completed form.
}
else
{
// throw an exception to take care of the possibility that the user might send
// in a 3rd value as a value for the hidden field.
}
}
Since you havent provided the code for selectProduct(this.value) , i presume that it submits the jsp page as when you change the value in the drop down.
If that the case in the servelt, set the value that you want to show in jsp in request object
request.setAttribute("valuetodisplay" ,valuetodisplay);
and now in jsp
<input type="text" value ='<%= request.getAttribute("valuetodisplay")%>' />
I would like to pass a variable wordId through JSON GET to Spring-mvc Controller in my webapp. I have no problem with static url to work with json but I do not know what is best practice to do it with dynamic/parametric urls.
Controller part:
#RequestMapping(value="/delete/{wordId}", method = RequestMethod.GET)
#ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteWord(#RequestParam ("wordId") Long wordId, Principal principal) {
wordService.deleteWord(wordId, principal.getName());
}
JSP part:
<c:choose>
<c:when test="${not empty accountWords}">
<c:forEach items="${accountWords}" var="word" varStatus="status">
<li class="word">
<input type="checkbox" name="word" class="word_checkbox" value="" />
<span>${word.word}</span>
<s:url value="/words/delete/${word.wordId}" var="delete_word"></s:url>
<img src="resources/gfx/delete.png" />
</li>
</c:forEach>
</c:when>
</c:choose>
jQuery part so far:
$("li.word a").click(function(e) {
e.preventDefault();
var deleteUrl = ...
$.getJSON(deleteUrl, function() {
});
});
Could you tell how should my jquery part look like to pass wordId variable to controller? I can get url from href attribute of a tag but i would like to have relative url. I'm stucked...
UPDATE:
$("#testJSON").click(function() {
$.getJSON("admin/json.html", function(w) {
$('#span_json').html("w.wordId + "<br>" + w.word);
});
});
Since the wordId is part of the URL, you should be using the #PathVariable annotation instead of #RequestParam.
Also, since you asked about best practices, I should point out that it's not a good practice to use the HTTP GET method for actions that aren't idempotent. In other words, you shouldn't use GET for actions that make a change to data on the server-side, such as deleting records from the database.
The proper HTTP method for performing a record deletion is the HTTP DELETE method. Some older browsers don't support DELETE, so you'll find a lot of code out there that does a POST for deletion instead. I don't think that's much of a problem anymore though. See http://annevankesteren.nl/2007/10/http-method-support for more detail.
Using DELETE instead of GET isn't just a good idea for the sake of "doing things the right way"... it can actually help you avoid some nasty problems. There are browser plugins that will speed-up people's experience on the web by pre-fetching all links on a page and storing them in their local cache. If a user has one of these plugins installed the plugin will "click" on every delete link on your page! Also, if you're building a public-facing application, search engine crawlers will also follow your delete links. I've seen this happen in the real world, so trust me it's a real concern!
Another RESTful best practice is to use URLs that follow the pattern of /noun/{id}, with the HTTP method serving as the verb. So, instead of /delete/{wordId} with a GET, it would be better to go with /word/{wordId} with a DELETE.
With all of my suggested changes your code would look like this:
Controller
#RequestMapping(value="/word/{wordId}", method = RequestMethod.DELETE)
#ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteWord(#PathVariable ("wordId") Long wordId, Principal principal) {
wordService.deleteWord(wordId, principal.getName());
}
Unfortunately, the jQuery and JSP become a little trickier when you use DELETE instead of GET. GET is really tempting because you can just build a link, as you did like this:
<img src="resources/gfx/delete.png" />
To get the browser to use DELETE instead, you either need to have a form whose method is DELETE, or you need to invoke some JavaScript that does an Ajax DELETE. (Since you're already using Ajax, that's the technique I'll go with.) I'd start by changing your link to a button:
<button class="delete-button" id="delete_${delete_word}"><img src="resources/gfx/delete.png" /></button>
This creates a button that stores the id of the word you want to delete in the id of the button itself. Somehow you need to associate the id of a word to delete with every button, and this is one way to do it. I've seen other people put the id in a hidden span next to the button. (To be honest, I've never loved either of these techniques, and I'm hoping somebody follows up my answer with a better way to do it.)
Anyway, with that change in the body of your JSP you'll also want to add some jQuery that handles the click of all delete buttons. (Notice I put a class on the button called "delete-button" so that it would be easy to reference in jQuery.)
jQuery:
$(".delete-button").on("click", function() {
var wordId = $(this).attr("id").substring("delete_".length);
$.ajax({
type: "DELETE",
url: "/word/" + wordId,
success: function() {
// Maybe put some code here that deletes the <li> ?
}
});
});
Notice how I extracted the word id from the id attribute of the button that was clicked:
var wordId = $(this).attr("id").substring("delete_".length);
Of course you could also do it this way:
var wordId = $(this).attr("id").substring(7);
I prefer the first way of doing it because it self-documents what the substring is doing. In the second example the number 7 is a magic number that doesn't explain what's happening.
I tried searching, but haven't found the answer. I see when you ask a question on stackoverflow, the input field for "tags" show the gray text "at least one tag such as...etc". Upon click, the gray text disappears and you can start typing your values. If I click off that, the instructions reappear. How do I do that? Are there out of box implementations of this functionality or does this require custom implementation?
Thanks!
Two JSF component libraries offering this functionality comes to mind:
OpenFaces input text with Prompt text
PrimeFaces Watermark
It's a blur/focus javascript event handler on the input field. In jQuery it would be something like the following:
HTML
<input type="text" name="your-input" id="your-input" title="Enter a value"/>
jQuery
$('#your-input').focus(function(){
var defaultVal = $(this).attr('title');
if($(this).val() == defaultVal)
$(this).val('');
});
$('#your-input').blur(function(){
var defaultVal = $(this).attr('title');
if($(this).val() == '')
$(this).val(defaultVal);
});
$('#your-input').trigger('blur');
It takes the default value from the input's title attribute and sets its value on focus and blur events depending on the current value of the input. The last trigger() call is so the input's value is correctly set when the page loads.
You can see it in action here.
The simplest example would be
window.onload = function() {
var txtField = document.getElementById('textField');
if(!txtField.value) {
txtField.value = 'Default Text';
}
}
<h:inputText id="txtField" value="#{bean.txtField}"
onfocus="window.default=this.value; this.value='';"
onblur="if(!this.value) { this.value = window.default; }"/>
In any case I would suggest to switch the window.onload to any dom ready function such as
document.observe('dom:loaded', function(){}); // Prototype
$(document).ready(function(){}); // jQuery