jquery replace issues - javascript

I have series of divs, that represent similar to a chess board. but this is a kinda tricky chess. basically users clicks on a piece, and clicks on enemy piece. if it can kill. it should move it to the enemies position. And enemy should be deleted.
<div class="column" data-square="4-4">
<div class="white-king lol">a</div>
</div>
<div class="column" data-square="4-5">
<div class="black-pawn lol">b</div>
</div>
<div class="column" data-square="4-6">
<div class="blue lol">c</div>
</div>
//so when users first clicks on whiteking, we get the data-square, assign it to a variable $from, then clicks on enemy black-pawn. does some validation in server, and should move the
​
inner div of square = 4-4 to inner div of square = 4-5 , the inner div of square = 4-5 should be deleted and the inner div of square= 4-4 should be presnet
I have tried using jquery clone. but it doesnt works out well
fiddle: http://jsfiddle.net/jm4eb/13/

I personally wouldn't get too bent out of shape replacing one element with another. I'd look at just swapping the attributes from one element to another. Remove the white-king class from one element and add it to another.

This is not the good way still, but you can try
(function() {
var from = null;
var $change =null;
var to = null;
$(".column" ).click(function(){
if(from === null)
{
$(this).css("background-color","yellow");
from = $(this).data('square');
$change= ($('<div/>').append($(this).clone(true).children()).html());
}
else
{
to = $(this).data('square');
$(this).html("").html($change);
$('div[data-square="'+from+'"]').html("<div class=lol>empty</div>").css("background-color","");
from = to = null;
}
});
}());​

Related

Html selector returns an html collection and I don't know how to get to the element I need to make changes on

I have 2 divs: 1 on the left half of the page (A), one on the right (B). When hovering over a certain element of the right section, I want something to be displayed over the left one.
I did this using the following approach:
<div className="A">
<div className="hidden-div1">DIV 1</div>
<div className="hidden-div2">DIV 2</div>
<div className="hidden-div3">DIV 3</div>
</div>
<div className="B">
<div className="base-div1">
<h2 onMouseOver={this.mouseOver} onMouseOut={this.mouseOut}>Project 1</h2>
</div>
</div>
mouseOver(e){
const hiddenDiv1 = document.querySelector(".hidden-div1");
hiddenDiv1.style.display = "block";
}
mouseOut(e){
const hiddenDiv1 = document.querySelector(".hidden-div1");
hiddenDiv1.style.display = "none";
}
Problem is, considering I have 3 different hidden-divs and 3 different base-divs, I wanted to make 2 universal mouseOver and mouseOut functions for all of them. The way I tried it, is this:
mouseOver(e){
let hiddenDivName = "hidden-div" + e.target.className.slice(-1);
let hiddenDivSelector = document.getElementsByClassName(hiddenDivName);
hiddenDivSelector.style.display = "block";
}
but it returns "Cannot set property 'display' of undefined".
I tried console logging hiddenDivSelector and it shows an HTML collection and I don't know how to get my element. I've tried reading about it and visiting other questions but I couldn't apply anything to my situation
Event target returns a reference to DOM element. On DOM elements we can use getAttribute method and replace all non-digit characters by ''; result may be used to search DOM and iterate over returned array;
mouseOver(e){
let hiddenDivName = "hidden-div" + e.target.getAttribute('class').replace(/\D/g, '');
let hiddenDivSelector = document.getElementsByClassName(hiddenDivName);
Array.from( hiddenDivSelector ).forEach(el => el.style.display ) = "block";
}

Creating a simple "Memory" card game. Need to allow only two clicks at a time

