Game Maker JS Extension - javascript

Hi I'm looking to add javascript functions to game maker, but the format of them is like this:
companyname.initialize({
soundMuteCallback: muteSound, // optional
soundUnmuteCallback: unmuteSound // optional
});
And in the file they look like this
this.initialize = function(params) {
companyname.getSharedEventCenter().postEvent(SharedEventKeys.API_INITIALIZE);
_isInitialized = true;
if (typeof params !== "undefined") {
var muteSoundCallback = ("soundMuteCallback" in params && typeof params["soundMuteCallback"] === "function") ? params["soundMuteCallback"] : undefined;
var unmuteSoundCallback = ("soundUnmuteCallback" in params && typeof params["soundUnmuteCallback"] === "function") ? params["soundUnmuteCallback"] : undefined;
_adsManager.setSoundCallbacks(function() {
typeof muteSoundCallback === "function" && muteSoundCallback();
[].forEach.call(document.getElementsByTagName("audio"), function(element){
element.muted = true;
});
}, function() {
typeof unmuteSoundCallback === "function" && unmuteSoundCallback();
[].forEach.call(document.getElementsByTagName("audio"), function(element){
element.muted = false;
});
});
}
_tryShowAd();
};
Does anyone have any idea how to do this in game maker? I don't know what information to put in the extension function properties.
Thanks,
Mitchell.

I would recommend creating a new function that Game Maker can understand and then use that to create your object and the constructor you are showing here.
company.initialize = function(params) {
companyname.getSharedEventCenter().postEvent(SharedEventKeys.API_INITIALIZE);
_isInitialized = true;
if (typeof params !== "undefined") {
var muteSoundCallback = ("soundMuteCallback" in params && typeof params["soundMuteCallback"] === "function") ? params["soundMuteCallback"] : undefined;
var unmuteSoundCallback = ("soundUnmuteCallback" in params && typeof params["soundUnmuteCallback"] === "function") ? params["soundUnmuteCallback"] : undefined;
_adsManager.setSoundCallbacks(function() {
typeof muteSoundCallback === "function" && muteSoundCallback();
[].forEach.call(document.getElementsByTagName("audio"), function(element){
element.muted = true;
});
}, function() {
typeof unmuteSoundCallback === "function" && unmuteSoundCallback();
[].forEach.call(document.getElementsByTagName("audio"), function(element){
element.muted = false;
});
});
}
_tryShowAd();
};
function createMuteCallback() {
muteCallback = function () {
// Code to handle the callback
}
return muteCallback;
}
function createUnmuteCallback() {
unmuteCallback = function () {
// Code to handle the callback
}
return unmuteCallback;
}
function createCompany (mute, unmute) {
if (mute == 1) {
soundMuteCallback.createMuteCallback();
}
if (unmute == 1) {
soundUnmuteCallback.createUnmuteCallback();
}
company.initialize(soundMuteCallback, soundUnmuteCallback);
}
So all of that goes in the same .js file. Create a new extension in Game Maker. Add the .js file to that extension. Add a function named createCompany with two optional parameters.
Then when you call createCompany(1, 1); in your Game Maker code, the .js file will run and will initialize the company object with the two callback functions.
Hope this helps.

Related

How to properly init a sub function in JavaScript?

