button onclick="handle_clicks()" .. handle_clicks is not defined AND can i use (this) as a parameter in html element.onclick? - onclick

Can you inspect this code and find out why is it not working well?
there are two things i want to clarify..
Why is the function is not defined?
can i use (this)?
HTML:
In head:
<script src="script.js"></script>
In body:
<button type="button" onclick="handle_clicks(this)">button1</button>
<button type="button" onclick="handle_clicks(this)">button2</button>
JS:
window.onload = () => {
function handle_clicks(btn) {
btn.style.background = 'green';
console.log('A button was clicked');
}
}

Paste your script tag at end of body, and call js function like:
<button type="button" onclick="handle_clicks(event)">button1</button>
Now in JS use simple function without windows.onload
function handle_clicks($event) { // $ is used for events
const elm = $event.target
elm.style.background = 'green';
console.log('A button was clicked');
}

Related

JavaScript can't select DOM element by ID in WordPress

Is there a way for JavaScript to interact with the DOM on a WordPress page. Or is interaction only possible through jQuery?
Button element in header.php:
<div id="settings" class="special-menu__item btn-settings">
<button class="special-menu__title">
<i style="margin-right: 10px" class="fa fa-cog" aria-hidden="true"></i>
Настройки
</button>
</div>
JavaScript Code:
const settingButton = document.getElementById("settings");
let toggle = false;
settingButton.addEventListener("click", function _f() {
if (toggle === false) {
settingButton.classList.add("active");
settingOpen.classList.add("open");
} else {
settingButton.classList.remove("active");
settingOpen.classList.remove("open");
}
toggle = !toggle;
removeEventListener("click", _f);
});
I was having this issue too.
In the console, I could grab any element I wanted with getElementById or querySelector. But when I would select it in my custom JS code, it would be null.
To get around this, you can just add your code in a load event listener. This way, after the page loads, you can run your code and change the DOM element how you want.
It might not be the most functional thing to watch, but it works.
example:
window.addEventListener('load', () => {
const element = document.querySelector('#elementId');
console.log('element I selected:', element)
})

Document element null in template due to helper condition

