Instance variable isn't accessible from method - coffeescript

I'm new to CoffeeScript but I have written a class with a constructor which assigns attributes to this. In my function these attributes aren't defined. Does anybody have an idea?
class ProcessVisualisation
constructer: (width, devMode = false) ->
#objProcess = null
#config =
devMode: false
loadProcess: (processPath) ->
console.log("loadProcess") if (#config.devMode) # <- config is not defined
that = #;
that.processPath = processPath
$.getJSON #processPath, {}, (response) ->
that.onProcessLoaded response
pv = new ProcessVisualisation(1023, true)
pv.loadProcess "data/process.json"

As stated in the comments, fix constructer and the function arrow.
class ProcessVisualisation
constructor: (width, devMode = false) ->
#objProcess = null
#config =
devMode: false
loadProcess: (processPath) =>
console.log("loadProcess") if (#config.devMode)
#processPath = processPath
$.getJSON #processPath, {}, (response) =>
#onProcessLoaded response
pv = new ProcessVisualisation(1023, true)
pv.loadProcess "data/process.json"

Related

How can I get the EDM type from 'context' bound to an element in SAPUI5?

I have an SAPUI5 application.
I defined an element by the smart fields like the following:
<smartField:SmartField value="{GefahrInVerzug}" width="auto">
<smartField:configuration>
<smartField:Configuration preventInitialDataFetchInValueHelpDialog="false" displayBehaviour="descriptionOnly"/>
</smartField:configuration>
</smartField:SmartField>
The GefahrInVerzug field is defined as a boolean in my metadata:
<Property Name="GefahrInVerzug" Type="Edm.Boolean" sap:creatable="true"
sap:updatable="true" sap:deletable="true" sap:label="Gefahr in Verzug"/>
Assume I have the following handler for onInputChange event of the rendered control:
onInputChange: function (oEvent) {
var oField = oEvent.getSource(),
oContext = oField.getBindingContext();
//oContext.getEdmType();
}
How can I get the Edm Type by accessing the element (i.e. oField) or the context object (i.e. oContext).
In this case I am looking for a solution that return Edm.Boolean to me!
We can define the following functions in our controller to extract Edm Type from a field:
// Returns a list that contains a map between
// UI5 elements' types and the property that contains the value!
// Normally bound to the oData property
_getFieldTypeAttribute: function () {
var aFieldTypes = {
"sap.m.Input": "value",
"sap.m.Select": "selectedKey",
"sap.m.ComboBox": "selectedKey",
"sap.m.CheckBox": "selected",
"sap.m.DatePicker": "dateValue",
"sap.m.DateTimePicker": "value",
"sap.m.TextArea": "value",
"sap.m.Switch": "state",
"sap.ui.comp.smartfield.SmartField": "value"
};
return aFieldTypes;
},
// Extract the EDM type from Metadata
_getEdmType: function(oField, sPropertyName){
var regex = /\/([^(]+)/gm,
oContext = oField.getBindingContext(),
oModel = oContext.getModel(),
oMetaModel = oModel.getMetaModel(),
sBindingPath = oContext.getPath(),
sType = null;
//
var aMatches = regex.exec(sBindingPath);
if(aMatches.length > 0){
var sSetName = aMatches[1],
oEntitySet = oMetaModel.getODataEntitySet(sSetName),
sEntityType = oEntitySet.entityType,
oEntityType = oMetaModel.getODataEntityType(sEntityType),
oProperty = oMetaModel.getODataProperty(oEntityType, sPropertyName);
if (oProperty ) {
sType = oProperty.type;
}
}
//
return sType;
},
// Is fied when the input value is changed!
onInputChange: function (oEvent) {
var oField = oEvent.getSource(),
oContext = oField.getBindingContext(),
oModel = oContext.getModel(),
aFieldTypes = this._getFieldTypeAttribute(),
sFieldType = oField.getMetadata().getName(),
sFieldPath = oField.getBinding(aFieldTypes[sFieldType]).getPath(),
sPropertyName = sFieldPath && sFieldPath.startsWith("/") ? sFieldPath.substring(1) : sFieldPath,
sBindingPath = sPropertyName ? oContext.getPath() + "/" + sPropertyName : null;
console.log(this._getEdmType(oField, sPropertyName));
}
It prints Edm.Boolean for example when this function is fired for an element of boolean type!
Take a look here
onInputChange: function (oEvent) {
var oField = oEvent.getSource(),
oContext = oField.getBindingContext(),
sType = oContext.getProperty("/#EntityName/GefahrInVerzug/#type");
}
In metadata MaxLength , Type are in capital letters but in that name
you can’t get the metadata values.

Swagger (spray) path parameters inside resource url

Say I have a parametrized resource url like
/customers/{CUSTOMER-ID}/ownedItems/{ITEM-ID}
How should I annotatate/split my spray routes (using the spray-swagger plugin) to generate a documentation that will recognize {CUSTOMER-ID} as a proper path parameter?
My problem is that the top level #Api annotation takes a path but no parameters, while the #ApiOperation can be annotated with path parameters but these get appended at the end. In other words, if I write:
#Api(value = "/customers/{CUSTOMER-ID}")
#ApiOperation(httpMethod = "GET")
#ApiImplicitParams(Array(
new ApiImplicitParam(name = "ITEM-ID", required = true, dataType = "string", paramType = "path"))
I get in the UI only ITEM-ID as testable parameter, while CUSTOMER-ID, while being reported as in { }, is just a string.
I'd like to have something where both are path parameters.
Any idea?
customers is your #Api entry point, not path parameters. Path parameters must be used only into #ApiOperation as follow (with more samples) :
#Api(value = "/customers")
#ApiOperation(value = "/{CUSTOMER-ID}/ownedItems/{ITEM-ID}", httpMethod = "GET")
#ApiImplicitParams(Array(
new ApiImplicitParam(name = "CUSTOMER-ID", required = true, dataType = "string", paramType = "path"),
new ApiImplicitParam(name = "ITEM-ID", required = true, dataType = "string", paramType = "path"))
#ApiOperation(value = "/{CUSTOMER-ID}", httpMethod = "GET")
#ApiImplicitParams(Array(
new ApiImplicitParam(name = "CUSTOMER-ID", required = true, dataType = "string", paramType = "path"))
#ApiOperation(value = "/", httpMethod = "POST")

