I was working on a web app and thought it would be awesome to give the user a tooltip or side note on a new feature that has been added.
This would be similar to the way Google or Facebook displays their tips about updates.
I had an idea of setting a cookie (or session variable) to say that the tip has been viewed and not display it again, but this would be running an unnecessary if statement on every page load.
Here is what I have so far:
if ($_COOKIE['displayTip'] != 'no') {
echo "tip";
}
Are there better ways of doing this, or is one if every page load worth it?
A single if - especially if it is not checking a database - is no problem. Don't worry about it, you can waste more CPU time with other things. If it adds functionality its fine.
One thing you could do is to have the logic on in the Browser (JavaScript) only. This has the advantage you do not have to generate two different pages. This might be beneficial for caching. In JS you can also access cookies to make that seen flag persistent.
Related
Apologies in advance for the lengthy post, just trying to explain the situation clearly.
I've created a PHP-driven website for searching a big (millions of records) MySQL database of people. On the search page you have your usual form for search criteria. Due to the way the people often use the site, the search criteria are saved into session variables so that if the search page is reloaded the previous criteria remain in the form fields (there's a button to manually reset the criteria, of course). This in itself works fine.
I also have two language selection links that store the language selection in a session variable (making the page header load an appropriate localization file), and as above, this in itself also works fine.
What's problematic is that when a user gets the search result, a list of people, and wants to open up detailed info on a person (thus going from search.php to info.php) and then wants to go back to the people listing via the back button, it takes too long to reload the previous page as the page re-sends the MySQL query etc, instead of going back to a cached page. It can take even 5 seconds or more sometimes as the queries produce up to 5000 results - but even say, 200-500 results takes long to reload because the database itself is big and not the fastest in the world. And limiting the number of results isn't really practical.
The obvious solution at first glance would SEEM to be enabling the browser cache. Which is exactly what I did via PHP header and pragma controls. And all seemed well, as going back to the list was basically instantaneous. However, I realized that enabling the cache means the updated session variables don't work. New search criteria doesn't properly replace the old ones when reloading the search page after having been to a different page, and even though you select another language, pages open up in the language you previously were using, because that's the way they were cached! You can force the language to update via F5, but that doesn't seem to help the search criteria much. But even if it did, F5-spam isn't really an answer, it needs to work automatically.
So long story short, how do I make the search result list open quickly without making session variables useless? Or will I simply have to make do with sluggish page loads when using back button, thus annoying users? I really don't want to open the info.php in a new page, either.
Have you considered caching the database results on the file system? I have found the Zend Framework caching class to be very easy to use. You can use any information you want, to differentiate cached results from other cached results. So the caching can be as fine grained as required.
http://framework.zend.com/manual/1.12/en/zend.cache.introduction.html
You don't need to use the whole of Zend Framework to use the class. You can use it on its own.
I want to make a page that will show all the users who are looking at that page right now. Ideally, a database would store which users are on the page and websockets would be used to update when users enter and leave.
The problem is that I don't know how to tell when users are viewing the page. I was thinking that I would be able to tell when they arrived and when they exited and add/remove accordingly. It's easy to tell when they arrive; however, it's difficult to tell when they leave - especially because users might do something like open multiple tabs, close one but keep the other open.
What is the best way to do this? I am using PHP as my server-side language.
You can use the blur and focus events on the window to toggle a variable. However, IE does some quirks which you will need to work around.
As a fallback to not working focus events, you might add a mousemove handler to the document. This might also throttle an automatic timeout which detects the loss of focus just by the fact that there was no user interaction for a specific period of time. However, you will never be able to detect a distracted user that has the site open but looks at something else...
To detect the window closing, you can hook on the unload event. This might be unreliable, but as you are using Websockets your server can easily detect a closed connection.
Well, one thing you could do, especially if you are using websockets is do a heartbeat/ping to the server every few seconds if you really wanted. If you don't get that heartbeat, you know they are not on the page anymore.... however, getting a response doesn't mean they are looking at the page, it would just mean that it is open, possibly in another tab. There is no way that I know of that will send a response to the server if the person loses focus on the page and opens another tab/window.
As Tim mentioned, Firefox and IE will run javascript in the background tabs, so there's no surefire way by simple polling to tell if the user is actually "looking" at the page or just has it open somewhere. Although I know of no way to tell if the user is actually looking at your page, a potential solution might be to bind polling to actions. So you might have some variable
var timesincelastaction=0;
var threshhold = 20;
Then
setInterval("timesincelastaction++",100);
Then
function keepAlive() {
if(timesincelastaction > threshhold) {
$.ajax(...tell the server you are alive...);
timesincelastaction = 0;
}
}
Then start thinking of actions like
$('a').mouseover(keepAlive);
$('div').mouseover(keepAlive);
$(window).scroll(keepAlive);
$(video).play(keepAlive); // okay this isn't a real one but you get the picture
So then you just brainstorm on everything the user can possibly be doing on the page that requires their attention and use those as your benchmark.
This seems a little intense I know, there's probably some nice ways to optimize it. Just thinking out loud. Curious to see what others come up with.
Every time one of your PHP scripts run, some user or entity has requested to view a page on your site (this usually occurs every time your script runs).
It is more challenging to detect when a user has left your page, which is why most online indicators are simply a timeout, i.e. if you have not been active on the website in the past 5 minutes, you are no longer considered online.
You can get information about the user who requested the page with variables like $_SERVER['REMOTE_ADDR'] or if you already have an authentication system you should be able to pull a users username, store this info in a database with the username/ip as a unique key with a timestamp, and simply not count them as online if their timestamp is older than 5 minutes.
You could probably use jQuery- ajax, unload and load. The ajax request will trigger on load telling you that they are viewing, and trigger on unload telling you they are no longer viewing. The rest is left to you to figure out because it sounds like you already have a grip on it.
Note. same result should be achievable in plain JS. Such as, onunload. Google will find you the rest.
On one of my pages I have users queue up search terms to be to queried from a 3rd party API. As they're building the queue, my site is making the queries in the background (through ajax) so I can cache the responses, saving them time when they submit. I store a session variable $_SESSION['isloading'] as true during the time that the background queries are running, and its false when they're done.
When they submit, the results page waits for $_SESSION['isloading'] to be false before querying the cache for result. Meanwhile they're shown a progress wheel.
Is there a name for this technique of using a session to locally "lock" a user before proceeding to the next step in the code? I came up with this approach on my own and was wondering if it is a common (or good) solution to this problem, and is used elsewhere.
Putting it in $_SESSION will be a wasted effort. Been there, done that and it didn't work out.
You will be much better off if you provide your "search query string" in as a $_GET variable for your XHR ( marketing people call it - Ajax ).
Off the top of my head, this sounds a little similar to the way some older forum software performs forum searches in the background, and the visible page does a repeated refresh until the background search is complete.
I don't think there's a name for it; I'm also note entirely convinced that it's a great solution. As stevecomrie pointed out, you're going to run into difficulties with concurrency (unless the session variable's name is unique per search query).
I'd instead recommend an XmlHttpRequest (as teresko points out, it's not really called "AJAX", ugh!) and you can handle the "waiting" quite simply with Javascript.
I asked about this on IRC (Hat-Tip to ##php on freenode), and they suggested I just make the search form and search results one page. Then, when they're done entering their searches the view would change rather than submitting to the next page. This would remove the necessity of keeping track of an 'isloading' state. This seems like a better approach to me, are there any problems with it?
I would imagine it would be done with a cookie or session, but what is the best way to remember an accordion menu's state if a user opens an item and leaves? How can I have "open" items in that state when the user comes back to the site?
I've just upgraded my custom CMS with a new interface, and the new menu needs something like this or usability will suffer greatly.
I don't need specifics, just how you would normally do it.
Thanks!
http://www.shopdev.co.uk/blog/cookies-with-jquery-designing-collapsible-layouts/
this helped me out, hopefully it does for you as well.
I think you would need to save it to a database or use local storage (which isn't supported by all browsers). Cookies would work, but they can be deleted by the user (so can local storage). Sessions wouldn't work because once the user closes their browser, they lose their sessions.
Saving to a database or flat file is the most bulletproof way to do it.
Like most things, it depends.
If this is something that will make a server side request, then storing it in the session global would be completely acceptable.
If it's not, then you would need to find some other method of storing it client side. These would include things like storing it in javascript (only available the page's life), a cookie (like you mentioned) or like Bryan Downing mentioned with local storage. Local storage doesn't have good browser support yet.
Do you want it to be remembered regardless of the computer they log in from? If you do then set a simple value in a table associated to that user as to which item is open so it can be open the next time they return.
I use the jquery UI accordion and it's easy to update a field to which option was last selected so the next time the user comes back I can have that remembered for them. I've done this with a simple ajax call to request the value from the DB and return it to my javascript as a variable that's then used to set the opened accordion section.
If you're not worried about remembering across different devices then a simple cookie should do the trick, just updated the cookie each time a selection is made.
I've worked on a CMS which would use Smarty to build the content pages as PHP files, then save them to disc so all subsequent views of the same page could bypass the generation phase, keeping DB load and page loading times down. These pages would be completely standalone and not have to run in the context of another script.
The problem was the instance where a user first visited a page that wasn't cached, they'd still have to be displayed the generated content. I was hoping I could save my generated file, then include() it, but filesystem latency meant that this wasn't an option.
The only solution I could find was using eval() to run the generated string after it was generated and saved to disc. While this works, it's not nice to have to debug in, so I'd be very interested in finding an alternative.
Is there some method I could use other than eval in the above case?
Given your scenario, I do not think there is an alternative.
As for the debugging part, you could always write it to disc and include it for the development to test / fix it up that way and then when you have the bugs worked out, switch it over to eval.
Not knowing your system, I will not second guess that you know it better than I do, but it seems like a lot of effort, especially since that the above scenario will only happen once per page...ever. I would just say is it really worth it for that one instance to display the initial page through eval and why could you not be the initial user to generate the pages?