How to make some changes when calling shouldUpdate? - lit-element

I want to do the following:
When the property "mobile" is changed, check to see if X is true, if so, set set a variable Y and call requestUpdate to re-render the element. The element will render something different based on variable X.
so shouldUpdate function could be:
shouldUpdate(changedProperties) {
if (changedProperties.has("mobile")) {
this._showDialog = true;
this.requestUpdate();
await this.updateComplete;
}
return this.openingDialog;
}
What's the best way to do this without using the shouldUpdate function?

You can use willUpdate to compute Y variable. willUpdate used to compute values needed during the update.
willUpdate(changedProperties) {
if (changedProperties.has("mobile")) {
this._showDialog = true;
}
}

Related

How can I set a Global Variable using an If statement within a function in node.js?

I'm new to JavaScript and I'm struggling tying a couple of things together.
I need to set a global variable from within a function. The function is essentially querying a DB, getting an answer and doing a comparison to determine what variable to set.
Then, in a separate function, I need to set a value based on the value of the previous variable.
The problem I'm having is that the variables are only available within the function and I don't know how to set them to be available outside the function. I've tried to simplify the code so you can see what I'm attempting to do:
ddb.scan(scanparams, function(err, data) {
if (err) {
console.log(err);
} else {
var dbResp = data.key.value; //key is the name of the key, value is the value
if (Number(dbResp) === Number(sessionId)) { //sessionId is defined elsewhere
var result = '1';
} else {
var result = '0';
}
}
});
if result === '1' {
doThing1;
} else {
doThing2;
}
I can't move the logic for doThing into the previous function as it breaks other things. How can I expose the results of the DB query to other functions?

How to update a module.exports properly?

I have this file that stores some of my environment variables.
Let's call it generalEnv.js
module.exports = {
CONSTANT_1: process.env.CONSTANT_1,
CONSTANT_2: process.env.CONSTANT_2
};
When the app initializes, I don't put the value of process.env.CONSTANT_1 in the env variables yet because I have to look into some places first if it exists(mongodb for instance). If it does not exists on mongodb, I will add a value into process.env.CONSTANT_1 and I was expecting that the value will reflect on generalEnv now.
When I tried accessing the CONSTANT_1 in another file.
Let's call it getConstantOne.js
const { CONSTANT_1 } = require('./generalEnv');
module.exports = () => {
// I was expecting that CONSTANT_1 will have a value here now
if(!CONSTANT_1) {
// do something
}
return CONSTANT_1
}
it does not reflect.. how do I update the closure of generalEnv.js for process.env.CONSTANT_1 to reflect on CONSTANT_1?
When assigning to a variable (or a value in an object/element in an array), the assignment will replace the value, not modify it. Therefore, any "copies" of that value will not be affected, and remain the same. Consider this example:
let a = 0;
let b = a;
a = 1;
What happens to b? Answer: Its value is 0.
To work around this we need some way of modifying the value instead of replacing it. Unfortunately, "primitive types" (strings/numbers/booleans etc.) cannot be modified in javascript. There are types that can be modified however, such as objects. You could solve this by wrapping your variables in an object called "env".
let env: {
CONSTANT_1: process.env.CONSTANT_1,
CONSTANT_2: process.env.CONSTANT_2
}
modules.exports = { env }
and then to modify:
env.CONSTANT_1 = "new value"
and to access:
if (!env.CONSTANT_1) { ... }

Initialize a Blockly Mutator within JavaScript

