JavaScript: can't immediately select elements after creating them? - javascript

My script contains the following code that is causing me issues:
btn.addEventListener('click', ()=> {
if (!gamePlay) {
setup()
let word=document.querySelectorAll('box')
console.log(word)
btn.classList.toggle('hidden')
gamePlay=true
}
})
The reset of the code can be seen at this JS fiddle (don't mind the code commented out by the way): https://jsfiddle.net/apasric4/6k7anpvu/1/
After all the div elements are created in the function setup(), I am trying to select them by their class name (box) however the node list from the section is an empty node list (which is also shown in the console).
I am assuming the code is synchronous. I just can't seem to access the elements created by the call to setup().

You are able to access and query document elements immediately after they are created.
The issue here is that you selector syntax is incorrect; to select the elements with box class, prefix the selector with a ".":
btn.addEventListener('click', () => {
if (!gamePlay) {
setup();
let word = document.querySelectorAll('.box'); // Prefix .
console.log(word);
btn.classList.toggle('hidden');
gamePlay = true;
}
})

Related

How to test relative positioning of elements in cypress?

I am currently new to cypress and wants to test that Forgot Password should be below Login button in Facebook page? Is there a way to do that?
Is there a way to test relative positioning of elements in cypress?
I think you can use jQuery .position()
cy.get('#element1')
.then($el => $el.position().top) // get 1st top value
.then(top1 => {
cy.get('#element2')
.then($el => $el.position().top) // get 2nd top value
.then(top2 => {
expect(top1).to.be.gt(top2)
})
})
Notes
Cypress use jQuery to find elements. Chaining .then($el => ... exposes the jQuery object containing the element, so now you can apply other jQuery functions that are not part of the Cypress commands.
In fact, any other Javascript functions you want.
You can also make reusable functions
const getTop = ($el) = $el.position().top;
cy.get('#element1').then(getTop)
.then(top1 => {
cy.get('#element2').then(getTop)
.then(top2 => {
expect(top1).to.be.gt(top2)
})
})
You can use the cypress method next() to determine the element next to Log in button like this. next() gets the immediately following sibling of each DOM element within a set of DOM elements.
cy.get('div[type="submit"]').next().should('have.text', 'Forgot password?')

Including a javascript function in a custom joomla module

I have a working codepen that uses some javascript
https://codepen.io/cbold/pen/jOWONKO
I am struggling to understand the correct method/syntax for including the javascript function with my custom Joomla module.
I have read the official documentation but it does not make it any clearer for me
https://docs.joomla.org/J3.x:Adding_JavaScript_and_CSS_to_the_page
I have also looked at several other similar questions posted on Stackoverflow, but I do not understand any of the examples/answers enough to apply them to my module.
I have tried to include the function as a separate file, and invoke it with my mod_mymodule.php :
$document = JFactory::getDocument();
$document->addScript(JURI::root(true)."modules/mod_mymodule/js/ mod_mymodule.js");
This is the javascript in mod_mymodule.js:
function clickHandler(target) {
// Get the element that should be selected
const elem = document.querySelector(target);
// There were no elements to be selected
if (!elem) return;
// Get the old selected element (if any)
const prevElem = document.querySelector('.selected');
if (prevElem) {
// If there was a previously selected element, it isn't anymore
prevElem.classList.remove('selected');
}
// Make the new element selected
elem.classList.add('selected');
}
The function does not occur.
I have tried both document.querySelector(target); and document.querySelector('#target');
I have also tried including the function at the end of my module’s default.php
<script type="application/javascript">
function clickHandler(target) {
// Get the element that should be selected
const elem = document.querySelector(target);
// There were no elements to be selected
if (!elem) return;
// Get the old selected element (if any)
const prevElem = document.querySelector('.selected');
if (prevElem) {
// If there was a previously selected element, it isn't anymore
prevElem.classList.remove('selected');
}
// Make the new element selected
elem.classList.add('selected');
}
</script>
But no luck.
Again I have tried both document.querySelector(target); and document.querySelector('#target');
I am pretty certain my <script> is wrong, but I don’t know enough about javascript – specifically the proper syntax required by Joomla – in order to make it work directly from my module.php.
Any help is greatly appreciated.
This ended up working for my needs, a short script in the module's default.php
<script>
jQuery('.target').click(function(){
var id = jQuery(this).attr('id');
jQuery('body').find('.selected').removeClass('selected');
jQuery('#target'+id).addClass('selected');
});
</script>

Check if element exist JEST tests

I'm trying to test if sgn.init() after call, generate and append element to DOM. However document.querySelector('.class') seems to always return null, even if I tried to add it manually in test function. Can you tell me what I'm doing wrong?
test('shoud be rendered', () => {
sgn.init();
const element = document.createElement('div');
element.classList.add('.element');
document.body.appendChild(element);
console.log(document.querySelector('.element'))
});
You have given the div a class of .element. Meaning that your class name contains a dot.
Try with classList.add('element')
The dot is only needed when searching, not creating.

Add additional result statement to jquery

I have the following script which is working nicely to hide a DIV when its child is empty:
jQuery(".field-items").filter(function() {
return !$.trim(this.innerHTML);
}).parent().parent().parent().parent().parent().parent().hide();
If that same DIV is empty from above I also want to hide another DIV on the same page. It's not a parent.
How can I add the following code to the above code? So that both occur when that specific DIV is empty?
$('#survey-monkey-title').hide();
var $empty = jQuery(".field-items").filter(function() {
return !$.trim(this.innerHTML);
});
if ($empty.length) {
$empty.parent().parent().parent().parent().parent().parent().hide();
$('#survey-monkey-title').hide();
}
I'd also like to give Brian Giaz his propers for utilizing .add() below:
$empty.parent().parent().parent().parent().parent().parent().add('#survey-monkey-title').hide();
You can use the add() function to add additional elements to the jquery object:
$('#elem').parent().add('#otherElem').hide();
for example.
I know you already got it working, but consider updating the stringed parent() calls to just a single parentUntil function.
var $empty = jQuery(".field-items").filter(function() {
return !$.trim(this.innerHTML);
});
if ($empty.length) {
$empty.parentsUntil('.someSelector').hide();
$('#survey-monkey-title').hide();
}

Creating a reusable jQuery function

Instead of re-writing a massive block of code each time, I'm trying to incorporate functions into my work but I'm having trouble making it work.
Basically, I've got a selection of radio buttons and I'm performing some stuff each time a radio button is clicked. (I'm actually loading an iFrame). However, I need to make the iFrame SRC different for each radio button so how would I cater for this within the function?
The function:
jQuery.fn.switchPreview = function () {
$('.liveDemoFrame').remove();
$('.liveDemoHand').append('<iframe class="liveDemoFrame" src="themes/src/' + themeName + '/" width="100%" height="300" scrolling="no"><p>Your browser does not support iframes.</p></iframe>');
$('.liveDemoHand').append('<div class="switchPreview"><div class="loadingPreview"></div></div>');
$('.liveDemoFrame').load(function() {
$('.switchPreview').fadeOut();
$('.switchPreview').remove();
$('.liveDemoFrame').fadeIn();
});
return this;
}
Within the iFrame SRC I have a variable called themeName. I need this to somehow change for each radio button. You can see within the code that calls the function I've tried to declare the variable each time but this still gives me an undefined error.
The code that calls it:
$('#cTheme1').click(function () {
$('input:radio[name=mgChooseTheme]:nth(1)').attr('checked',true);
var themeName = 'theme1';
$('.liveDemoFrame').switchPreview();
});
$('#cTheme2').click(function () {
$('input:radio[name=mgChooseTheme]:nth(2)').attr('checked',true);
var themeName = 'theme2';
$('.liveDemoFrame').switchPreview();
});
$('#cTheme3').click(function () {
$('input:radio[name=mgChooseTheme]:nth(3)').attr('checked',true);
var themeName = 'theme3';
$('.liveDemoFrame').switchPreview();
});
I'm sure this is something very simple but I'm still learning so little things always throw me off!
Pass in the themeName as an argument of the switchPreview function.
-Change the first line of the function to:
jQuery.fn.switchPreview = function (themeName) {
-For each of the three times you are calling the function, make sure you are passing in the argument, i.e:
$('.liveDemoFrame').switchPreview(themeName);
Why not just update the src tag of the iframe ...
$('#cTheme1').click(function () {
$('input:radio[name=mgChooseTheme]:nth(1)').attr('checked',true);
$('#liveDemoFrame').attr('src', <the new url>);
});
Then your iframe would already need to be part of the page :
<iframe id='liveDemoFrame' src='<default page>'></iframe>
i notice your using a CLASS attribute on your iFrame and accessing it using that - you really need to think about using the ID attribute if you are just wanting to refer to a single object. (as in my example above)

Categories