Why is setInterval() running as soon as my page loads and not on click event? - setinterval

Messing around with/learning about JS timing function for the first time. What I can't figure out is why my setInterval() function is running at the start of the page instead of on the click event like shown in my code.
jfiddle example: https://jsfiddle.net/uLsdfn1q/6/ (ignore the names, they don't make much sense)
function fadeOut() {
window.setInterval(printMsg, 1000 );
}
exit.addEventListener("click", fadeOut())
I know this is probably a pretty basic question, but I honestly cannot figure out why it is starting outside of the click event?

Related

office.js ExecuteFunction take long time to invoke after the first invoke

We are building an Excel Web Add-in using office.js.
We have a button on a custom tab with that triggers an ExecuteFunction action.
We noticed the function that is invoked works fine the first time but subsequent clicks take 3-4 minutes to invoke.
Does anyone experience the same issue? Any help on this would be appreciated.
We've also noticed the Refresh All Connections on Data tab also behaves the same way. Not sure if this is an larger issue with Excel Online.
Long time posted, no answer. Well, I think you have to call event.completed(); at the end of your function. Otherwise Excel Online will not know you're done. It will then wait for the event timeout, thus the long time to run after the first try.I had the same problem with my first add-in, which added a button to the ribbon to perform a minor task on a cell. The code structure should be like this:
function myFunction(event) {
Excel.run(function (context) { return context.sync(); })["catch"](function (error) { });
event.completed(); // This will do the magic.
}

Liferay IPC listener runs multiple times

First of all sorry if this question has been already asked somewhere, but after a few hours on google I still can't find an answer.
I am pretty new in portlet development, (but we have a shortage of developers and I have to work with it time to time), so the solution might be something trivial, but I really don't have enough experience with it.
The problem is I have two portlets on a page and I try to let one of them know about changes in the other. For this I use IPC. In the first one I have a Liferay.fire function:
function fire(key,value){
Liferay.fire(
'category',{
id: key,
name: value
}
);
}
In the other I have a Liferay.on('category',function(category){...}) function with an ajax call inside and some rendering methods.
Now if I visit the mentioned page and click on the corresponding buttons, at first everything works just fine. However, if I navigate from this page and come back, the listener will run two times. Navigating again -> three times. And so on... But if I reload the page (with F5 or CTRL+F5), it starts over, so until further navigation the listener runs only once.
The other strange thing is no matter how many times the function runs, the input parameters are all the same for each.
For example, if I have left the page and went back to it 3 times and last time I chose the category with 'id=1', then the function will run 3 times with 'id=1'. Now if I choose 'id=2' it will run 3 times with 'id=2'.
If anyone has any idea I would be really grateful as I am stuck for almost a day now.
Thank you very much in advance and please let me know if you need any further info.
the problem you're having is caused by the global Liferay.on listeners that are being created but never removed.
In Liferay Portal 7.x, SPA navigation is enabled by default. This means that when you are navigating, the page isn't being completely refreshed, but simply updated with new data coming from the server.
In a traditional navigation scenario, every page refresh resets everything, so you don't have to be so careful about everything that's left behind. In an SPA scenario, however, global listeners such as Liferay.on or Liferay.after or body delegates can become problematic. Every time you're executing that code, you're adding yet another listener to the globally persisted Liferay object. The result is the observed multiple invocations of those listeners.
To fix it, you simply need to listen to the navigation event in order to detach your listeners like this:
var onCategory = function(event) {...};
var clearPortletHandlers = function(event) {
if (event.portletId === '<%= portletDisplay.getRootPortletId() %>') {
Liferay.detach('onCategoryHandler', onCategory);
Liferay.detach('destroyPortlet', clearPortletHandlers);
}
};
Liferay.on('category', onCategory);
Liferay.on('destroyPortlet', clearPortletHandlers);

Does view.postscript() allow you to call functions loaded as output scripts?

