Dojo parser changes button id - dojo

I have the following code, straight from the tutorial:
<!DOCTYPE HTML>
<head>
<link rel="stylesheet" href="js/dijit/themes/claro/claro.css" />
<script src="js/dojo/dojo.js" data-dojo-config="async: 1, parseOnLoad: 1"></script>
<script>
require(["dojo/_base/fx", "dojo/on", "dojo/dom", "dojo/parser", "dojo/domReady!"], function(fx, on, dom, parser)
{
var fadeOutButton = dom.byId("fadeOutButton"),
fadeInButton = dom.byId("fadeInButton"),
fadeTarget = dom.byId("fadeTarget");
on(fadeOutButton, "click", function(evt)
{
fx.fadeOut({ node: fadeTarget }).play();
});
on(fadeInButton, "click", function(evt)
{
fx.fadeIn({ node: fadeTarget }).play();
});
});
</script>
</head>
<body class="claro">
<button data-dojo-type="dijit/form/Button" type="button" id="fadeOutButton">Fade block out</button>
<button data-dojo-type="dijit/form/Button" type="button" id="fadeInButton">Fade block in</button>
<div id="fadeTarget" style="background: red; height: 256px">
A red block
</div>
</body>
</html>
My goal is to have Dojo style the buttons. As far as I can see, this is done by the parser. The problem with this is that the parser will change the id of the button elements and therefore the events will not be triggered. If I remove dojo/parser from require or change parseOnLoad to 0, the buttons work, but they are not style. With the code above, buttons are styled but do not work. Is it possible to have both?

I think I figured it out -- I have to use registry.byId instead of dom.byId

Related

Leaflet map not loading in Bulma tab using Vue.js

