Get Id of TitlePane programatically defined to show/hide - javascript

I am very new to Dojo and this is what I am trying to do. I have a titlepane which is programatically declared using the code below:
var pane = this._createTitlePane(config.widgets.title, config.widgets.position,
config.widgets.open);
_createTitlePane: function (title, position, open, optclass) {
var tp = new TitlePane({
title: title,
open: open
}).placeAt(this.sidebar, position);
domClass.add(tp.domNode, 'titlePaneBottomFix titlePaneRightFix');
if (optclass) {
domClass.add(tp.domNode, optclass);
}
tp.startup();
return tp;
},
Later I am trying to hide this title pane when a button is clicked using esri.hide. My question is how do I get a reference to this title pane? There's no Id when it is defined.
When I look in the chrome debugger, I see the below line highlights the widget
<div class="titlePaneBottomFix titlePaneRightFix dijitTitlePane" title="" role="group" id="dijit_TitlePane_1" widgetid="dijit_TitlePane_1">
If I try to do something like esri.hide(dojo.byId("dijit_TitlePane_1")), then it hides the widget. But can I refer to the title pane using this widget Id?

You may want to just give the title pane its own id in the function:
_createTitlePane: function (title, position, open, optclass, paneId) {
var tp = new TitlePane({
title: title,
id: paneId, // TitlePane id here
open: open
}).placeAt(this.sidebar, position);
domClass.add(tp.domNode, 'titlePaneBottomFix titlePaneRightFix');
if (optclass) {
domClass.add(tp.domNode, optclass);
}
tp.startup();
return tp;
}
Then you can refer to it with and hide it with:
esri.hide(dijit.byId("theIdYouGaveIt").domNode);
To understand the difference between dojo.byId and dijit.byId, this link may help.

Also, if you're creating this in your own custom widget, you can also make the title pane a local reference, ie: this.tp = new TitlePane({...}). Anywhere you need to access it from inside the widget, you can simply call "this.tp". Outside of the widget, you can access it using dot notataion: myWidget.tp.doSomething(). Better yet, if you create it declaratively in a template like this: <div data-dojo-type=dijit/TitlePane" data-dojo-attach-point="tp" ...></div>, when the widget is instantiated it will automatically have a handle to "this.tp" via the attach point.

Related

How to extend Leaflet Icon Class to add data-open attribute to marker HTML?

