Set a dynamic variable? - javascript

This may be extremely simple, but my brain's just not grasping this for some reason.
I'm making a Tic-Tac-Toe/Hollywood Squares game, and all the square variables are set to null
square0Value = "";
square1Value = "";
etc.
When you click on one of the squares, it launches a bootstrap modal with a closeup of the square and two buttons, X and O, and passes all of the data from the grid square into the modal, so that I only need one modal markup block.
When you click the X or the O, I need it to dynamically set the square variable, that is associated with the modal to either X or O, once the modal is closed, another javascript function checks all the variables to see if there's a 3-in-a-row occurrence, and displays a console.log that X or O has won the game. But I'm not writing this correctly, and none of the square variables are being set.
Here's my code:
HTML:
<button class="squareButton" data-toggle="modal" data-target="#squareModal" data-square="" data-nameplate="" data-xo="" data-id="square0">
<div class="xo"></div>
<div class="nameplate"></div>
<div class="desk"></div>
</button>
(I have this replicated 9 times.)
[Modal markup]
<div class="modal fade-scale" id="squareModal" tabindex="-1" role="dialog" aria-labelledby="squareModal">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-body">
<div class="square">
<div class="squareModal">
<div class="xo"></div>
<div class="nameplate"></div>
<div class="desk"></div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" id="modalX" class="btn btn-default btn-xo" data-dismiss="modal">X</button>
<button type="button" id="modalO" class="btn btn-default btn-xo" data-dismiss="modal">O</button>
</div>
</div>
</div>
</div>
JS:
I have an array built that populates each square with a celebrity/personality, and an document.ready function that shuffles the array populates the squares:
$(document).ready(function(){
shuffle(squares);
for (i = 0; i < 9; i++) {
$("#square"+i).find('.squareButton').addClass(squares[i][0]);
$("#square"+i).find('.squareButton').data("square", squares[i][0]);
*// the [0] block of the array is a class filler*
$("#square"+i).find('.squareButton').data("nameplate", squares[i][1]);
*// the [1] block of the array is the celebrity's name*
$("#square"+i).find('.nameplate').html(squares[i][1]);
}
});
var square0Value = "";
var square1Value = "";
var square2Value = "";
var square3Value = "";
var square4Value = "";
var square5Value = "";
var square6Value = "";
var square7Value = "";
var square8Value = "";
var squareClass = "";
var squareName = "";
var squareXO = "";
var squareId = "";
$('#squareModal').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget);
squareClass = button.data('square');
squareName = button.data('nameplate');
squareXO = button.data('xo');
squareId = button.data('id');
console.log(squareId);
var modal = $(this)
modal.find('.modal-body').addClass(squareClass);
modal.find('.modal-body .nameplate').html(squareName);
modal.find('.modal-body .xo').html(squareXO);
})
$('#squareModal').on('hidden.bs.modal', function (event) {
var modal = $(this);
modal.find('.modal-body').removeClass(squareClass);
checkWin();
});
function clickX(){
$(eval(squareId+'Value')).val("X");
$(eval(squareId)).addClass('selected');
$(eval(squareId)).find(".squareButton").data("xo", "X");
$(eval(squareId)).find(".xo").html("X");
}
function clickO(){
$(eval(squareId)).addClass('selected');
$(eval(squareId+'Value')).val("O");
$(eval(squareId)).find(".squareButton").data("xo", "O");
$(eval(squareId)).find(".xo").html("O");
}
$("#modalX").on("click", function(e){
e.preventDefault();
clickX();
});
$("#modalO").on("click", function(e){
e.preventDefault();
clickO();
});
function checkWin() {
for (i = 0; i < 9; i++) {
console.log("Square"+i+": " + eval('square'+[i]+'Value'));
}
checkWinX();
checkWinO();
if (square0Value != "" && square1Value != "" && square2Value != "" && square3Value != "" && square4Value != "" && square5Value != "" && square6Value != "" && square7Value != "" && square8Value != ""){
checkBoardFull();
}
}
The issue lies in the clickX() and clickO() functions where I am trying to set the value of the (eval(squareId+'Value')) as the X or the O value that is needed. I want to make this as dynamic as possible so don't have to write a function for every modal.

Not sure why you are using eval.
$("#"+squareId).addClass()
may be enough

Here would be my suggestion.
var button = $(event.relatedTarget);
If I am reading this right, that is the button that was clicked that caused the modal to show. If that is the case, then I believe it is a far assumption that only one modal can show at a time. If that is true, then what you can do is make that variable scoped higher, not within that handler.
What does that do for you? Well, if you do that, then you can use that element within your clickX and clickY. For instance...
function clickX(){
button.data('xo', 'X');
button.find('.xo').html('X');
}
I'm unclear what the others are referencing, but if you have the button then you have access to finding it's nested children or looking for parent elements if you need to find them.

