Click counter without javascript - javascript

I'm using this javascript for a click counter in my blogger blog:
function clickCounter() {
if(typeof(Storage) !== "undefined") {
if (sessionStorage.clickcount) {
sessionStorage.clickcount = Number(sessionStorage.clickcount)+1;
} else {
sessionStorage.clickcount = 1;
}
document.getElementById("result").innerHTML = "Correct! " + sessionStorage.clickcount + " Smart answers 'til now.";
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support this quiz...";
}
}
<button onclick="clickCounter()" type="button">Suspension</button>
Is there any way to create something similar through a non javascript method?
Can you help me triger an event (extra text message through popup or within the page) every 5, 10, 20, 100 clicks?
Thank you very much

HTML, and the Web in general, was designed to be stateless.
When you pull up a page, it should be like the first time -- and every time -- you pull up the page.
Since then, people have come up with a number of techniques to add state -- to save data, but they all involved one of two methods -- or sometimes both.
Method 1: Store state on the server.
This method uses HTML forms or cookies to slip information to the server when you load and reload a page.
Method 2: Store state in the client
While there are some older versions of Internet Explorer that can be coded in VBA, we are going to ignore that. The only "real" way to run any kind of code on the client, to store any data, is to use JavaScript.
Method 3: Use the client to talk to the server
Using Ajax, you can let your client talk to the server, but without doing a page reload. This still uses JavaScript.
So, to answer your question:
Without a server
Without JavaScript
No, you cannot save or store anything.

I have not tried this but...
What if you put multiple buttons positioned on top of each other. As each one is clicked, it can be made to vanish with something like
a:visited { display: none; }
The ones that need to display a message (5th, 10th, etc.) have different behavior attached.
See on click hide this (button link) pure css

Related

JavaScript: Like-Counter with Memory

Complete - Edited Once
I am looking to create a Like Counter with persistent Memory!
Right now, my project is stored on a USB-Drive and I'm not thinking of uploading my semi-finished site to the Internet just yet. I'm carrying it around, plugging and working.
A feature of the site, is a Heart Counter and Like Counter, respective with their symbolic icons.
I have a little sideline JavaScript file that has a dozen functions to handle the click-events and such - such as the Number Count of the counters.
But, as the values of the counters are auto-assigned to Temporary Memory - if you were to reload the page - the counter number would reset to it's default, Zero. A huge headache...
Reading from .txt
I thought of using the experimental ReadFile() object to handle the problem - but I soon found that it needed a user-put file to operate (from my examinations).
Here's my attempt:
if (heartCount || likeCount >= 1) {
var reader = new FileReader();
var readerResults = reader.readAsText(heartsAndLikes.txt);
//return readerResults
alert(readerResults);
}
When loaded, the page runs through standard operations, except for the above.
This, in my opinion, would have been the ideal solution...
Reading from Cookies
Cookies now don't seem like an option as it resides on a per-computer basis.
They are stored on the computer's SSD, not in the JavaScript File... sad...
HTML5 Web Storage
Using the new Web Storage will be of big help, probably. But again, it is on a per-computer basis, no matter how beautiful the system is...
localStorage.heartCount = 0 //Originally...
function heartButtonClicked() {
if (localStorage.heartCount) {
localStorage.heartCount = Number(localStorage.heartCount) + 1
}
document.getElementById('heartCountDisplay').innerHTML = localStorage.heartCount
} //Function is tied to the heartCountButton directly via the 'onclick' method
However, I am questioning whether web storage can be carried over on a USB-Drive...
Summarised ideas
Currently, I am looking to Reading and Editing the files, as it's most ideal to my situation. But...
Which would you use? Would you introduce a new method of things?
Please, tell me about it! :)
if (typeof(Storage) !== "undefined") { //make sure local storage is available
if (!localStorage.heartCount) { //if heartCount is not set then set it to zero
localStorage.heartCount = 0;
}
} else {
alert('Local storage is not available');
}
function heartButtonClicked() {
if (localStorage.heartCount) { //if heartCount exists then increment it by one
localStorage.heartCount++;
}
//display the result
document.getElementById('heartCountDisplay').innerHTML = localStorage.heartCount
}
This will only work on a per computer basis and will not persist on your thumb drive. The only way I can think of to persist the data on your drive is to manually download a JSON or text file.

How do you detect and prevent a user from accessing a web app from multiple browser tabs using php/javascript?

