Including a javascript function in a custom joomla module - javascript

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>

Related

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

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;
}
})

How to access an HTML element that is dynamically filled with values?

I've read lots of stackoverflow questions with no luck. My problem is, I have an HTML page in which I have
<select id="myid"></select>
and there, there's a Firebase command that retrieves names of values i need, and put it inside the <option> like HERE:
reference.on("child_added", function (childSnapshot){
var key = childSnapshot.key;
var opt = document.createElement('option');
opt.textContent = key;
document.getElementById('myid').appendChild(opt);
});
Now, i need to somehow access these values, that by the way are correctly appearing in both HTML and my site, however:
var val = document.getElementById('myid').value;
console.log(val);
It always returns blank in console. I don't know how else can I access it. Whenever I type those values in <option> by myself in HTML, everything works as it should and console returns the names that are in database.
#edit: as far as i tried to crack it, it seems to do with the fact that javascript cannot access elements, that for javascript itself aren't yet loaded, but i tried doing window.onload and other similar ones and they don't help.
You can use AngularJS, with directive $scope.watch, i will write a simple example of how to use and the link of documentation, if you have any question talk back to me!
function MyController($scope) {
$scope.myVar = 1;
$scope.$watch('myVar', function() {
alert('hey, myVar has changed!');
});
$scope.buttonClicked = function() {
$scope.myVar = 2; // This will trigger $watch expression to kick in
};
}
AngularJS Documentation
I hope help with this :)

How do I call this function in other parts of my code?

Pardon me if this is a very silly question. I'm brand new to JS and I was wondering how I can use this function in other parts of my code. I looked at tutorials and other websites, but the way they define functions seems to be different than what I have here. Could anyone please nudge me in the right direction?
$('.message_div').each(function message_function()
{
console.log("One liner");
var th = $(this);
var ih = $(this).outerHeight(); // outer height
var oh = $(this).find('.message').outerHeight();
console.log("Oh", oh);
var txt = $(this).find('.message').html();
console.log("Ih", ih);
if (oh > ih)
{
th.html('');
th.html('<marquee class="message" direction="up" scrollamount="1" scrolldelay="0">' + txt + '</marquee>')
}
});
//message_function(); -----> Is this the right way?
There are several intricacies here with regards to what jQuery does. The simple way of referencing this function later on would be to store it in a variable:
function message_function()
{
console.log("One liner");
var th = $(this);
//... (rest of function omitted for brevity)
}
$('.message_div').each(message_function);//note that the function handle is used here,
//and not the result of the function which would
//have used the () to call it
///and then later on
message_function();
However, the problem here is with this. jQuery will bind this behind the scenes (which means it works fine in each), however in order to properly call the message function separately, you would need to have an element ready to bind. For example,
var element = document.querySelector("div");
message_function.call(element);
alternatively:
var element = document.querySelector("div");
var elementMessage = message_function.bind(element);
elementMessage();
Here is a broader explanation of what this is, and how jQuery interacts with it: https://stackoverflow.com/a/28443915/1026459
Inside the same file :
Move that code inside a function
Call the function
Outside of that file :
Move the function (you just created) to a .js file
Include the .js file in the desired document
Make sure the DOM elements properties match what's in the script

How to load google recaptcha dynamically based on language?

I have an application where one of four languages (English,French,Dutch,español) needs to be selected in form.
The google reCaptcha comes below it.
I want to make it load dynamically on base of language selected. The recaptcha is based on script tag to which language should be passed
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit&hl=en" async defer></script>
All I need to do is just to change the last argument of script (hl=en) based on input and load the script dynamically. But i can't understand how to make it work.
Also the script should load again if the language is changed in dropdown above.
Is this any way possible for this to make work?
You can use grecaptcha.render() and pass in the language to change it to your liking.
Note that you have to remove the previous captcha element before calling render.
// your desired language
let captchaLang = 'de';
let captchaSiteKey = '...';
let captchaElemId = 'container';
let captchaCallback = (e) => {
document.querySelector('#' + captchaElemId).remove();
// deal with success
// ...
};
// create new elem based on old one, keeps the styling
// you could also just use document.createElement()
let old = document.querySelector('#' + captchaElemId);
let clone = old.cloneNode(false);
old.replaceWith(clone);
// render captcha with new language
grecaptcha.render(captchaElemId, {
sitekey: captchaSiteKey,
callback: captchaCallback,
hl: captchaLang
});

Getting an attribute from the same html file I am working on

I am creating a plugin for a template. After publishing the template to the web, there is an attribute inside an inserted script that I need to get its value and use it in my plugin.
Is there a way to do it with JS/jQuery?
Here is the part of the page in which the attribute is located:
Platform.Utils.initWidget('#skyline', function (elem) {
new Website.tool.Constantin(elem, {
event: 'click',
transitionDuration: 93000
});
});
I need to find a way to search the html and get the value for transitionDuration i.e 93000.
Additional comment:
This code is generated by the template and I have no control on changing how it is formed.
I inspected the html, and the template places the code as a JS code ( "the code" ) somewhere in the body.
So I assumed that there might be a way that the plugin that I am making could be able to read the html, find the attribute and use it to get the same transition duration that the html defines on its elements.
After re-reading and seeing your comments, I assume your template inserts
a script somewhere and you want to get at the transitionDuration with the plugin.
As in
var scripts = document.getElementsByTagName("script"), duration=0;
for (var i=0;i<scripts.length;i++) {
var text = scripts[i].textContent;
if (text.indexOf("transitionDuration") !=-1) {
duration = parseInt(text.split("transitionDuration:")[1],10);
break;
}
}
alert(duration);
<script>
Platform.Utils.initWidget('#skyline', function (elem) {
new Website.tool.Constantin(elem, {
event: 'click',
transitionDuration: 93000
});
});
</script>
You can get CSS values in javascript and jQuery but in this case, is better if you store the value in a variable.
var transDuration = 93000;
Platform.Utils.initWidget('#skyline', function (elem) {
new Website.tool.Constantin(elem, {
event: 'click',
transitionDuration: transDuration
});
});
alert(transDuration);
You can access to the transDuration variable when you need it.
If you need to read a CSS value, take a look at this:
Get a CSS value with JavaScript
Good luck

Categories