So yeah... rebuilding my global Square Values into an array was a MUCH easier way of organizing things... sorry everyone.

Related

Protractor - Clicking button in div which has a span with certain text

I have a problem with clicking a button in Protractor. Simplified code looks like that:
<div class = "container">
<div class = "col1">
<span class = "hour">12:00</span>
</div>
<div class="col2">
<button class="btn">Test</button>
</div>
</div>
<div class = "container">
<div class = "col1">
<span class = "hour">13:00</span>
</div>
<div class="col2">
<button class="btn">Test</button>
</div>
</div>
I would like to click a button in div, where its span has "12:00" hour. The condition must check the hour.
I can easily check the span with
by.xpath('//span[contains(text(), "12:15")]')
My main concern is to select the button with parent div having this span. Is this possible?
Thank you.
I had a similar condition. But I had just to extract a value from DOM and compare it with the expected result, it looks like this:
records = await targeting_page.records.getText();
recordsNumber = parseFloat(records.replace(/,/g, ''));
recordsRange = recordsNumber >= 100 && recordsNumber < 90000000;
await expect(recordsRange).toEqual(true);
but your occasion is not a big difference.
that what I have written in browser console on this page of your question
async function fin() {
for(var i = 0; i < 100; i++) {
var myElement = document.querySelector("code span:nth-child(27)").textContent //your find your desired element
console.log(b)
typeof b == 'string' ? console.log(true) : console.log(false) //this is optionally
var res = parseFloat(b) //parse when it will be 12:00 you will get the 12 number
console.log(res)
res == 13 ? await b.click() : console.log("The button is not ready yet") //and here compare is there that number you need, if yes then click element(this doesn't work in console,
// if you use async/await in your protractor tests, there are it will work
}
}
fin()
That's what concerns directly this page.
In test, it will be looking something like this(it can be much better but I drafted it very quckly):
for(let i=0; i < 100; i++) {
var myE = await myElement.getText(); //where myElement -- your selector
var myNumber = parseFloat(myE.replace(/:/g, '')); // parse and get 12 out of "12:00"
if (myNumber == 12) {
await myElement.click()
} else {
console.log("The button is not ready yet")
}
}
by.xpath('//span[contains(text(), "12:15")]/ancestor::div//button[#class='btn']')
Hope this answer helps you!!
0506

Trying to switch image states - from still to animate - using giphy API