I have a web app that I would like to restrict to a single browser tab or window. So the idea is a user logs in and if they open a link in a tab/window or open a new browser tab/window it kills their session. I know many are against this but that's how the app needs to be.
The controller checks if the user is logged in via:
if (!isset($_SESSION['user_logged_in'])) {
Session::destroy();
header('location: '.URL.'login');
}
I have tried setting $_SESSION['user_logged_in'] to false if its true but then obviously you don't go any further than one page.
Is there a way to destroy the session when a new browser tab or window is opened? I'm guessing probably jquery/javascript but not across that side of things.
It's very complex to achieve, unfortunately.
And almost impossible to do it true cross-browser and supported by every browser.
Technically, every new browser tab doesn't differ from the latter, form server's point of view. They share cookies and session too.
The only things that differ is JavaScript session. Say, an example: a site that is fully AJAX-based. First page is always login page. Then everything's changed with AJAX. If you dare to open another tab with this site it will open the first page which is always logging you out be default, for example. This can make it possible, but it's very complex.
New technologies stack like localStorage might make this possible, where you can communicate between tabs sending messages in localStorage. But this isn't fully cross-browser and isn't supported by all browsers versions.
So if you are ok with only limited choice of latest browsers — then dig on localStorage and postMessage.
Just to piggy back on what Oleg said, it would be incredibly difficult since HTTP is stateless and browser tabs share data. One potential way of doing it COULD be on the front end, but a very specific set of circumstances would need to be present and they could easily be bypassed. IF the application is a SPA and the primary body is only loaded once, you could potentially generate a key on the body load and send that with each request. Then, if the body is reloaded (say in a new tab or new window), you could generate a new key which would start a new session.
However, the real question is why you would want to do this. Your user experience will suffer and no real security gains exist.
I have some solution and I want share it with you.
To restrict user to only one tab per session, you may use cookie. I describe here how you may build your webapp in order to archieve that goal.
Each time the web module needs to render the auth/login page, create and store a cookie with a given name. Let's call it browserName. The value of the cookie must be a generated value. You may use java.util.UUID if your programming language is java.
When the browser finished loading your auth/login page, set the browser's name with the generated cookie value. You have to know how to read cookie using JavaScript.
Each time the user load other page than auth/login page, check whether the current browser's name is that one stored in the cookie. If they are differents, prompt user and then you can run a snipt that reset session and redirect to auth/login page.
The following is an example of implementing what I've said.
Snipt to be added in the method that runs before your login page in shown Map<String, Object> v$params = new TreeMap<>();
v$params.put("path", "/");
FacesContext.getCurrentInstance()
.getExternalContext()
.addResponseCookie("browserName", UUID.randomUUID().toString(), v$params);
The mini JavaScript library that help you with cookie and other. Add it globally in your webapp.
/**
* http://stackoverflow.com/questions/5639346/shortest-function-for-reading-a-cookie-in-javascript
*/
(function() {
function readCookie(name, c, C, i) {
if (cookies) {
return cookies[name];
}
c = document.cookie.split('; ');
cookies = {};
for (i = c.length - 1; i >= 0; i--) {
C = c[i].split('=');
cookies[C[0]] = C[1];
}
return cookies[name];
}
window.readCookie = readCookie; // or expose it however you want
})();
// function read_cookie(k,r){return(r=RegExp('(^|;
// )'+encodeURIComponent(k)+'=([^;]*)').exec(document.cookie))?r[2]:null;}
function read_cookie(k) {
return (document.cookie.match('(^|; )' + k + '=([^;]*)') || 0)[2];
}
/**
* To be called in login page only
*/
function setupWebPage(){
window.name = read_cookie("browserName");
}
/**
* To be called in another pages
*/
function checkWebPageSettings(){
var curWinName = window.name;
var setWinName = read_cookie("browserName");
if( curWinName != setWinName){
/**
* You may redirect the user to a proper page telling him that
* your application doesn't support multi tab/window. From this page,
* the user may decide to go back to the previous page ou loggout in
* other to have a new session in the current browser's tab or window
*/
alert('Please go back to your previous page !');
}
}
Add this to your login page <script type="text/javascript">
setupWebPage();
</script>
Add this to your other page template <script type="text/javascript">
checkWebPageSettings();
</script>

Getting Backbutton to work in single page website and implementing "speaking" URLs

