Copy autocomplete value from previous group to the next using JS

Status
Not open for further replies.

rackem

Well-Known Member
I have a database join element, rendered as an auto-complete in a repeating group. I am trying to figure out the JS to copy the selection from the previous group when a user adds a group.

The following code performs this operation already for two dropdown elements. The last section (noted with comment) is where I am struggling.

Code:
Fabrik.addEvent('fabrik.form.group.duplicate.end', function(form, event, g_id, r_count){
	var tables = $('group' + g_id).getElements('select[name *= mps_bouts___table]');
	tables[r_count].selectedIndex = tables[r_count - 1].selectedIndex;
		
	var games = $('group' + g_id).getElements('select[name *= mps_bouts___game]');
	games[r_count].selectedIndex = games[r_count - 1].selectedIndex;

	// These last lines are the ones in question
	var opponents = $('group' + g_id).getElements('input[name *= mps_bouts___opponent]');
	var last = opponents[2 * r_count - 1].getValue();
	var new_id = opponents[2 * r_count + 1].id;
	form.formElements.get(new_id).update(last);
});

It is confusing because the getElements statement gets 2 elements per group for the autocomplete instead of just one like the dropdown elements. The 1st element contains the autocomplete's label and the 2nd contains its value.

The above code gets the previous group's element value and assigns it to the next group's element. However the autocomplete field remains empty.

I tried getting and updating the label but received the error "cannot call method 'update' of null". I also tried using "setValue" instead of "update" with basically the same result.

Is there another way to set an autocomplete using JS?
 
I was looking through the JS for the dbjoin element. It appears that if the setValue function is passed a value, then it should update the label as well?

So I changed my last line to
Code:
form.formElements.get(new_id).setValue(last);

As before, I confirmed the value is getting set in the form. However, the label corresponding to the value is not populated. Seems so close...
 
Hmmm, looks like setValue should grab the label from the server with an AJAX call, but as written that code just flat out won't work.

Looking at it now.

-- hugh
 
OK, should be fixed in github.

I replaced the AJAX stuff we had in setValue() with a call to updateFromServer(), which is what we call in a couple of other places, for updating the label on the autocomplete.

This is going slightly the long way round, as you could technically set the label yourself directly, as you already know what it is (from the repeat group you are grabbing from), so it's kind of an unnecessary AJAX call to the server to re-fetch it, but this will work.

Of course, it may have other side effects you don't actually want, like it fires the 'changed' and 'blur' events for that element, so if you have any calc or CDD elements which 'watch' this join, those will run their update methods ...

-- hugh
 
OK, should be fixed in github.
Thanks Hugh! I am away now but will try it when I return.

This is going slightly the long way round, as you could technically set the label yourself directly, as you already know what it is (from the repeat group you are grabbing from), so it's kind of an unnecessary AJAX call to the server to re-fetch it, but this will work.

If it is not too much to explain, I am curious to know how would I just set the label? "The long way around" approach should be fine for my case but it would provide a sense of triumph to learn the shortcut. Looking at the code in setValue(), this section appears to do it
Code:
if (typeOf(l) !== 'null') {
        labelfield = this.element.getParent('.fabrikElement').getElement('.autocomplete-trigger');
        this.element.value = v;
        labelfield.value = l;

but I'm not sure how to translate this into my code.
 
yup that code is the part that sets both the label field and (hidden) value fields values.
In that code 'this' refers to the element plugin you are accessing in

Code:
[FONT=monospace][/FONT][FONT=monospace]
[/FONT]form.formElements.get(new_id)


so you should be able to do:

Code:
[FONT=monospace]
[/FONT]labelfield = form.formElements.get(new_id).element.getParent('.fabrikElement').getElement('.autocomplete-trigger');[FONT=monospace]
[/FONT]labelfield.value = 'foo';
 
Hugh, the setValue() still doesn't update the label. I am happy to test again if you want to take another crack at it.

On a happy note ;D, and in the typically roundabout way that experimental learning occurs:rolleyes:, I realized I was over-thinking and missed the obvious. The following bit of code is all that was needed.8)

Code:
var opponents = $('group' + g_id).getElements('input[name *= mps_bouts___opponent]');
var val = opponents[2 * r_count - 1].getValue();
var label = opponents[2 * r_count - 2].getValue();
opponents[2 * r_count + 1].value = val;
opponents[2 * r_count].value = label;
 
Hmm, dunno why the changes I made don't work for you. They work for me, and it's the same code we use with no problems elsewhere to do exactly the same thing.

BTW, you may experience issues if you add a group, delete it, then add again, as I'm pretty sure that will leave a gap in the repeat sequence number, so the "r_count - 1" wouldn't work. Which is one of the reasons I suggested sticking with the setValue() approach.

Test it, and let me know.

BTW, do you use Firebug? You can test this stuff by hand, by setting a breakpoint at the start of the setValue() method in the databasejoin.js, then calling that by hand in the JS console, like ...

form_X.formElements.get('table___element').setvalue('x');

If nothing else, you can confirm that the AJAX call is firing off, and by setting a bp in the onComplete() method for it, you can see what it is returning.

