I want to prevent user from predicting the target script (test.php) AND do the whole "counter" logic on the server side.
I don't know how to achieve it with PHP.
I would like to open the file from the server side with PHP so the client will not have the possibility to see and know what file will open after 15 clicks. Because by typing the URL of the file it is possible to open it even before 15 clicks.
Thanks
HTML
<div id='overlay' class='overlay'></div>
<div class="view" id="view"></div>
<div class="canvas">
<div id="totalCounter" class="total-counter"></div>
<button id="clap" class="clap-container" tabindex="-1"></button>
<div id="clicker" class="click-counter">
<span class="counter"></span>
</div>
</div>
JAVASCRIPT
let accCounter = 0;
let totalCount = 0;
document.getElementById('totalCounter').innerText = totalCount;
document.getElementById('clap').onclick = function() {
const clap = document.getElementById('clap');
const clickCounter = document.getElementById("clicker");
upClickCounter();
loadDoc();
}
function upClickCounter() {
const clickCounter = document.getElementById("clicker");
const totalClickCounter = document.getElementById('totalCounter');
accCounter ++;
clickCounter.children[0].innerText = '+' + accCounter;
totalClickCounter.innerText = totalCount + accCounter;
}
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("view").innerHTML = this.responseText;
}
};
xhttp.open("GET", "clickcheck.php", true);
xhttp.send();
document.getElementById("view").style.visibility="visible";
if (totalCount + accCounter%15) {
document.getElementById('view').style.visibility="hidden";
}
document.getElementById('overlay').style.display = 'block';
if (totalCount + accCounter%15) {
document.getElementById('overlay').style.display = 'none';
}
}
clickcheck.php:
<?php
session_start();
if (!array_key_exists('clickcount', $_SESSION)) {
$_SESSION['clickcount'] = 1;
}
if ($_SESSION['clickcount'] < 15) {
header('HTTP/1.1 404 Not found');
exit();
} else {
include("test.php");
}
?>
I'm writing a google sheets add on that helps you track data as you play a game. In the sidebar, you can search for a monster in the game and after you hit the submit button the monster's stats, a list of what items they drop after a kill, and a link to the wiki is rendered on screen.
The problem I'm having is that when you search a new monster after having already searched for one, the old items from the drop section won't get removed. The other sections on stats and the wiki link will change, but instead of removing the old drop items, the new items just get added to the end of the list.
I've tried using parent.removeChild() and childNode.remove() and neither seem to do anything and I'm wondering if its because of how google apps script works.
Here is the html for the sidebar itself: note that include() is a custom function that google recommends you add to your script so you can import other files.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<?!= include('Info sidebar styles'); ?>
</head>
<body>
<form id="monsters">
<input class="monsterInput" type="text"placeholder="Monster Name" name="monsterName" />
<input class="monsterInput" type="text" placeholder="Monster Level" name="monsterLvl" />
<button id="submit">Search</button>
</form>
<div id="output">
</div>
<?!= include('sidebar script'); ?>
</body>
</html>
Here's the code for sidebar script:
<script>
if (document.readyState == 'loading') {
document.addEventListener('DOMContentLoaded', ready)
} else {
ready()
}
function ready(){
// create the divs that are later filled with info
var output = document.getElementById("output");
var stats = document.createElement("div");
stats.id = "statsDiv";
var drops = document.createElement("div");
drops.id = 'dropDiv';
var list = document.createElement("div");
list.id = "dropList";
var wiki = document.createElement("div");
wiki.id = "wiki";
output.appendChild(stats);
output.appendChild(drops);
output.appendChild(wiki);
var index = 0;
// the onSuccess for the onClick eventHandler. data is an object returned from the function call below
function onSuccess(data) {
console.log(`first index ${index}`);
// if the submit button has already been pushed and added the droplist to the DOM, increase the index
if(drops.getElementsByClassName("dropItem")[0]){
index++;
console.log(`second index ${index}`);
};
console.log(index);
// get the stats
var hitpoints = data.hitpoints;
var attackarray = data["attack_type"]
var attackTypes = '';
var attack1 = attackarray[0];
var attack2 = attackarray[1];
var attack3 = attackarray[2];
var attack4 = attackarray[3];
if(attackarray.length === 1){
attackTypes = attack1;
} else if (attackarray.length === 2){
attackTypes = `${attack1}, ${attack2}`;
} else if (attackarray.length === 3){
attackTypes = `${attack1}, ${attack2}, ${attack3}`;
} else if (attackarray.length === 4){
attackTypes = `${attack1}, ${attack2}, ${attack2}, ${attack4}`;
}
var attLvl = data["attack_level"];
var defLvl = data["defence_level"];
var magicLvl = data["magic_level"];
var rangeLvl = data["ranged_level"];
var maxHit = data["max_hit"];
var aggro = '';
if(data.aggressive){
aggro = "Yes";
} else {
aggro = "No";
}
var speed = data["attack_speed"];
// put the stats into html form
var statsInner =
`<h2> Stats </h2>
<ul id="statsList">
<li>Hitpoints: ${hitpoints}</li>
<li>Attack Level: ${attLvl}</li>
<li>Defense Level: ${defLvl}</li>
<li>Magic Level: ${magicLvl}</li>
<li>Ranged Level: ${rangeLvl}</li>
<li>Attack Style: ${attackTypes} </li>
<li>Attack Speed: ${speed}</li>
<li>Max Hit: ${maxHit} </li>
<li>Aggressive? ${aggro} </li>
</ul>`;
stats.innerHTML = statsInner;
drops.innerHTML = '<h2>Drops</h2>';
// Put the wiki url into HTML
var wikiURL = data["wiki_url"];
var wikiInner = `<p>For more info check out this monsters page on the wiki, <a href=${wikiURL}>here</a>.</p>`;
wiki.innerHTML = wikiInner;
// get the drop information and put it in html form. make the data-id attribute of each object equal the value of index
data.drops.forEach(function (item) {
var name = item.name;
var quant = item.quantity;
var members = '';
if(item.members){
members = "(m)";
}
var nameQM = `${name} (x${quant}) ${members}`;
var rarity = (item.rarity) * 100;
var rare = rarity.toFixed(2);
var nameNode = document.createElement("div");
var itemList =
`<p>${nameQM}</p>
<br>
<p> Rarity: ${rare} percent </p>`;
nameNode.innerHTML = itemList;
nameNode.className = "dropItem";
nameNode.dataset.id = index;
list.appendChild(nameNode);
})
drops.appendChild(list);
// if the drop item has a data-id that doesn't match the current index, remove it from the DOM.
var dropArray = list.getElementsByClassName("dropItem");
for(var i = 0; i < dropArray.length; i++){
var item = dropArray[i];
if(item.dataset.id != index){
item.remove();
}
}
}
//add the event listener to the submit button. getMonsterData makes an API call, parses the data, and returns an object filled with the data we add to the DOM through the success handler
document.getElementById("submit").addEventListener("click", function (e) {
e.preventDefault();
var parent = e.target.parentElement;
var monsterName = parent.elements[0].value;
var monsterlvl = parent.elements[1].value;
google.script.run.withSuccessHandler(onSuccess).getMonsterData(monsterName, monsterlvl);
});
}
</script>
I have been recently working on a website, which will mainly be used as a medium where various tourist agencies could post their travel offers.
The index page contains a functional filters area, where the user could perform an offer search based on multiple conditions.
<div id="offer-filters">
<h2>Filter search</h2>
<div id="filter-bars">
<ul id="filter-list">
<li>
<label for="searchagency">Agency</label>
<input list="agencies" id="searchagency" name="searchagency"
onclick="dataListFromOriginAgency('agencies', 'searchagency')">
</li>
<datalist id="agencies"></datalist>
<li>
<label for="searchdepart">Departure</label>
<input list="departures" id="searchdepart" name="searchdepart"
onclick="dataListFromOriginOffersDeparture('departures', 'searchdepart')">
</li>
<datalist id="departures"></datalist>
<li>
<label for="searchdestination">Destination</label>
<input list="destinations" id="searchdestination" name="searchdestination"
onclick="dataListFromOriginOffersDestination('destinations', 'searchdestination')">
</li>
<datalist id="destinations"></datalist>
<li>
<label for="searchpricerangefrom">Price below</label>
<input type="number" id="searchpricerangefrom" name="searchpricerangefrom" min="1"
max="1000000">
<label for="searchpricerangeto">over</label>
<input type="number" id="searchpricerangeto" name="searchpricerangeto" min="1"
max="1000000">
</li>
<li>
<label for="searchtransport">Transport</label>
<input list="transport" id="searchtransport" name="searchtransport"
onclick="dataListFromOriginOffersTransportation('transport', 'searchtransport')">
</li>
<datalist id="transport"></datalist>
<li>
<label for="searchstartdate">Start date</label>
<input type="date" name="searchstartdate" id="searchstartdate"></li>
<li>
<label for="searchenddate">Return date</label>
<input type="date" name="searchenddate" id="searchenddate">
</li>
</ul>
</div>
<button class="search-filter">Search</button>
</div>
The key idea is that the button present at the bottom would return functions based on how many inputs contain values, that saying how many inputs are not empty. I.e. an user performs a search of offers based on a certain agency, passing the agency name into the first input, and a destination which would be entered into the third one.
When i define a function that will return different results based on input conditions, some functions would never be called as the previous condition already evaulated.
function triggerFuncByScenario() {
if (!(document.querySelector("#searchagency").value === "")) {
getOffersByName();
}
else if (!(document.querySelector("#searchagency").value === "" && document.querySelector("#searchdestination").value === "")) {
getOffersByDestinationName();
}
Taken as an example, the first function normally occurs on button click, while the second one doesn't work because the first part of the condition is already evaluated, leading to the constant call of the first one.
Is there any solution so that every filter combination could be assigned to different functions?
The functions also use an AJAX request for obtaining the data.
function prepareOffers(type, route, objectJSON) {
var offer = document.getElementsByClassName("offer");
while (offer[0]) {
offer[0].parentNode.removeChild(offer[0]);
}
while (!(document.getElementById("offers-nav").innerHTML == "")) {
var nav = document.getElementById("offers-nav");
nav.innerHTML = "";
}
var httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState == 4) {
var response = httpRequest.responseText;
var respArray = response.split(",");
var arrayParsed = JSON.parse(respArray);
for (let i = 0; i < arrayParsed.length; i++) {
var offer = document.createElement("div");
offer.className = "offer";
document.getElementById("offers-list").appendChild(offer);
var offerFlex = document.createElement("div");
offerFlex.className = "offer-flex";
document.getElementsByClassName("offer")[i].appendChild(offerFlex);
var image = document.createElement("img");
image.setAttribute("alt", "Image description of an given agency offer destination");
image.setAttribute("src", ("img/" + arrayParsed[i].destination + ".jpg"));
image.setAttribute("class", "destination-image");
var image2 = document.createElement("img");
image2.setAttribute("alt", "Logo of an agency that provided the offer");
image2.setAttribute("src", ("img/" + arrayParsed[i].tourism_agency + ".png"));
image2.setAttribute("class", "agency-logo");
var markAsFavourite = document.createElement("a");
markAsFavourite.setAttribute("class", "favourite");
markAsFavourite.setAttribute("href", "#a");
markAsFavourite.setAttribute("onclick", "addToFavourites()");
markAsFavourite.innerHTML = "<i class='fas fa-star'></i> Add to favourites";
var list = document.createElement("ul");
document.getElementsByClassName("offer-flex")[i].appendChild(markAsFavourite);
document.getElementsByClassName("offer-flex")[i].insertBefore(list, markAsFavourite);
document.getElementsByClassName("offer-flex")[i].insertBefore(image2, list);
document.getElementsByClassName("offer-flex")[i].insertBefore(image, image2);
var element1 = list.appendChild(document.createElement("li"));
element1.setAttribute("class", "destination");
var element2 = list.appendChild(document.createElement("li"));
element2.setAttribute("class", "start");
var element3 = list.appendChild(document.createElement("li"));
element3.setAttribute("class", "end");
var element4 = list.appendChild(document.createElement("li"));
element4.setAttribute("class", "price");
var element5 = list.appendChild(document.createElement("li"));
element5.setAttribute("class", "transportation");
var element6 = list.appendChild(document.createElement("li"));
element6.setAttribute("class", "more-info");
document.getElementsByClassName("destination")[i].innerHTML = "Destination: " + arrayParsed[i].destination;
document.getElementsByClassName("start")[i].innerHTML = "Start date: " + arrayParsed[i].start;
document.getElementsByClassName("end")[i].innerHTML = "Return date: " + arrayParsed[i].end;
document.getElementsByClassName("price")[i].innerHTML = "Price: " + arrayParsed[i].price + " €";
document.getElementsByClassName("transportation")[i].innerHTML = "Transport: " + arrayParsed[i].transportation;
document.getElementsByClassName("more-info")[i].innerHTML = "For more info please click <a href='#offers-page' onClick='displayMoreInfo()'>here</a>";
document.getElementById("offers-count").innerHTML = "Showing " + document.querySelectorAll(".offer").length + " from " + arrayParsed.length + " offer(s):";
}
if (arrayParsed.length == 0) {
var noOffers = document.createElement("h2");
noOffers.setAttribute("id", "no-offers");
document.querySelectorAll(".show-offers")[0].insertBefore(noOffers, document.querySelector("#offers-list"));
document.querySelector("#no-offers").innerHTML = "No offers found!";
} else {
var noOffers = document.createElement("h2");
noOffers.setAttribute("id", "no-offers");
document.querySelectorAll(".show-offers")[0].insertBefore(noOffers, document.querySelector("#offers-list"));
document.querySelector("#no-offers").remove();
}
}
}
httpRequest.open(type, route, true);
if (!(objectJSON == "" || objectJSON == null)) {
httpRequest.setRequestHeader("Content-type", "application/json");
httpRequest.send(objectJSON);
} else {
httpRequest.send();
}
Thank you in advance.
So I've been looking it over and just a thought, have you tried to nest your if-else statements?
function triggetFuncByScenario(){
if(!(document.querySelector("#searchagency").value === "")){
if(!(document.querySelector("#searchdestination").value === "")){
getOffersByDestinationName();
}else{
getOffersByName();
}
}
}
To me, it looks like that little oversight is what is causing your problem.
By nesting this you are getting a certain check of all the given conditions.
Hope it is helpful and good luck with your project.
While simply changing the order in which you evaluate your conditions could get the result you want, a more verbose solution can make very clear what is happening at each step.
Here, the evaluateSearchFields function reports a single value representing which combination of fields the user filled in. With this information, you can be confident about which action to take.
I wouldn't bother with this level of detail in most cases, but sometimes clarity is what we need so we can proceed from a solid foundation.
function triggerFuncByScenario() {
const
searchAgency = document.getElementById("searchagency"),
searchDestination = document.getElementById("searchdestination"),
agencyEmpty = (searchAgency.value === ""),
destinationEmpty = (searchDestination.value === "");
if( evaluateSearchFields() == "agencyOnly" ){ getOffersByName(); }
else if( evaluateSearchFields() == "both" ){ getOffersByDestinationName(); }
}
function evaluateSearchFields(){
if(!agencyEmpty && !destinationEmpty){ return "both"; }
if(!agencyEmpty && destinationEmpty){ return "agencyOnly"; }
if( agencyEmpty && !destinationEmpty){ return "destinationOnly"; }
if( agencyEmpty && destinationEmpty){ return "neither"; }
else { return "this is impossible"; }
}
For this part removing else will evaluate both conditions and execute.
Also try to use getElementById if you need to get only one element by ID
function triggerFuncByScenario() {
var searchAgency = document.getElementById("searchagency");
if (!(searchAgency.value === "")) {
getOffersByName();
}
if (!(searchAgency.value === "" &&
document.querySelector("#searchdestination").value === "")) {
getOffersByDestinationName();
}
}
I am just trying to prototype a simple functionality using javascript for learning purpose, but the contents within the <p> tag are not updating and I am stuck at this point. My code is as follows:
<!DOCTYPE html>
<html>
<head>
<title> Ajax Search Box </title>
<script>
function LoadList()
{
var searchBox = document.getElementById("txtSearch");
var resultBox = document.getElementById("results");
var searchedChars = "";
var xHttp = new XMLHttpRequest();
searchedChars += searchBox.value;
xHttp.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200)
{
var xmlContent = this.responseXML;
var nameList = xmlContent.getElementsByTagName("name");
var dispText = "";
for(var i = 0 ; i < nameList.length ; i++)
{
dispText += nameList[i].textContent + "<br/>";
}
resultBox.innerHtml = dispText;
}
};
xHttp.open("GET","AssessorList.xml",true);
xHttp.send();
}
</script>
</head>
<body>
<input id="txtSearch" type="text" placeholder="Search" onkeyup="LoadList();" />
<p id="results">
No Data Available.
</p>
</body>
</html>
Could someone tell me why the innerHtml is not updating? Thanks in advance.
P.S: The code is fetching the data from the xml file as I could see in browser's console, the values being passed to the dispText variable.
<!DOCTYPE html>
<html>
<body>
<input id="txtSearch" type="text" placeholder="Search" onkeyup="LoadList();" />
<p id="results">No data available</p>
<script>
function LoadList() {
var xhttp = new
XMLHttpRequest();
var searchBox =
document.getElementById("txtSearch");
var resultBox = document.getElementById("results");
var searchedChars = "";
searchedChars += searchBox.value;
xhttp.onreadystatechange = function() {
//alert(this.status);
if (this.readyState == 4 && this.status == 200) {
var xmlContent = this.responseXML;
var nameList = searchedChars;
alert(nameList);
var dispText = "";
for(var i = 0 ; i < nameList.length ; i++)
{
dispText += nameList[i] + "<br/>";
}
resultBox.innerHTML = dispText;
}
};
xhttp.open("GET", "ajax.txt", true);
xhttp.send();
} </script>
</body>
</html>
Hope this may help you
I have the following script. After a user clicks submits I want to redirect the user to the same page and populate the drop down and input box with parameter values from the url. Unfortunately they are not populating once the redirect completes. I also need to strip off * from the FilterMultiValue parameter so that the textbox has the orginal value entered?
I've checked the parameter values using an alert function and that works?
<script type="text/javascript">
function getUrlParams() {
var paramMap = {};
if (location.search.length == 0) {
return paramMap;
}
var parts = location.search.substring(1).split("&");
for (var i = 0; i < parts.length; i ++) {
var component = parts[i].split("=");
paramMap [decodeURIComponent(component[0])] = decodeURIComponent(component[1]);
}
return paramMap;
}
function RedirectUrl() {
var tb = document.getElementById("tbSearch").value;
var cs = document.getElementById("sfield").value;
var url = "";
if (tb != "") {
url = "FilterName=" + cs + "&FilterMultiValue=*" + tb + "*";
window.location.href = "mypage.aspx?" + url;
var params = getUrlParams();
alert(params.FilterName);
document.getElementById("sfield").value = params.FilterName;
document.getElementById('tbSearch').value = params.FilterMultiValue;
}
else {
return false;
}
}
function ClearUrl() {
window.location.href = "mypage.aspx";
document.getElementById("sfield").value = "";
document.getElementById('tbSearch').value = "";
}
</script>
Search Field:
<select id="sfield">
<option selected value="Title" >Title</option>
<option value="Body">Body</option>
</select>
Search Text:
<input type="text" id="tbSearch" />
<input type="button" id="btnSearch" value="Search" onclick="return RedirectUrl();" />
<input type="button" id="btnClear" value="Clear" onclick="return ClearUrl();" />
window.location.href = "mypage.aspx?" + url;
reloads the page, which will result in all code after that not beeing executed.
What you want to do is to add code for pageload and check if the parameters are given, then populate the textbox.
Something like:
window.addEventListener('load', function(){
var params = getUrlParams();
if(typeof params.FilterName !== 'undefined'){
// removes the first and the last char from the string
var t = params.FilterMultiValue.substr(1, params.FilterMultiValue.length-2);
document.getElementById("sfield").value = params.FilterName;
document.getElementById('tbSearch').value = t;
}
});