Hi,
as far as I know, custom blocks in Blockly can be defined wether in JSON or in JavaScript, but how can a mutator be initialized in JavaScript?
with JSON:
Blockly.defineBlocksWithJSONArray([
{....
"mutator": "myMutatorName"
});
Then the Mutator_MIXIN must be defined and with Blockly.Extension.registerMutator('myMutatorName', Blockly.myMutator_MIXIN, null, null) the mutator is added to the Block.
with JavaScript:
Blockly.Blocks['blockName'] = {
init: function() = {
....
??? this.setMutator(???)???
};
}
So how can this be done in JavaScript?
Kind regards
a new one
I might be just a little bit late here, but I'll leave the answer anyway for those who need a bit more concrete example.
In JavaScript, you don't actually need to bind a mutator to your block, you just need to define mutationToDom() and domToMutation(xmlElement) functions, like so:
Blockly.Blocks['my_custom_block'] = {
init() {
// Define your basic block stuff here
},
// Mutator functions
mutationToDom() {
let container = document.createElement('mutation');
// Bind some values to container e.g. container.setAttribute('foo', 3.14);
return container;
},
domToMutation(xmlElement) {
// Retrieve all attributes from 'xmlElement' and reshape your block
// e.g. let foo = xmlElement.getAttribute('foo');
// this.reshape(foo);
},
// Aux functions
reshape(param){
// Reshape your block...
}
}
Blockly will automagically take care of the rest and allow you to treat your block as dynamic one.
And if you need to used Mutator Editor UI, you must define decompose(workspace) and compose(containerBlock) functions and call this.setMutator(...) to set which blocks are used in the Mutator Editor UI, like so:
Blockly.Blocks['my_custom_block'] = {
init() {
// Define your basic block stuff here
// Set all block that will be used in Mutator Editor UI, in this
// case only 'my_block_A' and
this.setMutator(new Blockly.Mutator(['my_block_A', 'my_block_B']));
},
// Mutator functions
mutationToDom() {
// Same as previous example
},
domToMutation(xmlElement) {
// Same as previous example
},
decompose(workspace) {
// Decomposeyour block here
},
compose(containerBlock) {
// Compose your block here
},
// Aux functions
reshape(param){
// Same as previous example
}
}
Hope that these short examples help someone :)
You have to declare how the xml is loaded to dom, and how it is saved to xml and redrawn. Also notice how it attaches a mutator to a block element in case that is the only part you need to reference a mutator already present.
init: initFunction (Like you have declared.)
mutationToDom: MutationToDom,
domToMutation: DomToMutation,
updateShape_: UpdateShape`
If all you require is to create a reference to a mutator then what you need is an element of this kind, which we will programatically create in a bit:
<mutation mutator_name="true"></mutation>
The following snippet is an example of the extra functions mutationToDom, DomtoMutation UpdateShape which attaches extra input conditionally. I have a block with a checkbox that when enabled, adds an extra input.
function MutationToDom() {
var container = document.createElement('mutation');
var continueOnError = (this.getFieldValue('HasCONTINUE') == 'TRUE');
container.setAttribute('continueOnError', continueOnError);
return container;
}
function DomToMutation(xmlElement) {
var continueOnError = (xmlElement.getAttribute('continueOnError') == 'true');
this.updateShape_(continueOnError);
}
function UpdateShape(continueOnError) {
// Add or remove a Value Input.
if (continueOnError) {
this.appendValueInput("CONTINUE_ON_ERROR")
.setCheck('CONTINUE_ON_ERROR');
} else {
if (this.childBlocks_.length > 0) {
for (var i = 0; i < this.childBlocks_.length; i++) {
if (this.childBlocks_[i].type == 'continue_on_error') {
this.childBlocks_[i].unplug();
break;
}
}
}
this.removeInput('CONTINUE_ON_ERROR');
}
}

Accessing variable outside of a closure in Groovy

Is there a way, i can access a variable outside the closure. The closure here is a stage in the Jenkinsfile. So, the snippet looks like this:
node('pool'){
try{
stage('init'){
def list = []
//some code to create the list
}
stage('deploy'){
//use the list create in the above stage/closure
}
}
catch(err){
//some mail step
}
}
With this code, i cannot access the list which was created in the first stage/closure.
How can i set to get this newly created list accessible to the next stage/closure?
#tim_yates.. with your suggestion. This works. It was easy at the end :)
node('pool') {
try {
def list = [] //define the list outside of the closure
stage('init') {
//some code to create/push elements in the list
}
stage('deploy') {
//use the list create in the above stage/closure
}
} catch (err) {
//some mail step
}
}
I know it's late, but worths mentioning that when you define a type or def (for dynamic resolution) you're creating a local scope variable that will be available only inside the closure.
If you omit the declaration the variable will be available to the whole script:
node('pool'){
try {
stage('Define') {
list = 2
println "The value of list is $list"
}
stage('Print') {
list += 1
echo "The value of list is $list"
}
1/0 // making an exception to check the value of list
}
catch(err){
echo "Final value of list is $list"
}
}
Returns :
The value of list is 2
The value of list is 3
Final value of list is 3

How to get web element (id) from the element position in D3.js force graph

I am working with the D3.js force graph but I am not able to find out the element id from the element position (which I know).
I am using Leap motion. I need to simulate a mouse event (a click, a move, a drag, etc.) without a mouse. And, if I am right, in order to be able to do this, I need to find out what is the the element id from the coordinates x and y (these coordinates I know from the Leap motion pointer). So from what you wrote above, I need to find out the ('.node’).
Here is what I already tried but it did not work:
Is it possible to use non-mouse, non-touch events to interact with a D3.js graph? If so, what is the most efficient way to go about it?
So I used this function (see below), but I need to know the element id to make it work correctly:
//graph.simulate(document.getElementById("r_1"), 'dblclick', {pointerX: posX, pointerY: posY});
//here id r_1 is hardcoded, but I need to find out id from x and y coordinates.
this.simulate = function (element, eventName) {
function extend(destination, source) {
for (var property in source)
destination[property] = source[property];
return destination;
}
var eventMatchers = {
'HTMLEvents': /^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/,
'MouseEvents': /^(?:click|dblclick|mouse(?:down|up|over|move|out))$/
};
var defaultOptions = {
pointerX: 0,
pointerY: 0,
button: 0,
ctrlKey: false,
altKey: false,
shiftKey: false,
metaKey: false,
bubbles: true,
cancelable: true
};
var options = extend(defaultOptions, arguments[2] || {});
var oEvent, eventType = null;
for (var name in eventMatchers) {
if (eventMatchers[name].test(eventName)) {
eventType = name;
break;
}
}
if (!eventType)
throw new SyntaxError('Only HTMLEvents and MouseEvents interfaces are supported');
if (document.createEvent) {
oEvent = document.createEvent(eventType);
if (eventType == 'HTMLEvents') {
oEvent.initEvent(eventName, options.bubbles, options.cancelable);
}
else {
oEvent.initMouseEvent(eventName, options.bubbles, options.cancelable, document.defaultView,
options.button, options.pointerX, options.pointerY, options.pointerX, options.pointerY,
options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.button, element);
}
element.dispatchEvent(oEvent);
}
else {
options.clientX = options.pointerX;
options.clientY = options.pointerY;
var evt = document.createEventObject();
oEvent = extend(evt, options);
element.fireEvent('on' + eventName, oEvent);
}
return element;
}
Many thanks for your help and ideas.
If you want access to the element, it's implicit in D3's iterators via this.
d3.selectAll('.node').each(function(d) {
console.log(this); // Logs the element attached to d.
});
If you really need access to the id, you can get it with selection.attr():
d3.selectAll('.node').each(function() {
console.log(d3.select(this).attr('id')); // Logs the id attribute.
});
You don't have to use each. Any of the iterators, such as attr or style, etc., have 'this' as the bound element:
d3.selectAll('.node').style('opacity', function(d) {
console.log(this);// Logs the element attached to d.
});
If you want the x and y coordinates of a node, it's part of the data:
d3.selectAll('.node').each(function(d) {
console.log(d.x, d.y); // Logs the x and y position of the datum.
});
If you really need the node attributes themselves, you can use the attr accessor.
d3.selectAll('.node').each(function(d) {
// Logs the cx and cy attributes of a node.
console.log(d3.select(this).attr('cx'), d3.select(this).attr('cy'));
});
EDIT: It looks like you need an element reference, but the only thing you know about the node in context is its position. One solution is to search through all nodes for a node with matching coordinates.
// Brute force search of all nodes.
function search(root, x, y) {
var found;
function recurse(node) {
if (node.x === x && node.y === y)
found = node;
!found && node.children && node.children.forEach(function(child) {
recurse(child);
});
}
recurse(root);
return found;
}
However this only gives you the node object, not the element itself. You will likely need to store the element references on the nodes:
// Give each node a reference to its dom element.
d3.selectAll('.node').each(function(d) {
d.element = this;
});
With that in place, you should be able to access the element and get its id.
var id, node = search(root, x, y);
if (node) {
id = node.element.getAttribute('id');
}
The brute-force search is fine for a small number of nodes, but if you're pushing a large number of nodes you might want to use D3's quadtree (example) to speed up the search.
Use d3.select('#yourElementId')
For more info check this out: https://github.com/mbostock/d3/wiki/Selections

Resources