Showing posts with label java script. Show all posts
Showing posts with label java script. Show all posts

Tuesday, July 28, 2009

updating more than one div with grails and ajax

sometimes it happens that you have to update several div's on one webpage, when you click on a form or a button.

Now you can either reload the complete page, which can take a while with a lot of data or just queue remote functions in a java script function like this


function addStandard() {

if (YAHOO.example.container.addstandard) {
YAHOO.example.container.addstandard.hide();
}

//get our element values
var conc = document.getElementsByName('qs_concentration')[0].value;
var pattern = document.getElementsByName('qs_pattern')[0].value;

//calls the remote functions
${remoteFunction(
controller: 'management',
action: 'addStandard_ajax',
params: '\'conc=\' + escape(conc) + \'&pattern=\' + escape(pattern)',
update: 'registered_standards')}

${remoteFunction(
controller: 'messenger',
action: 'showMessage',
params: '\'message=you should recalculate the database now!\'',
update: 'messenger')}
}

Monday, July 27, 2009

lesson of the day...

and god said you shall no duplicate div ids,
cause if you do,
you shall be send to the hell of css,
constant torture and misfortune will await you,

so do not duplicate your id's!

problem:

updating a you tab with some dynamic generated content, which generate the same div id over and over again...

Thursday, July 23, 2009

Grails - using several arguments with a remote function

in grails it's a bit tricky to use a remote function and pass more than one parameter, since it does not follow the map approach like the usual approach

After a bit of asking Dr Google I finally found an approach which worked


var conc = document.getElementsByName('qs_concentration')[0].value;
var pattern = document.getElementsByName('qs_pattern')[0].value;

${remoteFunction(
controller: 'management',
action: 'addStandard_ajax',
params: '\'conc=\' + escape(conc) + \'&pattern=\' + escape(pattern)',
update: 'registered_standards')}


now I just wish there would be an easier approach

grails remote function on image or checkbox

Today I was in the situation that I wanted to call a remote function on an image to emulate a button, to delete an object with a specific id.

It's simple enough,



<img name="${standard.getPosition()}" src="${createLinkTo(dir: 'images', file: 'remove.gif')}" alt="zoom" onclick="${remoteFunction(
controller: 'management',
action: 'removeStandard_ajax',
params: '\'standard=\' + + escape(this.name)',
update: 'registered_standards')}"/>


To make live easy we just save the id in the name field of the image, but you can also save it somewhere else, depending on your requirements.

Now another thing you can do is todo the same thing for checkfields.


<input type="checkbox" id="cacheSetting" name="cacheSetting" onchange="${remoteFunction(
controller: 'management',
action: 'updateCache_ajax',
params: '\'cacheSetting=\' + escape(this.checked)',
update: 'general_config')}"/>


If you want to preserve the check state you can do this with this


<input type="checkbox" id="cacheSetting" name="cacheSetting" <%if(cacheSetting) println "checked"%> onchange="${remoteFunction(
controller: 'management',
action: 'updateCache_ajax',
params: '\'cacheSetting=\' + escape(this.checked)',
update: 'general_config')}"/>


and an example controller function could look like this



def updateCache_ajax = {
assert params.cacheSetting != null, "you need to provide \"cacheSetting\" in the params object"
BinBaseQualityConnector.getQualityConfigService().setCaching(Boolean.parseBoolean(params.cacheSetting))

//define our model
def model = new HashMap()

//build the model
model.cacheSetting = BinBaseQualityConnector.getQualityConfigService().isCaching()

render(template: "general", model: model)
}

Thursday, July 16, 2009

YUI and Prototype - updating an element

Well currently I'm working a lot with YUI and specially tabs. So one of the first things I wanted todo is to select a tab and this selections should do two things
  • show the content of the tab, happens by default
  • update a div on the page somewhere with some content related to the tab content
so how do you do this?

Quite simple.



<script type="text/javascript">
var myTabs = new YAHOO.widget.TabView('demo');
var tab0 = myTabs.getTab(0);

function handleClick(e,tab) {
${"div_to_update"}.update("I just clicked on my tab!");
}

tab0.addListener('click', handleClick,tab0);
</script>



and as you can see we use the 'update' function from the prototype library.

Wednesday, July 15, 2009

Grails - ajax driven select and saving the selection

A couple of days ago I discovered the need of ajax populated forms to improve the navigation of the current website I'm working on.

And some nice person wrote a great tutorial about this here, but there was one thing missing. I wanted to render some elements on the same page and keep the selection stored in the text field.

The default approach is the following grails tag:


<g:select id="machine" name="machine" value = "${machine}"/>


but since this field is populated by an ajax function, the value can never be set,since the population happens after the page is loaed, so what can we do?

We enhance our little bit of java script and define the selection in there


//update the machine tag with the received values
function updateMachine(e) {
// The response comes back as a bunch-o-JSON
var machines = eval("(" + e.responseText + ")"); // evaluate JSON


if (machines) {
var rselect = document.getElementById('machine');

// Clear all previous options
var l = rselect.length;

while (l > 0) {
l--;
rselect.remove(l) ;
}

// Rebuild the select
for (var i = 0; i < machine =" machines[i];" opt =" document.createElement('option');" text =" machine;" machine = <%=machine%>'){
opt.selected = machine;
}
//just add another field and work with the default selection
else{
opt.value = machine;
}
try {
rselect.add(opt, null); // standards compliant; doesn't work in IE
}
catch(ex) {
rselect.add(opt); // IE only
}
}
}
}

//initilaize the variables on page load
var zselect = document.getElementById('database') ;
var zopt = zselect.options[zselect.selectedIndex]
${remoteFunction(controller: 'query', action: 'listmachines_ajax', params: '\'database=\' + zopt.value', onComplete: 'updateMachine(e)')}



we basically assume that our controller inject a variable with the name 'machine' on submitting the form. A controller closure could look like this:


def showTimeLine_ajax = {

assert params.database != null, "you need to provide the database in the params object"
assert params.machine != null, "you need to provide the machine in the params object"

def model = new HashMap()

//build our model, implementation not shown because of copyright
//model = buildModel(params.database,params.machine)

model.database = params.database
model.machine = params.machine

return model
}



and our form is simple enough


<g:form name="select_database_machine_form" method="post">
<g:select id="database" name="database" from="${dbs}" value="${database}"

onchange="${remoteFunction(
controller:'query',
action:'listmachines_ajax',
params:'\'database=\' + escape(this.value)',
onComplete:'updateMachine(e)')}"/>
<g:select id="machine" name="machine"/>

<g:submitToRemote action="showTimeLine_ajax" update="graph_content" value="execute query"/>
</g:form>