Why does this coffeescript blow up with the following error

Person = (name, age, job) ->
#name = name
#age = age
#job = job
#sayName = ->
console.log(#name)
kim = new Person("Kimothy Lozado", 37, "Skip Tracer")
console.log kim.sayName()
Returned Error
TypeError: Object function () {
return console.log(this.name);
} has no method 'sayName'
at Object.<anonymous> (/Users/aero/Downloads/m.coffee:11:17)
at Object.<anonymous> (/Users/aero/Downloads/m.coffee:1:1)
at Module._compile (module.js:456:26)
Your not quite defining classes properly. Namely you need a constructor and need to use :s instead of =s unlike regular js.
Do this instead:
class Person
constructor: (#name, #age, #job) ->
sayName: ->
console.log(#name)
kim = new Person("Kimothy Lozado", 37, "Skip Tracer")
console.log kim.sayName()
Demo in a fiddle : http://jsfiddle.net/4e8xZ/
Here's a great article on CoffeeScript class from the little book of CoffeeScript for your reference.
I recommend agconti answer for creating classes, but here I want to answer to why this error occurs.
When you write a constructor in javascript:
function Person(name) {
this.name = name;
}
var someone = new Person('someone');
The variable someone is assigned to the returned object of the new keyword.
But if the constructor returns a function:
function Person(name) {
this.name = name;
return function(){};
}
var someone = new Person('someone');
Unfortunately, instead of getting the new created object, someone is assigned to the function returned by the constructor.
If we look at the compiled code of your coffee:
Person = function(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
return this.sayName = function() {
return console.log(this.name);
};
};
We see that the constructor returns a function. this happens because coffescript always returns the last expression of a function.
You can fix it by returning nothing:
Person = (name, age, job) ->
#name = name
#age = age
#job = job
#sayName = ->
console.log(#name)
return

Coffeescript classes, method and instance variables

I'm going to implement some kind of a Pagniator class in Coffeescript. The Paginator class should hold the information about currentPage, maxPages, columnNames, ...
So my first approach is this:
class Paginator
currentPage = -1
rowCount = -1
pageSize= -1
columnNames = null
constructor: (#config) ->
setup: ->
#config.ajax(
cache: false
type: "GET"
contentType: "application/json"
dataType: "json"
success: (data) =>
this.configurationReceived(data)
)
configurationReceived: (data) =>
this.storeConfig(data)
this.setupGUI()
this.loadPage(1)
$('.pagination ul li').click( ->
Paginator.loadPage($(this).text())
return false
)
storeConfig: (jsonData) =>
rowCount = jsonData['rowAmount']
pageSize = jsonData['pageSize']
columns = jsonData['columns']
return
The #config is a jsRoutes.controllers.xxx from Play 2.0 Framework jsroutes object.
On Page load I do
paginator = new Paginator jsRoutes.controllers.PlayerController.paginatorConfiguration()
paginator.setup()
But I get a "this.storeConfig is not a function" all the time. Can someone help me on that? Do I misuse the class syntax here? My aim is to have the state of the Paginator encapsulated in a Paginator object (instance). On startup I want to do some initialization stuff that is done via a AJAX call to a "route" which is a HTTP endpoint.
Thanks
There seems to be a problem with the indentation here:
$('.pagination ul li').click( ->
Paginator.loadPage($(this).text())
return false
) # <---
should be
$('.pagination ul li').click( ->
Paginator.loadPage($(this).text())
return false
)
Because of this, the following code containing the definition of the method "storeConfig" is not part of the class, therefore "this.storeConfig" is not a function.
You can easily see this if you copy-past your code into the "Try-coffescript" form at coffeescript.org and examine the JavaScript output.

Sinon.JS stub for window.location.search

I am trying to test a simple function that makes a call to window.location.search. I'm trying to understand how to stub this call so that I can return a url of my choosing.
function:
getParameterByName: (name) =>
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]")
regexS = "[\\?&]" + name + "=([^&#]*)"
regex = new RegExp(regexS)
results = regex.exec(window.location.search) //Stub call to window.location.search
if(results == null)
return ""
else
return decodeURIComponent(results[1].replace(/\+/g, " "))
Test case:
describe "Data tests", () ->
it "Should parse parameter from url", () ->
data = new Data()
console.log("search string: " + window.location.search) //prints "search string:"
window.location.search = "myUrl"
console.log("search string: " + window.location.search) //prints "search string:"
console.log(data.getParameterByName('varName'))
expect(true).toBe(true)
My original attempt was to return a value directly like so:
sinon.stub(window.location.search).returns("myUrl")
This, of course, doesn't work. I don't think I'm specifying the stub correctly, but it shows my intent.
Any ideas on how to solve this would be greatly appreciated.
So, as mentioned before, you can't mock window.location directly. Nor did the mylib.search wrapper idea work with my situation. So, what I did was break out my call to window.location.search into its own function. My new class looks like so:
getParameterByName: (name) =>
console.log("name: #{name}")
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]")
regexS = "[\\?&]" + name + "=([^&#]*)"
regex = new RegExp(regexS)
results = regex.exec(#getWindowLocationSearch())
if(results == null)
return ""
else
return decodeURIComponent(results[1].replace(/\+/g, " "))
getWindowLocationSearch:() =>
window.location.search
Then in my test case, I replace the function with my test code like so:
describe "Data tests", () ->
it "Should parse parameter from localhost url", () ->
goodUrl = "http://localhost:3333/?token=val1"
Data::getWindowLocationSearch = () -> return goodUrl
unit = new Data()
result = unit.getParameterByName("token")
expect(result).toBe("val1")
For those who don't read Coffeescript, the equivalent javascript code is listed below:
it("Should parse parameter from localhost url", function() {
var goodUrl, result, unit;
goodUrl = "http://localhost:3333/?token=val1";
Data.prototype.getWindowLocationSearch = function() {
return goodUrl;
};
unit = new Data();
result = unit.getParameterByName("token");
expect(result).toBe("val1");
return expect(true).toBe(true);
});
As is my usual experience with Javascript. The working solution was not nearly as painful as the journey to get there. Thank you very much for your comments and contributions.
UPDATE: window.location, it seems, is a bit of a special case, see this discussion: https://groups.google.com/forum/?fromgroups#!topic/sinonjs/MMYrwKIZNUU%5B1-25%5D
The easiest way to solve this problem is to write a wrapper function around window.location, and stub that:
mylib.search = function (url) {
window.location.search = url;
};
And in your test:
sinon.stub(mylib, 'search').returns("myUrl")
ORIGINAL ANSWER:
Try this:
sinon.stub(window.location, 'search').returns("myUrl")