Event on node not calling the function when using the render function - mermaid

I'm trying to render dynamic charts and therefore need to use the mermaid.render function. But using click does not work when the code isn't entered in a static way as you can see in the snippet bellow:
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
mermaid.initialize({
theme: "base",
startOnLoad: false,
securityLevel: 'loose'
});
</script>
<p onclick="CreateGraph()">CreateGraph</p>
<div class="mermaid"></div>
<script>
var CreateGraph = function() {
var gdata = `
flowchart
a-->b
click a callback
`;
var div = document.getElementsByClassName("mermaid")[0];
mermaid.render("graphDiv", gdata, (svgCode, bindFunctions) => {
div.innerHTML = svgCode;
});
};
var callback = function() {
alert('A callback was triggered');
};
</script>
But if you were to put the content of gdata and put directly inside the mermaid div (as well as setting startOnLoad to true) then everything would work as expected.
Does anyone have a clue on what's happening or maybe a fix?
Thank you!

Alternative. Use href to include the function call in the parameter.
var gdata = `
flowchart
a-->b
click a href "javascript:callback();"
`;

For the click events to work, after updating the innerHTML of the element you must also set the bindFunctions.
element = document.querySelector('#some_id');
const insertSvg = function (svgCode, bindFunctions) {
element.innerHTML = svgCode;
bindFunctions(element);
};
const graphDefinition = 'graph TB\na-->b';
// Render the graph
const graph = await mermaid.mermaidAPI.render('graphDiv', graphDefinition, insertSvg);

Related

Call from one widget to another widget using odoo js

Js Xml Path : module_name-static-src-xml:
<div t-name="widget_1">
<button type="button" id = "button_1" >Click</button>
<div id = "test"> </div>
</div>
<div t-name="widget_2">
<p>Second Widget</p>
</div>
Js:
odoo.define("module_name.name", function(require) {
"use strict";
var Widget = require("web.Widget");
var Widget_Extend = Widget.extend({
template: "widget_1",
start: function() {
var self = this;
$(document).ready(function(){
setTimeout(function(){
$(document).on("click", "#button_1", function() {
var widget_call = '';
widget_call = '<div id ="test"></div>'
widget_call + = '<t t-call="widget_2"/>'
$('#test').html(widget_call);
});
});
});
}
});
core.action_registry.add("module_name.name", Widget_Extend);
});
Note:
I have tried to call "widget_2" using js but i could not get what i expect. I am not sure this the way to call the widget but i have tried a lot. If any one have some other way to call the 2nd widget from 1st widget using js kindly let me know.
Anticipating all kind of information about this problem.
Thanks.
you can inherited a widget to another widget As an example, it may look like this:
// in file a.js
odoo.define('module.A', function (require) {
"use strict";
var A = ...;
return A;
});
// in file b.js
odoo.define('module.B', function (require) {
"use strict";
var A = require('module.A');
var B = ...; // something that involves A
return B;
});

mithril.js issues with CKEditor

I've written this code using mithril.js + CKEditor
<body>
<script>
var frm = {};
frm.vm = (function () {
var vm = {};
vm.afterLoad = function () {
CKEDITOR.replace( 'editor1' );
};
vm.btnClick = function () {
console.log(document.getElementById('editor1').value);
};
return vm;
})();
frm.controller = function () {
};
frm.view = function (controller) {
return m("div", {config: frm.vm.afterLoad}, [
m("textarea", {id: "editor1"}),
m("button", {onclick: frm.vm.btnClick}, "Click here to see the text you've typed")
])
;
};
m.mount(document.body, frm);
</script>
</body>
but when I click the button, I see this error:
Uncaught The editor instance "editor1" is already attached to the provided element.
and console.log() prints a blank line.
What am I doing wrong?
I found the problem. To get the value of the CKEditor, one needs to use
CKEditor.instance.nameoftextarea.getData()

How add class to parent in CKEditor

