Accessing variables across different scopes in Javascript & YUI 3 - javascript

I'm new to YUI 3 and YUI in general. I'm trying to pass data between classes and methods.
In this example I'm using the gallery-sm-treeview plugin to build a file tree. There's a class named TreeView to initialize and render the tree. There's another class named MenuBar where I want to access some of the plugin-specific methods through TreeView's getter method.
However, the variable var treeview inside the YUI().use() scope is of course not accessible from outside. How to do it?
YUI.add('treetool.TreeView', function(Y) {
Y.treetool.TreeView = Class.extend({
init : function(elementId) {
YUI({
gallery: 'gallery-2013.06.20-02-07'}).use('gallery-sm-treeview', function (Y) {
// Create a new TreeView with a few nodes.
var treeview = new Y.TreeView({
// Tell the TreeView where to render itself.
container: elementId,
// Populate the treeview with some tree nodes.
nodes: [
{label: 'Node 1'},
{label: 'Node 2', children: [
{label: 'Child 1'},
]
});
// Render the treeview inside the #treeview element.
treeview.render();
});
},
getSomeData : function () {
return treeview.getSelectedNodes();
}
});
}, '0.0.1', {
requires : [ 'jquery' ]
});
and
YUI.add('treetool.MenuBar', function(Y) {
Y.treetool.MenuBar = Class.extend({
init : function(treeObj) {
var someData = treeObj.getSomeData();
},
});
}, '0.0.1', {
requires : [ 'jquery' ]
});

It might not be the "best" way to do it, but one way would be to define the treeview variable in a scope that is available in both places.
YUI.add('treetool.TreeView', function(Y) {
var treeview;
//...
and
treeview = new Y.TreeView({ // removed "var "

Related

How to obtain this ref to declaring class from Dojo gridx detailProvider (Dod module)

Using the Dojo framework.
I have a 2 nested grid. Grid 1 uses a Dod with a detailprovider to load details on demand when one clicks a expand icon. When pressed this opens a nested grid. I need to track changes made in both grids. In the declaring class I've got an array that keeps track on changes made. The problem is that I can't access the array from a detailprovider. Since I've to conform to the protocol which gridx later invokes. What can I do to obtain a ref to the declaring class
var myDeclaringClass = declare([_WidgetBase,_TemplatedMixin,_WidgetsInTemplateMixin], {
array: [],
initGrid: function(){
var grid = new Grid({
store: store,
structure: columns,
modules: [ {
moduleClass: Dod,
showExpando: true,
detailProvider: this.myDetailProvider
}]
});
// .... grid.placeAt() .. grid.startup()
},
myDetailProvider: function(parentGrid, rowId, detailNode, rendered) {
// construct Nested Grid ...
// How to obtain this reference here?
// to access this.array?
rendered.callback();
return rendered;
}
retrun myDeclaring;
}
EDIT:
I have also tried with a static var like:
statics: { array: [] }
But here I will stille need a instance ref to access it.
Try something like this
var myDeclaringClass = declare([_WidgetBase,_TemplatedMixin,_WidgetsInTemplateMixin], {
array: [],
var globalref : this,//here i'm assigning 'this' i.e. class level ref to the variable
initGrid: function(){
var grid = new Grid({
store: store,
structure: columns,
modules: [ {
moduleClass: Dod,
showExpando: true,
detailProvider: this.myDetailProvider
}]
});
// .... grid.placeAt() .. grid.startup()
},
myDetailProvider: function(parentGrid, rowId, detailNode, rendered) {
// construct Nested Grid ...
// How to obtain this reference here?
// to access this.array?
globalref.array//should give you access to the array
rendered.callback();
return rendered;
}
retrun myDeclaring;
}

How can I create dojo combobox dropdown

I created dojo div element for a dojo combo box . Now I want to create a tree like structure to choose drop down value. I want to attach tree object in div element through java script file using read or write store (dojo/data/ItemFileReadStore).....
I am trying the below html and js files for it but I am getting the below error message. no such method dom.byId
div element for combo box :
<div>
<tr>
<td><label for="fixedSubCategory">Fixed SubCategory</label></td>
<td><select data-dojo-type="dijit/form/ComboBox"
id="fixedSubCategory" name="fixedSubCategory" value="">
</select></td>
</tr>
JS file to attach tree object :
var displayData ={
"identifier":"id",
"label":"name",
"items":[
{
"type": "parent",
"name": "Countries",
"id": "countries",
"children":[
{"type":"Leaf", "name":"Country 1", "id":"country1"},
{"type":"Leaf", "name":"Country 2", "id":"country2"},
{"type":"Leaf", "name":"Country 3", "id":"country3"},
{"type":"Leaf", "name":"Country 4", "id":"country4"},
{"type":"Leaf", "name":"Country 5", "id":"country5"},
{"type":"Leaf", "name":"Country 6", "id":"country6"}
]
}]}
var store1 = new dojo.data.ItemFileReadStore({ data: displayData });
var treeModel = new dijit.tree.ForestStoreModel({
store: store1,
query: {"type": "parent"},
rootId: "root",
rootLabel: "Groups",
childrenAttrs: ["children"]
});
var treeObject = new dijit.Tree({
model: treeModel
}, "treeDiv")
if (dijit.byId("fixedSubCategory") != null) {
dom.byId("fixedSubCategory").appendChild(treeObject.domNode);
treeObject.startup();
}
Typically, dom.byId() and such is seen in the context of a proper AMD module, e.g.:
define([ 'dojo/dom', ... ], function (dom, ...) {
// do something with dom.byId
});
If you are writing modules in AMD format (which is heavily encouraged), make sure you are actually including the dojo/dom module in your dependencies list and assigning the module to the dom argument in your factory function (if you think you are already doing this, then make sure the dependencies array and function argument order match up). Then it should work fine.
(Also, the appropriate way to reference dijit.byId would be via the dijit/registry module, rather than the dijit global.)
On the other hand, it looks like most of your other code isn't really making use of the AMD format at all (e.g. dojo.data, dijit.tree, etc.). While it'd be recommended to update to the AMD format (and it seemed like you had been using it in Populating ComboBox dynamically in dojo with domAttr), the non-AMD, global equivalent to dom.byId is dojo.byId.
The easiest way is to use a combobox, i guess.
We managed it like this :
"results" is the result of a query on our street-shape-file.
function streetsToCombobox(results){
var adress;
var values = [];
var testVals={};
var features = results.features;
require(["dojo/_base/array","dojo/store/Memory","dijit/form/ComboBox"],
function(array,Memory,Combobox){
if (!features[0]) {
alert(noDataFound);
}
else {
array.forEach(features, function(feature, i){
adress = feature.attributes.STRASSE;
//Check for doublefeatures
if (!testVals[adress]) {
testVals[adress] = true;
values.push({
name: adress
});
}
});
values.sort(SortByName);
var dataItems = {
identifier: 'name',
label: 'name',
items: values
};
storeStreet = new Memory({
data: dataItems
});
}
var comboBox = new ComboBox({
id: "MyCB",
name: "street",
value: "",
store: storeStreet ,
searchAttr: "name"
},"DomeNodeForBox");
});
}
For all further Infos have a close look into the Documentation : http://dojotoolkit.org/reference-guide/1.10/dijit/form/ComboBox.html#dijit-form-combobox

Extend YUI TreeView with Treeview Sortable

I'm using YUI3 to create an instance of Y.TreeView.
var treeview = new Y.TreeView({
lazyRender: false,
container: treeview,
nodes: jsonTreeFile
});
Now I want to extend this object to use it with TreeView.Sortable, which mixes in Y.Tree.Sortable. The constructor is TreeView.Sortable () (See TreeView.Sortable Api ).
How do I do this, so I can use the TreeView.Sortable methods on the treeview object?
Here is the full context:
YUI({
gallery: 'gallery-2013.07.31-22-47'}).use(
'gallery-sm-treeview', 'gallery-sm-treeview-sortable', function (Y) {
// Create a new TreeView in container with nodes.
treeview = new Y.TreeView({
lazyRender: false,
container: treeview,
nodes: jsonTreeFile
});
// Render the treeview inside the #treeId element.
treeview.render();
// Now, how do I extend and sort the treeview object?
});
In case anyone is interested in the solution, this is how subclassing in YUI works (thanks to Ryan Grove for helping out: codepen.io/rgrove/pen/vAuep)
YUI({
gallery: 'gallery-2013.07.31-22-47'
}).use('gallery-sm-treeview', 'gallery-sm-treeview-sortable', function (Y) {
var SortedTreeView = Y.Base.create('sortedTreeView', Y.TreeView, [Y.TreeView.Sortable], {
sortComparator: function (node) {
return node.label;
}
});
var treeview = new SortedTreeView({
container: '#treeview',
nodes: [{label: 'hi!'}, {label: 'hello!'}]
});
treeview.render();
});

EXTJS Accessing Setters

Ext.define("E.model.P", {
extend: 'Ext.data.Model',
associations: [{
type: 'hasOne',
model: 'E.model.D',
associationKey: 'D',
name:'demo',
getterName: 'getD', // avoid dots in function name
setterName: 'set' // avoid dots in function name
}],
fields: [
{ name: 'id', type: 'int' },
{ name: 'CPR', type: 'string' },
]
});
I have a Store created with the Model P
var store = Ext.create("E.store.MyP");
store.load(function() {
store.each(function(record) {
var info = {
data: Ext.encode(record.getData()),
allData: Ext.encode(record.getData(true)),
personData: Ext.encode(record.getD()) //Here i get the getD is not a function
};
console.log(info);
});
});
The problem I am having is getD is not a function, It will only work if I do not have classes define ex: Ext.define("P").
So how do I access the getD so I can drill further down?
This works http://jsfiddle.net/aqHdC/
Now when I start seperating the classes, It stops working and says can't find function
The associated model (in your example E.model.D) class must be loaded for the getter to be generated.
That means you need to require this class in your base model class definition (or, as you have found out, have all your classes in the same file).
For example:
Ext.define("E.model.P", {
extend: 'Ext.data.Model',
// here's for the class loader!
requires: [
'E.model.D'
],
// rest of your definition
});

How to access a field outside of rootProperty from itemTpl's XTemplate in Sencha Touch?

Say, we have the following in a store:
{
"document": {
"success": "true",
"totalAllocation": "40000000.00",
"fundAllocation": [
{
"fundName": "Zais Opportunity Ltd Class B",
"allocation": "10000000.00"
},
{
"fundName": "Metacapital Mortgage Opportunities Ltd",
"allocation": "10000000.00"
},
...
]
}
}
And what I'd like to do is something like this:
itemTpl: Ext.create('Ext.XTemplate',
'<div>',
'<span>{fundName}</span>',
'<span>{[this.getPercentage(values.allocation, parent.totalAllocation)]}%</span>',
'</div>',
{
getPercentage: function (allocation, totalAllocation) {
return Ext.Number.toFixed(allocation / totalAllocation, 2);
}
}
)
But, of course, this doesn't work since 'parent' in this scope is empty.
Any idea how to fetch the value of the totalAllocation field inside XTemplate's fundtion to display the percentage allocated to the current fund in a list item?
Workarounds are welcomed as well.
From your data code it looks like document is the store root because there is a success property underneath it. Assuming that is the case, you can use the store reader's rawData property to get a reference to the value before you create the template. Then you can simply use the referenced value in the getPercentage function.
Your code does not show where you are creating this itemTpl in your class so I am assuming that you are creating this itemTpl inside the initComponent of the view you are instantiating.
I have no idea what type of component you are trying to create here other than the fact that it has an itemTpl config property which could be any subclass of Ext.view.AbstractView.
So I will assume that you are trying to use this in a gridpanel's view because that is the most common subclass of Ext.view.AbstractView.
Here's some code examples.
Example 1:
Ext.define('YourApp.view.TemplateGrid', {
extend: 'Ext.grid.Panel',
// column configs etc...
initComponent: function() {
var me = this,
templateStore = Ext.getStore('TemplateStoreId'),
totalAllocation = templateStore.proxy.reader.rawData.totalAllocation;
me.viewConfig.itemTpl = Ext.create('Ext.XTemplate',
'<div>',
'<span>{fundName}</span>',
'<span>{[this.getPercentage(values.allocation)]}%</span>',
'</div>',
{
getPercentage: function (allocation) {
return Ext.Number.toFixed(allocation / totalAllocation, 2);
}
}
)
}
});
Example 1 wouldn't work if you want to be able to load the store again (after initialization), it also assumes that your view store is already loaded. Here's another example showing the component set-up to handle multiple loads of the store without being recreated, it also assumes that the store is not loaded at the time when you create the view:
Example 2
Ext.define('YourApp.view.TemplateGrid', { // or whatever you are calling it
extend: 'Ext.grid.Panel',
// column configs etc...
totalAllocation = 0, // add this as a view property
initComponent: function() {
var me = this,
templateStore = Ext.create('YourApp.store.TemplateStore');
templateStore.on('load', function() {
me.totalAllocation = templateStore.proxy.reader.rawData.totalAllocation;
}
me.viewConfig.itemTpl = Ext.create('Ext.XTemplate',
'<div>',
'<span>{fundName}</span>',
'<span>{[this.getPercentage(values.allocation)]}%</span>',
'</div>',
{
getPercentage: function (allocation) {
return Ext.Number.toFixed(allocation / me.totalAllocation, 2);
}
}
)
templateStore.load();
me.callParent(arguments);
}
});

Categories

Resources