mxGraph: Click event from external button - javascript

Let's say, I have the following html document:
<div id="container" class="container">
// here comes the mxGraph
</div>
<div class="button-container">
<button id="myButton" type="button" name="button" onclick="myFunction()">Save</button>
</div>
</body>
Is there a way to catch the click-event of myButton in mxGraph?

Yes, you can catch event outside the mxgraph-div.
Do the following inside the jquery $(document).ready function:
Declare the graph has a global variable.
Create a function to load the graph inside the mx-graph div
Create the function for the external button click event.
Bind the function click event to the Step 3 Created function
Call the Step 2 function to load the mx-graph inside the div.
In the Step 3 function, you can access the graph object to trigger an xml save
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<ol class="breadcrumb">
<button id='genxml' class="btn btn-outline-success btn-sm m-2" onclick="this.blur();">
<span class="fas fa-fw fa-folder"></span> Download XML
</button>
</ol>
<div class="container">
<div class="row">
<div id="graphContainer" class="col-md-12" style="float:left;position:absolute;overflow:scroll;width:80%;height:80vh;cursor:default;outline:1px solid red">
</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function(){
var graph;
function downloadXML(){
// access the Graph object here to save the mxUtils
// Block of Code to get the mxGraph mxUtil in the function
// var node = encoder.encode(graph.getModel());
// mxUtils.popup(mxUtils.getPrettyXml(node), true);
}
function main(container){
// Block of Code to load a mxGraph in the Container
/* graph = new mxGraph(container);
graph.getModel().beginUpdate();
var v1 = graph.insertVertex(parent, 'r', req,req_grp_geo.x+30, req_grp_geo.y+40, 160, 40,'part_group');
var v2 = graph.insertVertex(parent, 'f', func,func_grp_geo.x+30, func_grp_geo.y+40, 160,40,'functional_group' );
graph.getModel().endUpdate();*/
}
$('#genxml').on('click', function(){
downloadXML();
});
main(document.getElementById('graphContainer'))
});
</script>

Related

JavaScript Removing Elements Dynamically! removeChild

Technology I am using is materialize and vanilla js. I've created a materialize button that opens a model. within the model is a form that takes user input, then places the input text onto the main page, when the Submit button is triggered. then I have a button that should remove/delete the input posted. So the issue I'm having is that the JavaScript linked to the button which should delete/removeChild isn't working. please help :)
// ----------------Models Materialize Framework----------------
document.addEventListener('DOMContentLoaded', () => {
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems);
});
//Delete From The Dom
const delExerciseBtn = document.querySelector('.del-exercise-btn');
delExerciseBtn.addEventListener('click', (e) => {
if(e.target.className == 'delete'){
const h6 = e.target.parentElement;
delExerciseBtn.removeChild(h6);
}
});
// Add User's To the Dom.
const addExerciseDom = document.querySelector('.exercise-dom');
const exerciseForm = document.querySelector('.exercises-form');
const disabledExersiceBtn = document.querySelector('.disabled-exersicebtn');
exerciseForm.addEventListener('submit', (e) => {
e.preventDefault();
// Get Input Value
const value = exerciseForm.querySelector('input[type="text"]').value;
// Create Elements
const h6 = document.createElement('h6');
// Add Content
h6.textContent = value;
// Append To Dom
addExerciseDom.appendChild(h6);
//Disable Btn
disabledExersiceBtn.setAttribute('disabled', 'disabled');
});
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<!-- Google icons -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet">
<!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<!-- Sytle.css -->
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<!----- user's input ------->
<div class="row">
<div class="col s12 center valign-wrapper center-align">
<div class=" exercise-dom delete"> <!--Users text input h6----> </div>
</div>
</div>
<!-- Btn/Modals/form -->
<div class="row">
<!-- Dom Btn -->
<div class="col s12 center ">
<a href="#exercise" class="btn-floating btn-small darken-4 z-depth-2 black center modal-trigger disabled-exersicebtn">
<i class="material-icons white-text">add </i>
</a>
</div>
<!-- Modal/form -->
<div class="modal modal-position" id="exercise">
<div class="modal-content">
<div class="row exercises-padding">
<form class="col s12 exercises-form" autocomplete="off">
<div class="input-field col s10">
<i class="material-icons prefix">fitness_center</i>
<input type="text" id="autocomplete-input" class="autocomplete center">
<label for="autocomplete-input" ><h6>Exercises</h6></label>
</div>
<div class="modal-footer">
<input class="modal-close btn black" type="submit" value="Submit">
</div>
</form>
</div>
</div>
</div>
<!-- Remove Users Btn -->
<div class="col s12 center remove-padding">
<a href="#" class="btn-floating btn-small darken-4 z-depth-2 black center modal-trigger del-exercise-btn">
<i class="material-icons white-text ">remove </i>
</a>
</div>
<!-- Compiled and minified JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<!-- app.JavaScript -->
<script src="app.js"></script>
</body>
</html>
Update:
you have a nesting error in your HTML, a </div> is missing, which is why the DOM doesn't contain the form
check the DOM with developer tools by inspecting elements, and you'll see that the structure is wrong
you can also use for example Codepen's "Analyze HTML" function in the HTML pane to check your HTML
the <form>'s class is Exercises-form, and the selector .exercises-form (from const exerciseForm = document.querySelector('.exercises-form');) therefore can't find the element, as CSS class names are case-sensitive. exerciseForm then becomes null, which causes the error Uncaught TypeError: Cannot read property 'addEventListener' of null
the delete button still doesn't work. I suggest to you try for yourself. Use the browser developer tools, especially the DOM element inspector and the console for interactive tests for your selector queries (and the element you select in the element inspector is accessible as $0 in the console.). There are many tutorials a Google search away.
Additional note: I oversaw that there's already an document.addEventListener('DOMContentLoaded', () => {... at the top of the file. You can put your code there, no need for another DOMContentLoaded event listener (although it doesn't hurt either).
Original answer:
You get
Uncaught TypeError: Cannot read property 'addEventListener' of null
that means that
const delExerciseBtn = document.querySelector('.del-exercise-btn');
couldn't find the node and returned null.
Probable reason: code runs too early, browser has not yet constructed the DOM.
Solution: wrap your code in a DOMContentLoaded event handler:
window.addEventListener('DOMContentLoaded', (event) => {
const delExerciseBtn = document.querySelector('.del-exercise-btn');
// ...
});
const h6 = e.target.parentElement;
delExerciseBtn.removeChild(h6);
You are trying to remove its parent from a button. And you need to remove the button from the parent.
const h6 = e.target.parentElement;
h6.removeChild(e.target);

