First off, I'm not sure if the title I came up accurately describes what I'm trying to do.
I have a table of tasks, with an assign action for each. Basically, in normal cases, the user would click the link, in which a call would be made to assign them to the task and then redirect them to the task details page. That can be done with a simple ng-click to call the assign function, and then using the $location.path() function for the redirect on success. Doing it this way, there is no need for the href attribute.
But, this also takes away the ability to open the link in a new tab by "middle clicking" or "ctrl + clicking" because there's no href value. For example, some users would typically assign themselves to multiple tasks at a time. On a typical site, it would just be a regular link that does some processing, finishes, and then loads the page they were intending to go to. So they could get away with opening multiple tabs, because all of them would process the request and then return the page as the response.
So I've added an ng-href attribute since I have an ID in there, and it kind of works. Middle clicking (or ctrl + clicking) will still call the ng-click function, and the ng-href will let the new tab open. But now the issue I have is that since the assign function call is async, sometimes the tab will load up not showing that they're assigned, since the page loaded before the assignment was processed.
Does anyone have an idea of what I can do to make this more reliable and accurate?
Can you not just use
$window.open(LOCATION);
instead of $location.path() ?
Related
I have a web page that shows remote asset data (for example weather station data) and that does background XMLHttpRequest()'s every 5 seconds to our server and reloads the page if new data from the remote asset has been received. This has all been working fine for years.
The page also has numerous links and submit buttons that can be used to go to other pages or submit commands to the server (which then sends a command to the asset). Issue I'm having is that some of the commands the server then executes involve calls to 3rd party web services, some of which can occasionally take up to 30 seconds to return or time out. But in the meantime if new data came in from the asset the background JS function reloads the page, thereby interrupting and cancelling the new http request that the user initiated.
I could probably work around this by adding onclick or onsubmit tags to every link and submit button to call a function to disable the timer, but as there can be dozens of links on the page I am hoping there might be a simpler, more elegant way where one simple function can tell me if the user clicked on something and thereby initiated a new active http session.
I enable my script by doing a setTimeout('myCheckServerFunction("'+url+'")',5000); from the html head. If the server then tells it there is new data it does a setTimeout(function(){location.reload();},5000);
So I'd like to disable the JS timer and prevent any reload if the user has clicked any link or button and thus if a new http session is active. Does there exist a function like this? eg. something like "window.isNewHttpRequestActive()" ? Or maybe there's a way I can check if the window.location changed? (not sure if that would get updated before the new http request is complete.)
Otherwise I could maybe attach a addEventListener() to every link and submit button on the page but I'm a PHP dev not JS so if anyone could recommend the best way to parse the DOM and attach a listener to every link and submit button that would work too.
I did try looking for events that "bubble" up to higher layers eg. the body element and that will catch link clicks but also catches any click even just a click on any blank area, So not sure how well that would work as I'd still need to filter that event to determine if it actually came from a link or button. Thank you.
Listening to all click events on body isn't necessarily a bad idea.
EDIT: As gre_gor pointed out in comment, it might be. The perceived target of the click is not always the link or button if other elements are inside of them.
So my original method, which was using event.target.tagName is to be avoided.
The following code would add an event listener for click on every a element of the document, and let you cancel the timer if it is set :
for (let element of document.getElementsByTagName("a") {
element.addEventListener("click", (event) => {
if (relocationTimeout !== undefined) {
clearTimeout(relocationTimeout);
relocationTimeout = undefined;
}
});
}
Up to you to adapt the selector in the loop to fit your needs.
Of course don't forget to store the timeout reference in a variable when you set it :
let relocationTimeout = setTimeout(function(){location.reload();},5000)
This may seem like a simple question, but it doesn't seem to be answered anywhere that i can find.
I am writing an onClick event handler that simply calls dataLayer.push() when an anchor is clicked.
Is dataLayer.push() a synchronous operation?
Will the GET request to google definitely be sent, even though the browser has unloaded the page it was requested from due to the link being followed?
Some browsers show the connection get cancelled, some show it success.
My question is if the computer is slow, is it possible for the page to get unloaded before the request is sent?
This is why i assume that google started using the eventCallback property to redirect the user after the link has been followed.
e.g.
https://developers.google.com/tag-manager/enhanced-ecommerce#product-clicks
This source code does not include the click handler, but implies that the onClick event should stop propogation and let the eventCallback function set document.location.
However, as soon as you cancel the event, all its information has gone.
This (in my opinion) is just the wrong way to do it.
e.g.
(CTRL or COMMAND) + Click opens a new tab on browsers. This will not work unless the onClick event handler allows the prorogation to continue.
Relying on eventCallback also means that if the google scrips didn't load for one of the many reasons it could (but is still unlikely), your links don't work. And your site is broken.
So this leaves the correct way to do it for the onClick event handler to allow the event to propagate and return true.
Which also means that dataLayer.push() would need return after the GET request was sent for any of this to work properly.
Code example:
NOTE: You will get mixed results in mixed environments.
Link
$(document).on('click', 'a', function(event) {
// Is dataLayer.push() guaranteed to fire a GET ?
// data set externally
dataLayer.push(data);
return true;
});
Is there anyone out there that can guarantee that the GET request will get fired to the google server?
Have the google developers forgotten something here?
EDIT: Updated title to be more relevant to the question.
datalayer.push does not send anything to Google. It pushes objects with key/value pairs to the datalayer array. This might contain an event which in turn fires a tag. Whether the tag is sent depends on the setup of the tag, not on the dataLayer.push.
As a consequence, when you write your own click handlers your are yourself responsible to make sure your tags are actually fired.
If you use the built-in click handler you can configure a delay to make sure your tag has time to fire before the link redirects:
Since link clicks usually cause the browser to load a new page and
interrupt any pending HTTP request, you have the option to add a small
delay to allow tags fired by Tag Manager to execute properly before
redirecting to the next page. Checking the “Wait For Tags” option will
delay opening of links until all tags have fired or the specified
timeout has elapsed, whichever comes first.
You should be able to mix both methods (push data on the click, but still use the "native" link click handler for the event).
You can also try to specify "beacon" as the transport method in your Google Analytics tags, on browsers that support this (which I think is only Chrome at the moment) GA will then use the navigator.sendBeacon interface, which sends the data even in case the page unloads.
You might think that Google's solution is not very elegant (but the simple delay has the advantage that it works for all tags, not just for GA), but they have not "forgotten" the problem.
Also solutions that combine GA hit callbacks with timeouts that redirects if the callback fails as proposed i.e. by Simo Ahava somewhere should be be doable with GTM, even if they are probably more cumbersome to implement in GA.
I have a link/anchor HTML like:
<a href='/some-form' ng-click='someFunction(item)'>Text</a>
What I have in mind is that user clicks this link, then I want to load an HTML from server, and after the loading of that HTML, I want someFunction to be executed, which fills the loaded form with some data.
However, by debugging my code, it seems that Angular JS first fires someFunction function, and then browser loads the HTML. Not only I want this to be reverse, but also I need them to be executed sequentially (synchronously).
Is my design a good design? Is there any other way to achieve this behavior? If not, what should I do to make it work?
so I think someFunction(item) should be in the other controller dealing with the route /some-form.
You may also consider using $location to manually navigate to /some-form.
Is there a way to group div IDs that are scared across multiple pages but get to be called to the same page at some point with Jquery.
I want to hide or show all the divs in a group while showing only a certain group. The reason some group gets to be included in other functions and writing all the list of this many div IDs is somehow not wise.
2nd question.
How do I program a button to reload page and then after run a function with jquery?
ok let me add some code to make sense of this reload problem.
$('#accountresult').click();
location.reload(); //Should reload page 1st and then function
$('#button').show("slow");
$("#Atresult").load("source_cxchange.html #account");
$("#result, #homeresult, #appleresult" ).empty()
});
but rather, it only runs reload and dies, someone please correct the syntax of putting two functions to successively follow one another.
My advice would be to group them using a class rather than a collection of ids. That way you can target them all at once with:
$('.someClass').hide()
As for reloading the page and running a function afterwards that gets a bit trickier can you explain what you are trying to achieve?
When you refresh the page you lose the javascript callstack so you will have to set a querystring or use cookies/local storage to persist a value. You can then use jQuery's onLoad() function to run your function only if the url parameter or cookie exists.
1) Assign some class to those ids and use $('.someclass') to refer them.
2) To reload page, you will need to call 'location.reload();'. then you can do whatever you should in $(function() {});, which is called whenever page is loaded.
I am using the HTML5 history API
I notice that if:
if I am on a page called /first
I use pushState to /second
And then hit the back button
The event handler for window.onpopstate() returns the state for /first, as documented.
In order to transition from /second to /first, I would like to see the URL that was popped - ie, /second in this case. What's the best way of doing that?
In lieu of a proper answer, I've implemented the following workaround:
Using a data-urlhack attribute on the <body> element when a page is loaded
In onpopstate() handler, checking the value of this attribute so I can transition from this page (where the back button was hit) to the page the back button has sent us to.
Also ensure that pages loaded in onpopstate() don't try and push use pushState() themselves.