-- hugh
 
Sorry to hear about the lightning damage Hugh. Hope you didn't loose too much.

BTW, you may experience issues if you add a group, delete it, then add again, as I'm pretty sure that will leave a gap in the repeat sequence number, so the "r_count - 1" wouldn't work.....Test it, and let me know.
Seems to work OK but I will definitely keep an eye on it. Thanks for mentioning it. I think I used the array length before but then saw r_count and went with that as it seemed to be the same.

Regarding the setValue(), I could not figure out why it doesn't work. Chrome displays better than Firefox on my laptop's small screen so I use Chrome Web Developer instead of Firebug. I turned on J! debug to see the uncompressed JS, set breakpoints, and stepped through the code as you suggested. With the exception of not seeing the workings of the AJAX, nothing jumped out at me but then again this is deeper into the nuts & bolts of things then I have gotten in to.

If you would like to take a look, I have created a simplified version of my setup using the setValue() code here: http://www.mypoolstats.com/index.php/component/fabrik/form/11/0 that behaves the same. Just select an opponent (Al, Gary, Jim, or Tom) and then add a group. The new group's opponent value is set but the label remains empty.

To re-summarize the setup: I have a left join between two lists, events and bouts, set to repeating. Bouts contains a database join element "Opponent", rendered as an auto-complete. When a group is added, I just want to copy the previous group's opponent into the new group. So I have the following custom JS in 11.js

Code:
Fabrik.addEvent('fabrik.form.group.duplicate.end', function(form, event, g_id, r_count){

	var opponents = $('group' + g_id).getElements('input[name *= bouts___opponent]');
	var val = opponents[2 * r_count - 1].getValue();
	var label = opponents[2 * r_count - 2].getValue();
	var new_id = opponents[2 * r_count + 1].id;
	
	form.formElements.get(new_id).setValue(val);
});
 
I couldn't get it to work either, I've fixed what I see as a couple of issues in the code at github and now doing this:

Code:
Fabrik.blocks['form_2'].formElements.join___3___regons___address_search_1.setValue(4)

works for me
Could you update and check if it works for you please?
 
I updated and found success with the line
Code:
Fabrik.blocks['form_11'].formElements.join___40___test_bouts___opponent_1.setValue(val);
However it wasn't quite what I needed as the element to be set will vary as the user adds entries. So I changed it to

Code:
form_11.formElements.get(new_id).setValue(val);

That worked too. Out of curiosity, I tried

Code:
form_11.formElements.get(new_id).update(val);

which matches the format called out in the Wiki. That works too. So, in summary, seems to work OK now. Thank you very much for all of your help and patience guys! :)

BTW, the full code is

Code:
Fabrik.addEvent('fabrik.form.group.duplicate.end', function(form, event, g_id, r_count){
	var opponents = $('group' + g_id).getElements('input[name *= bouts___opponent]');
	var val = opponents[2 * r_count - 1].getValue();
	var new_id = opponents[2 * r_count + 1].id;
	form_11.formElements.get(new_id).update(val);	
});
 
Just FYI, the difference between setValue() and update() is that setValue() ONLY sets the value. Whereas update() will also trigger any 'change' events (and, i think, 'blur' events) that may be watching that element. For instance, if the element is a database join, with a CDD (cascading dropdown element) "watching" it, using update() will trigger the CDD to update. Likewise if the element is observed by an autofill plugin. Or if you have defined any element JS effects (hide / show). Etc.

-- hugh
 
Talk about jumping through hoops ? and having to write a bunch of Javascript code ? when IF ONLY you would implement the ?carry-on? auto-fill feature I was harping about last week (a simple checkbox to optionally tag any element(s) in a group as whether to ?carry? that element?s value to a newly added record.) ? OR An ?auto-fill filtered columns? option in each List configuration that would act as a flag to ?carry over? the values of filtered columns (that need to be the same value anyhow to hold the filter together ? like userids, subscriptionIDs, catgeoryIDs, etc.)

A little reworking of the Fabrik code used to INSERT new records, (to check for other ?carried-on INSERT values) ? and users wouldn?t be scratching their heads and looking to support every time they need to do something like this. Sometimes I think people just like making things harder and more complicated than they need to be.

Now if you wanted to be REALLY cool? Instead of just an administrator backend setting ? there could be checkboxes in List headers or next to form labels - or double-clicking the column heading of the List, or the label of a Form element to toggle ? that would change color to indicate their ?carry-on? status and act as flags for any columns/form elements that the user wants to ?carry-on? the value to the next group when they add a new record.