I have an issue with loading Leaflet map using Vue.js and Bulma tab components (via Buefy).
If map is placed inside tab then it does not load all tiles until browser window is resized.
If map is placed outside of Bulma tabs component then it loads without any issue.
Calling map.invalidateSize() seems to help, but to do it automatically when tab changes I have to call it using setTimeout and put very big delay, like 1sec - which is very ugly.
How to get this working without this invalidateSize workaround?
Example with the issue: https://codepen.io/alxxnder/pen/zyYxwd
Example without the issue: https://codepen.io/alxxnder/pen/LMYEjr
Code:
new Vue({
el: '#app',
data: {
map: null,
},
methods: {
invalidateSize: function() {
this.map.invalidateSize();
}
},
mounted() {
this.map = L.map('map').setView([38.63, -90.23], 12);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(this.map);
}
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Leaflet Test</title>
<link rel="stylesheet" href="https://unpkg.com/buefy#0.7/dist/buefy.min.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.4/dist/leaflet.css">
</head>
<body>
<div class="section">
<div class="container" id="app">
<b-tabs position="is-centered">
<b-tab-item label="Tab 1">
<div class="section">
Tab 1
<div class="map" id="map" style="height: 400px; width: 100%"></div>
<button class="button is-info" #click="invalidateSize()">invalidateSize</button>
</div>
</b-tab-item>
<b-tab-item label="Tab 2">
<div class="section">
Tab 2
</div>
</b-tab-item>
</b-tabs>
</div>
</div>
</body>
<script src="https://unpkg.com/vue#2"></script>
<script src="https://unpkg.com/buefy#0.7/dist/buefy.min.js"></script>
<script src="https://unpkg.com/leaflet#1.3.4/dist/leaflet.js"></script>
</html>
As explained in Data-toggle tab does not download Leaflet map, the issue is caused by the fact that your map container does not have yet its full size when you initialize it. You may understand it more easily if your map had been in an initially hidden tab (e.g. in tab 2).
As for your initially active tab (i.e. tab 1), it is probable that Buefy / Bulma still takes some time to reveal the tab content.
Since there is no event when the tab transition completes, you have to wait for the transition duration before calling the invalidateSize method. In your case, 300ms seems to be fine.
Then you should also call it again when the user changes the tab (see Buefy tabs events), otherwise should the browser had changed size while your tab was hidden, the same issue would happen again.
Demo with maps in the 2 tabs:
new Vue({
el: '#app',
data: {
map: null,
map2: null,
tabMaps: []
},
methods: {
invalidateSize: function(tabIndex) {
setTimeout(() => {
if (typeof tabIndex === "number") {
this.tabMaps[tabIndex].invalidateSize();
} else {
// invalidate all maps
this.tabMaps.forEach(map => {
map.invalidateSize();
});
}
}, 300);
}
},
mounted() {
this.map = L.map('map').setView([38.63, -90.23], 12);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(this.map);
// map2 in tab2
this.map2 = L.map(this.$refs.map2).setView([38.63, -90.23], 12);
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png").addTo(
this.map2
);
this.tabMaps.push(this.map); // 0
this.tabMaps.push(this.map2); // 1
this.invalidateSize();
}
})
<link rel="stylesheet" href="https://unpkg.com/buefy#0.7/dist/buefy.min.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.4/dist/leaflet.css">
<div class="section">
<div class="container" id="app">
<b-tabs #change="invalidateSize" position="is-centered">
<b-tab-item label="Tab 1">
<div class="section">
Tab 1
<div class="map" id="map" style="height: 400px; width: 100%"></div>
<button class="button is-info" #click="invalidateSize()">invalidateSize</button>
</div>
</b-tab-item>
<b-tab-item label="Tab 2">
<div class="section">
Tab 2
<div class="map" ref="map2" style="height: 400px; width: 100%"></div>
</div>
</b-tab-item>
</b-tabs>
</div>
</div>
<script src="https://unpkg.com/vue#2"></script>
<script src="https://unpkg.com/buefy#0.7/dist/buefy.min.js"></script>
<script src="https://unpkg.com/leaflet#1.3.4/dist/leaflet.js"></script>

jqwidgets: initiating button inside window

I have a problem when initiating jqxButton inside jqxWindow:
Expected: When I click Add button, the Confirm button caption will be set to "Add", otherwise when I click Edit button.
Problem: The Confirm button caption is set to proper button at the first time I clicked, but then the caption will not changed.
Note: The problem raised if i set window property autoOpen: false.
This problem raised when I use jQWidgets V5.1.0.
When I use jQWidgets v4.3.0, this problem does not happen.
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="description" content="" />
<title></title>
<link rel="stylesheet" href="../../jqwidgets/styles/jqx.base.css" type="text/css" />
<script type="text/javascript" src="../../scripts/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxcore.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxwindow.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxbuttons.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxscrollbar.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxpanel.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxtabs.js"></script>
<script type="text/javascript" src="../../jqwidgets/jqxcheckbox.js"></script>
<script type="text/javascript" src="../../scripts/demos.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('#btnAdd').click(function () {
$('#window').jqxWindow('open');
$("#confirm").jqxButton({ value: "Add" });
});
$('#btnEdit').click(function () {
$('#window').jqxWindow('open');
$("#confirm").jqxButton({ value: "Edit" });
});
var jqxWidget = $('#jqxWidget');
var offset = jqxWidget.offset();
$('#window').jqxWindow({
autoOpen: false,
minWidth: 200,
height: 300,
width: 500,
initContent: function ()
{
$("#confirm").jqxButton();
}
});
});
</script>
</head>
<body class='default'>
<div id="jqxWidget">
<div style="float: left;">
<div>
<input type="button" value="Add" id="btnAdd" />
<input type="button" value="Edit" id="btnEdit" />
</div>
</div>
<div id="mainDemoContainer">
<div id="window">
<div id="windowContent">
<input type="button" id="confirm" />
</div>
</div>
</div>
</div>
</body>
</html>
This comes late of course, but does the change in the caption have to occur through the jqxButtons properties only? After testing your code I came to following:
$('#btnAdd').click(function () {
$('#window').jqxWindow('open');
$("#confirm").attr('value', "Add"); // Works !
//$("#confirm").jqxButton('val', "New Value"); // Does not work the first time only
//$('#confirm').jqxButton({ value: "Button" }); // uncaught exception: Invalid property: value
});
$('#btnEdit').click(function () {
$('#window').jqxWindow('open');
$("#confirm").attr('value', 'Edit');
});
May this answer help others who meet this issue.

Why onClick event not work on dojo MenuItem?

I'm studying Dojo 1.10.4, my problem is that the onClick event does not work on dijit/MenuItem. I tried it on other item widgets like dijit/CheckedMenuItem and dijit/RadioMenuItem, none of their click events work, and the API docs didn't give any tips about it.
At last, I found it only works if it's contained in dijit/MenuBar. Should Item widgets be contained in dijit/MenuBar or dijit/Menu? How are the events processed on dojo widgets?
For example:
<html>
<head>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dijit/themes/claro/claro.css">
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"
data-dojo-config="async:true,parseOnLoad: true"></script>
<script>
require(["dojo/parser"],function(parser){
parser.parse();
});
</script>
</head>
<body class="claro">
<div data-dojo-type="dijit/MenuBar" >
<div data-dojo-type="dijit/MenuItem" onclick="alert();">it works</div>
</div>
<div data-dojo-type="dijit/MenuItem" onclick="alert();">it doesn't work</div>
</body>
</html>
In this case MenuItem needs a ContainerWidget like Menu or MenuBar. You add the Item as a child like :
require([
"dojo/dom",
"dijit/MenuItem",
"dijit/DropDownMenu",
"dijit/form/DropDownButton"
],
function(dom,MenuItem,DropDownMenu,DropDownButton){
var myMenu = new DropDownMenu();
var menuItem1 = new MenuItem({
id:"M1",
label:"Show M1",
onClick:function(){
//do what you want to do here
}
});
myMenu.addChild(menuItem1);
});
Studying this might help you too to understand how it works.
http://dojotoolkit.org/reference-guide/1.10/dijit/DropDownMenu.html#dijit-dropdownmenu
Regards

