Grails: How do I make a g:textfield to load some data and display it in other g:textfield? - grails

I have two g:textfields
in the first one I should write a number lets say 12 and in the g:textfield next to it it should load the predetermined name for number 12.
The first one is named 'shipper' and the other 'shipperName'
Whenever I write the code 12 in the 'shipper' txtfield, it should return the name of the shipper in the 'shipperName' box.
Thanks in advance!
Examples:
If I write the number 12 it should return USPS
http://i53.tinypic.com/2i90mc.jpg
And every number should have a different 'shipperName'
Thanks again!

That's quite easy if you'll use jQuery. Check out the event handlers ("blur" is the one you want which occurs when the user leaves the numerical box).
For example:
$("#shipper").blur(function() {
$("#shipperName").load(
"${createLink(controller: 'shipper', action: 'resolveShipper')}?id=" +
$("#shipper").val()
);
});
The $(this).val() at the end is the value of the input field the user just left.
And the "ShipperController.resolveShipper" action would look something like this:
def resolveShipper = {
render text: Shipper.get(params.id).name, contentType: "text/plain"
}
There are other things you might want to do, like automatically filling in the shipperName field as the user types without leaving the edit field, probably after a delay. However the event handler stays the same, just the event is changing (from "blur" to "change" or something like this)

To relate two strings, it's easiest to use an object to create a dictionary/ map, as shown below;
$('#input1').bind('keyup',function() {
var map = {
"1":"One",
"2":"Fish",
"3":"Bar"
};
$('#input2').val(map[$(this).val()]);
});
You can see this in action here: http://www.jsfiddle.net/dCy6f/
If you want the second value only to update when the user has finished typing into the first input field, change "keyup" to "change".

Related

Accessing HTMLCollection

So I am trying to access all of a specific class name and then eventually ad an event listener to them. I'm doing it this way because I am building a hightcharts graph and cannot add click events specifically to the legend items. So after the graph is build I am trying to access the buttons and then add the event listener.
getButtons() {
let buttons = document.getElementsByClassName('legend-btn');
console.log(buttons);
console.log(buttons[0]);
},
The first console.log comes back with an HTMLCollection with a length of 48 (I know very long but for now it's more testing purposes than anything).
The second console.log comes back as undefined. Any ideas why? I was hoping to do something like this:
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function () {
changebackground(event);
});
}
Any suggestions for how I can add the click event for the newly built highcharts graph?
May I suggest that you try:
for (let button of buttons) {
button.addEventListener('click', changebackground);
}
I am not sure why you intended to call changebackground(event): in order to do that, you'd have to put event in the event listener's parentheses. Better pass changebackground directly (assuming it does take an event as a parameter).
I'm not quite sure about what I'm telling you: hard to tell without seeing more of the context.

Rendering dynamic scss-files with ajax, rails