I am using <xpScriptBlock> to store the contents of two rather long client side functions that loads an ExtJS grid. I can call the function using clientside javascript just fine.
I discovered that I need to show a different grid based on a condition in the underlining document. To reference the backend I moved the code to serverside and then tried to call the grid using view.postScript. This does not work and is the basis of my question.
Is this approach even possible? I do not wish to put all the code into the event. The functions are quite long and better kept in a script block for readability and maintainability. The functions are definitely loaded in the client, as I can manually load them using the firebug console. Perhaps I am missing something simple so I wanted to ask before changing my approach.
var typePO = document1.getItemValueString("typePO");
if(typePO == "AFS"){
view.postScript("loadGridAFS();")
} else {
view.postScript("loadGridOther();")
}
This code is in the serverside onClientLoad event of a panel. I have tried adding the 'return' keyword and it makes no difference.
UPDATE: I can't even get simple alerts to work using view.postscript(). Does this method only work in certain types of events in SSJS???
After some experimenting using a simple alert I can say that view.postScript() does NOT work everywhere.
For a test, I put the same code in an six event of the xpage. Here is an example of the code I used: view.postScript("alert('onClientLoad');"); I just changed the message to match the event.
Here are the results:
onClientLoad = nothing
beforePageLoad = XSP error
afterPageLoad = WORKS!
afterRestoreView = nothing
beforeRenderResponse = WORKS!
afterRenderResponse = nothing
I haven't tried every available event out there, but the bottom line here is that you shouldn't count on view.postscript() to work everywhere. And if it does do nothing, try a simple alert first to see of the event supports view.postscript before questioning the client javascript code you are attempting to run.

Web: The system will record the length of time the user displayed each page