Using Dojo TabContainer With Dojox.mvc

I am trying to use dijit/layout/TabContainer with dojox/mvc/Repeat. It seems that as the indivdual tab panes (contentPanes) are not immediate children of the tab container it does not render them as tabs. I end up with three content panes but no tabs.
I have created a paste bin which shows the issue. I have included a text box which binds to the stateful model to show that the scope is correct on the repeater.
http://jsbin.com/tufuzini/1/edit?html,output
Has anyone experienced this or have an alternative?
dojox/mvc/Repeat is a deprecated module as it has been take over by dojox/mvc/WidgetList. It'll allow you to place multiple occurrence of a template widget as immediate child of another widget, for example, dijit/layout/TabContainer. Here's an example:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/dojo/1.9.2/dojo/dojo.js" data-dojo-config="parseOnLoad: 0, async: 1"></script>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/dojo/1.9.2/dojo/resources/dojo.css">
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/dojo/1.9.2/dijit/themes/claro/claro.css">
<script>
require([
"dojo/_base/declare",
"dojo/aspect",
"dojo/parser",
"dojox/mvc/getStateful",
"dojox/mvc/Templated",
"dojox/mvc/WidgetList",
"dijit/layout/TabContainer",
"dojox/mvc/Element",
"dojo/domReady!"
], function(declare, aspect, parser, getStateful, Templated, WidgetList){
tabRecords = getStateful({
items: [
{first: "Anne", last: "Ackerman"},
{first: "Ben", last: "Beckham"},
{first: "Chad", last: "Chapman"}
]
});
declare("my.Templated", Templated, {
templateString: document.getElementById("innerTemplate").innerHTML
});
parser.parse();
});
</script>
<script id="innerTemplate" type="dojox/mvc/InlineTemplate">
<div>
<div>First: <input type="text" data-dojo-type="dojox/mvc/Element" data-dojo-props="value: at('rel:', 'first')"></div>
<div>Last: <input type="text" data-dojo-type="dojox/mvc/Element" data-dojo-props="value: at('rel:', 'last')"></div>
</div>
</script>
</head>
<body class="claro">
<script type="dojo/require">at: "dojox/mvc/at"</script>
<div data-dojo-type="dijit/layout/TabContainer"
data-dojo-mixins="dojox/mvc/WidgetList"
data-dojo-props="partialRebuild: 1, children: at(tabRecords, 'items')"
data-mvc-child-type="my.Templated"
data-mvc-child-props="title: at(this.target, 'first')">
</div>
</body>
</html>
Best,
Akira

Cannot get a reference to a dijit form when the form has a DateTextBox

I am having trouble getting a reference to the dijit form widget when the form contains a DateTextBox. The code snippet below demonstrates the problem. When executed, the alert box says "undefined". However, if I get rid of <input ... id="dateTextBox"... />, I am able to get a reference to the form widget.
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="//ajax.googleapis.com/ajax/libs/dojo/1.9.1/dijit/themes/claro/claro.css" media="screen">
<!-- load dojo and provide config via data attribute -->
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/dojo/1.9.1/dojo/dojo.js"
data-dojo-config="async: true, parseOnLoad: true">
</script>
<script type="text/javascript">
require(["dijit/form/TextBox", "dijit/form/DateTextBox"]);
</script>
<script type="text/javascript">
require(["dojo/parser", "dijit/registry", "dijit/form/Form", "dojo/domReady!"],
function(parser, registry) {
parser.parse();
alert(registry.byId("frm_test"));
});
</script>
</head>
<body class="claro">
<div data-dojo-type="dijit/form/Form" id="frm_test" encType="multipart/form-data" action="" method="">
<input type="text" id="textBox" name="textBox" data-dojo-type="dijit/form/TextBox" />
<input type="text" id="dateTextBox" name="dateTextBox" data-dojo-type="dijit/form/DateTextBox" />
</div>
</body>
</html>
I'd recommend wrapping the registry.byId into a ready call.
Keep parse onLoad: true, remove
require(["dijit/form/TextBox", "dijit/form/DateTextBox"]);
as the parser will auto require (when dojo>= 1.8) and use the following:
<script type="text/javascript">
require(["dojo/ready", "dijit/registry", "dojo/domReady!"],
function(ready, registry) {
// by default the prioirty of this ready call will be after the
// ready call used to parse when parseOnLoad is true
ready(function() {
alert(registry.byId("frm_test"));
});
});
</script>
Note that waiting for dojo/domReady! to fire is often not sufficient
when working with widgets. Many widgets shouldn’t be initialized or
accessed until the following modules load and execute:
dojo/uacss
dijit/hccss
dojo/parser
Thus when working with widgets you should generally put your code
inside of a dojo/ready() callback
http://dojotoolkit.org/reference-guide/1.9/dojo/domReady.html
http://dojotoolkit.org/reference-guide/1.9/dojo/ready.html#dojo-ready