Please consider the following code. This code works as expected.
function paging(totalItems, currentPage, itemsPerPage) {
this.totalItems = (typeof totalItems !== 'undefined') ? totalItems : 0;
this.currentPage = (typeof currentPage !== 'undefined') ? currentPage : 1;
this.itemsPerPage = (typeof itemsPerPage !== 'undefined') ? itemsPerPage : 18;
}
function viewModel(foo, bar, paging) {
this.foo = (typeof foo !== 'undefined') ? foo : true;
this.bar = (typeof bar !== 'undefined') ? bar : false;
this.paging = (typeof paging !== 'undefined') ? paging : {};
}
function init() {
// Create a new viewmodel object and assign it to $scope (AngularJS)
$scope.viewModel = new viewModel();
// Set the paging parameter to a new paging object
$scope.viewModel.paging = new paging();
// Now we can use dot notation to assign the value in the sub-function
$scope.viewModel.paging.currentPage = 1;
}
init();
Now, what I'm trying to do, and can't quite figure out, is how to call "new viewModel()" and have the paging property automatically populate itself with a new paging(), without having to make the extra call in init(). So, for example, something like this...
function viewModel(foo, bar, paging) {
this.foo = (typeof foo !== 'undefined') ? foo : true;
this.bar = (typeof bar !== 'undefined') ? bar : false;
this.paging = (typeof paging !== 'undefined') ? paging : new paging();
}
Which throws an error about a constructor if I remember correctly.
I also tried this:
function viewModel(foo, bar, paging) {
this.foo = (typeof foo !== 'undefined') ? foo : true;
this.bar = (typeof bar !== 'undefined') ? bar : false;
function paging(totalItems, currentPage, itemsPerPage) {
this.totalItems = (typeof totalItems !== 'undefined') ? totalItems : 0;
this.currentPage = (typeof currentPage !== 'undefined') ? currentPage : 1;
this.itemsPerPage = (typeof itemsPerPage !== 'undefined') ? itemsPerPage : 18;
}
}
... and several other forms of the above, but nothing seems to properly init the paging property except the original example. Isn't there a better way to handle this?

KnockoutJS: issues validating multiple rows with dropdownlists

So I'm trying validate the two dropdowns that I have on button click. When the dropdowns first initiate, they are initiated with a value of undefined because nothing has been selected. This is what I want. But when I click the add button to validate the dropdowns before I add another row, the validation never occurs.
JS
ko.validation.init({
insertMessages: false,
errorMessageClass: "ErrorLine"
});
ko.validation.rules['bothUndefined'] = {
getValue: function (o) {
return (typeof o === 'function' ? o() : o);
},
validator: function (val, params) {
var self = this;
var anyOne = ko.utils.arrayForEach(params, function (param) {
if (typeof param === "function") {
return typeof param() === "undefined";
} else {
return (typeof param === "undefined");
}
});
return (typeof anyOne !== "undefined");
},
message: 'Please select one change.'
};
ko.validation.registerExtenders();
function BookPossessionTransferVM() {
var self = this;
.
.
.
self.PossessionChanges = ko.observableArray([]);
self.PossessionChangesErrors = ko.validation.group(self.PossessionChanges(), { deep: true, live: true });
self.PossessionChanges.push(new PossessionChangeVM(self.PossessionChanges().length +1))
.
.
.
self.addPossessionChange = function () {
if (self.PossessionChanges().length < 1) {
self.PossessionChanges.push(new PossessionChangesVM(self.PossessionChanges().length + 1,
self.AllFrom()));
} else {
self.PossessionChangesErrors.showAllMessages();
}
}
}
function PossessionChangeVM(possessionChangeId) {
var self = this;
self.possessionChangeId = ko.observable(possessionChangeId);
self.SelectedFrom = ko.validatedObservable();
self.SelectedTo = ko.validatedObservable();
self.IsValidRow = ko.pureComputed(function() {
return typeof self.SelectedFrom !== "undefined" && typeof self.SelectedTo !== "undefined";
}).extend({
bothUndefined: {
params: [self.SelectedFrom, self.SelectedTo]
}
});
self.ChangeType = ko.pureComputed(function() {
if (self.SelectedFrom() !== undefined && self.SelectedTo() !== undefined) {
return 'Update';
} else if (self.SelectedFrom() === undefined && self.SelectedTo() === undefined) {
return '';
} else if (self.SelectedFrom() === undefined) {
return 'Add';
} else if (self.SelectedTo() === undefined) {
return 'Remove';
} else { return ''; }
});
}
After I click the add button, I am expecting PossessionChangesErrors to have one issue since it should load with undefined options. But I am getting nothing. Thanks again for helping!
EDIT:
Now I have the validation working, but I am not able to clear the validation to create a new row once one of the drop downs have been selected. Here is the fiddle: https://jsfiddle.net/p6x1nqm5/18/
Turns out I just didn't have the correct logic for the validation. Here is the new fiddle with the changes. https://jsfiddle.net/zw80kh2n/2/
self.IsValidRow became
self.IsValidRow = ko.pureComputed(function() {
return (!(self.SelectedFrom() === undefined && self.SelectedTo() === undefined))
}).extend({ bothUndefined: {}
});
and the validation became
ko.validation.rules['bothUndefined'] = {
getValue: function (o) {
return (typeof o === 'function' ? o() : o);
},
validator: function (val) {
return val;
},
message: 'Please select one change.'
};
ko.validation.registerExtenders();