I have this requirement:
The system will record the length of time the user displayed each page.
While trivial in a rich-client app, I have no idea how people usually go about tracking this.
Edited: By John Hartsock
I have always been curious about this and It seems to me that this could be possible with the use of document.onunload events, to accurately caputure star and stop times for all pages. Basically as long as a user stays on your site you will always be able to get the start and stop time for each page except the last one. Here is the scenario.
User enters your site. -- I have a
start time for the home page
User goes to page 2 of your site -- I have a stop time for the home page and a start time for page 2
User exits your site. -- How do you get the final stop time for page 2
The question becomes is it possible to track when a user closes the window or navigates away from your site? Would it be possible to use the onunload events? If not, then what are some other possibilities? Clearly AJAX would be one route, but what are some other routes?
I don't think you can capture every single page viewing, but I think you might be able to capture enough information to be worthwhile for analysis of website usage.
Create a database table with columns for: web page name, user name, start time, and end time.
On page load, INSERT a record into the table containing data for the first three fields. Return the ID of that record for future use.
On any navigation, UPDATE the record in the navigation event handler, using the ID returned earlier.
You will end up with a lot more records with start times than records with both start and end time. But, you can do these analyses from this simple data:
You can count the number of visits to each page by counting start times.
You can calculate the length of time the user displayed each page for the records that have both start and end time.
If you have other information about users, such as roles or locations, you can do more analysis of page viewing. For example, if you know roles, you can see which roles use which pages the most.
It is possible that your data will be distorted by the fact that some pages are abandoned more often than others.
However, you certainly can try to capture this data and see how reasonable it appears. Sometimes in the real world, we have to make due with less than perfect information. But that may be enough.
Edit: Either of these approaches might meet your needs.
1) Here's the HTML portion of an Ajax solution. It's from this page, which has PHP code for recording the information in a text file -- easy enough to change to writing to a database if you wish.
<html>
<head>
<title>Duration Logging Demo</title>
<script type=”text/javascript”>
var oRequest;
var tstart = new Date();
// ooooo, ajax. ooooooo …
if(window.XMLHttpRequest)
oRequest = new XMLHttpRequest();
else if(window.ActiveXObject)
oRequest = new ActiveXObject(“Microsoft.XMLHTTP”);
function sendAReq(sendStr)
// a generic function to send away any data to the server
// specifically ‘logtimefile.php’ in this case
{
oRequest.open(“POST”, “logtimefile.php”, true); //this is where the stuff is going
oRequest.setRequestHeader(“Content-Type”, “application/x-www-form-urlencoded”);
oRequest.send(sendStr);
}
function calcTime()
{
var tend = new Date();
var totTime = (tend.getTime() – tstart.getTime())/1000;
msg = “[URL:" location.href "] Time Spent: ” totTime ” seconds”;
sendAReq(‘tmsg=’ msg);
}
</script>
</head>
<body onbeforeunload=”javascript:calcTime();”>
Hi, navigate away from this page or Refresh this page to find the time you spent seeing
this page in a log file in the server.
</body>
</html>
2) Another fellow proposes creating a timer in Page_Load. Write the initial database record at that point. Then, on the timer's Elapsed event, do an update of that record. Do a final update in onbeforeunload. Then, if for some reason you miss the very last onbeforeunload event, at least you will have recorded most of the time the user spent on the page (depending upon the timer Interval). Of course, this solution will be relatively resource-intensive if you update every second and have hundreds or thousands of concurrent users. So, you could make it configurable that this feature be turned on and off for the application.
This has to be done with some javascript. As the other said, it is not completely reliable. But you should be able to get more than enough accurate data.
This will need to call your server from javascript code when the page is unloaded. The javascript event to hook is window.unload. Or you can use a nicer API, like jQuery. Or you could use a ready made solution, like WebTrends, or Google Analytics. I think that both record the length of time that the page was displayed.
Good web analytics is pretty hard. And it becomes harder if you have to manage a lot of traffic. You should try to find an existing solution and not reinvent your own ...
I've put some work into a small JavaScript library that times how long a user is on a web page. It has the added benefit of more accurately (not perfectly, though) tracking how long a user is actually interacting with the page. It ignores time that a user switches to different tabs, goes idle, minimizes the browser, etc. The Google Analytics method suggested has the shortcoming (as I understand it) that it only checks when a new request is handled by your domain. It compares the previous request time against the new request time, and calls that the 'time spent on your web page'. It doesn't actually know if someone is viewing your page, has minimized the browser, has switched tabs to 3 different web pages since last loading your page, etc.
As multiple others have mentioned, no solution is perfect. But hopefully this one provides value, too.
Edit: I have updated the example to include the current API usage.
http://timemejs.com
An example of its usage:
Include in your page:
<script src="http://timemejs.com/timeme.min.js"></script>
<script type="text/javascript">
TimeMe.initialize({
currentPageName: "home-page", // page name
idleTimeoutInSeconds: 15 // time before user considered idle
});
</script>
If you want to report the times yourself to your backend:
xmlhttp=new XMLHttpRequest();
xmlhttp.open("POST","ENTER_URL_HERE",true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
var timeSpentOnPage = TimeMe.getTimeOnCurrentPageInSeconds();
xmlhttp.send(timeSpentOnPage);
TimeMe.js also supports sending timing data via websockets, so you don't have to try to force a full http request into the document.onbeforeunload event.
In a web based system, there's no way to reliably do this. Sure, you can record each page that a user displays and record the length of time between each view but what happens when they close the browser on the last page they're displaying on? That's just one of dozens of problems with this requirement.
What about an AJAX based approach? It would only work when Javascript is on the client side, but sending a POST to some script every 15 seconds will get you a reasonable amount of granularity.
There are also more complicated "reverse-AJAX" things you might be able to do... but I don't know much about them.
You can use onunload to do what you need. Have it send a AJAX request to your server to update a database. You may want to return false then do document.close once the AJAX request has completed such that it won't quit prematurely and the ajax won't get discarded.
In the database you'll just want to store the page, the ip address, the time of the event, and whether it was a onload or onunload event.
That is all there is too it.
I recently made a example of recording html page spent time.
refresh would not interrupt the recording, and close would
I use sessionStorage to sotre "time" that page spent
if refresh
I would put it in to sessionStorage
if close
I can not get it from sessionSotrage , so I set time=0
here is my code
`
<body>
time spent :<div id="txt"></div>
</body>
<script>
$(function () {
statisticsStay();
})
function statisticsStay(){
var second=0;
if(sessionStorage.getItem('testSecond')!=null)
second=sessionStorage.getItem('testSecond');
var timer = setInterval(function(){
second++;
document.getElementById('txt').innerHTML=second;
},1000);
window.onbeforeunload = function(){
sessionStorage.setItem('testSecond',second);
};
}
</script>
`

YUI TabView.get("tabs") => null: race condition?

Inside my "dom ready" function, I create a TabView on an HTML element and call tabview.getTab(0).blah(). Unfortunately every now and then I get an error that tabView.get("tabs") returned null in my javascript console (firefox).
YAHOO.util.Event.onDOMReady(function() {
tabview = new YAHOO.widget.TabView("content");
var tab0 = tabview.getTab(0);
...
tabview.getTab(0) is implemented as tabs.get("tabs")[0].
This happens sometimes but not every time. Does anybody have an explanation for why this happens sometimes? The DOMReady event occurs after the entire DOM is in place but before anything is displayed, right?
Speaking of which, sometimes I see flashing of data in some of the other tabs. That does not bode well I think for the nice, clean experience I was hoping for.
This is YUI 2.7.0/
OK - I believe the answer is, I was trying to use prototype and YUI at the same time. In theory I think that is possible but you need to pick one or the other when it comes to doing things on the "dom:loaded"/onDOMReady events, if you know what I mean.
So I don't know what was happening, but it was some sort of race, and once I picked a single mechanism for doing things when the dom was ready, everything is working fine.

Resources