So I'm in a bootcamp, bout to begin the 7th week. We have an API assignment, and I chose to use the Giphy API. Okay, I've made the ajax call, have the json object, am displaying gifs with a button click. Once the gifs load, you should be able to make image animate, then upon next click, the image becomes still again. the process should be able to repeat itself ad nauseam. I have it set up the way that makes sense; however, I cant seem to get the urls to change upon click the way it's currently written. I tried .splice url, and using concat to complete updated url; however, I cant seem to figure out how to get the image to revert back to still state upon next click... been working on this for sooooo many hours, will someone please lend me a fresh set of eyes?
here's my js and jquery
// $("#loadTimer, .buttonGallery, #btnGeneratingbtn").hide();
var topics = ["Brandon", "Biggie Smalls", "Dr. Seuss", "Paul McCartney", "John Lennon", "Will Ferrell", "Jimmy Fallon", "Chris Farley", "Dane Cook", "Eminem", "Nas", "Jay-Z", "Rakim", "William Shakespeare","Jim Morrison", "James Maynard", "Serj Tankian"];
var gifcount = 0;
var gifLocation;
var clickCount = 0;
var buttonFactory = function() {
$(".buttonGallery").empty();
for (i = 0; i < topics.length; i++) {
var imAbutton = $("<button>");
imAbutton.addClass("yup");
imAbutton.attr("data-name", topics[i]);
imAbutton.text(topics[i]);
$(".buttonGallery").append(imAbutton);
}};
buttonFactory();
$("#anotherButton").on("click", function(event) {
event.preventDefault();
// This line grabs the input from the textbox
var onemorebutton = $("#user-input").val().trim();
// Adding movie from the textbox to our array
topics.push(onemorebutton);
// Calling renderButtons which handles the processing of our movie array
buttonFactory();
});
$(".yup").on("click", function(){
$("#gif-Gallery").empty();
var searchTermUpdate;
var searchTerm = $(this).attr("data-name");
// removing white space between two-word strings, replacing with a "+" \\
searchTermUpdate = searchTerm.replace(/ +/g, "+");
var queryURL = "http://api.giphy.com/v1/gifs/search?q=" + searchTermUpdate + "&api_key=dc6zaTOxFJmzC&limit=10";
$.ajax({
url: queryURL,
method: 'GET'
}).done(function(response) {
console.log(response);
var results = response.data;
for (var i = 0; i < results.length; i++){
gifcount = gifLocation;
var gifDIV = $("<div class='unit' data-state='still'>");
var pRating = $("<p>").text("Rating: " + results[i].rating);
var gifImg = $("<img id='gifimg' class='col-md-4'>");
gifImg.attr("src", results[i].images.fixed_height_still.url);
gifImg.attr({'data-animate' : results[i].images.fixed_height.url});
gifImg.attr({'data-state' : "still"});
gifImg.attr({'data-still' : results[i].images.fixed_height_still.url});
gifDIV.append(pRating);
gifDIV.append(gifImg);
gifDIV.append(gifLocation);
gifcount++;
// appending gif div to DOM \\
if (results[i].rating !== "g" || "pg" || "pg-13" || "y"){
$("#gif-Gallery").append(gifDIV);
}}
$(".unit").on("click", function(){
var state = $(this).attr('data-state');
if (state === "still") {
$(this).attr("src", $(this).attr("data-animate"));
$(this).attr("data-state", "animate");
} else {
$(this).attr("src", $(this).attr("data-still"));
$(this).attr("data-state", "still");
}
// var imgPath = this.children[1].src;
clickCount++;
var a;
var b;
var c;
var d;
var f;
// if (clickCount % 2 === 0 ){
// for (i=0; i < imgPath.length; i++){
// // locating index of underscore, storing that value in var a\\
// var a = imgPath.indexOf("_");
// // removing all characters to the right of the underscore \\
// var b = imgPath.slice(0, a);
// f = b;
// // setting var c to a string value of .gif \\
// var c = ".gif";
// // combining var b and var c to complete updated image path \\
// var d = b.concat(c);
// }
// setting image url to animated url \\
// $(gifImg).attr("src", d);
// this.children[1].src = d;
});
});}); //
and here is the html if needed :
<body>
<div class="jumbotron">
<div class="container">
<div class="myHeader">
<h1>WordSmiths</h1>
<span class="text-muted" id="jtronText">
<div id="sometimeGone">Sometimes</div><div id="loadTimer">someone opens their mouth and you can't help but to be dazzled with the magic.</div>
</span>
<p class="text-success" id="instructionsOne">
Click a button, see what happens!
</p>
<p class="text-success" id="instructionsTwo">
Now you can create your own buttons!!!
</p>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-lg-12">
<div class="buttonGallery"></div>
<h4>Create buttons, find Gifs!: </h4>
<form id="btnGeneratingForm">
<label for="input">Anything: </label>
<input type="text" id="user-input">
<br>
<input type="submit" id="anotherButton" value="More buttons">
</form>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div id="gif-Gallery"></div>
</div>
</div>
again, thanks in advance!
Robert
I am actually doing the same project! I did it a pretty a similar way. I think the issue may be that you're appending the animated src to the image holder div instead of the child image itself. This line:
$(this).attr("src", $(this).attr("data-animate"));
Is what is giving you trouble I think.
Best of luck with the project, I hope that helps.

How to .slice changing parts of a string in jQuery

I have several divs that use bootstrap Grid system to allow users of the site to "zoom" content.
In this example with the class="abcd b1 col-lg-6" everything works fine.
But then I have my b1 part of the classes.. it will go up beyond b10, which makes my code no longer work.
I have tried to change the code so it would read from right to left... but then when the col-lg-6 becomes col-lg-10 it no longer works either.
So my question: is there a better way to .slice the code so it will work even when my classes length changes?
<div id="col" class="abcd b1 col-lg-6"> //the div
<div class="tn bg1">
<div class="ca">
<div class="bp">
<button type="button" id="plus" class="btn" data-toggle="tooltip" data-placement="left" title="Bigger Size"></button> //the button
<button type="button" id="minus" class="btn" data-toggle="tooltip" data-placement="left" title="Smaller Size"></button>
</div>
</div><!--ca-->
</div><!--tn-->
</div><!--col-->
<!--Plus Button-->
var className = ('col-lg-'); //make className = "col-lg-"
$('button#plus').click(function() { //find button#plus and add clickfunction on it.
$this = $(this).closest('div#col'); //find the div that shall change on click, closest div with id=col
var counter = $this.attr('class').split(className)[1]; //get the last section of the class. class "col-lg-6" will set the counter to = 6
var classList = $($this).attr('class').split(/\s+/); //get all the classes of that div, in an objekt array stored in "classList3"
var classString = classList.toString(); //make that objekt array into a string. classstring = "abcd,b1,col-lg-6"
var oldClass = classString.slice(8); //slice out the part i want. oldClass = "col-lg-6"
var nextNum = 1;
if (counter != '') //if the counter has already started
nextNum = parseInt(counter) + 2; //add +2 on click
if (counter < 12) { //if counter are less then 12
$this.removeClass(oldClass).addClass(className + nextNum); //Remove class "col-lg-6" (or what ever the number are at the moment)
}
else { //if counter are bigger or = 12
//do nothing
}
})
I found a way to fix it :)
First i add the variable:
var otherClasses = $this.attr('class').split(className)[0];
This variable store the other classes " abcd b1 ", not the " col-lg-6 "
Then i changed this:
$this.removeClass(oldClass).addClass(className + nextNum);
To this:
$this.removeClass().addClass(otherClasses + className + nextNum);
This will remove all the classes and then add the old ones + the new one back.
And remove this completly, there are no need for it anymore.
var classList = $($this).attr('class').split(/\s+/);
var classString = classList.toString();
var oldClass = classString.slice(8);

