How to use remoteFunction inside a .js file in grails - javascript

I have requirement, that whenever i click on a day(in a fullcalendar) i need to throw a pop up with details. I need to trigger an action/controller to get the details. I have my event.click in my .js file. I have been trying to use remoteFunction inside my full calendar jquery. But grails is not recognizing remoteFunction call and my screen is going awry (because of unavailability of .js template). Please help me out if possible,
$(calId[calNo]).fullCalendar({
header : {
left : ' ',
center : 'title',
right : ' '
},
defaultView: 'month',
selectable: true,
weekMode : 'variable',
eventColor : 'white',
editable : false,
year : eventYr,
month : calNo,
events : allocData,
dayRender: function (event, element, view) {
for (i = 0, l = holidayData.length; i < l; i++) {
var dateString = holidayData[i].substring(0,10);
view.element.find('.fc-day[data-date="' + dateString + '"]').css('background-color', '#FF9999');
view.element.find('.fc-other-month').css('background-color', '#FFFFFF');
}
},
eventRender: function(event, element, view)
{
if(event.start.getMonth() !== view.start.getMonth()) { return false; }
},
eventClick: function(event) {
var selectedDate = String(event.start);
var newData = ${remoteFunction(controller: 'PreSchedule', action: 'calProcess')};
alert(newData);
$('#dateAllocation #selectedDate').text(String(selectedDate).substring(0,10) + ' ,' + String(selectedDate).substring(28,33));
$('#dateAllocation').modal('show');
},
select: function(date) {
var selectedDate = date;
$('#dateAllocation #selectedDate').text(String(selectedDate).substring(0,10) + ' ,' + String(selectedDate).substring(28,33));
$('#dateAllocation').modal('show');
}
});
May be i am mixing server side code and client side code, messing up with basics. Thanks in advance.
Instead of using remotefunction, i tried using jquery.ajax/ createLink. But the url is not getting resolved.
$("#link").click(function(event){
alert('link');
event.preventDefault();
date = '1985-01-01';
$.ajax({
url:'${createLink(controller:"Student",action:"checkLink")}',
// url:'/checkLink',
dataType: 'json',
type: 'POST',
//data: date,
success: function() {
console.log("The returned data is: ");
// show your modal, or do whatever you want.
}
});
I can see the error in browser developer tools
Failed to load resource: the server responded with a status of 404 (Not Found)
//smsFrontEnd/student/$%7BcreateLink(controller:%22Student%22,action:%22checkLink%22)%7D
if possible, please help me out

If your controller is returning JSON data you can fetch and use it as follows:
Instead of:
var newData = ${remoteFunction(controller: 'PreSchedule', action: 'calProcess')};
alert(newData);
Use the jQuery $.ajax method:
$.ajax({
dataType: 'json',
url: '${createLink(controller: 'preSechedule', action: 'callProcess')}',
data: {}, // no parameters
success: function(data) {
window.alert("The returned data is: "+data);
// show your modal, or do whatever you want.
}
});

I don't think you would be able to use grails ajax tag libs in .js files.
However, adding to this these taglibs are deprecated and you should not be using them anyway. As this is not considered to be a good practice
http://grails.org/doc/latest/ref/Tags/remoteFunction.html
The formFunction tag and other Ajax related tags have been deprecated and will be removed from a future version of Grails. Applications may provide their own Ajax tags and/or Javascript plugins may provide Ajax tags of their own.
http://en.wikipedia.org/wiki/Unobtrusive_JavaScript
I think you are better of using jquery.Ajax instead of remoteFunction there.

Related

How to send multiple variables from a HTML web page to a python script without form submissions

This is going to be a strange one if I'm honest so please bare with me.
Im currently working on a project that requires me to call python scripts that are part of a webserver that is running a HTML webpage from the page itself i.e You move a slider on the webpage and it calls the python script and passes the value of the slider and an ID value that the script requires to pass the value to its relevant end point. In this case its a monitor ID and the slider value is the brightness value that the brightness must be set to.
Currently I have achieved this with a form submission action but I don't want the webpage to reset once a new value is sent and so JavaScript is my next best option using Ajax requests and while I have made some progress I am basically a noob with web development and have hit a brick wall.
Here is the script I have attempted and the python script that it calls.
<script>
slider.oninput = function (event, ui)
{
var slider_val=event.target.id;
console.log(slider_val);
$( "#"+slider_val ).val( ui.value );
$( "#amount_"+slider_val ).val( $( "#"+slider_val ).slider( "value" ) );
changeBrilliance();
}
function changeBrilliance(value, monid)
{
$.ajax({
type: "POST",
url: "/brilliancechange",
data: { mydata: value, mon: monid }
});
}
</script>
Python:
#app.route('/brilliancechange', methods=['POST'])
def brillchange():
userinput = request.form['mydata']
selectedMon = request.form['mon']
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
DATA = "A6" + selectedMon + "0000000401C0"
DATA += hex(int(userinput)).lstrip("0x")
check = checksum(bytes.fromhex(DATA))
DATA += hex(int(check)).lstrip("0x")
dataarray = hextobyte(DATA)
s.sendall(dataarray)
s.close()
What should the javascript look like if i want to call this method with a different ID and value each time without it reloading the webpage everytime?
It looks like changeBrilliance() accepts two parameters but when called nothing is getting passed. I'm not too familiar with the Python framework being used, but as long as it accepts content-type: application/json in POST body you could do:
// not totally sure which value/id combo you need but just pass the necessary ones here
changeBrilliance(slider_val, ui);
function changeBrilliance(value, monid)
{
var myObj = { 'myData': value, 'mon': monid };
$.ajax({
type: "POST",
url: "/brilliancechange",
contentType: "application/json",
data: JSON.stringify(myObj)
});
}
Then if you want something in the browser to change, you'll have to callback on done if successful or fail if something goes wrong, and always callback for some behavior that should always happen:
$.ajax({
type: "POST",
url: "/brilliancechange",
contentType: "application/json",
data: JSON.stringify(myObj)
}).done(function(data) {
// do something
}).fail(function(jqXHR, textStatus, err) {
// handle error
}).always(function(data) {
// always callback
});

Parsing BBCode on AJAX success

I am in a spot here trying to parse BBCode upon a AJAX success : item.message object. I am using jQuery 1.11. I have tried passing the var result in place of item.message, and only shows the [object] errors. I have tried wrapping item.message with XBBCODE and same thing.
Im not sure what to do, the script is great otherwise. We must parse bbcode to HTML or a method that can be managed PHP-side, but I don't think this is possible over JSON data.
Currently this is my jQuery code:
$(document).ready(function () {
$.ajax({
url: "/ajax/shoutbox.php",
method: "GET",
dataType: 'JSON',
success: function (data) {
var html_to_append = '';
$.each(data, function (i, item) {
// Object array repeated - not working
var result = XBBCODE.process({
text: 'item.message',
removeMisalignedTags: false,
addInLineBreaks: false
});
/*
currentPost = jQuery(this);
postHTML = bbcodeToHTML(currentPost.html());
currentPost.html(postHTML);
*/
html_to_append +=
'<div class="shoutbox-container"><span class="shoutDate">' +
jQuery.timeago(item.date) +
' <span style="color:#b3b3b3">ago</span></span><span class="shoutUser"><img src="' +
item.avatar +
'" class="shout-avatar" /></span><span class="shoutText">' +
item.message +
'</span></div><br>';
});
$("#shoutbox").html(html_to_append);
$(".shoutbox-container").filter(function () {
return $(this).children().length == 3;
}).filter(':odd').addClass('shoutbox_alt');
$(".shoutbox-container").each(function () {
$(this).parent().nextAll().slice(0, this.rowSpan - 1).addClass('shoutbox_alt');
});
}
});
});
As you see, I'm trying to make use of the following javascript:
https://github.com/patorjk/Extendible-BBCode-Parser
I've followed the instructions exactly, before moving into the JS above with no success either way. I get this:
[object][Object]
For each iteration of the message object coming back (its a custom AJAX shoutbox).
Commented, you can see another method I have tried to no success. Any help is appreciated!
Update: Working
Thank you, Quiet Nguyen for the suggestion for replacing item.message with result.html and updating text: object

Why append part does not work in ajax call

In the code below after I upload my document I wrote a loop which is supposed to add some images into a division called Divnavigation, but this part doesn't work.
Also when I make it uncommented even my documentViewer can not be loaded. Am I allowed to add something to my division from AJAX call?
function navigate(target) {
$.ajax({
url: '#Url.Action("Download", "Patient")',
type: 'GET',
async: true,
dataType: 'json',
cache: false,
data: { 'filepath': target },
success: function (results) {
// documentViewer.loadDocument(results);
documentViewer.uploadDocumentFromUri(results[results.length -1]);
documentViewer.addEventListener(gnostice.EventNames.afterDocumentLoad, function (eventArgs) {
document.getElementById("TotalPage").textContent = documentViewer.viewerManager.pageCount;
document.getElementById("pageNumber").value = documentViewer.viewerManager.currentPage;
$("#Divnavigation").empty();
//Get all images with the help of model
for (var i = 0; i < results.length; i++) {
$("#Divnavigation").append(" <ul> " +
"<li>" +
"<img src=" + results[i] + ">" + "</img>" +
"" + "" +
"</li>"
+ "</ul>");
}
});
//showImages();
},
error: function () {
alert('Error occured');
}
});
}
Hi Answer to your question first:
Am I allowed to add something to my division from .ajax call?
you are 100% allowed to add something to your division from .ajax call. there is no doubt in that. I done personally many times
This time you are not getting because of some other reason.
Now my suggestion is try using $("#Divnavigation").html().
Official doc: https://api.jquery.com/html/
so first as first step try by putting simple html like this $("#Divnavigation").html("<p>test</p>) and see whether you get the output. if you get then change, html string whatever you want ,that can be hardcoded string or even you can get that string from the action method.
Hope above information was helpful. kindly share your thoughts
Thanks

How to make ajax call and get results back while typing in input text

I want to implement some functionality which is when I enter some text in
<input path="tags" id="input-search"/>
there should appear a list of suggested tags just like
after making ajax call. I have database query
public interface TagRepository extends JpaRepository<Tag, Integer> {
#Query("SELECT t FROM Tag t WHERE name LIKE CONCAT('%', :name, '%')")
List<Tag> findTagByName(#Param("name") String name);
}
and the controller code is
#RequestMapping(value = "/getTags", method = RequestMethod.POST, produces = "application/json")
public #ResponseBody List<Tag> getTags(#RequestBody Tag tag, HttpServletResponse response) {
System.out.println("Found " + String.valueOf(tagService.findTagByName(tag.getName()).size()));
return tagService.findTagByName(tag.getName());
}
javascript for ajax is
$(document).ready(function() {
$("#tag-search").autocomplete({
source: function(request, response) {
$.ajax({
url: "/app/getTags/",
type: "POST",
data: JSON.stringify({tag : request.term}),
dataType: "json",
success: function(data) {
response($.map(data, function(v,i){
console.log();
return {
label: v.empName,
value: v.empName
};
}));
}
});
}
});
});
<div class="col-md-10 col-md-push-1">
<label class="floating-label" for="login-username">Tags</label>
<form:input path="tags" cssClass="form-control" id="tag-search"/>
</div>
when I run the app I see this javaScript error in Developers Tools
Important
I'm using Daemonite/material for my front-end & jQuery-Autocomplete, finally a good thing is that the latest version of App is on GitHub
can any one tell me how can I get rid of that error any response is welcome.
for the problem above i mostly use select2 jquery plugin. it's has a lot of build in feature, so no need of reinventing the wheel. check this link out for a demo - http://select2.github.io/select2/#infinite
screen shot:
code sample:
$("#e7").select2({
placeholder: "Search for a repository",
minimumInputLength: 3,
ajax: {
url: "https://api.github.com/search/repositories",
dataType: 'json',
quietMillis: 250,
data: function (term, page) { // page is the one-based page number tracked by Select2
return {
q: term, //search term
page: page // page number
};
},
results: function (data, page) {
var more = (page * 30) < data.total_count; // whether or not there are more results available
// notice we return the value of more so Select2 knows if more results can be loaded
return { results: data.items, more: more };
}
},
formatResult: repoFormatResult, // omitted for brevity, see the source of this page
formatSelection: repoFormatSelection, // omitted for brevity, see the source of this page
dropdownCssClass: "bigdrop", // apply css that makes the dropdown taller
escapeMarkup: function (m) { return m; } // we do not want to escape markup since we are displaying html in results
});
now layout is not exactly same as screenshot you provided, but check if this layout work for you.
Update:
function repoFormatResult(repo) {
var markup = '<div class="row-fluid">' +
'<div class="span2"><img src="' + repo.owner.avatar_url + '" /></div>' +
'<div class="span10">' +
'<div class="row-fluid">' +
'<div class="span6">' + repo.full_name + '</div>' +
'<div class="span3"><i class="fa fa-code-fork"></i> ' + repo.forks_count + '</div>' +
'<div class="span3"><i class="fa fa-star"></i> ' + repo.stargazers_count + '</div>' +
'</div>';
if (repo.description) {
markup += '<div>' + repo.description + '</div>';
}
markup += '</div></div>';
return markup;
}
function repoFormatSelection(repo) {
return repo.full_name;
}
Another approach:
Hi if above solution not fit for your problem then you can use this one instead. it's called typeahead.js a JavaScript library provide by twitter. you can find examples here.
Check jquery vendor library is loaded properly or not.
To cross check:
<script>
if (window.jQuery) {
alert('jQuery is loaded');
} else {
alert('jQuery is not loaded');
}
</script>
It simply means that you are getting HTML instead of JSON in response.
"Unexpected <" is referring to the first character of your request's response.
in chrome console you can go to network tab and click on your request and in the right side see what exactly your server is returning back to client.
You missed jquery.js. Add it and you'll get it working.
I am adding the codes here so that it would be better readable;
Write a new method to parse json on Java side before returning to jquery. Current code returns Java list as output for Ajax and this would possibly throw Uncaught syntax error : Unexpected token.
public static String toJSON(Object object)
{
if ( object == null ){
return "{}";
}
try {
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(object);
}
catch (Exception e) {
e.printStackTrace();
}
return "{}";
}
for the above piece of code you need to include 3 jars jackson-core-2.2.3.jar, jackson-annotations-2.2.3.jar and jackson-databind-2.2.3.jar.
Change you controller as following;
#RequestMapping(value = "/getTags", method = RequestMethod.POST, produces = "application/json")
public #ResponseBody String getTags(#RequestBody Tag tag, HttpServletResponse response) {
System.out.println("Found " + String.valueOf(tagService.findTagByName(tag.getName()).size()));
return toJSON(tagService.findTagByName(tag.getName()));
}
$(document).ready(function() {
var autoCompleteResult = '';
$("#tag-search").autocomplete({
source: function(request, response) {
$.ajax({
url: "/app/getTags/",
type: "POST",
data: JSON.stringify({tag : request.term}),
dataType: "json",
success: function(data) {
autoCompleteResult = jQuery.parseJSON(data);
response($.map(autoCompleteResult, function(v,i){
console.log();
return {
label: v.empName,
value: v.empName
};
}));
}
});
}
});
});
Please share your results after trying this.
Try this:
https://github.com/tanwaniniranjan/autosuggest
It's a plugin made for the same purpose. very less documentation, but i hope to put up the documentation soon.
Yu can read the comments in the js file to get an idea on the usage
Edit:
I now read your question more carefully,
what is happening is:
the response that you are getting from the server side is giving an error.
the error will usually start like sorry bro, 404
since you are trying to map the data, jQuery just cant parse it, and it gives you the error.
check your server side first. use the postman plugin to make requests, verify your response and then implement jQuery: https://chrome.google.com/webstore/detail/postman-launcher/igofndmniooofoabmmpfonmdnhgchoka?hl=en
As i see there could be a issue of 500 internal server error because you have a dataType: "json", in your ajax while at your controller you aren't returning any json.
#RequestMapping(value = "/getTags", method = RequestMethod.POST, produces = "application/json")
public #ResponseBody List<Tag> getTags(#RequestBody Tag tag, HttpServletResponse response) {
System.out.println("Found " + String.valueOf(tagService.findTagByName(tag.getName()).size()));
return tagService.findTagByName(tag.getName());
}
Here at your conroller this: produces = "application/json" says it will return json as output and with this: return tagService.findTagByName(tag.getName()); you can producing any json.
Just add below tag to your ajax call
contentType: 'application/json; charset=utf-8',
This is the type for requested data,in your case it simply text format that you type in text box
And remove below line from your ajax call if your response data is not json type
dataType: 'json',
This may remove Json Parsing Error in your code
Change your JavaScript as the below
$(document).ready(function() {
$("#tag-search").autocomplete({
source: function(request, response) {
$.ajax({
contentType: 'application/json; charset=utf-8',
url: "/app/getTags/",
type: "POST",
data: JSON.stringify({'tag' : "'"+request.term+"'"}),
dataType: "json",
success: function(data) {
response($.map(data, function(v,i){
console.log();
return {
label: v.empName,
value: v.empName
};
}));
}
});
}
});
});

JQuery AutoComplete From XML (Dynamic Results)

Perhaps I'm not understanding this concept (I'm an AJAX/javascript/Web newbie). I'm using the JQuery autocomplete feature and if I specify a small, limited items flat file (suggestions.xml) the function works fine, but when I use an actual production data file (3 MB) of suggestions the script doesn't work at all.
So I created a web service that generates XML based on the characters in the textbox but it appears this JQuery doesn't run on each keypress, rather only when the page first loads. Obviously, for this function to be of any use it needs to fetch results dynamically as the user types into the input field.
$(document).ready(function () {
var myArr = [];
$.ajax({
type: "GET",
// this line always sends the default text; not what the user is typing
url: "Suggestions.aspx?searchString=" + $("input#txtSearch").val(),
dataType: "xml",
success: parseXml,
complete: setupAC,
failure: function (data) {
alert("XML File could not be found");
}
});
function parseXml(xml) {
//find every query value
$(xml).find("result").each(function () {
myArr.push({ url: $(this).attr("url"), label: $(this).attr("name") + ' (' + $(this).attr("type").toLowerCase() + ')' });
});
}
function setupAC() {
$("input#txtSearch").autocomplete({
source: myArr,
minLength: 3,
select: function (event, ui) {
$("input#txtSearch").val(ui.item.label);
window.location.href = ui.item.url;
//alert(ui.item.url + " - " + ui.item.label);
}
});
}
});
On the server I expected to see a few requests corresponding to the characters the user is typing into the search box but instead I get a single message:
2013-10-18 22:02:04,588 [11] DEBUG baileysoft.mp3cms.Site - QueryString params: [searchString]:'Search'
My flat file of suggestions appears to be way to large for JQuery to handle and my web service script is never called, except when the page is first loaded.
How do I generate suggestions dynamically as the user is typing in the search box if I can't run back to the database (via my web service) to fetch suggestions as the user is typing?
Ok, I got it all worked out.
On the ASPNET side; I created a form to receive and respond to the AJAX:
Response.ContentType = "application/json";
var term = Request.Form["term"];
var suggestions = GetSuggestions(term); // Database results
if (suggestions.Count < 1)
return;
var serializer = new JavaScriptSerializer();
Response.Write(serializer.Serialize(suggestions);
On the AJAX side I modified the js function:
$("input#txtSearch").autocomplete({
minLength: 3,
source: function (request, response) {
$.ajax({
url: "Suggestions.aspx",
data: { term: $("input#txtSearch").val() },
dataType: "json",
type: "POST",
success: function (data) {
response($.map(data, function (obj) {
return {
label: obj.Name,
value: obj.Url
};
}));
}
});
},
select: function (event, ui) {
$("input#txtSearch").val(ui.item.label);
window.location.href = ui.item.value;
}
});
Everything is working as expected now.
Hope this helps someone else who might get stuck trying to figure out JQuery stuff for ASPNET.

Categories