I recently was given a solution to checking if a pop up has been shown and then only showing it once using cookies. But after implementing cookies the pop up no longer shows. I have googled the issue, and tried to find a solution but my lack of knowledge on the subject has made it difficult for me to understand the issue and fix it.
This is the code i am using, i have implemented the use of cookies and i believe that they should work but the pop up however is not working
function setCookie(cname,cvalue) {
document.cookie = cname + "=" + cvalue;
}
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for(var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
function checkCookie() {
var user=getCookie("ageverification");
if (user != "") {
return null;
} else {
var overlay = $('<div id="overlay"></div>');
overlay.show();
overlay.appendTo(document.body);
$('.popup').show();
$('.close').click(function() {
$('.popup').hide();
overlay.appendTo(document.body).remove();
return false;
user = true;
setCookie("ageverification", user);
});
}
}
function goBack() {
window.history.go(-2);
}
<div class='popup'>
<div class='cnt223'>
<h1>Important Notice</h1>
<p>
You must be over 18 to Purchase products on this website!
<br/>
<br/>
I Am Over 18
I Am Not
</p>
</div>
</div>
I applied some changes to your code and now it should work.
As a summary, I applied these changes:
removed dead code from checkCookie;
simplified the code for getCookie;
eliminated the overlay div (which did nothing: it was just created empty, attached to the DOM and then removed from it);
changed "popup" from a class to an id;
made the selector strings more specific.
To improve the getCookie function, I eliminated an unnecessary loop and a few substrings. You can get to the same result more cleanly using the trim method (which eliminates preceding and trailing whitespace from a string) and splitting the cookie by "=".
To improve checkCookie, I eliminated some dead code (which couldn't run because it was after a return statement), some redundant one (which declared variables for values needed only once) and the apparently useless div tag. Also, I changed the selector strings to explicitly reference the "a" node inside the popup and I added a call to preventDefault(). This last part (changing the selector strings and calling preventDefault) was the one solving the issue.
function setCookie(cname,cvalue) {
document.cookie = cname + "=" + cvalue;
}
function getCookie(cname) {
var ca = decodeURIComponent(document.cookie).split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i].trim().split('=');
if (cname == c[0] && c.length > 1) {
return c[1];
}
}
return "";
}
function checkCookie() {
if (getCookie("ageverification") == ""){
$('#popup').show();
$('#popup a.close').click(function (event) {
event.preventDefault();
$('#popup').hide();
setCookie("ageverification", 'true');
});
$('#popup a.goBack').click(function ( event ) {
event.preventDefault();
goBack();
});
} else {
return null;
}
}
function goBack() {
window.history.go(-2);
}
<div id='popup'>
<div class='cnt223'>
<h1>Important Notice</h1>
<p>
You must be over 18 to Purchase products on this website!
<br/>
<br/>
I Am Over 18
I Am Not
</p>
</div>
</div>
Related
I have this keyboard site launcher script, which I copied from some place years ago and it works fine as is. I want to enhance it by adding a cascading keypress launch for some of the keys. Here is my code:
<html><head>
<script language="JavaScript">
<!-- Begin
var key = new Array();
key['a'] = "https://www.arstechnica.com";
key['g'] = "https://www.google.com";
key['s'] = "https://slashdot.org";
key['y'] = "http://www.yahoo.com";
function getKey(keyStroke) {
isNetscape=(document.layers);
eventChooser = (isNetscape) ? keyStroke.which : event.keyCode;
which = String.fromCharCode(eventChooser).toLowerCase();
// alert('['+which+'] key \n has been stroke');
runUrl(which);
}
function runUrl(which) {
for (var i in key)
if (which == i) {window.location = key[i];}
}
document.onkeypress = getKey;
// End -->
</script></head>
<body>
Make a selection<br>
<br>
key['a'] = "https://www.arstechnica.com";
key['g'] = "https://www.google.com";
key['s'] = "https://slashdot.org";
key['y'] = "http://www.yahoo.com";
<br>
<br>
<!-- I solemnly swear this page is coded with vi or notepad.exe depending on the OS being used -->
</body>
</html>
Now, I want to modify the action for pressing the letter "s" to launch a submenu of sorts and ask me to select if I want to go to "Slashdot" or Spotify" for instance. like if I press an "s" second time, it goes to slashdot and if I press "f" for instance, it goes to spotify.
My problem is, I have never programmed in Javascript other than copying and pasting code and changing string values in the code, like here, changing the pressed keys and site URLs.
Any pointers, regarding how to start modifying this code, are greatly appreciated.
to be honest, the code provided is a bit outdated but I keep it so you can see the necessary changes that I made for the menu to be added and to implement the feature it's just a sketch but I will do the job I think from here you can expand, hope this puts you in the right direction
let isopenMenu = true;
const menu = document.getElementById("menu");
function toggleMenu() {
isopenMenu = !isopenMenu;
menu.style.display = isopenMenu ? "block" : "none";
}
var key = new Array();
key["a"] = "https://www.arstechnica.com";
key["g"] = "https://www.google.com";
key["s"] = "https://slashdot.org";
key["y"] = "http://www.yahoo.com";
key["b"] = "http://www.stackoverflow.com";
key["c"] = "http://www.test.com";
const menuSite = ["b", "c", "s"];
function getKey(keyStroke) {
isNetscape = document.layers;
eventChooser = isNetscape ? keyStroke.which : event.keyCode;
which = String.fromCharCode(eventChooser).toLowerCase();
runUrl(which);
}
function runUrl(which) {
for (var i in key)
if (which == i) {
if (which === "s") {
return toggleMenu();
}
if (!isopenMenu && menuSite.includes(which)) {
return;
}
window.location = key[i];
}
}
document.onkeypress = getKey;
window.addEventListener("load", toggleMenu);
<html><head>
<script language="JavaScript">
</script></head>
<body>
Make a selection<br>
<br>
key['a'] = "https://www.arstechnica.com";
key['g'] = "https://www.google.com";
key['s'] = "to toggel menu
key['y'] = "http://www.yahoo.com";
<br>
<br>
<ul id="menu">
<li>key['b'] = "http://www.stackoverflow.com";</li>
<li>key['c'] = "http://www.test.com</li>
</ul>
</body>
</html>
Indeed the code you've provided seems a bit dusted. There's some stuff that isn't done in that way nowadays. Notepad is an editor I still occassionally use though.
Since you've mentioned that you never really used JavaScript it's a bit hard to give you advice. You can do things way more elegant and even improve the look - but I'd say this would just confuse you even more. So let's work on something based on your code.
At the moment the keys and the corresponding targets are stored in an object (yeah, it's an object not an array). We can use a second object - let' say subKey - to store the additional targets upon pressing s.
var key = {};
key.a = "https://www.arstechnica.com";
key.g = "https://www.google.com";
key.s = "subMenu";
key.y = "http://www.yahoo.com";
var subKey = {};
subKey.a = "https://www.stackoverflow.com";
subKey.g = "https://www.startpage.com";
subKey.s = "goBack";
As you can see I've reserved the key s to go to the sub menu and inside the sub menu this button is used to go back to the main menu.
Now instead of hardcoding what the user gets to see on screen, we can iterate over those objects and use the information from there. To do this we need to reserve a html element - I've chosen an empty <div> which acts as some sort of container. As we iterate over the object we construct a string with the keys and it's associated targets and ultimately assign this this to the div's .innerHTML property.
let container = document.getElementById("container");
container.innerHTML = "Make a selection<br><br>";
for (var i in obj) {
container.innerHTML += "key['" + i + "'] = " + obj[i] + "<br>";
}
As the procedure is the same for both objects we just need to wrap it inside a function and pass it a reference to the desired object.
Your runUrl function needs to be modified a bit to take care of the additional options. This is best done with a simple if-else construct. So in pseudo-code:
if choice is subMenu open sub menu
if choice is goBack open main menu
if it's none of the above open a link
If we put everything together, your example looks a little bit like this:
(Just click on 'Run code snippet' and make sure to click somewhere inside the window so it'll have key focus)
<html>
<head>
</head>
<body>
<div id="container">
</div>
</body>
<script type="text/javascript">
var key = {};
key.a = "https://www.arstechnica.com";
key.g = "https://www.google.com";
key.s = "subMenu";
key.y = "http://www.yahoo.com";
var subKey = {};
subKey.a = "https://www.stackoverflow.com";
subKey.g = "https://www.startpage.com";
subKey.s = "goBack";
var currentObj = key;
function getKey(event) {
let which = String.fromCharCode(event.keyCode).toLowerCase();
runUrl(which)
}
function runUrl(which) {
for (var i in currentObj) {
if (which == i) {
if (currentObj[i] != "subMenu") {
if (currentObj[i] != "goBack") {
window.location = currentObj[i];
} else {
populateMenu(key);
}
} else {
populateMenu(subKey);
}
}
}
}
function populateMenu(obj) {
currentObj = obj;
let container = document.getElementById("container");
container.innerHTML = "Make a selection<br><br>";
for (var i in obj) {
container.innerHTML += "key['" + i + "'] = " + obj[i] + "<br>";
}
}
populateMenu(key);
document.onkeypress = getKey;
</script>
</html>
It looks like could achieve this with arbitrary list of sites. If so, you could handle this a little more generically by providing a list of sites and filtering the sites based on keystrokes.
If so, you can achieve it with the following:
const sites = [
'https://www.arstechnica.com',
'https://www.google.com',
'https://mail.google.com',
'https://slashdot.org',
'https://spotify.com',
'http://www.yahoo.com',
];
let matches = sites;
document.getElementById('keys').addEventListener('keyup', event => {
const keys = event.target.value.toLowerCase().split('');
matches = sites
.map(site => ({ site, stripped: site.replace(/^https?:\/\/(www\.)?/i, '')})) // strip out https://wwww. prefix
.filter(site => isMatch(site.stripped, keys))
.map(site => site.site);
if (event.keyCode === 13) {
if (matches.length === 0) {
alert('No matches');
} else if (matches.length === 1) {
alert(`launching ${matches[0]}`);
} else {
alert('More than one match found');
}
matches = sites;
}
document.getElementById('matches').textContent = matches.join(', ');
});
// find sites matching keys
function isMatch(site, keys) {
if (keys.length === 0) return true;
if (site.indexOf(keys[0]) !== 0) return false;
let startIndex = 1;
for (let i = 1; i < keys.length; i++) {
let index = site.indexOf(keys[i], startIndex);
if (index === -1) return false;
startIndex = index + 1;
}
return true;
}
document.getElementById('matches').textContent = matches.join(', ');
<div>Keys: <input type="text" id="keys" autocomplete="off" /> press Enter to launch.</div>
<p>Matches: <span id="matches" /></p>
The key parts to this are:
Define a list of sites you want to handle
Ignore the the https://wwww prefixes which is achieved with site.replace(/^https?:\/\/(www\.)?/i, '')
Implement filter logic (in this case it is the isMatch method) which tries to match multiple keystrokes
For demonstration purposes, I've wired keyup to an input field instead of document so that you can see it in action, and the action is triggered with the enter/return key.
Right now I am using a window to view details that are not shown in the grid. I have made my own custom editor in the window as well which hides the details and replaces them with inputs.
Unfortunately I cannot get the Update button to have the same functionality as an update button in the kendo toolbar.
I am using transport and parameter map for my create which works perfectly. I just need to be able to hit the update, which I haven't been able to.
Here is a snippet of code for the template:
<li><b>Change Control Objective</b></li>
<li><textarea type="text" class="k-textbox k-input" data-bind="value:ChangeControlObjective">#= ChangeControlObjective #</textarea></li>
<li><b>Change Control Specifics</b></li>
<li><textarea type="text" class="k-textbox k-input" data-bind="value:ChangeControlSpecifics">#= ChangeControlSpecifics #</textarea></li>
<span class="k-update k-icon k-i-tick"></span>Save
I can't show my JS code but it is based off this dojo: http://dojo.telerik.com/abUHI
UPDATE:
I am able to hit the update in the parametermap off of my save button click but it's sending the old data to the update instead of the new. Here is the button click code:
$("#saveChanges").click(function () {
dataItem.dirty = true;
$("#ccrGrid").data('kendoGrid').saveChanges();
});
Each input has a data-bind attribute and the parametermap looks like this:
case "update":
var changeControlRequestId = options.ChangeControlRequestID;
var changeControlObjective = options.ChangeControlObjective;
var changeControlSpecifics = options.ChangeControlSpecifics;
var productAssociation;
if (options.AccountChangeInfo.ProductAssocation == undefined) {
productAssociation = "";
} else { productAssociation = options.ProductAssocation; }
var amortization;
if (options.AccountChangeInfo.Amortization == undefined) {
amortization = "";
} else { amortization = options.Amortization; }
var productType;
if (options.ProductChangeInfo.ProductType == undefined) {
productType = "";
} else { productType = options.ProductType; }
var productName;
if (options.ProductChangeInfo.ProductName == undefined) {
productName = "";
} else { productName = options.ProductName; }
var productDescription;
if (options.ProductChangeInfo.ProductDescription == undefined) {
productDescription = "";
} else { productDescription = options.ProductDescription; }
var productContract;
if (options.ProductChangeInfo.ProductContractualFeatures == undefined) {
productContract = "";
} else { productContract = options.ProductContractualFeatures; }
var productBehavior;
if (options.ProductChangeInfo.ProductBehavioralAssumptions == undefined) {
productBehavior = "";
} else { productBehavior = options.ProductBehavioralAssumptions; }
var evaluationBehavior;
if (options.ProductChangeInfo.ProductEvaluationBehavior == undefined) {
evaluationBehavior = "";
} else { evaluationBehavior = options.ProductEvaluationBehavior; }
var productStratification;
if (options.ProductChangeInfo.ProductStratificationRoutines == undefined) {
productStratification = "";
} else { productStratification = options.ProductStratificationRoutines; }
if (content.isreadonly == "True") {
alert("you have readonly access");
}
else {
var urlString = "env=" + content.env + "&allyid=" + content.userId + "&changeRequestID" + changeRequestID + "&changeControlObjective=" + changeControlObjective + "&changeControlSpecifics=" + changeControlSpecifics +
"&productAssociation" + productAssociation + "&amortization" + amortization +
"&productType" + productType + "&productName" + productName + "&productDescription" + productDescription +
"&productContract" + productContract + "&productBehavior" + productBehavior + "&evaluationBehavior" + evaluationBehavior +
"&productStratification" + productStratification;
return urlString;
I've been going through this a couple months ago. Per my extensive research there are 2 key sources for doing custom popup editing in Kendo in entire Internet ;) :
Custom editor template
I aslo created a simplified version of this for you here: http://jsbin.com/qudotag/
to cut the elements which can be expanded once you grap the key concepts. Note that this does not work fully as changes are not persisted. It is expected behaviour, as you would need to define the CRUD operations for the grid (what happens when save, cancel etc. is done).
How to deal with CRUD is available in the second source:
Crud with external form
Some heavy studying of these 2 along with going into some more depths of MVVM (which might be intimidating at first, but then really useful for much smoother work with Kendo) will get you going.
Edit: actually you could do with just first approach, which is easier and retain the state by refreshing the grid after cancel.
I'm working on a page that refreshes itself every 5 minutes
<meta http-equiv="refresh" content="1200;url=?meta_refresh=true" />
On the page is a JS script that should run the first two times the page reloads. When the page reload's for the third time, the script should not execute.
So far, I've created a cookie and given it an initial value of 0, for every refresh I increment it's value (rewrite the cookie) and if the value is smaller than 3 i execute the part of a script. The things is that if I close the tab and reopen the page in another tab, the cookie has the incremented value, and I want it to always start from 0.
Here's what i've done so far:
var value = 0;
$(document).ready(function() {
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i=0; i<ca.length; i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1);
if (c.indexOf(name) == 0) return c.substring(name.length,c.length);
}
return "";
}
function checkCookie() {
var cookieValue = getCookie('siteRefreshCookie');
if (cookieValue !== '') {
var newValue = parseInt(getCookie('siteRefreshCookie')) + 1;
if (newValue < 3) {
//script to be executed
document.cookie = "siteRefreshCookie="+ newValue +";";
}
} else {
document.cookie = "siteRefreshCookie="+ value +";";
}
}
checkCookie();
})
Could I suggest using a query string instead?
<meta http-equiv="refresh" content="1200;url=?meta_refresh=true&count=1" />
Then as an ASP programmer myself I would do something like:
<meta http-equiv="refresh" content="1200;url=?meta_refresh=true&count=<%=CInt(0 & Request.Querystring("count")) + 1%>" />
But you can probably achieve this using PHP, or even JS I imagine if you have no back-end language suitable.
The problem with using cookies is that they are tied to that website, rather than that window. Even if you reset the cookie with an unload function like Pete suggested, you'll then run into problems like if for example you have two tabs open with the same page.
Being a Javascript novice I am having some trouble implementing Google's Adwords GCLID tracking on our site. I am following their code examples show here https://support.google.com/adwords/answer/2998031.
You can see the cookie being stored but when trying to retrieve it and populate a hidden form field the result is just blank. I have used other variations but that simply results in "Undefined" as the field value.
Here is the code I'm using
Simplified HTML Form
<form class="signup-form" name="signupform" method="post" action="step2.php">
<input type="hidden" name="gclid" id="gclid" value="" />
</form>
Cookie Write Script
<script type="text/javascript">
function setCookie(a,d,b){var c=new Date;c.setTime(c.getTime()+864E5*b);b=";
expires="+c.toGMTString();document.cookie=a+"="+d+b}function getParam(a) {return(a=RegExp("[?&]"+a+"=([^&]*)").exec(window.location.search))&&decodeURIComponent(a[1].replace(/\+/g," "))}var gclid=getParam("gclid");if(gclid){var gclsrc=getParam("gclsrc");(!gclsrc||-1!==gclsrc.indexOf("aw"))&&setCookie("gclid",gclid,90)};
</script>
Cookie Read Script
<script>
function readCookie(name) {
var n = name + "=";
var cookie = document.cookie.split(';');
for(var i=0;i < cookie.length;i++) {
var c = cookie[i];
while (c.charAt(0)==' ') {
c = c.substring(1,c.length);
}
if (c.indexOf(n) == 0){
return c.substring(n.length,c.length);
}
}
return null;
}
function() {
document.getElementById('gclid').value = readCookie('gclid');
}
</script>
function() {
document.getElementById('gclid').value = readCookie('gclid');
}
this is a function without a name that's never called. try replacing it with only
document.getElementById('gclid').value = readCookie('gclid');
I rewrote your write script, I think your cookie is never set.
function setCookie(a,d,b) {
var c = new Date;
c.setTime(c.getTime()+864E5*b);
b="; expires=" + c.toGMTString();
document.cookie = a + "=" + d + b
}
function getParam(a) {
return(a=RegExp("[?&]"+a+"=([^&]*)").exec(window.location.search))&&decodeURIComponent(a[1].replace(/\+/g," "))
}
var gclid=getParam("gclid");
if(gclid) {
var gclsrc = getParam("gclsrc");
if(!gclsrc||-1 !== gclsrc.indexOf("aw")) {
setCookie("gclid", gclid, 90);
alert("Cookie Set!");
}
}
Working script modified from https://support.google.com/adwords/answer/3285060. I just changed the document.onload to window.onload It seems there was too much going on off screen in the DOM.
<script>
window.onload = function getGclid() {
document.getElementById("gclid").value = (name = new
RegExp('(?:^|;\\s*)gclid=([^;]*)').exec(document.cookie)) ?
name.split(",")[1] : ""; }
</script>
Why is my code picking up the following error?
Line 32, Column 14: character "<" is the first character of a delimiter but occurred as data
for(i=0; i <= length; i++) {
This message may appear in several cases:
You tried to include the "<" character in your page: you should escape it as "<"
You used an unescaped ampersand "&": this may be valid in some contexts, but it is recommended to use "&", which is always safe.
Another possibility is that you forgot to close quotes in a previous tag.
Line 32, Column 14: StartTag: invalid element name
for(i=0; i <= length; i++) {
Code:
<script type="javascript">
function randomRange(minVal,maxVal)
{
var randVal = minVal+(Math.random()*(maxVal-minVal));
return (Math.floor(randVal));
}
function GetCaptcha() {
var encStr = "123456789ABCDEFGHJKMNPQRSTUVWXYZ";
var length = randomRange(4,8);
var result = "";
var i = "";
var char = "";
for(i=0; i <= length; i++) {
char = encStr.substr(randomRange(1,encStr.length),1);
result += char;
}
return result;
}
function InitCaptcha() {
var hidFld = document.MyForm.captchaHidFld;
str = GetCaptcha();
hidFld.value = str;
document.getElementById('captchaTxt').innerHTML = str;
document.getElementById('captchaBtn').value = str;
}
function ValidateCaptcha (theForm) {
var inpStr = (document.MyForm.captchaInpFld.value).toUpperCase();
var captStr = document.MyForm.captchaHidFld.value;
if (inpStr.length == captStr.length)
{
if (inpStr.match(captStr)) { return true; }
}
return false;
}
function cmdSubmit(theForm)
{
if (!ValidateCaptcha(theForm))
{
alert ("Please enter valid CAPTCHA Code.");
return false;
}
if (theForm.name.value == "")
{
alert ("Please enter your name.");
theForm.name.focus();
return false;
}
if (theForm.email.value == "")
{
alert ("Please enter your e-mail address.");
theForm.email.focus();
return false;
}
return true;
}
</script>
With that transitional XHTML DOCTYPE you'll need to enclose inline Javascript and CSS like this:
<script type="text/javascript">
//<![CDATA[
/* script here */
//]]>
</script>
Compare these results:
this is invalid
this validates
What are you using to validate this? You could always include the javascript as an external javascript file to get around this?
Also: Make sure the script tag is inside a <head> or <body> element?
Your code looks correct. If you bebug the code partially, i.e. GetCaptcha() using firebug, you will be able to track the error quickly.
or Post the HTML related to this code :)