Access JS this from Scala.js - javascript

I'm trying to convert this code from js library docs into scala.s:
$('#myTable').on( 'click', 'tbody td', function () {
editor.inline( this, {
submitOnBlur: true
} );
} );
Code I tried:
$("#table").on("click", ".editable", (thiz: js.Dynamic) => {
editor.inline(thiz, JC(
submitOnBlur = true
))
})
But it gives me error:
Cannot read property 'contents' of undefined at f.inline

The callback function you wrote, i.e.,
(thiz: js.Dynamic) => {
editor.inline(thiz, JC(
submitOnBlur = true
))
}
is a function of 1 parameter (that happens to be called thiz), instead of a function that receives this as a parameter. In other words, it is equivalent to the following in JS:
function(thiz) {
editor.inline(thiz, JC(...))
}
To get access to the this, you need to force your callback function to be a js.ThisFunction, as follows:
((thiz: js.Dynamic) => {
editor.inline(thiz, JC(
submitOnBlur = true
))
}): js.ThisFunction
This will take the first argument of the Scala lambda (in this case, the only one) and attach it to the this value of JavaScript, which is what you want.

Related

How to pass a parameter to a function that is passed to another function as string?

I have the following piece of code :
accountSelector.executeInParallel('processAccounts', 'postProcess');
function processAccounts() {
return JSON.stringify(syncMasterLists());
}
And instead of having this, I want to be able to pass a value to the processAccounts accounts function.
For the purpose I changed the code so it's looking like this now :
accountSelector.executeInParallel('processAccounts("DE")', 'postProcess');
function processAccounts(arg) {
return JSON.stringify(syncMasterLists());
}
Unfortunately, after introducing the change I started getting the following error :
Cannot find function processAccounts("DE").
I cannot understand am I doing this wrong(and if yes then what is wrong) or it's just something that can't be done.
I cannot understand am I doing this wrong(and if yes then what is
wrong) or it's just something that can't be done.
accountSelector.executeInParallel takes the function name as parameter and execute the same, processAccounts("DE") is not a valid function name or the name of the function that exists.
As per documentation, there is a way to pass optionalInput parameter
The input, if specified by optionalInput, will be passed into the
function specified by functionName
accountSelector.executeInParallel(functionName, optionalCallbackFunctionName, optionalInput)
In your case, it will be
accountSelector.executeInParallel('processAccounts', 'postProcess', 'DE' );
Why don't you call the function first and replace the result in the 'executeInParallel' method as follows:
var res = processAccounts("DE");
accountSelector.executeInParallel(res, 'postProcess');
function processAccounts(arg) {
return JSON.stringify(syncMasterLists());
}
Some closure can probably solve your problem, depends on how accountSelector.executeInParallel is implemented
const accountSelector = {
executeInParallel(pre, post) {
let result = eval(pre)()
eval(post)(result)
}
}
accountSelector.executeInParallel(processAccountsWithArg('Foo'), 'postProcess');
function processAccount(arg) {
console.log('processAccount', arg)
return JSON.stringify({
key: 'value'
});
}
function processAccountsWithArg(arg) {
return function() {
return processAccount(arg)
}
}
function postProcess(result) {
console.log('postProcess', result)
}

inside Array.push without a function call

I want to perform more logic before writing an element to an array:
tempDatensatz.push( () => {
var current = window.dataForDataTable[i].outbounds[key].updatedAt;
if (current) {
return current.toString();
} else {
return "".toString();
}
});
Getting the value from that array will be achieved like this:
tempDatensatz[0]()
But I want the same logic in it without having a function to call. I need a normal array, where I get a value like this:
tempDatensatz[0]
What can I do instead?
Updated
I published my project to gitHub, you can take a look if you need a better understanding :)
https://github.com/te2020/GoEuro/blob/master/GoEuro/Views/Home/Index.cshtml
Use an immediately invoked function instead of just a function:
tempDatensatz.push( (function(){
var current = window.dataForDataTable[i].outbounds[key].updatedAt;
if (current) {
return current.toString();
} else {
return "".toString();
}
})());
The function will be executed immediatly after it definition, returning the result. So push won't push a reference to that function but instead it will push it returned value (the result).
You can write a proxy as follows:
function makeProxy(array) {
return new Proxy(array, {
get(target, property) {
return !isNaN(property) ? target[property]() : target[property];
}
});
}
const tempDatensatz = [];
const useThisOne = makeProxy(tempDatensatz);
useThisOne.push(() => alert("Hi, Jane!"));
useThisOne[0];
Pushing/writing to the array will work as expected, but retrieving its elements will go through the get handler, which will execute the function.
You could just use an expression, like:
tempDatensatz.push(
(window.dataForDataTable[i].outbounds[key].updatedAt || '').toString();
);
For more complex expressions you can often use the ternary operator. For the above that would look like this:
tempDatensatz.push(
window.dataForDataTable[i].outbounds[key].updatedAt
? window.dataForDataTable[i].outbounds[key].updatedAt.toString()
: ''
);
Your code
When looking at the github code you linked to, you can do all that pushing with this "oneliner":
var tempDatensatz =
['companyId', 'mode', 'duration', 'outboundId', 'journeyId', 'departureTime',
'arrivalTime', 'stops', 'price', 'updatedAt', 'segments']
.map( prop => (window.dataForDataTable[i].outbounds[key][prop] || '').toString() );