I have a single page website and would like to achieve the following:
back button working as if it was a normal website
and instead of say,
www.mysite.com/index.php?p=#this-is-a-great-product
I'd like to have this url
www.mysite.com/this-is-a-great-product
while still having back button working properly.
Regarding 1.) I use the following code ive found which works great:
<!-- Getting BackButton to work properly -->
<script type="text/javascript">
var times = 0;
function doclick() {
times++;
}
function doclick() {
times++;
location.hash = times;
}
window.onhashchange = function() {
if (location.hash.length > 0) {
times = parseInt(location.hash.replace('#',''),10);
} else {
times = 0;
}
}
</script>
…but of course it just changes any anchors to /#1, then /#2 and so forth ro get the backbutton to work. But as I'm not a programmer I don't know how to change it… :(
Regarding 2.) i can add in htaccess this:
>RewriteEngine On
>RewriteRule ^([^/.]+)/?$ /index.php?page=$1
and this changes /index.php?p=products to /products.
So how do I change the above code (under 1.) so it doesn't change all anchors to #1, #2, etc. but instead references / uses the urls I achieved under 2, like
www.mysite.com/this-is-a-great-product
And (probably a very dumb question, but a very important one) -given I use only the new url links on my site- is there any danger that this still might result in duplicate content in any way?
Regarding this, should I (for that reason or any other) sefreferential my single page index.php to itself using rel canonical link=index.php?
Thanks so much in advance!
As mentioned, you will want to use the HTML5 History API. Please note, this API is relatively new and therefore browser support is a concern. At the time of writing, approximately 71% of global Internet users have support for it (see http://caniuse.com/#feat=history for browser support information). Therefore, you will want to ensure you have a fall-back solution for this. You will likely want to use the older #! solution that was popular before the HTML 5 History API was adopted.
If you use the history API to replace, for example, example.com/#!settings with example.com/settings and a user bookmarks that nicer URL, then when they go to visit it, their browser will make a request to the server for /settings (which doesn't actually exist in the web server's context). Therefore, you will need to make sure your web server has some redirection rules (i.e. RewriteEngine) such that it can take the pretty URLs and redirect them to the #! version (and then if the user's browser supports the history API it can replace that with the nice URL).
If you aren't very comfortable programming yourself, I'd recommend using a JavaScript library that does a lot of the work for you. I did some quick searching and discovered the following, though there might be better ones out there: https://github.com/browserstate/history.js
Basically i have created a small prototype on jsfiddle which tracks all the urls accessed via ajax calls.
Also contains navigation to access links back and forth .
How It Actually Works:
I have created a global array called history, which keeps track of all urls accessed via ajax in sequence.
also there a global index defined to keep track of the url being accessed when navigating back and forth the links in history array.
There is History section at the bottom of the jsfiddle, which shows the sequence in which the links are accessed by capturing the link names and posting them in the order in which they were accessed.
JS Code:
$(function () {
var history = [];
var index = 0;
$('.links').on('click', function () {
$('#history').append($(this).text());
var address = $(this).attr('data-ref');
index += 1;
history[index] = address;
$('.links').attr('disabled', 'disabled');
loadExternalPage(address);
console.log('list:' + history);
});
$('#back').on('click', function () {
console.log(index);
index -= 1;
console.log(index);
console.log(history[index]);
loadExternalPage(history[index]);
});
$('#forward').on('click', function () {
console.log(index);
index += 1;
console.log(index);
console.log(history[index]);
loadExternalPage(history[index]);
});
var loadExternalPage = function (address) {
console.log(history[index]);
$('#result-section').load(address, function () {
console.log('data-loaded');
$('.links').removeAttr('disabled');
});
};
});
Live Demo # JSFiddle:http://jsfiddle.net/dreamweiver/dpwmcu0b/8/
Note: This solution is far from being perfect, so dont consider it as final solution but rather use it as a base to build upon
On using BACK and FORWARD functions in the browser top-left button:
In principle, there is no great problem with this as long as you work with the existing storage object (a stack) for previously visited web pages on your browser. This object is the history object and you can see what is in it anytime by right-clicking and selecting "Inspect", then selecting the "Console" tab, then enter window.history and enter.
Check out the Browser Object Model (BOM) section of Pro Java For Web Developers (Frisbee) for the background to the history object. (Just a few pages, an easy read, don't worry.) Just remember that in this process you are storing the new page that you move to, not the old page that you are leaving !
For a simple SPA example, look at this example. codepen.io/tamjk/pen/NWxWOxL
In regard to the URL, the method that the history object uses to load a new page state into the history stack, i.e. pushState(...), has an optional third parameter for associating a dummy URL for each web page that is stored.
Personally, when I first sorted out the BACK & FORWARD functions, I did not use dummy URLs as the browser was being confused by them and I had enough to do sorting out the history sequence using just the first two parameters, i.e.
the state object - a JSON holding enough data to recreate the page stored
a title for the page I expect that you could also use a dummy URL but I will leave that to the student as an exercise, as they say.
But you can add the URL of the new page if you want to.
In the example above, for the state object I just used the IDs of the page's nav link and its content element.
For the title, I programmatically changed the HTML's page title element with each change of page. I did this after noticing that the browser listed the previous pages according to the title element in the HTML code.
Unfortunately, this title does not show up on CodePen when you right-click on the browser BACK and FORWARD buttons due to CodePen's system not allowing it. But it will show on your own sites.
It's important that whatever method you use to store current web page states when using the navbar links to navigate, you DO NOT ADD page states to the browser history when you arrive at them using BACK or FORWARD buttons. Otherwise your history stack will have repetitions of entries going back and deletion of entries going forward.
In the CodePen, this was achieved by having the addToHistory(..) function separate to and outside the scope of the switchPage(...) function. This allows you use of the switchPage function in both normal navbar navigation and browser BACK/FORWARD navigation. The third parameter of switchPage(...) is a boolean indicating if the page is to be stored in history or not.
Anyway, this is just something to get you started.

Let user navigate to new URL manually, within the same site, and not refresh the page

For a new web app I would like to modify history when users click on a link, so that the URL changes, but the page does not reload. I'll have some part of the page load in ajax. This can be done easily and is documented in a lot of places (e.g. Mozilla, diveintohtml5, Stack Overflow).
However, I'm wondering if there's a way to let the user modify the URL without reloading the page. Say for example someone gives them a link within the same domain, or they want to manually type the URL for some reason. I'd like to load the new page in the same way as I would if they had clicked a link - without reloading the page but rather modifying the history.
Is there any way to do this? Here's the gist of what I was thinking, but the magic functions getNewURLFromEvent, preventUserFromActuallyLeavingPage, and carryOn need to be implemented (if possible):
window.addEventListener('unload', function(event) {
var newURL = getNewURLFromEvent(event);
if (isInThisDomain(newURL)) {
preventUserFromActuallyLeavingPage();
window.history.pushState('content', 'title', document.URL);
} else {
// Let the user leave (the internet is a free place after all)
carryOn();
}
});
function isInThisDomain(URL) {
/* Would probably implement some error checking here too */
var thisDomain = document.URL.match(/:\/\/(.+?)\//)[1],
thatDomain = URL.match(/:\/\/(.+?)\//)[1]);
return thisDomain === thatDomain;
}
function getNewURLFromEvent(e) {
/* Figure out where the user want's to go */
}
function preventUserFromActuallyLeavingPage() {
/* Since we're changing the content it still looks
like the user's leaving, but really they haven't
gone anywhere from the site's perspective */
}
function carryOn() {
/* Essentially do nothing, but maybe more magic is needed? */
}
If you feel this is a bad idea - yet still possible - please explain why it's a bad idea.
Thank you.
Any change the value of the address bar, other than using a URL hash, will instruct the browser to go to that location. You cannot (and should not) change this behaviour. This would open a whole can of worms regarding URL cloaking and other malware nastiness.

Chrome JavaScript location object

I am trying to start 3 applications from a browser by use of custom protocol names associated with these applications. This might look familiar to other threads started on stackoverflow, I believe that they do not help in resolving this issue so please dont close this thread just yet, it needs a different approach than those suggested in other threads.
example:
ts3server://a.b.c?property1=value1&property2=value2
...
...
to start these applications I would do
location.href = ts3server://a.b.c?property1=value1&property2=value2
location.href = ...
location.href = ...
which would work in FF but not in Chrome
I figured that it might by optimizing the number of writes when there will be effectively only the last change present.
So i did this:
function a ()
{
var apps = ['ts3server://...', 'anotherapp://...', '...'];
b(apps);
}
function b (apps)
{
if (apps.length == 0) return;
location.href = apps[0]; alert(apps[0]);
setTimeout(function (rest) {return function () {b(rest);};} (apps.slice(1)), 1);
}
But it didn't solve my problem (actually only the first location.href assignment is taken into account and even though the other calls happen long enough after the first one (thanks to changing the timeout delay to lets say 10000) the applications do not get started (the alerts are displayed).
If I try accessing each of the URIs separately the apps get started (first I call location.href = uri1 by clicking on one button, then I call location.href = uri2 by clicking again on another button).
Replacing:
location.href = ...
with:
var form = document.createElement('form');
form.action = ...
document.body.appendChild(form);
form.submit();
does not help either, nor does:
var frame = document.createElement('iframe');
frame.src = ...
document.body.appendChild(frame);
Is it possible to do what I am trying to do? How would it be done?
EDIT:
a reworded summary
i want to start MULTIPLE applications after one click on a link or a button like element. I want to achieve that with starting applications associated to custom protocols ... i would hold a list of links (in each link there is one protocol used) and i would try to do "location.src = link" for all items of the list. Which when used with 'for' does optimize to assigning only once (the last value) so i make the function something like recursive function with delay (which eliminates the optimization and really forces 3 distinct calls of location.src = list[head] when the list gets sliced before each call so that all the links are taken into account and they are assigned to the location.src. This all works just fine in Mozilla Firefox, but in google, after the first assignment the rest of the assignments lose effect (they are probably performed but dont trigger the associated application launch))
Are you having trouble looping through the elements? if so try the for..in statement here
Or are you having trouble navigating? if so try window.location.assign(new_location);
[edit]
You can also use window.location = "...";
[edit]
Ok so I did some work, and here is what I got. in the example I open a random ace of spades link. which is a custom protocol. click here and then click on the "click me". The comments show where the JSFiddle debugger found errors.

Categories

Resources