As the title suggests, my main objective is to render a dynamic scss(.erb) file after an ajax call.
assets/javascripts/header.js
// onChange of a checkbox, a database boolean field should be toggled via AJAX
$( document ).ready(function() {
$('input[class=collection_cb]').change(function() {
// get the id of the item
var collection_id = $(this).parent().attr("data-collection-id");
// show a loading animation
$("#coll-loading").removeClass("vhidden");
// AJAX call
$.ajax({
type : 'PUT',
url : "/collections/" + collection_id + "/toggle",
success : function() {
// removal of loading animation, a bit delayed, as it would be too fast otherwise
setTimeout(function() {
$("#coll_loading").addClass("vhidden");
}, 300);
},
});
});
});
controller/collections_controller.rb
def toggle
# safety measure to check if the user changes his collection
if current_user.id == Collection.find(params[:id]).user_id
collection = Collection.find(params[:id])
# toggle the collection
collection.toggle! :auto_add_item
else
# redirect the user to error page, alert page
end
render :nothing => true
end
All worked very smooth when I solely toggled the database object.
Now I wanted to add some extra spices and change the CSS of my 50+ li's accordingly to the currently selected collections of the user.
My desired CSS looks like this, it checks li elements if they belong to the collections and give them a border color if so.
ul#list > li[data-collections~='8'][data-collections~='2']
{
border-color: #ff2900;
}
I added this to my controller to generate the []-conditions:
def toggle
# .
# .
# toggle function
# return the currently selected collection ids in the [data-collections]-format
#active_collections = ""
c_ids = current_user.collections.where(:auto_add_item => true).pluck('collections.id')
if c_ids.size != 0
c_ids.each { |id| #active_collections += "[data-collections~='#{id}']" }
end
# this is what gets retrieved
# #active_collections => [data-collections~='8'][data-collections~='2']
end
now I need a way to put those brackets in a scss file that gets generated dynamically.
I tried adding:
respond_to do |format|
format.css
end
to my controller, having the file views/collections/toggle.css.erb
ul#list<%= raw active_collections %> > li<%= raw active_collections %> {
border-color: #ff2900;
}
It didn't work, another way was rendering the css file from my controller, and then passing it to a view as described by Manuel Meurer
Did I mess up with the file names? Like using css instead of scss? Do you have any ideas how I should proceed?
Thanks for your help!
Why dynamic CSS? - reasoning
I know that this should normally happen by adding classes via JavaScript. My reasoning to why I need a dynamic css is that when the user decides to change the selected collections, he does this very concentrated. Something like 4 calls in 3 seconds, then a 5 minutes pause, then 5 calls in 4 seconds. The JavaScript would simply take too long to loop through the 50+ li's after every call.
UPDATE
As it turns out, JavaScript was very fast at handling my "long" list... Thanks y'all for pointing out the errors in my thinking!
In my opinion, the problem you've got isn't to do with CSS; it's to do with how your system works
CSS is loaded static (from the http request), which means when the page is rendered, it will not update if you change the CSS files on the server
JS is client side and is designed to interact with rendered HTML elements (through the DOM). This means that JS by its nature is dynamic, and is why we can use it with technologies like Ajax to change parts of the page
Here's where I think your problem comes in...
Your JS call is not reloading the page, which means the CSS stays static. There is currently no way to reload the CSS and have them render without refreshing (sending an HTTP request). This means that any updating you do with JS will have to include per-loaded CSS
As per the comments to your OP, you should really look at updating the classes of your list elements. If you use something like this it should work instantaneously:
$('li').addClass('new');
Hope this helps?
If I understood your feature correctly, actually all you need can be realized by JavaScript simply, no need for any hack.
Let me organize your feature at first
Given an user visiting the page
When he checks a checkbox
He will see a loading sign which implies this is an interaction with server
When the loading sign stopped
He will see the row(or 'li") he checked has a border which implies his action has been accepted by server
Then comes the solution. For readability I will simplify your loading sign code into named functions instead of real code.
$(document).ready(function() {
$('input[class=collection_cb]').change(function() {
// Use a variable to store parent of current scope for using later
var $parent = $(this).parent();
// get the id of the item
var collection_id = $parent.attr("data-collection-id");
show_loading_sign();
// AJAX call
$.ajax({
type : 'PUT',
url : "/collections/" + collection_id + "/toggle",
success : function() {
// This is the effect you need.
$parent.addClass('green_color_border');
},
error: function() {
$parent.addClass('red_color_border');
},
complete: function() {
close_loading_sign(); /*Close the sign no matter success or error*/
}
});
});
});
Let me know if my understanding of feature is correct and if this could solve the problem.
What if, when the user toggles a collection selection, you use jquery change one class on the ul and then define static styles based on that?
For example, your original markup might be:
ul#list.no_selection
li.collection8.collection2
li.collection1
And your css would have, statically:
ul.collection1 li.collection1,
ul.collection2 li.collection2,
...
ul.collection8 li.collection8 {
border-color: #ff2900;
}
So by default, there wouldn't be a border. But if the user selects collection 8, your jquery would do:
$('ul#list').addClass('collection8')
and voila, border around the li that's in collection8-- without looping over all the lis in javascript and without loading a stylesheet dynamically.
What do you think, would this work in your case?

Event listener for multiple elements - jQuery

In the ASP MVC page I'm currently working on, the values of three input fields determine the value of a fourth. Zip code, state code, and something else called a Chanel Code will determine what the value of the fourth field, called the Territory Code, will be.
I just started learning jQuery a couple weeks ago, so I would first think you could put a .change event that checks for values in the other two fields and, if they exists, call a separate method that compares the three and determines the Territory code. However, I'm wondering if there is a more elegant way to approach this since it seems like writing a lot of the same code in different places.
You can bind a callback to multiple elements by specifying multiple selectors:
$(".field1, .field2, .field3").click(function() {
return field1 +
field2 +
field3;
});
If you need to perform specific actions depending on which element was clicked, another option would be to create a function which performs the actual computation and then invoke that from each callback.
var calculate = function() {
return field1 +
field2 +
field3;
};
And then invoke this function when on each click:
$(".field1").click(function() {
// Perform field1-specific logic
calculate();
});
$(".field2").click(function() {
// Perform field2-specific logic
calculate();
});
// etc..
This means that you do not repeat yourself.
This works for me
jQuery(document).on('scroll', ['body', window, 'html', document],
function(){
console.log('multiple')
}
);
Adding another possibility, just in cased this may help someone. This version should work on dynamically created fields.
$("#form").on('change', '#Field1, #Field2, #Field3', function (e) {
e.preventDefault();
console.log('something changed');
});

How to delete a jqgrid row without reloading the entire grid?

I have a webpage with multiple jqgrids each with inline editing enabled, "action" column (edit icons) enabled and pager disabled. I need to handle the delete event for each row so that I can process the delete without reloading server-side data. I've looked at the approach mentioned in jqGrid Delete a Row and it's very helpful except I have two questions that are stumping me -
Are there more details around the rp_ge parameter in the delOptions.onClickSubmit event?
My column has the delOptions set as this -
delOptions: {onclickSubmit: function(rp_ge, rowid) {return onRowDelete(rp_ge,rowid);}},processing:true }},
Is there a way to get the grid id from within that event? I'd like to have a generic function that I can use to handle delete events from all the grids on the page. The rp_ge parameter has a gbox which sometimes contains the grid id appended? But I have no idea what it is since i'm not able to figure out when it's populated, when it's not.
function onRowDelete(rp_ge, rowid) {
//hardcoded grid id.. don't like it.
var gridid = '#Grid_X';
//what is this gbox?? can i get grid id predictable from it?
//var gridid = rp_ge.gbox.replace("#gbox_", "");
var grid = $('#Grid_X');
rp_ge.processing = true;
var result = grid.delRowData(rowid);
if (result) {
$("#delmod" + grid[0].id).hide();
}
return true;
}
In the jqGrid Delete a Row approach, the code $("#delmod"+grid[0].id).hide(); is hiding the popup delete confirmation dialog manually. What I noticed is that when the dialog pops-up, jqgrid de-emphasizes the background page (makes it light greyish). But after the popup is manually closed (hidden actually?), the background remains de-emphasized. So it looks like the page doesn't have focus (or even disabled). Any way this can be fixed? This can also be seen on the demo that Oleg wrote.
Any help would be appreciated.
(PS - I would've commented on the same post but I don't have enough points to comment on someone else's answer yet.)
In answer to your second point.
Several examples by Oleg such as this one have the following modification.
$("#delmod" + grid[0].id).hide();
is replaced with
$.jgrid.hideModal(
"#delmod"+grid_id,
{gb:"#gbox_"+grid_id,jqm:rp_ge.jqModal,onClose:rp_ge.onClose}
);
This will return focus after the delete operation.

ShareThis setting properties in callback don't work

I'm using the ShareThis widget. I need to change the url property after the object has been created so I'm using the callback function option. In the callback function, I attempt to change the url property but the email that goes out still contains the old value.
Has anyone been able to solve this problem? If so, I would appreciate your help!
Here's a code sample
<script type="text/javascript">
SHARETHIS.addEntry({
title: 'ShareThis'},
{ onclick: myCustomCallback }
function myCustomCallback(SharedObject) {
SharedObject.properties.url = "http://www.myurl.com";
return true;
};
</script>
Use this:
$('span[class^="st_"]').html(''); // Empty span contents
$('span[class^="st_"]').attr('st_processed',null); // Reset ST plugin
$('span[class^="st_"]').attr('st_url',url); // Set new url
stButtons.makeButtons(); // Renew buttons
It's not possible to change the URL dynamically. If you want to do something funky, you'll need to create a new button with the new URL. This can be accomplished a few ways, the simplest being creating an element to contain the button and trigger creation of a custom button element every time something happens that should trigger the URL change.
I can show you a sample implementation that we put together for HP a few weeks ago. They actually call the "share" function from inside a Flash movie, but this prototype triggers it from a button.
You can reach me at sragan#sharethis.com

Resources