Sharing variable around different instances of YUI - module

I have made up the custom module as :
YUI.add('util', function(Y) {
Y.namespace('com.myCompany');
var NS = Y.com.myCompany;
NS.val = undefined;
}, '3.3.0', {
requires : []
});
What I am trying to do is share this variable val in the instances where I use this module "util". As in
YUI().use("util","node","event",function (Y) {
Y.namespace('com.myCompany');
var MV = Y.com.myCompany;
var setVal = function(e){
MV.val = 10;
}
Y.on("click", setVal,"#one");
});
Now if I want to get this in other instance I am doing as the following:
YUI().use("util","node","event",function (Y) {
Y.namespace('com.myCompany');
var MV = Y.com.myCompany;
var getVal = function(e){
alert(MV.val);
}
Y.on("click", getVal,"#two");
});
But this does not seem to be working. Is there a way to get this behavior. I am doing this only to split up the code.

In this case, you should only create one sandbox. The correct way to break up your code is to use YUI.add to create the modules and specify their dependencies. One way to do this is to structure your code as follows:
// util.js
YUI.add('util', function (Y) {
var NS = Y.namespace('com.MyCompany');
NS.val = null;
}, 'version', {
requires: ['some', 'dependencies']
});
// one.js
YUI.add('one', function (Y) {
var NS = Y.namespace('com.MyCompany');
Y.on('click', function (e) { NS.val = 23; }, '#one');
}, 'version', {
requires: ['util']
});
// two.js
YUI.add('two', function (Y) {
var NS = Y.namespace('com.MyCompany');
Y.on('click', function (e) { alert(NS.val); }, '#two');
}, 'version', {
requires: ['util']
});
// index.html
<button id="one">Set the value</button>
<button id="two">Get the value</button>
<script>
YUI.use('one, 'two', 'node', 'event', function (Y) {
// main application logic here
});
</script>
This allows you to break up your code into separate modules that share the same YUI sandbox instance.
Note also YUI.namespace returns the namespace in question, so you don't need the extra variables.

The problem is that YUI() is creating a new sandbox with each execution. If you want to reuse it you need to capture its value after the first "use" execution and reuse that value later. There may be a better YUish way to do this but I use a global YUI_MAIN:
var YUI_MAIN = YUI().use("util","node","event",function (Y) {
Y.namespace('com.myCompany');
var MV = Y.com.myCompany;
var setVal = function(e){
MV.val = 10;
};
Y.on("click", setVal,"#one");
});
YUI_MAIN.use(function (Y) {
Y.namespace('com.myCompany');
var MV = Y.com.myCompany;
var getVal = function(e){
alert(MV.val);
};
Y.on("click", getVal,"#two");
});
If you really wanted to share between separate sandboxes and avoid an extra global you could use a closure to create a private variable with something like this:
YUI.add('util', (function () {
var privateUtilNS = {};
return function(Y) {
privateUtilNS['val'] = undefined;
Y.setVal = function(e){
privateUtilNS.val = 10;
};
Y.getVal = function(e){
alert(privateUtilNS.val);
};
};
}()), '3.3.0', {
requires : []
});
YUI().use("util","node","event",function (Y) {
Y.on("click", Y.setVal,"#one");
});
YUI().use("util","node","event",function (Y) {
Y.on("click", Y.getVal,"#two");
});

Related

Web Application ArcGIS JS API error adding layer