I'm trying to trigger some functionality based on the click of a marker on a GeoJSON layer in Leaflet. The eventual functionality I'm trying to implement is a flyout, or scroll out type modal populated from the individual feature's JSON attributes. Essentially, I'm trying to implement the functionality in this Tutsplus Tutorial with dynamic feature content based on the marker click.
I THINK I've figured out most of the pieces I need, but I'm struggling with how to add a data attribute, specifically data-open, to the individual marker. Building on an earlier question of mine I've realized it's not enough to just update a DOM element's CSS, but rather my app should be implementing changes based on data attributes to fully get the functionality I want.
From this question I know that this should be done by extending the L.Icon class that Leaflet provides, but the answer is a bit too terse for my current JS skills. I apologize for this effectively being a "ELI5" of a previously asked question, but I'm not sure where the options and slug come into function. I think they're implied by the question, rather than the answer I'm citing and being set on the marker itself.
Here's a simplified version of the the click handler on my markers, which grabs and zooms to location, gets feature info, and populates that info to a div. The zoom functionality works, as does extracting and placing the feature info, but I'm struggling with how to connect the functionality to trigger the modal and place the div with the feature info over the map.
function zoomToFeature(e) {
var latLngs = [e.target.getLatLng()];
var markerBounds = L.latLngBounds(latLngs);
var street = e.target.feature.properties.str_addr;
document.getElementById('street').textContent = street;
mymap.fitBounds(markerBounds);
//where the modal trigger should be
document.getElementById('infoBox').classList.add('is-visible');
}
Here are the event listeners taken from the linked tutorial, which are currently not firing, but I have them working in a standalone implementation:
const openEls = document.querySelectorAll("[data-open]");
const closeEls = document.querySelectorAll("[data-close]");
const isVisible = "is-visible";
//this is the event I want to trigger on marker click
for (const el of openEls) {
el.addEventListener("click", function() {
const modalId = this.dataset.open;
console.log(this);
document.getElementById(modalId).classList.add(isVisible);
});
}
for (const el of closeEls) {
el.addEventListener("click", function() {
this.parentElement.parentElement.parentElement.classList.remove(isVisible);
});
}
document.addEventListener("click", e => {
if (e.target == document.querySelector(".modal.is-visible")) {
document.querySelector(".modal.is-visible").classList.remove(isVisible);
}
});
So, where I'm trying to get is that when my markers are clicked, the trigger the modal to appear over the map. So, I think I'm missing connecting the marker click event with the event that triggers the modal. I think what's missing is adding the data attribute to the markers, or some way chain the events without the data attributes. As there's no direct way to add an attribute to the markers, I try to add slug option on my circle markers:
var circleMarkerOptions = {
radius: 2,
weight: 1,
opacity: 1,
fillOpacity: 0.8,
slug: 'open',
}
and If I read the previously asked question's answer correctly, than extending the Icon Class this way should add a data-open attribute.
L.Icon.DataMarkup = L.Icon.extend({
_setIconStyles: function(img, name) {
L.Icon.prototype._setIconStyles.call(this, img, name);
if (options.slug) {
img.dataset.slug = options.slug;
}
}
});
A stripped down version of my code is here (thanks #ghybs). My full implementation pulls the markers from a PostGIS table. It's a bit hard to see in the Plunker, but this code adds my class to my modal, but doesn't trigger the functionality. It does trigger the visibility if the class is manually updated to modal.is-visible, but the current implementation which renders modal is-visbile doesn't, which I think is because the CSS is interpreted on page load(?) and not in response to the update via the dev tools, while the concatenated css class matches extactly(?). When I do trigger the modal via the dev tools, the close modal listeners don't seem to work, so I'm also missing that piece of the puzzle.
So, it's a work-around to setting the data attribute, but I realized I was shoe-horning a solution where it wasn't needed. Assuming someone ends up with the same mental block. Appropriate listeners on the modal close button and another function passed to the existing marker click listener produce the desired functionality.
const closeM = document.querySelector(".close-modal");
closeM.addEventListener("click", closeMe);
var modal = document.getElementById('infoBox');
and
function modalAction(){
modal.style.display = 'block';
}
function closeMe(){
modal.style.display = 'none';
}

How to identify the main global object for Vanilla Picker?

Vanilla Picker is an absolutely fantastic color picker (example one, example two). However the documentation is a bit lacking. I know how to initialize though I don't know how to identify whatever global object (besides Picker) so I do not know how to access the show(), hide() and/or movePopup(options, open) methods.
The code I've come up with below at least prevents additional popups beyond one-per-element. However it would make more sense (and waste less memory) to simply use the movePopup() method though again I do not know what parent object to refer to. If I console.log(Picker); and looking through the events in the inspector tools of Waterfox and Chrome has me a bit lost. I also have to click twice initially for the popup to be displayed.
How do I identify the global / primary object which I can then use movePopup to only initialize a single Picker with Vanilla Picker?
No frameworks or libraries, except of course of Vanilla Picker itself.
JavaScript
// See URL for Vanilla Picker code:
// https://unpkg.com/vanilla-picker#2.8.0/dist/vanilla-picker.min.js
window.onclick = function(event)
{
if (event.target.hasAttribute('data-color') && event.target.getAttribute('data-color')[0] == '#')
{
console.log(event.target.getAttribute('data-color'));
var picker = new Picker({alpha : true,
color: event.target.getAttribute('data-color'),
editor : true,
editorFormat : 'rgb',
onChange: function(color)
{
event.target.setAttribute('data-color',color.rgbaString);
event.target.style.backgroundColor = color.rgbaString; console.log(color);
},
//onDone: function(color) {console.log(color);},
parent : event.target,
//popup : 'bottom'
});
}
}
HTML
<div data-color="#f00" id="color1">Color 1</div>
<div data-color="#0f0" id="color2">Color 2</div>
<div data-color="#00f" id="color3">Color 3</div>
As you instantiate an instance of Picker you assign it to a variable you can reference it through. If this variable is defined in the global scope, you can access this instance and thus all of its methods from anywhere in your code.
Here's a simple example, where we re-use the same Picker for two different DIVs:
var picker = new Picker();
function changePicker(e) {
picker.movePopup({
parent: e.currentTarget
}, true);
}
document.getElementById("divA").addEventListener("click", changePicker);
document.getElementById("divB").addEventListener("click", changePicker);
picker.onDone = function(color) {
this.settings.parent.style.backgroundColor = color.rgbaString;
};
<script src="https://unpkg.com/vanilla-picker#2.8.0/dist/vanilla-picker.min.js"></script>
<div id="divA">TestA</div>
<div id="divB">TestB</div>
This will set backgroundColor of a DIV as soon as the done button of the picker is pressed. If you take a look at the onDone callback function, you'll notice this.settings. This is an object returned by the picker itself. Among other things it returns the HTML element which is currently associated with the picker - this.settings.parent.

CKEditor v4 : Dynamic title of dialog in homemade plugin

I'm using CKEditor v4 and I made an homemade plugin (tu upload image and edit informations). 2 tabs (upload and edit informations) work good, but I want to set title of dialog using condition (new image or edit existing image). Is there a way to give a parameter to dialog fuciton when I call CKEDITOR.dialog.add or change the title on the onShow event or other issue ?
Thx a lot for your help and sorry for my frenchy english !
I had the same problem and couldn't find an 'official' way, I was however able to change the title dynamically using following workaround (this is a CKEDITOR.dialog element):
this.getElement().getFirst().find('.cke_dialog_title').getItem(0).setText('[insert new title here]')
Basically, you go via the actual DOM of the dialog element (getElement().getFirst()), retrieve the title DOM element (find('.cke_dialog_title').getItem(0)), and set the text there. This relies solely on the CSS class name of CKEditor, so isn't really stable, but it's a start.
$(dialog.parts.title.$).text(someTitleText)
in short:
CKEDITOR.dialog.add('dynamictitle', function (editor) {
...
...
return {
title: "initial title here",
...
...
// set title onLoad(),or onShow()
onLoad: function () {
var currentTitle = editor.config.dynamictitle;
var dialog = CKEDITOR.dialog.getCurrent();
$(dialog.parts.title.$).text(currentTitle)
}
}
});
...
in your page:
CKEDITOR.replace('<ckeditorelementid>', {
.....
.....
dynamictitle: <title text value>,
.....
.....
});

Why i can't show new Ext.Window twice

I have a html with one div and two scripts with Ext Js 3.4.0
<script type="text/javascript" src="js/listaBancos.js"></script>
The file listaBancos.js show a Grid with toolbar button in the divListaBancos, the first time i click the button "Agregar" and i see the Window declared in altaBanco.js.
==============Part of the grid in listaBancos.js============
tbar:[{
text:'Agregar',
tooltip:'Agrega un banco',
iconCls:'add',
handler: agregaBanco
}]
function agregaBanco(){
var win =Ext.getCmp('myWin');
win.show();
}
==============Window declared in altaBanco.js================
var winAltaBanco = new Ext.Window({
id : 'myWin',
height : 250,
width : 400,
});
When i close the window then click the button again the windows doesn't showed.
Can you help me ???
The default close action of a windows is close, i.e., it destroys the component, hence it cannot be accessed using Ext.geCmp() again since it doesn't exist on the DOM anymore. To achieve what you want either set closeAction : hide or
var cmp = Ext.getCmp('myId');
if(!cmp)
{
cmp = new Ext.Window({
id : 'myId'
});
}
cmp.show();
Prefer hiding to recreating.
Make sure in window config close action is set to hide.
closeAction:'hide'
check this
There is no need to make any trick, simply remove your window id. In ExtJS component ids must be unique.

Display a chart in a pop-up/modal on mouse click (jquery?) without loading chart first? (mvc3/razor)

I'm using the FileStreamResult (or FileResult) method to display a chart on a razor view page (from a Controller action) and this works as expected.
However, I'm wondering if it's possible to display the chart ONLY when an html element is clicked.
e.g. Click on an element, display chart in modal pop-up.
I can get a modal to display using Jquery...but ONLY if I have already loaded the chart into a div.
I'd like to have the page load without the chart (for performance reasons), and then only generate/load the chart when the is clicked.
I guess I need an Ajax call of somekind...but I'm a little stuck as to how to proceed and googling didn't return anything useful (just lightbox for photos)
Pseudo Code:
HTML:
<img src='small chart icon.jpg' alt='click me to see chart' id='showchart'/>
<div>
rest of page goes here...
</div>
C#:
public FileStreamResult GetChart(){
//generate any chart
return FileStreamResult(newchartstream, "image/png");
}
JS:
<script>
$(document).ready(function(){
$('#showchart').click(function(){
//make ajax call to generate chart
//show in modal with "close" button
//OR
//open a new page as a modal?
});
});
</script>
EDIT
Clarification:
Controller generates a ViewModel (from an EF4 model) which contains the results of lots of calculations, and some "summary" rows (totals, averages etc)
View displays the results (ViewModel) as tables.
Requirement:
Click on one of the summary rows, opens modal window displaying a chart for that summary row.
Would like to avoid sendind the parameters for the ViewModel and re-generating it from scratch (doing all the calcs again etc) for two reasons
1) The figures in the back-end db may have changed...so the chart doesn't reflect whats being shown in the tables.
2) It takes time to do the calcs!
I'd also like to ONLY generate the chart if the row is clicked, as opposed to loading the chart always and hide() show() with jquery.
I've thought about an ajax call, but unsure about how to return an image, or how to open a new page.
Can't see a way to pass a complex model in the Url.Action() method.
Think caching may be the best option, and have the click method call "old fashioned" javascript for a new window, passing over the parameters to get the object from cache?
You have many ways to do that, but here is what I would do.
1/ Create an action which returns a tag with the good src (assuming that your controller's name is ChartsController).
public ActionResult GetImage(int chartId = 0)
{
var image = #"<img id='chart' src='" + Url.Action("GetChart", new {controller = "Charts", chartId = chartId}) + #"'/>";
return this.Content(image);
}
2/ I assume that, in your view, you have a div somewhere which contains your modal's content (like jQuery-ui would do) with an img inside, for the chart.
<div id="modal-div">
<div id="chart-div"></div>
</div>
3/ For every row, you have to create an Ajax link who will call your "GetImage" action and replace "chart-div" with your . You can specify a "OnBegin" Javascript function, this is where you will put your code to launch the modal.
#Ajax.ActionLink("Show me the chart!", "GetImage", "User", new { chartId = #Model.Rows[i]}, new AjaxOptions()
{
HttpMethod="GET",
OnBegin = "showModalWindow",
UpdateTargetId="modal-div",
InsertionMode = InsertionMode.Replace
});
Everytime you will click on an Ajax link, the modal will be launched and the inside will be replaced (in fact, all the content of the modal will be replaced).
Don't forget to include "Scripts/jquery.unobtrusive-ajax.js" and "Scripts/jquery.validate.unobtrusive.js" for the Ajax links to work.
You have some difference question mixed in one. You should split them each in one question. For your question's title, -loading an image by AJAX- you can use code-snippet below:
HTML:
<div id="chartholder"></div>
<a id="showchart">Show the chart</a> <!-- or any element else you want to fire show event -->
JS:
$(document).ready(function(){
$("#showchart").click(function(){
// Put your controller and action (and id if presented) below:
var file = "/YourControllerToGetChart/GetChart/id"
$("<img />").attr("src", file).load(function () {
$(this) // the loaded image
.css({"some-css-you-want":"some-value"})
.appendTo($("#chartholder")); // fixed syntax
});
});
});
Let me know if you have any questions or need clarifications on any part or you want to know how to css the div id="chartholder" to display it as an modal. Cheers.

Categories

Resources