Invoke Typescript from a Javascript callback - javascript

I'm using Markdown-it in my Angular 2 project. I want to create a plugin to extend Markdown-it. I have the basic Markdown-it working and can add a javascript plugin like this
PluginSetup(md) {
console.log('Enter PluginSetup');
md.inline.ruler.after('emphasis', 'cards', function x(state, silent) {
return false;
});
}
I see the console message and everything works fine.
Now I want the callback to invoke some Typescript. I've tried
export class PlugIns {
CardSymbols(state, silent) {
console.log('Enter CardSymbols');
return false;
}
PluginSetup(md) {
console.log('Enter PluginSetp');
md.inline.ruler.after('emphasis', 'cards', function x(state, silent) {
console.log('Enter x');
return this.CardsSymbols(state, silent);
});
}
}
I see the 'Enter x' console message and then
EXCEPTION: Error in ./ArticleDisplayComponent class ArticleDisplayComponent - inline template:0:5 caused by: Object doesn't support property or method 'CardSymbols'
How do I call Typescript from a javascript callback?
RESOLVED
None of the suggestions or referenced articles changed the error message but I do have a resolution.
md.inline.ruler.after('emphasis', 'cards', Plugins.prototype.CardSymbols);
Thanks for all the suggestions

Related

NextJS TypeError: Cannot read properties of null (reading 'length')

Anyone know the cause of this error?
warn - Fast Refresh had to perform a full reload. Read more: https://nextjs.org/docs/basic-features/fast-refresh#how-it-works
TypeError: Cannot read properties of null (reading 'length')
at eval (webpack-internal:///./node_modules/next/dist/client/dev/error-overlay/hot-dev-client.js:262:55)
I have tried commenting out any components running in pages and creating a new NextJS-ts project from scratch but the error persists.
Yeah, seems like a next 13 bug. It doesn't seem to be breaking anything that I can tell.
It is probably the following const hasUpdates = Boolean(updatedModules.length); just needs to be const hasUpdates = Boolean(updatedModules && updatedModules.length);
I checked this directory:"./node_modules/next/dist/client/dev/error-overlay/hot-dev-client.js:262:55" in v "13.0.1" and v"13.0.3". In both this function is defined same:
function tryApplyUpdates(onHotUpdateSuccess) {
if (!module.hot) {
// HotModuleReplacementPlugin is not in Webpack configuration.
console.error('HotModuleReplacementPlugin is not in Webpack configuration.');
// window.location.reload();
return;
}
if (!isUpdateAvailable() || !canApplyUpdates()) {
(0, _client).onBuildOk();
return;
}
function handleApplyUpdates(err, updatedModules) {
if (err || hadRuntimeError || !updatedModules) {
if (err) {
console.warn('[Fast Refresh] performing full reload\n\n' + "Fast Refresh will perform a full reload when you edit a file that's imported by modules outside of the React rendering tree.\n" + 'You might have a file which exports a React component but also exports a value that is imported by a non-React component file.\n' + 'Consider migrating the non-React component export to a separate file and importing it into both files.\n\n' + 'It is also possible the parent component of the component you edited is a class component, which disables Fast Refresh.\n' + 'Fast Refresh requires at least one parent function component in your React tree.');
} else if (hadRuntimeError) {
console.warn('[Fast Refresh] performing full reload because your application had an unrecoverable error');
}
performFullReload(err);
return;
}
const hasUpdates = Boolean(updatedModules.length);
if (typeof onHotUpdateSuccess === 'function') {
// Maybe we want to do something.
onHotUpdateSuccess(hasUpdates);
}
if (isUpdateAvailable()) {
// While we were updating, there was a new update! Do it again.
// However, this time, don't trigger a pending refresh state.
tryApplyUpdates(hasUpdates ? undefined : onBeforeHotUpdate, hasUpdates ? _client.onBuildOk : onHotUpdateSuccess);
} else {
(0, _client).onBuildOk();
if (process.env.__NEXT_TEST_MODE) {
afterApplyUpdates(()=>{
if (self.__NEXT_HMR_CB) {
self.__NEXT_HMR_CB();
self.__NEXT_HMR_CB = null;
}
});
}
}
// in here its call handleApplyUpdates
}
this is just definition of the function. But difference is when call it: In v"13.0.1", this is how they call
module.hot.check(/* autoApply */ true).then((updatedModules)=>{
// without any check "updatedModules" is just passed assumet it is an array
handleApplyUpdates(null, updatedModules);
}, (err)=>{
handleApplyUpdates(err, null);
});
in v"13.0.3", they made a type checking first
module.hot.check(/* autoApply */ false).then((updatedModules)=>{
if (typeof onBeforeHotUpdate === 'function') {
const hasUpdates = Boolean(updatedModules.length);
onBeforeHotUpdate(hasUpdates);
}
return module.hot.apply();
}).then((updatedModules)=>{
handleApplyUpdates(null, updatedModules);
}, (err)=>{
handleApplyUpdates(err, null);
});
Probably it was a bug in your next.js version. if you use v"13.0.3", it should work
Instead of using export default function Page(){}
Change this to an es6 function const Page = () => {}
And add export default Page to the bottom.
I did this for the Layout as well.
This worked for me somehow :)
I ran into this same issue. I was also following the tutorial with the exception of creating an about page instead of an index. When I used a regular function in about.js I received the same error. The function looked like this:
function AboutPage() {
return <div>The About Page</div>;
}
export default AboutPage;
When I changed it to an arrow function the error went away. The arrow function looked like this:
const AboutPage = () => {
return <div>The About Page and Stuff</div>;
}
export default AboutPage;
I'm not sure why next threw an error on the regular function, but changing it to an arrow functions seems to have done the trick.

Sentry on Internet Explorer 11

I'm using Sentry to log some errors on Javascript but while using Internet Explorer 11 I'm getting Syntax Error while configuring the scope
function addSentryTag(key, value) {
if (Sentry) {
Sentry.configureScope(scope => { scope.setTag(key, value);})
}
}
I assume the problem is using the lambda expression. Is there another way to add Tags to the scope?
I dont think IE11 supports the arrow syntax => are you running your code through any compilers like babel before trying it in the browser if not?
You can try this syntax:
function addSentryTag(key, value) {
if (Sentry) {
Sentry.configureScope(function(scope) {
scope.setTag(tag, value)
})
}
}
Give it a go :)
The same code without the lambda function:
function addSentryTag(key, value) {
if (Sentry) {
Sentry.configureScope(function(scope){
scope.setTag(key, value);
});
}
}