This Meteor client code is expected to show a progress bar animation when a button is clicked. The problem is that the progress element is null when the animation code tries to use it.
How can it be fixed? thx
Template.registerHelper('session', (value) => {
return Session.get(value);
})
Template.footer.events({
'click button[data-action=carSearch]': function (e) {
e.preventDefault();
clickInfo();
}
});
'clickInfo': function () {
Session.set('inProgress', true); // makes the element visiable
progressBarStart(); // start the animation
}
'progressBarStart': function () {
let bar = document.getElementById('bar'); //<-- bar is always null
if (bar.value < 70) {
setTimeout(lib.progressBarStart(), 1000); controls the speed
bar.value += 1;
}
}
<template name="nameSearch">
<div id="nameSearch">
<p id="result" data-id={{_id}}>
{{{display.result}}} <br>
{{#if (session 'inProgress')}}
<progress id="bar" value="0" max="70"></progress>
{{/if}}
</p>
</div>
</template>
You should give the render a time to re-render after calling Session.set('inProgress', true);, 50ms will be enough.
Next, you should declare clickInfo and progressBarStart correctly, not like you have them now.
function clickInfo() {
Session.set('inProgress', true);
Meteor.setTimeout(progressBarStart, 50);
}
function progressBarStart() {
...
}
I'd also recommend to use dedicated helper to obtain inProgress status:
Template.footer.helpers({
isInProgress: function() {
return Session.equal('inProgress', true);
}
});
And use it in your template:
{{#if isInProgress}
...
{{/if}}
You must not use Session variables for such a small reason. Meteor JS has given a facility to use Reactive Variables at template level manipulations.
You should give the render a time to re-render after calling Template.instance().inProgress.set(true);.
I'd also recommend to use dedicated helper to obtain inProgress status:
Template.footer.onCreated(function(){
this.inProgress = new ReactiveVar(false);
});
Template.footer.helpers({
isInProgress: function() {
return Template.instance().inProgress.get();
}
});
And use it in your template:
{{#if isInProgress}
...
{{/if}}

How do I make Paper.js package for Meteor work in Meteor.js?

After doing: meteor add marcinn:paperjs.
It generates an error because Path is not defined (the paperjs Path() function in framePreview.js)
What is missing (paper.js is present in packages and package list file)
here is my test:
---tsite01.html (stands for test site 01)
<head>
<title>tsite01</title>
<!-- Load the Paper.js library-->
<script type="text/paperscript" src="papers/framePreview.js" canvas="framePreview"> </script>
</head>
<body>
<h1>Hello World!</h1>
{{> hello}}
<canvas id="framePreview" resize></canvas>
</body>
<template name="hello">
<button>Click here</button>
<p>You've pressed the bouton {{counter}} times.</p>
</template>
--- framePreview.js in papers subdirectory
var path=new Path();
path.strokeColor='black';
var start= new Point(100,100);
path.moveTo(start);
path.lineTo(start+[10,-50]);
-- tsite.js
if (Meteor.isClient) {
// counter starts at 0
Session.setDefault('counter', 0);
Template.hello.helpers({
counter: function () {
return Session.get('counter');
}
});
Template.hello.events({
'click button': function () {
// increment the counter when button is clicked
Session.set('counter', Session.get('counter') + 1);
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
To make paper.js work in Meteor, the paper function (which wraps the entire library) needs to be displayed in the window.
Let me know if this package helps you:
https://github.com/maddymaxey/Paperjs
To use it, make sure that everything is called with paper. E.g: new paper.Point instead of new Point.

Get values from two text-box and display sum of that on template in meteor.js

I'm trying to display sum value in template page using meteor.js.
Here is my html code:
<head>
<title>Sum</title>
</head>
<body>
<h1>Sum of two values</h1>
{{> sumForm}}
</body>
<template name="sumForm">
<form>
<input type="text" name="value1"> + <input type="text" name="value2"><p>Total: {{totalSum}}</p>
<input type="submit" value="Sum">
</form>
</template>
and my js code:
if(Meteor.isClient){
Template.sumForm.events({
'submit form': function(event){
event.preventDefault();
value1Var = parseInt(event.target.value1.value);
value2Var = parseInt(event.target.value2.value);
Template.sumForm.totalSum = value1Var + value2Var;
return Template.sumForm.totalSum;
}
});
}
But this does not work.
Can any one help?
You can user reactive-var to achive what you want
First you have to add the lightweight reactive-var package
meteor add reactive-var
Then at your Template file add:
if (Meteor.isClient) {
Template.sumForm.created = function () {
//We set default value
this.counter = new ReactiveVar(0);
}
Template.sumForm.helpers({
totalSum: function () {
return Template.instance().counter.get();
}
});
Template.sumForm.events({
'submit form': function(event, template){
event.preventDefault();
value1Var = parseInt(event.target.value1.value);
value2Var = parseInt(event.target.value2.value);
var sum = value1Var + value2Var;
return template.counter.set(sum);;
}
});
}
Template.sumForm.helpers({
totalSum: function(){
return Session.get("sum");
}
});
And at the end of your submit event
Session.set("sum", value1Var + value2Var);
For a cleaner solution also consider using reactive-var instead of session variables.

How to call a javascript function with Lift after clicking a button?

Here's my HTML code:
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string','Year');
data.addColumn('number','D1');
data.addColumn('number','D2');
data.addRows(2);
data.setValue(0,0,'1900');
data.setValue(1,0,'1910');
data.setValue(0,1,1);
data.setValue(1,1,2);
data.setValue(0,2,3);
data.setValue(1,2,1);
var options = {title: 'Tree Chart',
hAxis: {title: 'Time', titleTextStyle: {color: 'red'}},
pointSize: 5};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
function showChart(){
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
}
</script>
<form class="form-inline lift:form.ajax">
<div class="lift:DChart.render">
<button id="getChart" value="Get Chart" class="btn btn-inverse">Get Chart</button>
</div>
</form>
<div id="chart_div"></div>
the showChart() function displays the chart in chart_div
Here's my Lift code:
object DChart {
def render = {
def process():JsCmd = Run("showChart();")
"#getChart" #> SHtml.button("Get Chart", process)
}
}
Clicking on the button should execute the showChart() function.. sadly it doesn't work..
Please help me understand how to run the script function from lift!
SHtml.button takes as an argument () => Any so any JavaScript will not get returned to the browser and executed.
I would do one of two things:
Use SHtml.ajaxButton instead since the method body expects a JsCmd return
Bind the event instead, like: "#getChart [onclick]" #> SHtml.onEvent((str) => process())
Both do essentially the same thing and should get your code working. Option 1 will replace your entire HTML button with the one lift renders, Option 2 will just add the ajax to an onclick event on the existing HTML button.
I assume you'll be doing something more complicated, and actually want to make an ajax call - but if you just want to add the showChart() call clientside, you can simply say: "#getChart [onclick]" #> process().toJsCmd
I've figured out what was the problem.. I was calling the method showChart() but this method uses the google function setOnLoadCallback() so the chart could be displayed only if the method is called loading the page (from what I've understood so far).
The solution: just call the drawChart() method instead!
I've tryed every of the solution posted from jcern with the drawChart() method, all are working.
thx jcern :)

Resources