What a marvelous feature that would be. (If you?re really interested in making things easy on the ?stupid user?, and aren?t really targeting your product to the programmer types ? as Rob explained to me last week ? then you need to make up your minds. Because most of this stuff requires users to have some pretty comprehensive knowledge of Javascript and php in order for users to get things working the way they want. Half of the support instruction I read in these forums is above my head, so I can only imagine a less computer-literate individual trying to ?experiment? with this product.

I?m just saying ? instead of always passing some fancy javascript workarounds and php code that no one but you understands ? how about just making the software a little more user-friendly so users don?t have to turn to writing their own code? In the 10 times it takes to explain something like this in a support forum to a customer ? you could be writing the code and changing the Fabrik UI core so that it makes it easy for the user to do the same thing without having to write any code ? or ?bother? you about their problem.

I suppose this is just a matter of 2 different approaches to programming, providing solutions to common problems, and customer support - but the way it seems to be done around here always has me scratching my head.
 
Sometimes I think people just like making things harder and more complicated than they need to be.
Thats not it, its just that this is not that common a request, so we've helped him resolve the issue with our product as it stands.

Its not a question of us making it harder on purpose, its just that in a flexible system as soon as you add a new feature e.g. at one stage we could not make repeatable groups at all. Then all the peripheral features expotentialy can more potential possibilities.

So yes some of those possibilities are not coded for or possible with a gui switch, and yes some of them would be good to implement and others less so, but these things do not just take 5 minutes to do, trust me

You have to think also that people only ask questions about things that can't easily achieve, and sometimes they ask for things there we have not coded. We try to advise people the best way to go about achieving their needs with the code as it is. If there's an easy kill or a bug then we fix, if not well either they will have to wait till we can provide a simpler solution or implement what we suggest as the best possible solution at the current time.
 
In the 10 times it takes to explain something like this in a support forum to a customer ? you could be writing the code and changing the Fabrik UI core so that it makes it easy for the user to do the same thing without having to write any code

That's quite a few times you've opined on how quick / easy it would be to code up a given feature, which shows a remarkable insight and in depth knowledge of how Fabrik works. I'm impressed that you think you could code this up so quickly, as I've been dicking around with the code to do just this for several months now, as one of my back burner tasks, and still haven't had time to get it working right. Turns out it's not as simple as some folk might think, to provide a generic way of doing this. Perhaps if I was free to just dedicate a continuous chunk of time to it, it would come together, but right now there's always more important issues to deal with in the 3.x shake-out process.

Once we get 3.x truly bedded in and all the 2.x -> 3.x / J! 1.5 -> 2.5 rewrite issues resolved, we can start concentrating more time on adding features. Until then, berating us for not implementing feature X is a) a waste of time and b) is just going to piss me off. You think I'm not aware that this would be a useful feature, and that it's a pain to have to find a personalized solution whenever I get asked this question? And that I wouldn't love to have the time to get it done?

-- hugh
 
I'm flattered this thread was chosen for this discussion. :rolleyes: My two cents as a fellow engineer (hardware not software) in a similar situation everyday: It is always great to hear ideas for improvement. How useful they may be and how trivial they are to implement is a fuzzy science. Balance that with human error and limited resources. The decision is best left to those intimately familiar with the project as they know the compromises that must be made. So let the ideas fly; the best will rise and the rest will disappear or languish. Over the short time I've been using Fabrik I feel Hugh and Rob have found reasonable balance.

Given the choice, my vote is flesh out the documentation as time allows. Fabrik is super capable already but the learning curve is very steep, especially for the non-programmer (like me!). Way too much time is spent in this forum rehashing many of the same questions. Granted much can be attributed to users not looking up the information that does exist. And OK, I will admit I am guilty of not adding to the wiki when my own light bulb finally brightens. But, by golly, it is way more fun to tweak, experiment, and write code than it is to explain how things work!

Keep up the good work! :)

Just FYI, the difference between setValue() and update() is that setValue() ONLY sets the value. Whereas update() will also trigger any 'change' events (and, i think, 'blur' events) that may be watching that element.
OK, thanks for explaining!
 
We're steadily working on fleshing out the Wiki, and obviously actively encourage others to contribute. The problem is obviously just time constraints. I'd love to be able to take time out to build all the documentation we need, but whilst supporting two wildly different versions of J!/F!, and going through the knee of the 3.x bedding in / bug shake-out curve, if I take my eye off the forums for more than half a day a week, the backlog grows beyond my ability to catch up.

We went through the same curve in the J! 1.0.x -> 1.5.x / F! 1.x -> 2.x migration, so I know that fairly soon we'll get 3.x settled down, be able to end-of-life 2.x (when J! 1.5 is end of lifed in August), and get some breathing room to build a decent set of tutorials, and add Wiki entries for all the core features and (most) of the plugins.

-- hugh
 
Looking further down the road, one very bright ray of sunshine is J!'s move to splitting out the platform and the CMS, providing a much longer life cycle, and a much smoother transition between new versions from here on out. So no more huge, monolothic changes like J! 1.0 to 1.5, and 1.5. to 2.5, which have both required huge swathes of code in Fabrik to be rewritten.

This will make Rob and I's life MUCH easier in the long term, as we'll be able to keep up with the incremental changes in the platform, and not be faced with essentially rewriting Fabrik every 18 months.

I think Joomla.org and every extension developer on the planet learned some hard lessons in the 1.0 to 1.5 to 2.5 progression, and "future proofing" is very much on everyone's mind these days.

-- hugh
 
Status
Not open for further replies.
We are in need of some funding.
More details.

Thank you.

Members online

Back
Top