Classy Dojo - Internal method calls

I am a total beginner at dojo and am trying to move some of my interface code into a class just to keep the methods out of my main file.
My problem - I am unable to use internal class functions as part of other functions.
After I create an interface object in an external file as shown, I am able to sucessfully:
appInterface = new (interface)
appInterface.showGraphWindow()
appInterface.hideGraphWindow()
However I am unable to work out how to use these functions inside of the toggleGraphWindow function. (Due to context ?)
If I attempt to call:
on(registry.byId("graphBtn"),"click", appInterface.toggleGraphWindow);
It crashes on the line:
this.showGraphWindow()
or
this.hideGraphWindow()
With: "Undefined is a not a function"
How do I code the toggleGraphWindow function?
Iterface.js
define([
"dojo/_base/declare",
"dojo/on",
"dijit/registry"
],
function(
declare,
on,
registry
){
return declare (null, {
hideGraphWindow : function () {
dijit.byId("graphWindowMain").domNode.style.display = 'none';
dijit.byId("applicationWindow").resize();
},
showGraphWindow : function () {
dijit.byId("graphWindowMain").domNode.style.display = 'block';
dijit.byId("applicationWindow").resize();
},
toggleGraphWindow : function (){
if (dijit.byId("graphBtn").checked == true)
{this.showGraphWindow()}
else
{this.hideGraphWindow()}
}
});
});
What's wrong with
toggleGraphWindow : function (){
if (dijit.byId("graphBtn").checked == true) {
this.showGraphWindow();
}
else {
this.hideGraphWindow();
}
}
?
Thanks to you both, you were indeed correct Ken, I had read this similar post a lot of times, and somehow didnt understand the answer within:
Calling object methods internally in dojo
After reading what you have posted, I have somehow understood the answer linked above and now understand what my problem was! Thanks to all.
I fixed it by altering my code in the main application as follows:
var appInterface = new Interface();
on(registry.byId("graphBtn"),"click", appInterface.toggleGraphWindow);
changed to:
var appInterface = new Interface();
var graphToggle = dojo.hitch(appInterface, "toggleGraphWindow");
on(registry.byId("graphBtn"),"click", graphToggle);
I believe the reason for the error, was that the "this" object at runtime, was actually the "graphBtn" instead of the appInterface.

Methods in YUI module pattern don't show up in IDE structure view