Pass additional parameters to bind?

I have two functions that look like this:
primaryImageLoaded () {
this.setState({primaryImageLoaded: true})
}
secondaryImageLoaded () {
this.setState({ secondaryImageLoaded: true })
}
They are called like this(using react):
onLoad={this.secondaryImageLoaded.bind(this)
This feels excessive and I would like to have just one function and pass the state-variable as a parameter, but how can I pass an additional argument to .bind? and is it possible to use a variable as key in the object i'm passing to setState?
You can pass additional arguments to bind that will be passed when your function is invoked:
this.secondaryImageLoaded.bind(this, arg1, arg2)
If you are using ECMAScript 2015 and onwards, you can use a variable as a key by wrapping it in square brackets:
this.setState({
[myVar]: value
});
So you could rewrite it to be more like:
function imageLoaded(which) {
this.setState({
[which]: true
});
}
onLoad={this.imageLoaded.bind(this, 'secondary')}
You can use arrow function for definition your function, and this way you don't need bind method.
secondaryImageLoaded = () => {
this.setState({ secondaryImageLoaded: true })
}
After that, in your jsx code:
onLoad={this.secondaryImageLoaded}
If you want know more about that you read this article

jQuery cssHooks is not called

I am trying to hook css get/set. However after installing a simple pass thru hook it seems to be not called: (no error messages in Chrome console)
$.cssHooks['padding-left'] = {
get: function( elem, computed, extra ) {
return $.css( elem, $['padding-left'] );
},
set: function( elem, value) {
// Setting breakpoint here in Chrome, this line is not called:
elem.style[ $.support['padding-left'] ] = value;
}
};
// Proof of concept: Should not this statement initiate the hooked setter call?
// This statement is called, confirmed via breakpoint
$('#et-top-navigation').css('padding-left', '0px');
What am I missing?
Use the camel-case javascript property name rather than the hyphenated css style.
$.cssHooks['paddingLeft'] = { ...
You need wrap all of that in a document ready call, because jQuery writes cssHooks at this time and will get rid of your functions if they exist.
Take a look at the skeleton template in the API
https://api.jquery.com/jQuery.cssHooks/
(function( $ ) {
// First, check to see if cssHooks are supported
if ( !$.cssHooks ) {
// If not, output an error message
throw( new Error( "jQuery 1.4.3 or above is required for this plugin to work" ) );
}
// Wrap in a document ready call, because jQuery writes
// cssHooks at this time and will blow away your functions
// if they exist.
$(function () {
$.cssHooks[ "someCSSProp" ] = {
get: function( elem, computed, extra ) {
// Handle getting the CSS property
},
set: function( elem, value ) {
// Handle setting the CSS value
}
};
});
})( jQuery );

Set ReactiveDict() variable inside of custom event function

I try to set a ReactiveDict-variable on a custom event inside of on(), but I get this error: Uncaught TypeError: Cannot read property 'templateDictionary' of null.
The second question is, if it would make sense to define the ReactiveDict() in onRendered?
Template.something.onCreated(function() {
this.templateDictionary = new ReactiveDict();
});
Template.something.onRendered(function() {
anything.on({
'element:mouseover': function(elementView, event){
Template.instance().templateDictionary.set( 'showExtraFields', true );
}
});
});
Template.something.helpers({
anything: function() {
var result = Template.instance().templateDictionary.get( 'showExtraFields' );
console.log(result);
}
});
Put instance reference inside onRendered function. Not inside another function. Scope issue.
I have no idea what anything.on is, but try this:
Template.something.onRendered(function() {
anything.on({
'element:mouseover': (elementView, event) => {
this.templateDictionary.set( 'showExtraFields', true );
}
});
});
Use the ES6, Luke!

Categories