I'm developing a custom widget for WebApp Builder. The widget calls a Geoprocessing service and the result must be added to map, but when I call a function this.map.addLayer() I receive the error message:
TypeError: this.map.addLayer is not a function
at Widget.js?wab_dv=2.6:839
at Object._successHandler (init.js:2238)
at Object._getResultDataHandler (Geoprocessor.js:11)
at init.js:63
at Object.load (Geoprocessor.js:12)
at init.js:1042
at c (init.js:103)
at d (init.js:103)
at b.Deferred.resolve.callback (init.js:105)
at c (init.js:104) "TypeError: this.map.addLayer is not a function
This is the snippet of my code:
submitGpLr: function (tab1) {
let params = {
json: tab1
};
// lancia il geoprocessing, i callback sono sotto
this.gpLr.submitJob(params, lang.hitch(this, this.gpLrJobComplete), this.gpLrJobStatus, this.gpLrJobFailed);
},
gpLrJobComplete: function (jobinfo) {
this.gpLr.getResultData(jobinfo.jobId, "Output_Layer", function (results) {
console.log(results);
let jsonResult = results.value;
// function addResultToMap
let SR = jsonResult.spatialReference;
let GT = "esriGeometryPolyline";
let layerDefinition = {
"geometryType": GT,
"spatialReference": SR,
"fields": jsonResult.fields
};
let featureCollection = {
layerDefinition: layerDefinition,
featureSet: {
"geometryType": GT,
"spatialReference": SR,
"features": jsonResult.features
}
};
let resultLayer = new FeatureLayer(featureCollection, {
showLabels: true,
spatialReference: SR
});
let sls = new esri.symbol.SimpleLineSymbol(
esri.symbol.SimpleLineSymbol.STYLE_SOLID,
new esri.Color([255, 0, 0]), 3.5
);
this.map.addLayer(resultLayer);
});
},
gpLrJobFailed: function (err) {
console.log("error");
console.log(err);
},
gpLrJobStatus: function () {
}
This is my setEventHandler:
this.own(on(this.gpLr_Submit, "click", () => {
let id = this.selectedMainTabId;
let tabNewStr = JSON.stringify(this.grids[id + '_IN']['_originalData']);
this.submitGpLr(tabNewStr);
}));
How can I fix this error? I don't try the error in my code.
I think, "this" reference to "Window" object. Your this should reference to, your widget class.You should set instance like this when, onstartup event in widget.Then you can use instance.map like this:
startup: function () {
console.log('YourCustomWidget::startup');
YourCustomWidget.SetInstance(this);
}
//Singleton design
YourCustomWidget.Instance = undefined;
YourCustomWidget.GetInstance = function () {
return this.Instance;
}
YourCustomWidget.SetInstance = function (instance) {
AkkrFiltrelemeVeRaporlama.Instance = instance;
}
...
...
...
...
gpLrJobComplete: function (jobinfo) {
var instance = YourCustomWidget.Instance;
//
//
//
instance .map.addLayer(resultLayer);
}

React Native: how can I achieve the dynamic keys with multiple objects

Here is my code I tried,
var array=[];
var list = this.state.list;
var getList = function(i){
var add = +i + 1;
return {
["value"+add]:{
Description:list[i].Description,
Length:list[i].Length,
Height:list[i].Height,
Weight:list[i].Weight,
VolumeWeight:list[i].VolumeWeight,
ActualWeight:list[i].ActualWeight,
}
}
}.bind(this)
for(var i in list){
array.push(getList(i));
}
var dataArray = array.map(function(e){
return JSON.stringify(e);
});
dataString = dataArray.join(",");
data1 = {
ConsigneeBranchName:this.state.searchText,
ConsigneeBranchCode:this.state.code,
ConsigneeBranchFullAddress:this.state.DAddress,
SenderBranchCode:this.state.code1,
SenderBranchName:this.state.searchTexts,
SenderBranchFullAddress:this.state.Address,
CreatedByEmployeeCode:id,
CreatedByEmployeeFullName:userName,
jsonString:{
JsonValues:{
id:"MyID",
values:dataString
}
}
}
But I want the result is exactly this
var result = {
"ConsigneeBranchName":"",
"ConsigneeBranchCode":"",
"ConsigneeBranchFullAddress":"",
"SenderBranchCode":"",
"SenderBranchName":"",
"SenderBranchFullAddress":"",
"CreatedByEmployeeCode":"",
"CreatedByEmployeeFullName":"",
"jsonString":"{
"JsonValues": {
"id": "MyID",
"values": {
"value1":{
"Description”:"testSmarter1",
"Length”:"60",
"Height”:"50",
"Weight”:"70",
"VolumeWeight”:"75",
"ActualWeight”:”78"
},
"value2:{
"Description":"Documents",
"Length":"120",
"Height":"68",
"Weight":"75",
"VolumeWeight":"122.4",
"ActualWeight":"123"
},
}
}
}
};
Please any one help me
I want the object with dynamic keys within a single object {key1:{des:1,value:as},key2:{des:2,value:aw},key3:{des:3,value:au}}
can you please help me I have tried so many times
see this below image I want this part, inside the single object, I can join multiple objects with dynamic keys
lodash already has a function called keyBy, you can use it to get this functionality. If adding lodash doesn't make sense in your project.
I have implemented a vanilla JS version.
function keyBy(array, mapperFn) {
const resultObj = {};
array.map(item => resultObj[mapperFn(item)] = item);
return resultObj;
}
function arrayToObject (array, keyName = 'id') {
return keyBy(array, function(element) {return element[keyName]});
}
API:
arrayToObject(targetArray, stringNameOfThePorpertyYouWantToUseAsKey);
USAGE:
const listOfUsers = [{name: 'Jenitha', reputation: 6}, {name: 'Chandan', reputation: 3}];
const mapOfUsersByName = arrayToObject(listOfUsers, 'name');