Regular expression getElementById

I need to use pure Javascript for the first time in a long while, and having gotten used to the comfy mattress of jQuery, all the important stuff is escaping me.
I need to select a bunch of divs on regular expression. So I have stuff like this;
<div id="id_123456_7890123"> .. </div>
<div id="id_123456_1120092"> .. </div>
<div id="id_555222_1200192"> .. </div>
<div id="id_123456_9882311"> .. </div>
And I'd need to create a loop that goes through all the divs with an id that begins with id_123456_. How would I go about doing that?
I used jQuery with the :regex filter plugin before, but looking at it, it doesn't seem like there's much I could salvage in a pure javascript rewrite.
In plain javascript, you could do this generic search which should work in every browser:
var divs = document.getElementsByTagName("div"), item;
for (var i = 0, len = divs.length; i < len; i++) {
item = divs[i];
if (item.id && item.id.indexOf("id_123456_") == 0) {
// item.id starts with id_123456_
}
}
Working example: http://jsfiddle.net/jfriend00/pYSCq/
HTML DOM querySelectorAll() method will work here.
document.querySelectorAll('[id^="id_"]');
Borrowed from StackOverFlow here
This works by recursively traversing the whole DOM.
It's possibly not the most efficient, but should work on every browser.
function find_by_id(el, re, s) {
s = s || [];
if (el.tagName === 'DIV' && re.exec(el.id) !== null) {
s.push(el);
}
var c = el.firstChild;
while (c) {
find_by_id(c, re, s);
c = c.nextSibling;
}
return s;
}
var d = find_by_id(document.body, /^id_123456_/);
See http://jsfiddle.net/alnitak/fgSph/
Here you are: http://jsfiddle.net/howderek/L4z9Z/
HTML:
<div id="nums">
<div id="id_123456_7890123">Hey</div>
<div id="id_123456_1120092">Hello</div>
<div id="id_555222_1200192">Sup</div>
<div id="id_123456_9882311">Boom</div>
</div>
<br/>
<br/>
<div id="result"></div>​
Javascript:
divs = document.getElementsByTagName("div");
divsWith123456 = new Array();
for (var i = 0;i < divs.length;i++) {
if (divs[i].id.match("id_123456") != null) {
divsWith123456.push(divs[i]);
document.getElementById("result").innerHTML += "Found: divs[" + i + "] id contains id_123456, its content is \"" + divs[i].innerHTML + "\"<br/><br/>";
}
}​

Remove existing code side of div code

Goal:
If there are any html syntax code or data inside of
<div id="feedEntries"></div>
Then everything should be removed and be contained empty only.
Problem:
What syntax do I need in order to remove every code and data inside of
<div id="feedEntries"></div>
Please remember that i don't want to add any class or id inside of "feedEntries"
<h3>Search</h3>
<div class="content">
<form>
<input type="text" width="15" value="searchword" id="searchTermTextField"><input type="button" name="some_name" value="Sök" id="searchButton">
</form>
<div id="feedEntries">
</div>
</div>
function fetchSearchResults(json) {
var feedEntriesDivElement = document.getElementById('feedEntries');
var ulElement = document.createElement('ul');
if (feedEntriesDivElement.children.length >= 0)
{
// Syntax code to remove the code/data
}
for (var i = 0; i < json.responseData.results.length; i++)
{
var liElement = document.createElement('li');
var personText = document.createTextNode(json.responseData.results[i].titleNoFormatting);
var newlink = document.createElement('a');
newlink.setAttribute('href', json.responseData.results[i].url );
newlink.appendChild(personText);
liElement.appendChild(newlink);
ulElement.appendChild(liElement);
}
feedEntriesDivElement.appendChild(ulElement);
}
Using pure DOM and Javascript (sometimes considered better than altering innerHTML):
if ( feedEntriesDivElement.hasChildNodes() )
{
while ( feedEntriesDivElement.childNodes.length >= 1 )
{
feedEntriesDivElement.removeChild( feedEntriesDivElement.firstChild );
}
}
feedEntriesDivElement.innerHTML = ''; should do the trick.
you can use jquery like this $('#feedEntries').empty()
to remove from javascript please check the post
document.getElementByIf('feedEntries').innerHTML = ''

Categories