Can we have nested targets in Dojo? - dojo

I have two divs nested under a parent div and I want all these to be source as well as targets for dojo.dnd.
I want to be able to add nodes to the div over which the content was dropped and also allow the user to move this in between the 3 divs.
Something like this -
http://www.upscale.utoronto.ca/test/dojo/tests/dnd/test_nested_drop_targets.html
This is I gues implemented in older version of Dojo and doesn' seem to work with 1.4
Is the support for nested targets removed? Is there any way to achieve this?

Nested sources/targets are not supported currently. In most cases you can work around this restriction by using independent sources/targets, yet positioning them as you wish with CSS.

I used a workaround for this case. I create another DIV element which positioned at the same place of the nested target with same width and height but with higher z-Index value. Then the new DIV element covers the nested target. When user is trying to drop on the nested target, he actually drops to the above new DIV element. As long as the new DIV element is not nested in the parent drop target, Dojo's dnd operation works well. I usually put the new DIV element as a child of the body element.
What you need to do is to create the new DIV in onDndStart and destroy it in onDndCancel, then everything should work well.

Dojo version 1.10 still does not support nested Dnd.
CSS positioning and overlay div's didn't work for me. But I noticed that dragging an element out of a dndContainer into a parent dndContainer doesn't trigger onMouseOverEvent for the parent.
In case someone is still using dojo and has the same problem, here is my approach to solve this:
Declare your own dndSource e.g. nestedDndSource.js
define([
"dojo/_base/declare",
"dojo/dnd/Source",
"dojo/dnd/Manager"
], function(declare,dndSource, Manager){
var Source = declare("dojo.dnd.Source", dndSource, {
parentSource: null,
onOutEvent: function(){
if(this.parentSource != undefined)
Manager.manager().overSource(this.parentSource)
Source.superclass.onOutEvent.call(this);
}
});
return Source;
})
Use that nestedDndSource for the children instead of dojos and make sure to provide the dndSource of the parent as parentSource-Parameter:
var parentDndSource = new dojoDndSource(parentNode, {..});
var childDnDSource = new nestedDndSource(childNode,{
parentSource: parentDndSource,
onDropExternal: ...
});
Working example: https://jsfiddle.net/teano87/s4pe2jjz/1/

Related

addStyleClass for ad-hoc styles?

When writing a control, prior to it's rendering you can add css classes to it's html representation's root dom node:
FooLayout.prototype.init = function() {
this.addStyleClass('fooCssClass');
};
This will work assuming writeClasses is executed during rendering:
oRenderManager.writeClasses();
--
There is another RenderManager function writeStyles which can add in-line styles to the html string buffer:
oRenderManager.addStyle("color", "green");
oRenderManager.writeStyles();
But there doesn't seem to be an analogous function to addStyleClass for adding these at the control level to be picked up during rendering.
Is there a way I can hook into writeStyles outside of the renderer?
I have to ask: What styling cannot be applied on control level with a class that can be done with a specific style attribute?
Anyway, the "solution" (which I do not like) would be to add a delegate to the class and do something on onAfterRendering:
oControl.addDelegate({
onAfterRendering: function() {
this.$().css("opacity", "0.5");
}.bind(oControl)
});
Here is an example: http://jsbin.com/seqemaqedo/1/edit?js,output
But as I said, I would advice against it because using a good name for a class uses less code and is much easier to read:
oControl.addStyleClass("semiTransparent");
Update:
After our discussion in the comments, here is an example of how to wrap a control that does not support setting width and height.
You still have to write CSS that references the inner control structure, but in this case it is very unlikely that it will change:
http://jsbin.com/lohocaqixi/3/edit?html,js,output

how can i delete a div that i created with dojo?

i create a div with heading and UL inside with dojo.create. how can i totaly delete this div with heading and UL children so that i can create a div with this id again (with different content)?
I create the div like this (i delete some attributes and the h1 and ul creation because it was too much code, i do it the same way like i create the div):
var newAlarmDiv = new dojox.mobile.ScrollableView({
id: "divAlarms",
dojoType: "dojox.mobile.ScrollableView",
});
newAlarmDiv.placeAt('mobileView','first');
i already tried it with the dojo.destroy command but when i create a new div after destroying it i get many different errors so it seems not to be deleted correctly.
How do i correctly "undo" the div creation?
greets
Tom
You are creating a "Widget", which has DOM elements associated with it. If you were destroying only dom elements you would use dojo.destroy.
Since you want to destroy the widget, you should use destroy or destroyRecursive. The API Docs have a good overview of what each method does.
var scrollableViewWidget = new dojox.mobile.ScrollableView({/*params*/});
scrollableViewWidget.placeAt('someDiv','first');
scrollableViewWidget.destroyRecursive();

Dynamically add regions to Marionette layout