I use simpleuploads plugin.
When images are uploaded i need add to parent of them a class.
This is HTML code wich is pasted after image upload process
<div><img src="link/to/image"><img src="link/to/image2"></div>
Now i need to add class to the 'div' element but i don't know how.
To remove height and width attributes of < img > elements i use this code:
<script>
CKEDITOR.on('instanceReady', function(e) {
e.editor.on( 'simpleuploads.finishedUpload' , function(ev)
{
var element = ev.data.element;
if (element.getName() == 'img')
{
var img = element.$;
img.removeAttribute('width');
img.removeAttribute('height');
ev.stop(); // Stop the event in case the listener is inserted twice
}
});
});
</script>
so will be great if someone can help me to add class using it.
This is the right code:
<script>
CKEDITOR.on('instanceReady', function(e) {
e.editor.on( 'simpleuploads.finishedUpload' , function(ev)
{
var element = ev.data.element;
if (element.getName() == 'img')
{
var img = element.$;
img.removeAttribute('width');
img.removeAttribute('height');
img.parentNode.setAttribute('class','classname');
ev.stop(); // Stop the event in case the listener is inserted twice
}
});
});
</script>

event click Handlebars

Using Handlebars and OpenDatabase i have small problem. When you click on a link and nothing happens
my JS.
db.transaction(function (tx) {
tx.executeSql('SELECT * FROM exhibition', [], function (tx, results) {
var source = document.querySelector("#exhibition-template").innerHTML;
var data = [];
template = Handlebars.compile(source);
for(var i=0;i < results.rows.length; i++) {
data.push(results.rows.item(i));
}
var context = (data);
if (language == 'pl')
{
var html = template({o:context,language_pl:true});
}else{
var html = template({o:context,language_en:true});
}
document.querySelector("#template").innerHTML = html;
}, null);
$(".exl").on("click", function(){
alert('event click!');
});
});
and my html
{{#each o}}
<a href='' class='exl'>{{name_pl}}</a>
{{/each}}
You're probably binding events before the generated DOM is appended to the page. So, you can either wait for Handlebars template to be rendered (In your case this mean binding event in the callback from tx.executeSql). Or you can use event delegation with jQuery:
$(document).on("click", ".exl", function(){
alert('event click!');
});

Can't get Isotope JS to work off the the height and width values of each image

I'm using the Isotope JS sort and arrange images and it's working fine apart from when the page loads the script doesn't run until all the images have loaded. On the Isotope JS help page it states providing the high and width values will give the script the information it needs to arrange the items without the images loading. I did this but the script is still only being triggered after all the images have loaded. I'm new to JS coding so I was trying to find what I had missed.
<script src="js/jquery.isotope.min.js"></script>
$(window).load(function(){
$('#container').isotope({
itemSelector : '.item'
});
});
var $container = $('#container');
$('.filters a').click(function(){
var selector = $(this).attr('data-filter');
$container.isotope({ filter: selector });
return false;
});
$('#options').find('.option-set a').click(function(){
var $this = $(this);
// don't proceed if already selected
if ( !$this.hasClass('selected') ) {
$this.parents('.option-set').find('.selected').removeClass('selected');
$this.addClass('selected');
}
});
$(window).load(function(){
$('#container').isotope({
itemSelector : '.item'
});
});
var $container = $('#container');
$('.filters a').click(function(){
var selector = $(this).attr('data-filter');
$container.isotope({ filter: selector });
return false;
});
$('#options').find('.option-set a').click(function(){
var $this = $(this);
// don't proceed if already selected
if ( !$this.hasClass('selected') ) {
$this.parents('.option-set').find('.selected').removeClass('selected');
$this.addClass('selected');
}
});
<script>
$(window).load(function(){
$('#container').isotope({
itemSelector : '.item'
});
});
var $container = $('#container');
$('.filters a').click(function(){
var selector = $(this).attr('data-filter');
$container.isotope({ filter: selector });
return false;
});
$('#options').find('.option-set a').click(function(){
var $this = $(this);
// don't proceed if already selected
if ( !$this.hasClass('selected') ) {
$this.parents('.option-set').find('.selected').removeClass('selected');
$this.addClass('selected');
}
});
Providing inline height and width is required but your code also runs only once the imagesLoaded plugin fires the load() event.
What you need to do is change your code to be triggered by jQuery's ready() function like this:
$(document).ready(handler)
instead of
$(window).load(handler)
You can see more about the imagesLoaded plugin included in Isotope here.
Plugin creator himself writes "This is because Isotope needs to know the exact width of an item before it lays out all the items" here Need help reversing a function; reverting an animated expansion of a div Maybe the images you're using are way too large or too plentiful or both? Had same issue when mistakingly linking to folder with original size images instead of their website equivalents.

Resources