I am using the jquery/ajax autocomplete, below is the code snippet of my simple app:
external .jsp:
$(function () {
$("#inputfield").autocomplete({
source: '/fruitapp/findFruit'
});
});
and in my controller:
def findFruit = {
def fruitsearch= Fruit.withCriteria {
ilike 'fruit', params.term + '%'
}
render (fruitsearch?.'fruit' as JSON)
}
As you can see, it will only fill in a single text field which is the "inputfield". Now, I want that if I select an item from the autocomplete list, it will fill in at least two fields. How would I do it?
Thanks in advance.
The autocomplete can get a "select" event. There you can do whatever you want.
From their documentation
$( ".selector" ).autocomplete({
select: function(event, ui) { ... }
});
Bind to the select event by type: autocompleteselect.
$( ".selector" ).bind( "autocompleteselect", function(event, ui) {
...
});
Here is a fiddle I made from their example.
As you can see, once an autocomplete option is selected, I am updating 2 different divs.
This is the code responsible for it:
$( "#tags" ).autocomplete({
source: availableTags,
select:function(e,u){
console.log([e,u]);
$("#output").text("This is the label:" + u.item.label);
$("#more_output").text("this is the value:" + u.item.value);
}
});
And just to be perfectly clear - "u" can contains anything you want.
Here I modified the fiddle to contain a single complex JS object. You can access all the fields.
I added a log print for you to see. Use chrome's developer tools to see the log print and view objects' content.
Related
Is it possible to add styling to only some of the results returned in an autocomplete dropdown?
The code below works fine, however, I would like to style the individual results based on the value of data[x].restricted. When it is true, I still want to display those items but disable or grey them out within the autocomplete dropdown list. If data[x].restricted is false then I do not want to apply any additional styling to those items.
source: function (request, response) {
$.ajax({
url: $("#AutoCompleteCustomerNameUrl").val(),
type: "POST",
dataType: "json",
data: {
srchCus: request.term
},
success: function (data) {
var x, array = [];
for (x in data) {
array.push({
label: (data[x].restricted ? 'Restricted Access - ' : '') + data[x].customerName,
name: data[x].customerFullName
});
}
}
});
}
Any assistance on how to accomplish this would be much appreciated.
Approach 1 (feels hacky)
This doesn't feel like a great option, but you could probably do this by using jQuery to target elements based on their text content. Autocomplete suggestions are generated as <li>s, so something like this might work:
$('li:contains("Restricted Access")').addClass('grey');
The question is then when to run that? Those elements are added dynamically of course, after page load, so that would have to run after they've been created - you'd have to run it based on some autocomplete event. Looking through the list in the docs, maybe the open event would be best. A handler for that event will run whenever the menu is opened, so it could add a CSS class to all the just-created suggestions matching that selector. Eg (untested):
$("#selector").autocomplete({
// ... your normal autocomplete code ...
open: function(event, ui) {
// Add a CSS class to those suggestions matching the text
$('li:contains("Restricted Access")').addClass('grey');
}
});
I haven't tested this, as it doesn't feel like the right approach. Below is a much better, tested and working option.
Approach 2 (feels good)
You can also do this using the _renderItem extension point. If you check the example they give there you can see it is the function which actually generates the HTML which shows up as your autocomplete suggestion. If we can customise that, we could do anything - eg check details of the item, add specific CSS classes, etc.
I don't find those docs super clear, but it isn't hard to find examples of it in use, eg the Custom Data example (that #Simon-K linked to in the comments above) shows how to use it:
$("#selector").autocomplete({
// ... your normal autocomplete code ...
}).autocomplete("instance")._renderItem = function(ul, item) {
// Here we have complete control of what is returned, and access to
// the items!
return $("<li>").append("<div>" + item.label ...).appendTo(ul);
};
So with your requirements, we could do something like this:
$("#selector").autocomplete({
// ... your normal autocomplete code ...
}).autocomplete("instance")._renderItem = function(ul, item) {
var style = (item.restricted) ? 'grey' : '';
return $("<li>")
.append("<div class='" + style + "'>" + item.label + "</div>")
.appendTo(ul);
};
And then of course add a CSS class to style those items:
.grey {
color: #ccc;
}
Working JSFiddle.
I'm trying to get the hang of using ajax loads (mostly via jquery) to make my site more efficient. Wondering if anyone can provide any suggestions re "best practices" for using ajax?
Is there a way to simplify a script for multiple ajax calls? For example, I currently have the working script:
$(document).ready(function() {
$('#dog').click(function () {
$('#body').load("dog.html");
});
$('#cat').click(function () {
$('#body').load("cat.html");
});
$('#bird').click(function () {
$('#body').load("bird.html");
});
$('#lizard').click(function () {
$('#body').load("lizard.html");
});
});
The script just gets longer and longer with each additional function. Is there a simpler, more efficient way to write this script to cover multiple load scripts?
Also, should I be using ajax loads to replace the majority of actual links?
Here is a suggestion, since the code you posted seems to have a pattern between the id and the filename:
$(document).ready(function () {
$(document).on('click', 'commonParentElementHere', function (e) {
$('#body').load(e.target.id + ".html");
});
});
This suggestion uses .on() and you just need to add a commonParentElementHere, a id or a class of the common parent of those elements.
Another option is to use a class on all elements that should be clickable, and then use the code passing the id to the html file name, like:
$(document).ready(function () {
$(document).on('click', '.theCOmmonClass', function () {
$('#body').load(this.id + ".html");
});
});
I'd say give all the elements you want to click on a class say ajax then.
$(document).ready(function() {
$('.ajax').click(function () {
$('#body').load(this.id + ".html");
});
});
Assuming that the id matches the file name the script can be simplified to:
$(document).ready(function() {
$('#dog,#cat,#bird,#lizard').click(function () {
var fileName = this.id + ".html";
$('#body').load(fileName);
});
});
This script simply specifies each id in a single selector that separates each id with a comma. This will calls the click function to be fired for each element. With the anonymous function attached to the click event, the id of each element is obtained and concatenated to create the file name which is then passed to the load function.
If the id doesn't always match the element you could use the following approach.
var mappings = [
{id: "fileName1", file:"file.html"},
{id: "fileName2", file:"file2.html"}
];
$(document).ready(function() {
for(var i = 0; i < mappings; i++){
createMapping(mappings[i]);
}
function createMapping(mapping){
$("#" + mapping.id).click(function(){
$('#body').load(mapping.file);
});
}
});
How to check if a button is clicked or not in prototype JavaScript?
$('activateButton').observe('click', function(event) {
alert(hi);
});
The code above is not working.
With this button:
<button id="mybutton">Click Me</button>
Use this:
$('mybutton').observe('click', function () {
alert('Hi');
});
Tested and works, here.
You might want to encase it in a document.observe('dom:loaded', function () { }) thingy, to prevent it executing before your page loads.
Also, just an explanation:
The single dollar sign in Prototype selects an element by its id. The .observe function is very similar to jQuery's .on function, in that it is for binding an event handler to an element.
Also, if you need it to be a permanent 'button already clicked' thingy, try this:
$('mybutton').observe('click', function () {
var clicked = true;
window.clicked = clicked;
});
And then, if you want to test if the button has been clicked, then you can do this:
if (clicked) {
// Button clicked
} else {
// Button not clicked
}
This may help if you are trying to make a form, in which you don't want the user clicking multiple times.
How one may do it in jQuery, just for a reference:
$('#mybutton').on('click', function () {
alert('Hi');
});
Note that, the jQuery code mentioned above could also be shortened to:
$('#mybutton').click(function () {
alert('Hi');
});
jQuery is better in Prototype, in that it combines the usage of Prototype's $ and $$ functions into a single function, $. That is not just able to select elements via their id, but also by other possible css selection methods.
How one may do it with plain JavaScript:
document.getElementById('mybutton').onclick = function () {
alert('Hi');
}
Just for a complete reference, in case you need it.
$('body').delegate('.activateButton', 'click', function(e){
alert('HI');
});
There is a new Tooltip Widget in jQuery UI 1.9, whose API docs hint that AJAX content can be displayed in it, but without any further details. I guess I can accomplish something like that with a synchronous and blocking request, but this isn't what I want.
How do I make it display any content that was retrieved with an asynchronous AJAX request?
Here is a ajax example of jqueryui tootip widget from my blog.hope it helps.
$(document).tooltip({
items:'.tooltip',
tooltipClass:'preview-tip',
position: { my: "left+15 top", at: "right center" },
content:function(callback) {
$.get('preview.php', {
id:id
}, function(data) {
callback(data); //**call the callback function to return the value**
});
},
});
This isn't a complete solution obviously, but it shows the basic technique of getting data dynamically during the open event:
$('#tippy').tooltip({
content: '... waiting on ajax ...',
open: function(evt, ui) {
var elem = $(this);
$.ajax('/echo/html').always(function() {
elem.tooltip('option', 'content', 'Ajax call complete');
});
}
});
See the Fiddle
One thing to lookout for when using the tooltip "content" option to "AJAX" the text into the tooltip, is that the text retrieval introduces a delay into the tooltip initialization.
In the event that the mouse moves quickly across the tooltip-ed dom node, the mouse-out event may occur before the initialization has completed, in which case the tooltip isn't yet listening for the event.
The result is that the tooltip is displayed and does not close until the mouse is moved back over the node and out again.
Whilst it incurs some network overhead that may not be required, consider retrieving tooltip text prior to configuring the tooltip.
In my application, I use my own jquery extensions to make the AJAX call, parse the resutls and initialise ALL tooltips, obviously you can use jquery and/or your own extensions but the gist of it is:
Use image tags as tooltip anchors, the text to be retrieved is identified by the name atrribute:
<img class="tooltipclassname" name="tooltipIdentifier" />
Use invoke extension method to configure all tooltips:
$(".tooltipclassname").extension("tooltip");
Inside the extension's tooltip method:
var ids = "";
var nodes = this;
// Collect all tooltip identifiers into a comma separated string
this.each(function() {
ids = ids + $(this).attr("name") + ",";
});
// Use extension method to call server
$().extension("invoke",
{
// Model and method identify a server class/method to retrieve the tip texts
"model": "ToolTips",
"method": "Get",
// Send tooltipIds parameter
"parms": [ new myParmClass("tipIds", ids ) ],
// Function to call on success. data is a JSON object that my extension builds
// from the server's response
"successFn": function(msg, data) {
$(nodes).each(function(){
// Configure each tooltip:
// - set image source
// - set image title (getstring is my extension method to pull a string from the JSON object, remember that the image's name attribute identifies the text)
// - initialise the tooltip
$(this).attr("src", "images/tooltip.png")
.prop("title", $(data).extension("getstring", $(this).attr("name")))
.tooltip();
});
},
"errorFn": function(msg, data) {
// Do stuff
}
});
// Return the jquery object
return this;
Here is an example that uses the jsfiddle "/echo/html/" AJAX call with a jQuery UI tooltip.
HTML:
<body>
<input id="tooltip" title="tooltip here" value="place mouse here">
</body>
JavaScript:
// (1) Define HTML string to be echo'ed by dummy AJAX API
var html_data = "<b>I am a tooltip</b>";
// (2) Attach tooltip functionality to element with id == tooltip
// (3) Bind results of AJAX call to the tooltip
// (4) Specify items: "*" because only the element with id == tooltip will be matched
$( "#tooltip" ).tooltip({
content: function( response ) {
$.ajax({
url: "/echo/html/",
data: {
'html': html_data
},
type: "POST"
})
.then(function( data ) {
response( data );
});
},
items: "*"
});
here is this example on jsfiddle:
I have 3 different tabs where i am displaying data using jQGrids(each tab contain one grid).
But i just thought that my grids are completely the same, only the difference is that they using different url to get data.
So I have three similar girds on each tab only with different urls:
First: url: '/Home/GetData?id=1' Second: url: '/Home/GetData?id=2' and Third: url: '/Home/GetData?id=3'
So i was thinking that may be i may declare grid only once and than on each tab click a can pass the url to load data? So on each tab click jQGrid will be populating from the new url.
May be some one may have any ideas about that?
Or may be some one may have better ideas how to reduce "jQGrid copy-paste" in that case?
UPDATE 0:
Nearly get it work i mean it is working but there is one small problem,
When i am switching tabs the header of the grid getting lost...and some jqgrid formatting as well.
here is my code:
$("#tabs").tabs({
show: function (event, ui) {
if (ui.index == 0) {
//$("#Grid1").appendTo("#tab1");
//$("#Grid1Pager").appendTo("#tab1");
//When Appending only pager and grid div, header getting lost so i've append the whole grid html instead
$("#gbox_Grid1").appendTo("#tab1");
changeGrid("#Grid1", 1);
}
else if (ui.index == 1) {
//$("#Grid1").appendTo("#tab2");
//$("#Grid1Pager").appendTo("#tab2");
$("#gbox_Grid1").appendTo("#tab2");
changeGrid("#Grid1", 2);
}
else if (ui.index == 2) {
//$("#Grid1").appendTo("#tab3");
//$("#Grid1Pager").appendTo("#tab3");
$("#gbox_Grid1").appendTo("#tab3");
changeGrid("#Grid1", 3);
}
}
});
function changeGrid(grid, id) {
$(grid).jqGrid('setGridParam', {
url: '/Home/GetData?id=' + id
});
$(grid).trigger('reloadGrid');
}
UPDATE 1
All right, i've changed the code to append the whole grid instead of appending grid div and pager only. So it is working like that.
You can basically make the tabs as regular buttons that will call some function which sets new URL parameter to the grid and reloads it.
The function should be something like this:
function changeGrid(grid, id) {
$(grid).jqGrid('setGridParam', {
url: '/Home/GetData?id=' + id, page: 1
});
$(grid).trigger('reloadGrid');
}
Note that I set the page to 1. Keep in mind that you might need to set the default sorting column or something similar depending on your solution.
UPDATE
If you really want to go with the tabs, the 'show' event handler can be simplified.
Try this:
$("#tabs").tabs({
show: function (event, ui) {
var id = ui.index + 1;
$("#gbox_Grid1").appendTo("#tab" + id);
$("#Grid1").jqGrid('setGridParam', {
url: '/Home/GetData?id=' + id
});
$("#Grid1").trigger('reloadGrid');
}
});