I have a layout, but cannot define all of its regions in advance because they are not known.
So later on an ItemView is created and I'd like to create a new region in the layout using the view's ID as the region's name so I can then say:
layout.dynamicRegionName.show(newItemView);
But there is cyclic dependency here.
I haven't rendered the view yet, so I cannot make a reference to its DOM element to be used in the layout's call to .addRegion()
I cannot render it, precisely because I want it to get attached to the DOM tree through the dynamically added region by calling its .show()
#DerickBailey In the Marionette.Layout docs in github I believe there is an error in the example that has: layout.show(new MenuView());
but technically this is close to what we'd need here i.e. to be able to do:
layout.addRegion(VAR_WITH_NEW_REGION_NAME, aViewInstance);
and have this add a new Region into the layout rendering inside it directly the view instance.
Am I missing some other obvious way to achieve this? Is that a known missing functionality? Is there a reason not to have it?
I'm aware of this previous Q: "Dynamically add/remove regions to a layout"
but don't see any clear/definite answer to it.
Marionette v1.0 (v1.0.2 is latest, right now) supports dynamic regions in Layouts.
var MyLayout = Marionette.Layout.extend({
template: "#some-template"
});
var layout = new MyLayout();
layout.render();
layout.addRegion("someRegion", "#some-element");
layout.someRegion.show(new MyView());
In one of my projects, I faced a similar issue. I needed to create a form dynamically, i.e the form would contain different field views that could not be determined prior runtime. I needed the fields to be Marionette views because they had pretty complicated behaviour.
The way I have done it in Marionette 1.4 in CoffeeScript:
class Module.AdditionalOptionsLayout extends Marionette.Layout
tagName: 'form'
initialize: (options = {}) ->
#_fieldViews = options.fieldViews || []
onRender: ->
#_showFields #_fieldViews
_showFields: (fieldViews) ->
fieldViews.forEach (fieldView) => #_addRegion().show fieldView
_addRegion: ->
regionClass = _.uniqueId('field-region__')
#$el.append $("<div class=\"#{regionClass}\"></div>")
#addRegion regionClass, '.' + regionClass
Please, let me know if it needs further explanation or I can clarify this in JS. I am also aware that it is a late answer, however, hope somebody could find it still useful. Also, note - the answer is relevant only for Marionette 1.x

Is there a way in Dojo to find all widget descendants in a DOM element?

Is there a way in Dojo to find all widget descendants in a DOM element? I used the example below it will only list the children of the element, in this case any widgets that are children of the document object, but not all the descendants or nested widgets. Hopefully that's clear.
var widgets = dijit.findWidgets(dojo.doc);
dojo.forEach(widgets, function(w) {
console.log(w);
});
I could just write my own recursive function but I want to make sure I'm not missing out on a Dojo method which already does this.
Many thanks
Hmm, dijit.findWidgets(parentWidget.domNode) ?
Edit Oh, now I nee findWidgets doesn't search recursively.
I checked the dijit.findWidgets source code and all it does is check for nodes with a widgetid attribute that are represented in the dijit registry. The following version uses dojo.query to do this same search recursively:
function findEvenTheNestedWidgets(innitialNode){
return dojo.query("[widgetid]", innitialNode)
.map(dijit.byNode)
.filter(function(wid){ return wid;}) //filter invalid widget ids that yielded undefined
}

Confusion using dijit.byId and dojo.byId

I am trying to understand the difference between
dijit.byId and dojo.byId
For this i have taken a Button and a div .(To set the
data inside the div on click of the Button)
Show Me!
<div id="findMe">
Hiya!
</div>
This is working (dojo.byId)
function callMe()
{
var node = dojo.byId('findMe');
node.innerHTML = "Hello World";
}
But this isn't working (dijit.byId)
function callMe()
{
var node = dijit.byId('findMe');
node.innerHTML = "Hello World";
}
My understanding is , when refering to the div we need to use dojo.byId
and when we are refering to Individual components use dijit.byId
Please correct me if i am wrong .
As previously stated, dojo.byId retrieves the DOM node with that id if existent.
dijit.byId retrieves the instance of a dijit._Widget (and its subclasses), that is dojo's abstraction of UI objects, rather than the widget's DOM node. But it is important to note that dijit.byId searches through the widgets by the atrribute "widgetId", not "id". These are equal if you declare your widgets by passing a container node that already has an "id", but still dojo creates an attribute "widgetId" for every widget if not specified explicitly.
This means that widgetId and id are usually the same, but it is possible that they are different. Plus, widgetId is always set for a given widget even in cases where the id attribute of the container node is absent.
This implies that you should use dojo.byId whenever you intend to work on the DOM tree itself and dijit.byId only in case where you'd like to obtain the instance of a certain widget instance. If no widgets are present, there is no reason to use dijit.byId at all.
You are right:
dojo.byId finds elements in the DOM tree of your website with a certain ID - it searches and returns HTML elements.
dijit.byId finds dijits you created with a certain id - it searches and returns dijits (javascript objects), although these objects usually refer to a certain DOM node.