DRY way to throw the same TypeError in more than one functions

I have some functions that each one uses an object as an argument.
All these objects have similar structure, so instead of making the same checks in each function, I've created some check functions:
const checkIfOptionsIsObject = options => {
if (typeof options === 'object') {
return true;
} else {
throw new TypeError('The function argument should be an object.');
}
}
and
const checkOptionsMinMax = options => {
if (isNaN(options.min) || isNaN(options.max)) {
throw new TypeError("'min' and 'max' should both be numbers.");
} else if (options.min > options.max) {
throw new Error("'min' shouldn't be greater than 'max'");
} else {
return true;
}
}
And here is how I am using them:
const firstFunction = options => {
checkIfOptionsIsObject(options);
checkOptionsMinMax(options);
// do some stuff
return result;
}
const secondFunction = options => {
checkIfOptionsIsObject(options);
checkOptionsMinMax(options);
// do some other stuff
return result;
}
const thirdFunction = options => {
checkIfOptionsIsObject(options);
// do some stuff that doesn't use min and max
return result;
}
Is there any problem in this code?
1) note that in your first check typeof object === 'object' if that variable named object is actualy an array it will also give you the type of 'object'. You can see this in your console by entering typeof [ ] === 'object' and notice that it'll return true. It's better to use o !== null && typeof o === 'object' && Array.isArray(o) === false; for object testing.
const checkIfOptionsIsObject = options => {
if (options !== null && typeof options === 'object' && Array.isArray(options) === false) {
return true;
} else {
throw new TypeError('The function argument should be an object.');
}
}

How can I create empty JSON keys (nested or not) using a string?