Mithril redraw only 1 module

If I have like 10 m.module on my page, can I call m.startComputation, m.endComputation, m.redraw or m.request for only one of those modules?
It looks like any of these will redraw all of my modules.
I know only module 1 will be affected by some piece of code, I only want mithril to redraw that.
Right now, there's no simple support for multi-tenancy (i.e. running multiple modules independently of each other).
The workaround would involve using subtree directives to prevent redraws on other modules, e.g.
//helpers
var target
function tenant(id, module) {
return {
controller: module.controller,
view: function(ctrl) {
return target == id ? module.view(ctrl) : {subtree: "retain"}
}
}
}
function local(id, callback) {
return function(e) {
target = id
callback.call(this, e)
}
}
//a module
var MyModule = {
controller: function() {
this.doStuff = function() {alert(1)}
},
view: function() {
return m("button[type=button]", {
onclick: local("MyModule", ctrl.doStuff)
}, "redraw only MyModule")
}
}
//init
m.module(element, tenant("MyModule", MyModule))
You could probably also use something like this or this to automate decorating of event handlers w/ local
Need multi-tenancy support for components ? Here is my gist link
var z = (function (){
//helpers
var cache = {};
var target;
var type = {}.toString;
var tenant=function(componentName, component) {
return {
controller: component.controller,
view: function(ctrl) {
var args=[];
if (arguments.length > 1) args = args.concat([].slice.call(arguments, 1))
if((type.call(target) === '[object Array]' && target.indexOf(componentName) > -1) || target === componentName || target === "all")
return component.view.apply(component, args.length ? [ctrl].concat(args) : [ctrl])
else
return {subtree: "retain"}
}
}
}
return {
withTarget:function(components, callback) {
return function(e) {
target = components;
callback.call(this, e)
}
},
component:function(componentName,component){
//target = componentName;
var args=[];
if (arguments.length > 2) args = args.concat([].slice.call(arguments, 2))
return m.component.apply(undefined,[tenant(componentName,component)].concat(args));
},
setTarget:function(targets){
target = targets;
},
bindOnce:function(componentName,viewName,view) {
if(cache[componentName] === undefined) {
cache[componentName] = {};
}
if (cache[componentName][viewName] === undefined) {
cache[componentName][viewName] = true
return view()
}
else return {subtree: "retain"}
},
removeCache:function(componentName){
delete cache[componentName]
}
}
})();

Dojo - don't repeat yourself