I have made a YUI module a little like the code shown below, which is the recommended pattern for YUI3 stuff, both within YUI's own core files and within Moodle as per here.
The problem is that now I can't see any of the methods (such as initializer() and show() in the code below) in the IDE's file structure/navigator pane. It seems that the Y.extend() logic is too much to handle, despite previous use of YAHOO.lang.Extend() outside of the sandboxed pattern used below working fine.
Has anyone any suggestions as to how to fix this? Is it just my IDE (tried IntelliJ IDEA - bug here, and NetBeans)? Surely the YUI devs don't have this same problem do they?
YUI.add('moodle-local_hub-comments', function (Y) {
var COMMENTSNAME = 'hub_comments';
var COMMENTS = function () {
COMMENTS.superclass.constructor.apply(this, arguments);
}
M.local_hub = M.local_hub || {};
Y.extend(M.local_hub, Y.Base, {
// Invisible property:
event : null,
// Invisible function:
initializer : function (params) {
// function code here
},
// Invisible function:
show : function (e) {
// function code here
},
// Invisible function:
hide : function () {
// function code here
}
}, {
NAME : COMMENTSNAME,
ATTRS : {
commentids : {value : 450}
}
});
}, '#VERSION#', {
requires : ['base', 'overlay', 'moodle-enrol-notification']
//Note: 'moodle-enrol-notification' contains Moodle YUI exception
});
Every IDE I've ever seen (I've tried NetBeans, jEdit, Sublime, and at least four different Eclipse JS editors) has failed to display methods like your's in the outline view. I know there's a ticket to fix the issue in Eclipse (https://bugs.eclipse.org/bugs/show_bug.cgi?id=266113), but I'm not holding my breath: this seems to be something that's very hard for IDEs to do.
If you wanted, you could always refactor your code to be more IDE-friendly, but you'd lose your encapsulation:
function initializer(e) {
// function code here
}
function show() {
// function code here
}
function hide {
// function code here
}
function moodle-local_hub-comments (Y) {
var COMMENTSNAME = 'hub_comments';
var COMMENTS = function () {
COMMENTS.superclass.constructor.apply(this, arguments);
}
M.local_hub = M.local_hub || {};
Y.extend(M.local_hub, Y.Base, {
event : null,
initializer : initializer,
show : show,
hide : hide
}
YUI.add('moodle-local_hub-comments', moodle-local_hub-comments, {
NAME : COMMENTSNAME,
ATTRS : {
commentids : {value : 450}
}
});
}, '#VERSION#', {
requires : ['base', 'overlay', 'moodle-enrol-notification']
//Note: 'moodle-enrol-notification' contains Moodle YUI exception
});
This appears to be a possible bug with IntelliJ, with details here. Good to know that they at least in theory support it.
As a worksround, JSDoc can be added above the extends function like this:
/**
* #class M.local_hub
**/
Y.extend(M.local_hub, Y.Base, {
Which makes all the methods show up :)

JavaScript how to mock confirm method

I have following code in my JavaScript code.
if (window.confirm('Are you sure?')) {
AdminData.actOnResult('delete');
}
I am writing test for this piece of code. How do I mock window.confirm method? I tried following code but it did not work.
window.confirm = function(arg) {
return true;
};
I can move the window.confirm method to another function and then I can mock that method. However I was wondering if there is a better solution.
Your own code works fine for me in IE. Just the following in the global scope should override it:
var confirm = function () { return true; }
EDIT
I've seen a few questions on SO in the past about trying to override confirm, mostly because they don't like it (and who would?). If you're trying to bypass it for this sort of reason, I suggest you look at changing your code to implement a callback-based replacement for confirm. Take a look at jQuery UI's modal confirm for a good example of this.
I am using Jasmine for unit testing and have mocked alert and confirm with the following
alert = function (alertString) {debug.log('ALERT:', alertString);};
var confirmValue = true; //set this before you expect the confirm statement to be shown
confirm = function (confirmString) {
debug.log('CONFIRM:', confirmString, confirmValue);
return confirmValue;
};
Then I can say:
describe("test", function () {
it('should test true confirm workflow', function () {
confirmValue = true; // or false if you like
//expect outcomes that would come from any confirms being called with true
});
});
It's not perfect, and if you have multiple confirms that could pop between setting that confirmValue, you could be in trouble. Perhaps then it would be good to setup a cue of expected confirm return values... tricky...
I'd think about implementing a wrapper around static methods on the window (or other) object. Then provide your wrapper to whatever uses the static method. Obviously this is easier if you are using a "class"-based implementation. Then, in order to mock the method, simply provide a different wrapper that returns the value that you want.
var windowWrapper = {
confirm: function(msg) { return confirm(msg); },
...
};
var mockWrapper = {
confirm: function(msg) { return true; },
...
}
var wrapper = windowWrapper;
if (test) {
wrapper = mockWrapper;
}
...
if (wrapper.confirm('Are you sure?')) {
AdminData.actOnResult('delete');
}

Categories