On this problem some more people have stumbled and for non-ajax scenario there is already a solution :
How to prevent multiple inserts when submitting a form in PHP?
(answered Jan 25 '10 at 17:02)
I'd like to know how could be implemented efficiently on both the server and client side a similar solution for the following problem :
there is a wall listing containing multiple items on which the users can click an ajax-enabled "i like" button (no page reload)
the user can have multiple browser windows opened on which can click "i like" buttons
Expected :
Only the first click on the "I like" button for any of the wall items is taken at the server side into account and the following requests for the wall item are not handled anymore.
Keep track of the liked items of each user on the serverside (for example an extra database table). When a new like is going to be inserted, check if there is already an existing record in this table. If there is, the user has already liked this item and you dont't have to count it anymore.
I think the best way is to use a session variable that store the current state, ie when someone clicks you "i like", on the server side, you check the state of the SESSION var.
Related
I have a question on the subject of composite attributes that I would be grateful if you could help me with.
I posted this before on other question blogs but got no response I am satisfied with.
I am writing JavaScript that will update the fields (i.e. address1_line1, address1_line2, address1_line3, address1_city, address1_stateorprovince, address1_postalcode, address1_country) in the composite (address1_composite). When the fields are updated the composite does not seem to update. I have to open the composite and close it again. Is there a way of doing this automatically in JavaScript?
I have tried the following ideas:
Idea 1:
Xrm.Page.data.entity.save();
This is recomended at http://community.dynamics.com/crm/b/magnetismsolutionscrmblog/archive/2013/10/22/working-with-dynamics-crm-2013-composite-fields-fly-out-menu.aspx
This is not any good as my customers want to view the composite before saving the page. Also I would not want to save the page for my customers as they do not want this. They would like to decide when to do this themselves.
Idea 2:
Xrm.Page.data.refresh();
This is not really what I wanted as I do not want to refresh the whole page. I just want to refresh the composite. Also it bring up a popup that warns you about not having saved the page which will be annoying for my customers.
Idea 3:
Writing the address from the address lines to the composite.
This feels like a nasty hack.
There is probably more than one way of doing this. I used the function
Xrm.Page.getAttribute("address1_composite")._attribute.setValueForCompositeField();
I do not like this for the following reasons:
This is a hack as it is not using the system functionality of the done button to write the data.
You do not get the system formatting you get with the done button although this will get done when the form is saved so it is not so bad.
In the future if customers are allowed to add their own composite fields it could cause problems as the field names could be different.
It requires me to write extra code for each form that has a composite which has fields with different schema names. E.g. I have to write different code for forms with ShipTo and BillTo addresses as the code for the account form will not work.
Another idea was to set the focus to the composite field after a change has been made to any of the fields inside the composite.
Xrm.Page.data.entity.attributes.get("address1_composite").controls.get(0).setFocus();
This is the best idea so for but it is far from perfect. This forces the user to press the done button and hence the fields will be written. I was hoping for something more automated.
My Question:
What would be great is if there was a way to click the composite done button in JavaScript. This would give me the formatting of the done button and the automation I need.
Update - 14/04/2014
Since posting this question I have been in contact with Microsoft and they say there is no supported way of clicking the done button via a program.
If the field is locked down CRM JavaScript does not send the data back to the server for updating. Another approach would be:
perform the update using JavaScript (so the user sees the change); and
use a server side plugin on the Update event so the value is persisted.
I have a site with a shopping cart system, the issue is that we are having some members hit the remove item button, which updates the line item with a "removed" flag - then hitting the browser back button, which then shows the cart in the previous state - with the line item intact.
If they pay in this state we are getting all sorts of issues when the sales is processed as one of more of the items that they pay for don't get processed. which means we manually have to pick up the pieces at a later date.
Is there any standard way to handle this situation - ie I know we can provide an "undo" button - but the user is not always going to use it.
You have to use filter for this situation. And ya... You can also prevent user to go back by disabling back button using simple java script.
http://www.viralpatel.net
visit this one.
This will become helpful for you.
I am going to detail the solution that I am ending up with, in case other people have a similar issue.
Our payment gateway provides a way to pass custom information on to our payment process system, we are planning to pass along the id's of all items that are in the cart, and when we get them back we will use this to un-remove the removed items.
This works using the same process that is causing the issue in the first place, as the cart page does not reload on a browser back.
This is assuming that by pressing the back is the user trying to undo his action, as the payment value is confirmed prior to the sale we can be reasonably sure that the cart is how the user wanted it if its is pushed though.
we are also providing a undo system as well as having the javascript back protection in order to prevent it from being needed, 10 solutions are better than one in these situations.
I know that you can capture the event when a person clicks a "like" button from within a Facebook tab via the edge.create method, but what im wondering is if there is a way to capture when the Facebook like button at the top of a page is clicked, the purpose being to be able to find out which tab within my fan page is generating likes.
When the page reloads i will know that the page IS liked, but i dont know if the like was generated from one tab, or another tab on the same page.
The only solution I can think about which is sufficiently accurate is the following:
Start a session on server side with the first app request.
Remember the like state from the signed_request and the timestamp when it was issued.
Embed a javascript interval in your tab app(s), firing an AJAX request to your server every couple seconds. I think you have go with something between 2 and max 5 seconds.
The AJAX request refreshes only the timestamp in the session.
If the user clicks like on top of the page, now, the whole facebook page gets reloaded - so does your app and you get a new signed request which has the liked state now set to 1.
Have a look at your session > was the state 0 before? Yes? Is the timestamp max. 6-10 seconds old? Yes? Well, its most likely then that the user liked the page while being on the tab.
I hate the solution with the AJAX interval polluting the network (and on a big site with many users this will stress your server), but I can't think of any other solution, because there is no other way to keep track if the user is still looking on your tab. If the interval is too high, the user would be able to navigate away to the wall or info section and like the page there. If he directly returns to your tab after this, you wouldn't be able to track if he left the tab at all...
Another solution would be to listen for the body.unload event and fire a AJAX request to the server, telling you that the user has left the tab, but it is possible that the event never gets fired on certain browsers or the AJAX request is not fast enough to be processed before the tab page unloads. On the other hand would this solution take way less resources of both the users network and your servers performance.
This are just theoretically solutions and have to be tested, first!
I think this could be accomplished like this:
When the like button on top of the page or on the left side are clicked, facebook refreshes the currently displayed tab.
You can capture this refresh if you record the like state from the signed request, and when a tab transitions from not-liked to liked you can count it as a conversion.
This should work, have never used it, and it's better then nothing. You will probably need to add a limit on the user ip address to prevent unlike/like events increasing the counter.
Good luck, and please post here if you find a better solution, this can be interesting.
for example, we have a web form to let the user enter personal info such as address and phone number, then the user need to enter the spouse and dependents information. I usually use a gridview for this, but some users complain it is difficult to use. so what is the most user-friendly or conventional way to handle it?
thanks.
I usually use AJAX to do this. Usually a Button and/or programming triggered by an event to add form items.
For example:
Username:
Password:
(+) PHONE
.. then every time you add "+ PHONE" I would add a new set of text boxes for more phone numbers.
One option might be to have a more user-friendly form where the user fills in information for a single individual, and then an "add" button that takes the contents of the form and inserts it into the gridview where it can be reviewed while simultaneously clearing the rest of the form to allow another individual's info to be added.
I am familiar with several approaches to making the back button work in AJAX applications in various situations, but I have not found a solution that will work gracefully in my specific scenario.
The pages I am working with are the search interface for a site. You enter terms in a normal search box, click "go and wind up at a search results page. On the search results page there are a ton of UI controls for filtering/sorting the search results to find what you are looking for. Some of the operations triggered by these controls may take a (relatively) long time to complete (e.g. several seconds).
This latency is fine in case where the user is initially filtering/sorting their results... there's a nice AJAX spinner and so on... however when the user clicks on a search result and then clicks on the BACK button, I would like the page to instantly be restored to the state it was in when they clicked through.
I can restore the states using IFRAMEs/fragment identifiers as a dictionary of page history, but what ends up happening is that when the user first hits the back button the initial page is loaded, then it (re) makes the AJAX query to get the page state back, which triggers the AJAX spinner and another wait of possible several seconds.
Is there any approach that does not require this kind of two-stage load of the page when the user returns to the page via the BACK button?
Edited to add: I am partial to jquery but I'd be happy with solutions that depend on other libraries/toolkits or that are standalone/raw javascript.
Edited to add: I should've added that I'm trying to avoid cookies/sessions because this prevents people having multiple brower windows/tabs open and manipulating different sets of search results at the same time.
Edit: Matt, can you elaborate on your proposed solution (triggering a page change event via fragment identifer)? I see how this would help with BACK button clicks across the same page but not coming BACK to the search results page after clicking on a specific result.
Just use a cookie.
Have you investigated the YUI Browser History Manager?
Try to use localStorage object. Here is crossbrower libs jStorage and WEBSHIMS json-storage
Would it help to trigger a page change event using the "Add some info to the # at the end of the URL approach".
That way, clicking the back button shouldn't actually change the page, and you should be able to restore state without the first page load.
Use something persistent that is tied to the user's profile.
Cookies and sessions are good ideas, but you can also keep those stuff in the database. That gives you an added advantage of being able to save the user's filtering preferences accross different browsing session.(if, for exampple, he was looking for something in the office and then decided to continue searching when he is back at home).
It all depends on the complexity of the filters and weather or not it is something you think that the user will want to use accross diffrent browsing sessions..
Edited to add: I should've added that
I'm trying to avoid cookies/sessions
because this prevents people having
multiple brower windows/tabs open and
manipulating different sets of search
results at the same time.
You can create a random token and assign it to the fragment identifier.
on first page load create a token if no fragment identifier is set
before navigating out, store all the temporary ajax data in a cookie with that token as index.
when hitting back, if you have a fragment identifier set, load the data from the corresponding token in the cookie.
you can even add a "time" field to expire tokens, etc...
sample cookie (JSON):
{"ajaxcache":[{"token":<token>,"time":<time>,"data":<data>}, ... ]}