Is there a simpler way to write something like this in dojo (instead of having a function for each thing i want to show or hide)? I know there must be a way to avoid such repetition but I'm not sure how to do it.
on(dom.byId("thing_toggle2"), "click", function(){
if(thing_list2.style.display == "none") {
thing_list2.style.display = "block";
dom.byId("toggle2_sign").innerHTML = "(-)";
} else {
thing_list2.style.display = "none";
dom.byId("toggle2_sign").innerHTML = "(+)";
};
});
on(dom.byId("thing_toggle3"), "click", function(){
if(thing_list3.style.display == "none") {
thing_list3.style.display = "block";
dom.byId("toggle3_sign").innerHTML = "(-)";
} else {
thing_list3.style.display = "none";
dom.byId("toggle3_sign").innerHTML = "(+)";
};
});
I didn't test this, but it should give you a starting point. Adding an additional section, would just involve adding to the array of data.
var fnToggle = function(nodeMap) {
var expand = domStyle.get(dom.byId(nodeMap.contentNode), 'display') == 'none';
domStyle.set(dom.byId(nodeMap.contentNode), 'display', expand ? 'block' : '');
html.set(dom.byId(nodeMap.expandoNode), expand ? '+' : '-');
};
var nodes = [
{ eventNode: 'thing_toggle2', contentNode: thing_list2, expandoNode: 'toggle2_sign' },
{ eventNode: 'thing_toggle3', contentNode: thing_list3, expandoNode: 'toggle3_sign' }
];
array.forEach(nodes, function(nodeMap) {
on(dom.byId(nodeMap.eventNode), "click", function(){ fnToggle(nodeMap); });
});
// domStyle -> dojo/dom-style
// html -> dojo/html
// array -> dojo/_base/array
You could use dojo/fx/Toggler which uses dojo/_base/fx.fadeOut and dojo/_base/fx.fadeIn
I actually decided to do this as a plain old javascript function which I can reuse elsewhere, including pages that might not need dojo. Something like this:
[1]
[2]
<div id="myName" style="display:none;">Antonio</div>
<div id="anothername" style="display:none;">Elliot</div>
<script type="text/javascript">
function showlayer(layer){
var myLayer = document.getElementById(layer).style.display;
if(myLayer=="none"){
document.getElementById(layer).style.display="block";
} else {
document.getElementById(layer).style.display="none";
};
}
</script>

Deferring a Dojo Deferred

I'm having a bit of a problem getting a deferred returned from a method in a widget. The method is itself returns a Deferred as it's an xhrPost. The code is as such (using dojo 1.8)
Calling Code:
quorum = registry.byId("quorumPanel");
var deferredResponse = quorum.updateSelectionCount();
deferredResponse.then(function(data){
console.log("Success: ", data);
}, function(err){
console.log("Error: ", err);
});
and the code in the widget:
updateSelectionCount: function() {
var self = this;
var deferredResponse = xhr.post({
url: "ajxclwrp.php",
content: [arguments here],
handleAs: "json"});
deferredResponse.then(function(response) {
var anotherDeferred = new Deferred();
var _boolA = true;
var _boolB = true;
dojo.forEach(response.result, function(relationshipInfo){
[do a bunch of stuff here too set _boolA and/or _boolB]
});
self._sethasRequiredAttr(_hasRequired);
self._setHasRequestedAttr(_hasRequested);
self.quorumInfo.innerHTML = quorumHtml;
// Below is not working
anotherDeferred.resolve('foo');
return anotherDeferred;
});
}
Do I need to set up another promise and use promise/all. Im confused/frustrated at this point.
TIA.
the .then() method returns another deferred. You just need to put a return statement in.
updateSelectionCount: function() {
var self = this;
var deferredResponse = xhr.post({
url: "ajxclwrp.php",
content: [arguments here],
handleAs: "json"});
return deferredResponse.then(function(response) {
var _boolA = true;
var _boolB = true;
dojo.forEach(response.result, function(relationshipInfo){
[do a bunch of stuff here too set _boolA and/or _boolB]
});
self._sethasRequiredAttr(_hasRequired);
self._setHasRequestedAttr(_hasRequested);
self.quorumInfo.innerHTML = quorumHtml;
return "foo";
});
}