I currently have this code built in JS, but it's really, really ugly.
Is there any better way to approach it?
The way it works basically is pushing a string like app.chat.test to be the key, and value like teststr.
I test the lengths to see if the "parent" key is there, otherwise we build it.
function constructJson(jsonKey, jsonValue){
//REWRITE!!!!!!!!
let jsonObj = langFile;
let jsonKeyArr = jsonKey.split('.')
if (jsonKeyArr.length === 1) {
if (valToAdd === undefined) {
if (jsonObj[jsonKey] === undefined) {
jsonObj[jsonKey] = {}
}
} else {
if (jsonObj[jsonKey] === undefined) {
jsonObj[jsonKey] = valToAdd
}
}
} else if (jsonKeyArr.length === 2) {
if (jsonObj[jsonKeyArr[0]] === undefined) {
jsonObj[jsonKeyArr[0]] = {}
}
if (jsonObj[jsonKeyArr[0]][jsonKeyArr[1]] === undefined) {
jsonObj[jsonKeyArr[0]][jsonKeyArr[1]] = jsonValue
}
} else if (jsonKeyArr.length === 3) {
if (jsonObj[jsonKeyArr[0]] === undefined) {
jsonObj[jsonKeyArr[0]] = {}
}
if (jsonObj[jsonKeyArr[0]][jsonKeyArr[1]] === undefined) {
jsonObj[jsonKeyArr[0]][jsonKeyArr[1]] = {}
}
if (jsonObj[jsonKeyArr[0]][jsonKeyArr[1]][jsonKeyArr[2]] === undefined) {
jsonObj[jsonKeyArr[0]][jsonKeyArr[1]][jsonKeyArr[2]] = jsonValue
}
} else if (jsonKeyArr.length === 4) {
if (jsonObj[jsonKeyArr[0]] === undefined) {
jsonObj[jsonKeyArr[0]] = {}
}
if (jsonObj[jsonKeyArr[0]][jsonKeyArr[1]] === undefined) {
jsonObj[jsonKeyArr[0]][jsonKeyArr[1]] = {}
}
if (jsonObj[jsonKeyArr[0]][jsonKeyArr[1]][jsonKeyArr[2]] === undefined) {
jsonObj[jsonKeyArr[0]][jsonKeyArr[1]][jsonKeyArr[2]] = {}
}
if (jsonObj[jsonKeyArr[0]][jsonKeyArr[1]][jsonKeyArr[2]][jsonKeyArr[3]] === undefined) {
jsonObj[jsonKeyArr[0]][jsonKeyArr[1]][jsonKeyArr[2]][jsonKeyArr[3]] = jsonValue
}
} else if (jsonKeyArr.length === 5) {
if (jsonObj[jsonKeyArr[0]] === undefined) {
jsonObj[jsonKeyArr[0]] = {}
}
if (jsonObj[jsonKeyArr[0]][jsonKeyArr[1]] === undefined) {
jsonObj[jsonKeyArr[0]][jsonKeyArr[1]] = {}
}
if (jsonObj[jsonKeyArr[0]][jsonKeyArr[1]][jsonKeyArr[2]] === undefined) {
jsonObj[jsonKeyArr[0]][jsonKeyArr[1]][jsonKeyArr[2]] = {}
}
if (jsonObj[jsonKeyArr[0]][jsonKeyArr[1]][jsonKeyArr[2]][jsonKeyArr[3]] === undefined) {
jsonObj[jsonKeyArr[0]][jsonKeyArr[1]][jsonKeyArr[2]][jsonKeyArr[3]] = {}
}
if (jsonObj[jsonKeyArr[0]][jsonKeyArr[1]][jsonKeyArr[2]][jsonKeyArr[3]][jsonKeyArr[4]] === undefined) {
jsonObj[jsonKeyArr[0]][jsonKeyArr[1]][jsonKeyArr[2]][jsonKeyArr[3]][jsonKeyArr[4]] = jsonValue
}
} else if (jsonKeyArr.length > 5) {
return console.log("Length over 5 not supported yet!")
}
return jsonObj;
}
Regards.
OF course it's possible, a simple loop will perfeclty do the job.
function constructJson(jsonKey, jsonValue){
//REWRITE!!!!!!!!
langFile = {a:{}, foo:{}};// remove this for your own code
var jsonObj = langFile;
var jsonKeyArr = jsonKey.split('.');
var currentValue = jsonObj;
for(var i = 0; i < jsonKeyArr.length;i++){
if(currentValue[jsonKeyArr[i]]===undefined){
currentValue[jsonKeyArr[i]] = {};
}
if(i < jsonKeyArr.length-1){
currentValue = currentValue[jsonKeyArr[i]];
}else{
currentValue[jsonKeyArr[i]] = jsonValue;
}
}
return jsonObj;
}
alert(JSON.stringify(constructJson("a.b.cd.ef", "toto")));
I just assigning to a temporary variable each sublevel. When i'm on the last i'm assigning the value.
Yes you can, using the javascript reduce function on the array created from the splitted string.
function namespaceCreateExceptLast(representationOfElementToCreate, baseNamespace) {
var tokens;
if (typeof representationOfElementToCreate !== 'string')
throw new Error('Expecting string as first parameter');
if (baseNamespace === undefined)
baseNamespace = window;
tokens = representationOfElementToCreate.split('.');
// Remove the last element (which will contain the value)
tokens.pop();
// Use reduce to create part by part your new object
return tokens.reduce(function (prev, property) {
if (typeof prev !== 'object') {
throw Error('One property is already defined but not an object, namespace creation has failed', property);
return undefined;
} else {
if (!prev[property])
prev[property] = {};
return prev[property];
}
}, baseNamespace);
};
Then you can have:
function constructJson(jsonKey, jsonValue){
let jsonObj = langFile;
var lastItem = namespaceCreateExceptLast(jsonKey, jsonObj);
var lastKey = jsonKey.substring(jsonKey.lastIndexOf('.') + 1);
lastItem[lastKey] = jsonValue;
}
I have added some comments and exceptions to help you understand how it's done, but it's mainly based on the reduce function which you can easily get help for (https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Array/reduce).

What does Dart's output look like?