Different values for innerHTML in debug and console log

I'm encountering a typical situation while accessing the innerHTML property using jQuery. I've fetched the target button using the jQuery attribute selector.
Below is the snippet of jQuery attribute selector.
jQuery('button[type="button"][class="btn btn-primary"]').each(function () {
var btn = jQuery(this);
console.log(btn);
if (btn[0].innerHTML === "OK") {
console.log("ok");
jQuery(this).click();
}
});
Following is the screenshot of the console log of the target button. It's innerHTML property is set to OK.
Following is the screenshot of the value of the innerHTML while debugging the target button object. In this case the value is "".
Ideally, the values of the innerHTML should be the same for both the cases.
EDIT
Why does this behavior differ that the ideal one? For both of the cases, the value of the innerHTML should be the same.
Also, there were multiple buttons. I have taken screenshots of different buttons. Thus their ID's are different. But still, the behavior is same.
Try something like this.
function SomeEvent($ele) {
alert($ele.html());
return false;
}
function invokeBtnEvents() {
$("[data-action=some-event]").off(); // clear old events
$("[data-action=some-event]").on("click", function() {
var $this = $(this);
return SomeEvent($this);
}) // define event(s)
return false;
}
$(document).ready(function() {
invokeBtnEvents();
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="col-12">
<br />
<button data-action="some-event" class="btn btn-primary">Button 1</button>
<button data-action="some-event" class="btn btn-primary">Button 2</button>
<button data-action="some-event" class="btn btn-primary">Button 3</button>
<button data-action="some-event" class="btn btn-primary">Button 4</button>
</div>
</div>
</div>
Your issue
What you are doing that I think is your main issue is the $.each() method.
Store the buttons in a variable,
let $button = $("button"); // this returns an array of all the buttons on the DOM
You can then use the $.each() method to get the clicked element
$.each($button, function(index, btn){
const $this = $(btn);
$this.off();
$this.click(function(){someEvent($this)});
});
I would not invoke button clicks like this because every time you click a button, this each loop gets ran. It will then send all of the buttons to that action unless you parse by an ID or something (you are using the innerText).
If you use the code in my snippet, only the clicked button will be triggered.
An alternative approach to my first snippet is using something like a dispatcher.
function DoActionOneClick($ele){
alert("Action 1 " + $ele.html());
}
function DoDefaultClick($ele){
alert("Default Action " + $ele.html());
}
function DispatchEvent(action, $ele){
switch(action){
case "some-event-1":
DoActionOneClick($ele);
break;
default:
DoDefaultClick($ele);
break;
}
}
function invokeActions(){
$("[data-action]").off();
$("[data-action]").on("click", function(){
// get this
var $this = $(this);
// get action
var action = $this.data().action;
DispatchEvent(action, $this);
});
}
$(document).ready(function(){
invokeActions();
})
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="col-12">
<br />
<button data-action="some-event-1" class="btn btn-primary">Button 1</button>
<button data-action="some-event-2" class="btn btn-primary">Button 2</button>
<button data-action="some-event-2" class="btn btn-primary">Button 3</button>
<button data-action="some-event-2" class="btn btn-primary">Button 4</button>
</div>
</div>
</div>

button, jquery and modals

I'm trying to understand modals and js better. I have tried to use buttons that are realated to php files in order to make the content of the php files appear in a modal window once the button is clicked.
so...
button_1 gets file_1 and puts it in modal once it is clicked.
button_2 gets file_2 and puts it in modal once it is clicked.
etc.
I have acheived most of this but for some reason, each button needs to be clicked twice (for the first appearence of the modal window) for the modal to work. Afterwards, a simple click works fine, until the page is refreshed. At that point, two clicks are again needed.
My code works fine if I don't try to insert the information from the php file into a modal window. So... I'm guessing it is releated to the fact that the button has to do two things. 1. get the info and 2. open the modal window.
How do I combine both in one click?
I have tried to prefech files.
<link rel="prefetch" href="/folders/to/php/files/1.php">
I have also tried to pre-insert the modal in the html .
I have tried to use the load instead of click in the function.
I my tries have not changed the fact that I need to double click the buttons at first.
Any help appreciated!!
BONUS:
If I could get the buttons to dynamically find their related file, that would be bonus. Meaning I could simply add or remove buttons and they would find the correct files. All I would need to do is to add as many files as buttons.
Thanks for your time and help!
Here are the codes:
$("#liste > button").on('click', apar);
function apar() {
$(this).addClass("active").siblings().removeClass("active");
$('#main_p').load("/folders/to/php/files/" + (1 + $(this).index()) + ".php");
$(document).ready(function() {
// Do something with the DOM
$('.active').click(function() {
});
});
}
function renderHTML(data) {
var htmlP = data.url;
$('#main_p').html(htmlP);
}
// On page load, click on the first `btn` to automatically load the data for it
$('#liste > button:first').click(renderHTML);
.btn {
margin: 5px;
padding 0px 5px;
text-align: center;
background-color: #0095ff;
color: #FFF;
border: none;
}
.btn:hover,
.btn:focus {
outline: none !important;
color: #FFF;
}
.active {
background-color: #891;
}
<!doctype html>
<html>
<head>
<title> Modals </title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div id="liste">
<button class="btn" data-toggle="modal" data-target="#myModal_1">
<div class="tree">to file 1</div>
</button>
<button class="btn" data-toggle="modal" data-target="#myModal_2">
<div class="tree">to file 2</div>
</button>
<button class="btn" data-toggle="modal" data-target="#myModal_3">
<div class="tree">to file 3</div>
</button>
<h4 id="main_tit"></h4>
<div class="main_p" id="main_p"></div>
<div id="main_ima"></div>
<script src="js/main.js" async></script>
</body>
</html>
here is the example of a 1.php file:
<div id="myModal_1" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Look 1</h4>
</div>
<div class="modal-body">
<?php
echo "I have the 1.php <br>";
echo "its a go!";
?>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
UPDATE: I have added the automatic selection on button. So I have removed the button attributes in the html and have added this at the top of the JS:
var idVar = $("#liste").find("button").each(function(index){
$(this).attr("data-target","#myModal_" + (1+$(this).index()));
$(this).attr("data-toggle","modal");
$(this).attr("class","btn");
});
At the top of your js file there is $("#liste > button").on('click', apar);
Try to change it to:
$('body').on('click', '#liste > button', apar);
And put it at the end of your code after your $('#liste > button:first').click(renderHTML);
Let me know if this doesn't fix it.
Edit: Try creating new custom class for those buttons in HTML. It is good to set a marker to your custom classes, something like l-custom-class, or customClass, try to follow this example:
HTML:
<div id="#liste">
<button type="button" class="l-liste-button">btn1</button>
<button type="button" class="l-liste-button">btn2</button>
<button type="button" class="l-liste-button">btn3</button>
</div>
JS:
function apar(){
//some code for apar function..
}
function renderHTML(){
//some code for renderHTML function
}
$('body').on('click', '.l-liste-button', apar);
$('body').on('click', '.l-liste-button:first', renderHTML);
Here is JSFiddle

Trying to make a button in JavaScript but it's not working

I'm new in JavaScript and I took an app here to learn how to use the language.
So, In my index.html I have this code here:
<div data-role="collapsible">
<h3>Reset Score</h3>
<button type="button" id="resetscore">Reset</button>
<script type="text/javascript">
function reset() {
localStorage.setItem('total_win', 0);
localStorage.setItem('total_lose', 0);
}
</script>
</div>
and this as footer:
`<div id="scores" class="ui-grid-b">
<div class="ui-block-a">Tries left:<span id="tries_left">4</span></div>
<div class="ui-block-b">Total win:<span id="total_win">0</span></div>
<div class="ui-block-c">Total lost:<span id="total_lose">0</span></div>
</div>`
What I'm basically trying to do is just reset the score to zero. But It's not working...
I tried to put some alert() inside reset() function but didn't work also.
Does someone has a clue why this is happening?
Thanks for helping!
Use onclick property:
<div data-role="collapsible">
<h3>Reset Score</h3>
<button type="button" id="resetscore" onclick="reset()">Reset</button>
<script type="text/javascript">
function reset() {
localStorage.setItem('total_win', 0);
localStorage.setItem('total_lose', 0);
}
</script>
</div>
You are declaring the function but not calling it anywhere. So you need to call the function at onclick event of button.
You should add an event listener for the click event.
Because of your comment, you can change the DOM by changing the inner HTML, see below snippet and code:
document.getElementById('resetscore').addEventListener('click',function() {
//localStorage.setItem('total_win', 0);
//localStorage.setItem('total_lose', 0);
document.getElementById('total_win').innerHTML = 0;
document.getElementById('total_lose').innerHTML = 0;
});
document.getElementById('win').addEventListener('click',function(){
var a = parseFloat(document.getElementById('total_win').innerHTML);
document.getElementById('total_win').innerHTML = (a+1).toFixed(0);
});
document.getElementById('loss').addEventListener('click',function(){
var b = parseFloat(document.getElementById('total_lose').innerHTML);
document.getElementById('total_lose').innerHTML = (b+1).toFixed(0);
});
<div data-role="collapsible">
<h3>Reset Score</h3>
<button type="button" id="resetscore">Reset</button>
<button type="button" id="win">+1 Win</button>
<button type="button" id="loss">+1 Loss</button>
</div>
<div id="scores" class="ui-grid-b">
<div class="ui-block-a">Tries left:<span id="tries_left">4</span></div>
<div class="ui-block-b">Total win:<span id="total_win">0</span></div>
<div class="ui-block-c">Total lost:<span id="total_lose">0</span></div>
</div>
your script tag can't be inside a div. You need to move all your javascript to the end of your body, right before its closing tag, after all the html
Just add this:
<button type="button" onclick="reset()" id="resetscore">
You need to tell which one of your functions to use, notice the onclick, it does just that, so reset executes on click
Your button needs to call reset
<button type="button" id="resetscore" onclick="reset()">Reset</button>

Adding list item using jQuery and Bootstrap

I had a simple to-do list app that worked fine, recently I overhauled the app using Bootstrap, before I wasnt using any css framework. Now the jQuery is not working properly... Why is this?
Here is the relevent HTML:
<div id="to-do">
<form class="form-inline">
<input class="form-control" type="text" id ="input" placeholder ="I need to...">
<button class="btn btn-primary" id ="add" type="submit">Add Item</button>
</form>
<ul id="list"></ul>
</div>
This is my Javascript code:
$(function() {
// configuration
// button
var add = $('#add');
// list container
var listContainer = $('#list');
// click event for button
add.on('click', function() {
// value of input
inputValue = $('#input').val();
// add new list item
listContainer.prepend('<li> ' + inputValue + '</li>');
// clear value input
$('#input').val('');
});
});
Mine works fine, does is what you needed to do ?
$(function() {
// configuration
// button
var add = $('#add');
// list container
var listContainer = $('#list');
// click event for button
add.on('click', function() {
event.preventDefault(); // stop default behaviour of submit button
// value of input
inputValue = $('#input').val();
// add new list item
listContainer.prepend('<li> ' + inputValue + '</li>');
// clear value input
$('#input').val('');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<div id="to-do">
<form class="form-inline">
<input class="form-control" type="text" id ="input" placeholder ="I need to...">
<button class="btn btn-primary" id ="add" type="submit">Add Item</button>
</form>
<ul id="list"></ul>
</div>

Categories