I am creating a simple Memory card game. I have the structure and card designs set up with CSS, now I just need to enable the actual playing of the game.
I need to have only two clicks allowed at a time. If the two cards match, the cards are removed. If the two cards don't match, they are "flipped" back over.
...I am only including the first row of the game, even though it is a 4x4 setup.
HTML
<div class="cardHolder">
<div id="card1" class="card" onClick="revealBlueCard()"></div>
<div id="card2" class="card" onClick="revealGreenCard()"></div>
<div id="card3" class="card" onClick="revealGreenCard()"></div>
<div id="card4" class="card" onClick="revealBlueCard()"></div>
</div>
JAVASCRIPT
// blue cards
var card1Ref = document.getElementById("card1");
var card4Ref = document.getElementById("card4");
card1Ref.addEventListener("click", revealBlueCard);
card4Ref.addEventListener("click", revealBlueCard);
function revealBlueCard(event){
event.target.style.backgroundColor = "#2155a8";
event.target.innerHTML = "<p>8</p>";
}
// green cards
var card2Ref = document.getElementById("card2");
var card3Ref = document.getElementById("card3");
card2Ref.addEventListener("click", revealGreenCard);
card3Ref.addEventListener("click", revealGreenCard);
function revealGreenCard(event){
event.target.style.backgroundColor = "#3cb260";
event.target.innerHTML = "<p>3</p>";
}
I am still very new to Javascript. I am assuming I am using a click event for "card" and applying if statements. I am also wondering if I need to apply data attributes to each card.
Why don't you add classes to the cards like blue class and green class.
CSS:
.blue{
background: #2155a8;
}
.green{
background: #3cb260
}
and also use event delegation (try to avoid adding event listeners to each card)
document.querySelector('#cardHolder').addEventListener('click', function(evt){
var clickedCard = evt.target;
if(clickedCard.classList.contains('blue'){
//do whatever for blue card
} else if(clickedCard.classList.contains('green')){
//do whatever for green card
}
});
there's a better way:
Use
onclick="cardClicked(this)"
for all your cards.
then in js
function cardClicked(elCard) {
if (elCard.classList.contains('flipped')) {
return;
}
// Flip it
elCard.classList.add('flipped');

Close and reopen HTML tags with jQuery

I'm pretty sure this isn't as easy as I wish, but looking for confirmation.
I want to replace an image with a closing div, the image, and the re-opened div.
Here is an example:
http://jsfiddle.net/fdCu5/1/
At the end of the day I want to take HTML that looks like this:
<div class="post">
<div class="constrained">
<p>Hello hello</p>
<img src="http://www.nicenicejpg.com/400/100">
<p>Some more text</p>
</div>
</div>
and make it look like this:
<div class="post">
<div class="constrained">
<p>Hello hello</p>
</div>
<img src="http://www.nicenicejpg.com/400/100">
<div class="constrained">
<p>Some more text</p>
</div>
</div>
Do I need to go up a level and work with it's parent?
http://jsfiddle.net/billymoon/fdCu5/4/
// get reference to the image
var img = $('img')
// get reference to the parent object
var parent = img.parent()
// clone and store parent (should have all same classes and attributes etc...)
var dolly = parent.clone()
// empty the clone
dolly.html("")
// move everything after the image into the clone
dolly.append(img.nextAll("*"))
// put the clone after the parent
parent.after(dolly)
// put the image after the parent (before the clone)
parent.after(img)
Advantage of keeping as objects when moving them round, as opposed to just copying as HTML, is that events should stay bound to the objects even after they are moved.
This method does not rely on prior knowledge of the outer container classes/attributes etc...
Try:
$('.constrained p').wrap('<div class="constrained" />').parent().unwrap();
jsFiddle example
The produces:
<div class="post">
<div class="constrained"><p>Hello hello</p></div>
<img src="http://www.nicenicejpg.com/400/100">
<div class="constrained"><p>Some more text</p></div>
</div>
Just to add another option, here's a merged solution of Billy Moon and j08691's answers. You can just modify the variables as needed to select the children you want to wrap - or you can hard-code it to condense your code.
var containerClass = '.constrained';
var childrenToWrap = '.constrained > *:not(img)';
var container = $(containerClass).clone().empty();
$(childrenToWrap).unwrap().wrap(container);
I figured out a solution that is pretty flexible:
/*
Wide Images
*/
$('img.size-wide').each(function(i,el){
// cache the element
var that = $(el);
// test to see if its a captioned image
if(that.parent().hasClass('wp-caption')) {
that = $(that.parent());
}
var parent = that.parent();
var parentHTML = parent[0].outerHTML;
var childHTML = that[0].outerHTML;
var newHTML = "</div>"; // close the .constrained div to break out
newHTML += childHTML;
newHTML += "<div class='constrained'>"; // open it back up again
parentHTML = parentHTML.replace(childHTML,newHTML);
parent.parent().html(parentHTML);
});

Javascript Loop Show hide elements in document (Jquery OK too)

I have a redundant process for making div's visible / hidden and I believe the way to make it more efficient is to use a loop.
Currently I have numerous div's through the document but there are 6 in particular that I want to deal with. I have a series of buttons that correspond to the six div's. When person clicks button A I want to show (make visible) div A and hide Div's B,C,D,E,F. My javascript is something like this:
<a href="#" onclick="ShowMe('A'); return false" />
<a href="#" onclick="ShowMe('B'); return false" />
<a href......etc />
<div id="A">blah...blah</div>
<div id="B">blah...blah</div>
<script type="java....">
function ShowHideDiv(DivName)
{
if(DivName == 'A')
{
var diva = document.getElementById('A');
div.style.visibility = 'visible';
var divb = document.getElementById('B');
div.style.visibility = 'hidden';
etc....
}
else if (DivName == 'B')
{
var diva = document.getElementById('A');
div.style.visibility = 'hidden';
var divb = document.getElementById('B');
div.style.visibility = 'visible';
etc...............
}
}
</script>
So as mentioned a prime candidate for loop but my question is how to contain the loop. For example if my loop went through the entire document object then I would have divs that I want visible being hidden so how do I avoid this?
I had two thought but was if others had additional thoughts, ideas, techniques etc.
Give my divs a really oddball prefix to their name like ShowHide_A then my loop can go through all the divs in the document object, parse it's name, if it doesn't have the prefix then move to the next one. This of course would be very inefficient if we had a large document and the script was getting every object and parsing then checking the name.
Wrap the div's in question in a parent container such as:
Then my javascript could be contained to looping through just the DivParent tree. But what if my div's are at different places in the document model? Do I keep them in the ParentDiv and position then where they belong with with css position properties?
Any other ideas would be greatly appreciated
JB
Let me suggest a better approach.
If you can use jQuery, you can do the following:
Assign a class (e.g. box) to all of your divs. Then your button needs to call this function:
function toggleDiv (divID) {
$(".box").hide();
$("#"+divID).show();
}
What you can also do is assign e.g. data-div attribute to your button which contains the ID of the div to hide/show, and then you can transform the above to the following (assuming your buttons have the button class):
$(".button").click(function () {
var divID = $(this).attr("data-div");
$(".box").hide();
$("#"+divID).show();
});
The above covers everything, assigning events to the buttons and hiding/showing divs.
see suppose you have markup like this
<div id="A" class="marked" >A</div>
<div id="B" class="marked" >B</div>
<div id="C" class="marked" >C</div>
<div id="D" class="marked" >D</div>
<div id="E" class="marked" >E</div>
<input type="button" value="Show A" data-target-div="A" />
<input type="button" value="Show B" data-target-div="B" />
then add a script like this:
$('input[type=button]').click(function(){
$('.marked').hide(200);
$('#'+$(this).data('target-div')).show();
});
it should work.
see this fiddle
so, you are not iterating through all the dom elements, you are picking exactly the ones you need to deal with. upon click, you hide all of them, and show the one which is target i.e. data-target-div
jQuery based solution:
Add a class to your div's that allow hiding/showing and then do
function ShowHideDiv(DivName)
{
$(".ShowHide").not("#" + DivName).hide();
$("#" + DivName).show();
}
Add class='switchable' (or whatever) to each such DIV then using prototype.js you could do something like this
function showMe( elem ) {
$$( '.switchable' ).each( function( switchable ) {
if ( switchable.id == $(elem).id )
switchable.show();
else
switchable.hide();
} );
}

How to continuously rotate children in a jQuery animation?

I have a div with class 'bannergroup' that contains multiple divs 'banneritem'. I want these items to rotate (fade in then fade out) in place of each other.
I can have several divs with the class bannergroup and each one should rotate separately.
Here is the HTML:
<div class="bannergroup">
<div class="banneritem">Only visible one at a time</div>
<div class="banneritem">Only visible one at a time</div>
<div class="banneritem">Only visible one at a time</div>
<div class="banneritem">Only visible one at a time</div>
</div>
<div class="bannergroup">
<div class="banneritem">Only visible one at a time</div>
<div class="banneritem">Only visible one at a time</div>
<div class="banneritem">Only visible one at a time</div>
<div class="banneritem">Only visible one at a time</div>
</div>
My Jquery looks like:
$('.banneritem').css('display', 'none');
$('.bannergroup').children('.banneritem').each(function( i ) {
$(this).fadeIn().delay(4000).fadeOut();
});
The problem: the each statement continues to run before the previous div completes. I want it to wait until the previous child is gone. Also, I need this to continuously run. After a single time it stops. I can put this into a function, but I am not sure how to know to call it again.
EDIT: There are not always 4 child items. Also one group may have a different number of children than the others, but they should both rotate in-sync. It is ok if one completes before the other and then just restarts itself.
I have answered this question multiple times before. This time I will try wrapping it in a jQuery plugin. The .rotate() function will apply the effect you want to the children of the matched elements, a fade in/out effect per children in a continuous animation.
$.fn.rotate = function(){
return this.each(function() {
/* Cache element's children */
var $children = $(this).children();
/* Current element to display */
var position = -1;
/* IIFE */
!function loop() {
/* Get next element's position.
* Restarting from first children after the last one.
*/
position = (position + 1) % $children.length;
/* Fade element */
$children.eq(position).fadeIn(1000).delay(1000).fadeOut(1000, loop);
}();
});
};
Usage:
$(function(){
$(".banneritem").hide();
$(".bannergroup").rotate();
});
See it here.
jsFiddle example
$('div.bannergroup').each(function () {
$('div.banneritem', this).not(':first').hide();
var thisDiv = this;
setInterval(function () {
var idx = $('div.banneritem', thisDiv).index($('div.banneritem', thisDiv).filter(':visible'));
$('div.banneritem:eq(' + idx + ')', thisDiv).fadeOut(function () {
idx++;
if (idx == ($('div.banneritem', thisDiv).length)) idx = 0;
$('div.banneritem', thisDiv).eq(idx).fadeIn();
});
}, 2000);
});
You can solve this problem in 2 ways. The one below is the easiest, using the index to increase the delay per item.
$('.banneritem').css('display', 'none');
$('.bannergroup').children('.banneritem').each(function( i ) {
$(this).delay(4000 * i)).fadeIn().delay(4000 * (i+1)).fadeOut();
});

Categories