Dart, Google's new web language, says it supports outputting to JavaScript.
What does a simple conversion look like?
main() {
print('Hello, Dart!');
}
When compiled with dart2js (as of 2013-04-26) (see note at bottom) it is converted into:
// Generated by dart2js, the Dart to JavaScript compiler.
// The code supports the following hooks:
// dartPrint(message) - if this function is defined it is called
// instead of the Dart [print] method.
// dartMainRunner(main) - if this function is defined, the Dart [main]
// method will not be invoked directly.
// Instead, a closure that will invoke [main] is
// passed to [dartMainRunner].
function Isolate() {}
init();
var $ = Isolate.$isolateProperties;
// Bound closures
$.Primitives_printString = function(string) {
if (typeof dartPrint == "function") {
dartPrint(string);
return;
}
if (typeof window == "object") {
if (typeof console == "object")
console.log(string);
return;
}
if (typeof print == "function") {
print(string);
return;
}
throw "Unable to print message: " + String(string);
};
$.main = function() {
$.Primitives_printString("Hello, Dart!");
};
$.String = {builtin$cls: "String"};
var $ = null;
Isolate = Isolate.$finishIsolateConstructor(Isolate);
var $ = new Isolate();
// BEGIN invoke [main].
if (typeof document !== "undefined" && document.readyState !== "complete") {
document.addEventListener("readystatechange", function () {
if (document.readyState == "complete") {
if (typeof dartMainRunner === "function") {
dartMainRunner(function() { $.main(); });
} else {
$.main();
}
}
}, false);
} else {
if (typeof dartMainRunner === "function") {
dartMainRunner(function() { $.main(); });
} else {
$.main();
}
}
// END invoke [main].
function init() {
Isolate.$isolateProperties = {};
Isolate.$finishIsolateConstructor = function(oldIsolate) {
var isolateProperties = oldIsolate.$isolateProperties;
isolateProperties.$currentScript = typeof document == "object" ? document.currentScript || document.scripts[document.scripts.length - 1] : null;
var isolatePrototype = oldIsolate.prototype;
var str = "{\n";
str += "var properties = Isolate.$isolateProperties;\n";
var hasOwnProperty = Object.prototype.hasOwnProperty;
for (var staticName in isolateProperties) {
if (hasOwnProperty.call(isolateProperties, staticName)) {
str += "this." + staticName + "= properties." + staticName + ";\n";
}
}
str += "}\n";
var newIsolate = new Function(str);
newIsolate.prototype = isolatePrototype;
isolatePrototype.constructor = newIsolate;
newIsolate.$isolateProperties = isolateProperties;
return newIsolate;
};
}
//# sourceMappingURL=out.js.map
Note for posterity: The original answer to this question has been modified to reflect the current state of affairs.
On 2012-05-12 the dart output for Hello World was 18,718 characters.
On 2012-08-29 the output was 1531 characters.
On 2013-04-26, the output was 2642 characters.
dart2js can minify code. Here is an example (as of 2013-04-26)
// Generated by dart2js, the Dart to JavaScript compiler.
function I(){}
init()
var $=I.p
$.ib=function(a){if(typeof dartPrint=="function"){dartPrint(a)
return}if(typeof window=="object"){if(typeof console=="object")console.log(a)
return}if(typeof print=="function"){print(a)
return}throw "Unable to print message: " + String(a)}
$.E2=function(){$.ib("Hello, Dart!")}
$.qU={builtin$cls:"qU"}
var $=null
I = I.$finishIsolateConstructor(I)
var $=new I()
if (typeof document !== "undefined" && document.readyState !== "complete") {
document.addEventListener("readystatechange", function () {
if (document.readyState == "complete") {
if (typeof dartMainRunner === "function") {
dartMainRunner(function() { $.E2(); });
} else {
$.E2();
}
}
}, false);
} else {
if (typeof dartMainRunner === "function") {
dartMainRunner(function() { $.E2(); });
} else {
$.E2();
}
}
function init(){I.p={}
I.$finishIsolateConstructor=function(a){var z=a.p
z.$currentScript=typeof document=="object"?document.currentScript||document.scripts[document.scripts.length-1]:null
var y=a.prototype
var x="{\n"
x+="var properties = I.p;\n"
var w=Object.prototype.hasOwnProperty
for(var v in z){if(w.call(z,v)){x+="this."+v+"= properties."+v+";\n"}}x+="}\n"
var u=new Function(x)
u.prototype=y
y.constructor=u
u.p=z
return u}}//# sourceMappingURL=out.js.map
On 2013-04-26, the minified code was 1386 characters.
The output of the Dart->JavaScript compiler is a moving target. The first release (technical preview) didn't do a lot of tree shaking and was thus pretty big.
The new (experimental) frog compiler is much better in this respect (David Chandler's blog), but I expect DartC to improve considerably too.

Categories