I used the jQuery autocompletion for my Struts2 application.
Pratically, my action made a list of strings that jQuery use. This is the script:
$().ready(function() {
$("#tag").autocomplete("/myAction/Action", {
multiple : true,
autoFill : true,
minChars:1
});
});
During typing appear the box with the suggestions. The problem is that the box render another value,
exactly render the code of my JSP ( links to CSS for the autocomplete plug-in).
How can I solve this?
This is my JSP:
<html>
<head>
<script src="<%=request.getContextPath()%>/scripts/jquery-latest.js"></script>
<link rel="stylesheet" href="<%=request.getContextPath()%>/scripts/main.css" type="text/css" />
<link rel="stylesheet" href="<%=request.getContextPath()%>/scripts/jquery.autocomplete.css" type="text/css" />
<script type="text/javascript" src="<%=request.getContextPath()%>scripts/jquery.bgiframe.min.js"></script>
<script type="text/javascript" src="/<%=request.getContextPath()%>/query.dimensions.js"></script>
<script type="text/javascript" src="<%=request.getContextPath()%>/scripts/jquery.autocomplete.js"></script>
<script type="text/javascript">
$().ready(function() {
$("#tag").autocomplete("/myAction/Action", {
multiple : true,
autoFill : true,
minChars:1
});
});
</script>
</head>
<body>
<s:form action="Action" theme="simple">
<s:iterator value="elencoMateriali" var="asd">
<s:property value="#asd" escape="false"/>
</s:iterator>
<s:textfield id="tag" name="tagField" label="tag" />
</s:form>
</body>
I think it's too late for an answer, but the probles is still remaining in Struts2. I have made some modifications to solve such problem:
Copy the jquery.struts2.js file into you js path.
Edit the jquery.struts2.js fil and look for 'success: function(data)' in the handle of the Autocompleter Widget, and replace the function for the next one:
success: function(data) {
var x = 0;
if (data[o.list] !== null) {
var isMap = false;
if (!$.isArray(data[o.list])) {
isMap = true;
}
var result = [];
$.each(data[o.list], function(j, val) {
if (isMap) {
result.push({
label: val.replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "<strong>$1</strong>" ),
value: val,
id: j
});
}
else {
if (o.listkey !== undefined && o.listvalue !== undefined) {
result.push({
label: val[o.listvalue].replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "<strong>$1</strong>" ),
value: val[o.listvalue],
id: val[o.listkey]
});
}
else {
result.push({
label: data[o.list][x].replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "<strong>$1</strong>" ),
value: data[o.list][x],
id: data[o.list][x]
});
}
}
x++;
});
response(result);
}
}
Now, if you subscribe a onSelectTopics method on your jsp code, you will have a new item.id element available, so you can set the id value into a hidden o whatever you want.
Now, your autocompleter show a list with the strong word, fills the input with the selection, and mantains the id in a variable you can catch.
Remember to add the modified js in the include header section.
<%# taglib prefix="s" uri="/struts-tags" %>
<%# taglib prefix="sx" uri="/struts-dojo-tags" %>
<s:form action="ActionJson" theme="simple">
<s:url id="elencoFuffa" action="ActionJSON"/>
<sx:autocompleter id="autocompleter" name="materiale" loadOnTextChange="true" preload="false" href="%{elencoFuffa}" size="24" loadMinimumCount="1" showDownArrow="false" cssClass="dropDown" onchange="submit();"/>
<s:submit value="Prosegui"/>
<s:property value="luoghiSmaltimento"/>
</s:form>
Now, the Action:
public class Action extends ActionSupport {
private String materiale;
private String luoghi;
private List<String> elencoMateriali;
private Map<String, String> json;
public String execute() throws Exception {
System.out.println("------------------" + materiale);
return SUCCESS;
}
public String getMateriali() throws Exception {
MaterialiDAO dao = new MaterialiDAO();
List<Materiali> toResult = new ArrayList<Materiali>();
toResult = dao.findAll();
elencoMateriali = new ArrayList<String>();
Iterator i = toResult.iterator();
while (i.hasNext()) {
Materiali m = (Materiali) i.next();
elencoMateriali.add(m.getValueNomemateriale());
}
return SUCCESS;
}
public String getJson() throws Exception {
json = new HashMap<String, String>();
if (materiale != null && materiale.length() > 0) {
MaterialiDAO dao = new MaterialiDAO();
List<Materiali> materiali = dao.findByLikeValue(materiale);
for (Materiali m : materiali) {
json.put(m.getValueNomemateriale(), "" + m.getIdMateriali());
}
}
return SUCCESS;
}
public String trovaLuogo() throws Exception {
LuoghismalDAO daoL = new LuoghismalDAO();
MaterialiDAO daoM = new MaterialiDAO();
Materiali m = daoM.findByMaterialiName(materiale);
if (m != null) {
luoghi = m.getLuoghismal().getValueDescrluogo();
return SUCCESS;
} else {
luoghi = "-- Scegliere un materiale --";
return SUCCESS;
}
}
/* Getters and setters */
At the end the struts.xml
<action name="ActionJSON" class="it.action.Action"
method="getJson">
<result type="json">
<param name="root">json</param>
</result>
</action>
Related
Am using Jquery FormData for the first time, but seems am missing something. In the JS - postAjax method, when new FormData() is called, it just skips the remaining lines and goes to the end of the function without any errors. What am I doing wrong here?
template.js //script files in this order
<script src="js/jquery-2.1.0.js"></script>
<script src="js/jquery.form.js"></script>
<script src="js/bootstrap.js"></script>
<script src="js/bootstrapValidator.js"></script>
<script src="js/hemoncCBCFunctions.js"></script>
<script src="js/validations.js"></script>
JSP
<form name ="newSectionSubmitForm" id="newSectionSubmitForm" class="form-horizontal" role="form" method="post" ENCTYPE="multipart/form-data">
<table>
<tr>
<td>
<input type="file" id='imageFile0' name='imageFile0' class="form-control" />
</td>
</tr>
</table>
<form>
JS
function submitNewSection(targetUrl, form) {
postAjaxData(null, 'content', targetUrl, form, null, null);
}
function postAjaxData(initiatingElement, targetElement, targetUrl, form,
additionalParamMap, successCallback) {
var $targetElement = $('#' + targetElement);
var serializedFormData;
serializedFormData = $('#' + form).serialize();
for ( var j in additionalParamMap) {
serializedFormData += "&" + j + "=" + additionalParamMap[j];
}
alert('serialized form data ' + serializedFormData);
var formData = new FormData(serializedFormData);//**exits the function no errors**
formData.append("file", $('#imageFile0').files[0]);
alert('serialized form data ' + formData);
$.ajax({
type : "POST",
cache : false,
data : formData,
url : targetUrl,
success : function(data) {
processRedirect(data);
$targetElement.html(data);
$targetElement.show();
if (successCallback != null) {
successCallback(data);
}
},
error : function(xhr, httpRequest, textStatus, errorThrown) {
var errorId = xhr.getResponseHeader("errorId");
var errorMsg = xhr.getResponseHeader("errorMessage");
if (errorId != null && errorId != undefined) {
$("#page_error").html(
"An unexpected error has occurred. Error Id: "
+ errorId);
} else {
$("#page_error").html("An unexpected error has occurred.");
}
},
});
Controller File (however the code does not reach here)
#RequestMapping(value = "/submitNewSection.html")
public String submitNewSection( MultipartHttpServletRequest req, HttpServletRequest request, Model model) {
Iterator<String> itr = req.getFileNames();
MultipartFile mpf = req.getFile(itr.next());
System.out.println("file name " + mpf.getOriginalFilename() +" uploaded!");
}
Thanks so much.
Could you please give me an example how to query the information?
We have the example to query defect in the way as below,
var queryConf = { type: 'defect',
key : 'defects',
fetch: true
};
Per Web Services API documentation Artifact object has Changesets collection on it. Defects inherit from Artifacts. Here is an example that builds a table of defects by priority with associated Changesets data:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- Copyright (c) 2010 Rally Software Development Corp. All rights reserved -->
<html>
<head>
<title>Defects By Priority with associated Changesets Example</title>
<meta name="Name" content="App Example: Defects by Priority and associated Changesets" />
<meta name="Version" content="2010.4" />
<meta name="Vendor" content="Nick M Rally lab" />
<script type="text/javascript" src="https://rally1.rallydev.com/apps/1.33/sdk.js?apiVersion=1.43"></script>
<script type="text/javascript">
var table;
var rallyDataSource = null;
function showTable(results) {
if(table) {
table.destroy();
}
for (var i=0; i < results.defects.length; i++) {
if(results.defects[i].Changesets.length > 0){
results.defects[i].ChangesetsMessages = "";
console.log(results.defects[i].Changesets.length);
for (var j=0; j < results.defects[i].Changesets.length; j++) {
results.defects[i].ChangesetsMessages += results.defects[i].Changesets[j].Revision;
results.defects[i].ChangesetsMessages += ' ';
results.defects[i].ChangesetsMessages += results.defects[i].Changesets[j].Message;
results.defects[i].ChangesetsMessages += '<br />';
}
}
}
var config = {
columnKeys : ['FormattedID', 'Name', 'Priority','ChangesetsMessages'],
columnHeaders : ['Formatted ID', 'Name', 'Priority','Changesets - Revision, Message'],
columnWidths : ['150px','150px', '150px', '300px'],
};
table = new rally.sdk.ui.Table(config);
table.addRows(results.defects);
table.display("defects");
}
function onSelectionChanged(sender, eventArgs) {
var queryObject = {
key : 'defects',
type : 'defect',
query: '(Priority = "' + eventArgs.value + '")',
fetch: 'Name,FormattedID,Priority,Changesets,Changeset,ObjectID,Message,Revision'
};
rallyDataSource.findAll(queryObject, showTable);
}
function onLoad() {
rallyDataSource = new rally.sdk.data.RallyDataSource('1111','2222','false','false');
var dpConfig = {
type : "defect",
attribute: "priority",
defaultDisplayedValue: "Low",
label: "Defect Priority:",
showLabel: true
};
var dpDropdown = new rally.sdk.ui.AttributeDropdown(dpConfig, rallyDataSource);
dpDropdown.display("priorityDiv", onSelectionChanged);
}
rally.addOnLoad(onLoad);
</script>
</head>
<body>
<div id="priorityDiv"></div><div id="defects"></div>
</body>
</html>
My default action code:
public ViewResult Act(int? id)
{
if (id == null)
ViewData["p"] = GetDefaultView();
else
ViewData["p"] = GetEditView((int)id);
return View("Index");
}
My Index view code:
<!DOCTYPE html><html><head></head><body>
<div id="content">#Html.Raw(ViewData["p"])</div></body></html>
How it is possible to use instead of ViewData a string ? How I can update #content only by means of $.ajax?
Before being able to use the $.ajax function you will first need to render a view which includes the jquery.js script:
<!DOCTYPE html>
#{ Layout = null; }
<html>
<head>
</head>
<body>
<div id="content"></div>
<!-- TODO: Adjust your proper jquery version here: -->
<script type="text/javascript" src="~/scripts/jquery.js"></script>
<script type="text/javascript">
$.ajax({
url: '#Url.Action("act")',
data: { id: 123 },
success: function(result) {
$('#content').html(result);
}
});
</script>
</body>
</html>
then you should adapt your Act controller action so that it returns some partial view or a Content result:
public ActionResult Act(int? id)
{
if (id == null)
{
return Content("<div>id was null</div>");
}
return Content("<div>id value is " + id.Value.ToString() + "</div>");
}
If you want to return a string, you could change your controller to return a ContentResult.
public ContentResult Act(int? id)
{
string html = "";
if (id == null)
html = GetDefaultView();
else
html = GetEditView((int)id);
var content = new ContentResult();
content.Content = html;
return content;
}
I'm displaying a Bing Map (v7) in my Webmatrix2 website with a series of pushpins & infoboxes drawn from a SQL Express database using a JSON enquiry.
While the maps appears in all 3 browsers I'm testing (IE, FF & Chrome) the pushpins are sometimes not showing in FF & Chrome, particularly if I refresh with Cntrl+F5
This is my first JSON and Bing Maps app so expect there's a few mistakes.
Any suggestions on how to improve the code and get display consistency?
#{
Layout = "~/_MapLayout.cshtml";
}
<script type="text/javascript" src="~/Scripts/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"></script>
<link rel="StyleSheet" href="infoboxStyles.css" type="text/css">
<script type="text/javascript">
var map = null;
var pinLayer, pinInfobox;
var mouseover;
var pushpinFrameHTML = '<div class="infobox"><a class="infobox_close" href="javascript:closeInfobox()"><img src="/Images/close2.jpg" /></a><div class="infobox_content">{content}</div></div><div class="infobox_pointer"><img src="images/pointer_shadow.png"></div>';
var pinLayer = new Microsoft.Maps.EntityCollection();
var infoboxLayer = new Microsoft.Maps.EntityCollection();
function getMap() {
map = new Microsoft.Maps.Map(document.getElementById('map'), {
credentials: "my-key",
zoom: 4,
center: new Microsoft.Maps.Location(-25, 135),
mapTypeId: Microsoft.Maps.MapTypeId.road
});
pinInfobox = new Microsoft.Maps.Infobox(new Microsoft.Maps.Location(0, 0), { visible: false });
AddData();
}
$(function AddData() {
$.getJSON('/ListSchools', function (data) {
var schools = data;
$.each(schools, function (index, school) {
for (var i = 0; i < schools.length; i++) {
var pinLocation = new Microsoft.Maps.Location(school.SchoolLat, school.SchoolLon);
var NewPin = new Microsoft.Maps.Pushpin(pinLocation);
NewPin.title = school.SchoolName;
NewPin.description = "-- Learn More --";
pinLayer.push(NewPin); //add pushpin to pinLayer
Microsoft.Maps.Events.addHandler(NewPin, 'mouseover', displayInfobox);
}
});
infoboxLayer.push(pinInfobox);
map.entities.push(pinLayer);
map.entities.push(infoboxLayer);
});
})
function displayInfobox(e) {
if (e.targetType == "pushpin") {
var pin = e.target;
var html = "<span class='infobox_title'>" + pin.title + "</span><br/>" + pin.description;
pinInfobox.setOptions({
visible: true,
offset: new Microsoft.Maps.Point(-33, 20),
htmlContent: pushpinFrameHTML.replace('{content}', html)
});
//set location of infobox
pinInfobox.setLocation(pin.getLocation());
}
}
function closeInfobox() {
pinInfobox.setOptions({ visible: false });
}
function getCurrentLocation() {
var geoLocationProvider = new Microsoft.Maps.GeoLocationProvider(map);
geoLocationProvider.getCurrentPosition();
}
</script>
<body onload="getMap();">
<div id="map" style="position:relative; width:800px; height:600px;"></div>
<div>
<input type="button" value="Find Nearest Schools" onclick="getCurrentLocation();" />
</div>
</body>
The JSON file is simply
#{
var db = Database.Open("StarterSite");
var sql = #"SELECT * FROM Schools WHERE SchoolLon != ' ' AND SchoolLon != 'null' ";
var data = db.Query(sql);
Json.Write(data, Response.Output);
}
Add your pinLayer, infobox, and infoboxLayer before calling the AddData function and see if that makes a difference. Also verify that school.SchoolLat and school.SchoolLon are numbers and not a string version of a number. If they are a string, then use parseFloat to turn them into a number. Other than that everything looks fine.
In his blog post, Christian Cantrell shows how to use STORAGE_VOLUME_MOUNT in ActionScript.
He has written a Flex app called FileTile.
I would like to see a JavaScript alert box that says “You have inserted “ + e.storageVolume.name, and “You have removed a storage volume”.
<html>
<head>
<title>New Adobe AIR Project</title>
<script type="text/javascript" src="lib/air/AIRAliases.js"></script>
<script type="text/javascript" src="lib/air/AIRIntrospector.js"></script>
<script type="text/javascript" src="lib/jQuery/jquery-1.4.3.min.js"></script>
<script type="text/javascript">
var msg = '<h1>Please insert your SwatchDog (SD) card.</h1>';
function trace() {
var message = 'Hello Max';
air.Introspector.Console.log(message);
}
function readFile(v) {
var myFile = air.File.desktopDirectory.resolvePath("MyFile.txt");
var fileStream = new air.FileStream();
fileStream.open(myFile, air.FileMode.READ);
$('#app').append('<p>' + fileStream.readUTFBytes(fileStream.bytesAvailable) + '</p>');
fileStream.close();
}
function onVolumeMount(e) {
$('#app').html('<h1>Thank you</h1><p>I can see you have multiple devices:</p>');
var volumes = air.StorageVolumeInfo.storageVolumeInfo.getStorageVolumes();
for (var i = 0; i < volumes.length; i++) {
$('#app').append(volumes[i].rootDirectory.nativePath);
}
if (e.storageVolume.isRemovable) {
if (e.storageVolume.name == 'SWATCHDOG') {
$('#app').append('<p>And SwatchDog is drive: ' + e.storageVolume.rootDirectory.nativePath + '</p>');
readFile(e.storageVolume)
} else {
$('#app').append('<p>But the one you just plugged in is not SwatchDog.</p>');
}
}
}
function onVolumeUnmount(e) {
$('#app').html('<h1>Goodbye!</h1>' + msg);
}
jQuery(function($){
var PluggedIn = false;
var volumes = air.StorageVolumeInfo.storageVolumeInfo.getStorageVolumes();
for (var i = 0; i < volumes.length; i++) {
if (volumes[i].isRemovable) {
PluggedIn = true;
if (volumes[i].name == 'SWATCHDOG') {
$('#app').append('I see you already have SwatchDog plugged in!');
readFile(volumes[i])
} else {
$('#app').append('What you have plugged in is not SwatchDog.');
}
}
}
if (!PluggedIn){
$('#app').append(msg);
}
air.StorageVolumeInfo.storageVolumeInfo.addEventListener(air.StorageVolumeChangeEvent.STORAGE_VOLUME_MOUNT, onVolumeMount);
air.StorageVolumeInfo.storageVolumeInfo.addEventListener(air.StorageVolumeChangeEvent.STORAGE_VOLUME_UNMOUNT, onVolumeUnmount);
})
</script>
</head>
<body>
<div id="app">
</div>
<button onclick="trace();">Say Hello Max!</button>
</body>
</html>