Is it valid to put expressions in a case statement? I have this switch case statement.
var switchValue:String = StatusUpdateErrorEvent.UPDATE_ERROR;
switch (switchValue) {
case caseValue: { // it's implied here that (switchValue==caseValue)
}
case StatusUpdateErrorEvent.UPDATE_ERROR: {
}
case event is StatusUpdateErrorEvent && StatusUpdateErrorEvent.UPDATE_ERROR: {
}
// is this what I should do if I add my own expression?
case event is StatusUpdateErrorEvent && StatusUpdateErrorEvent.UPDATE_ERROR==type: {
}
}
It doesn't throw any errors when I add an expression is the switchValue==caseValue expression thrown out?
switch (switchValue) {
case caseValue:
//1
break;
case StatusUpdateErrorEvent.UPDATE_ERROR:
//2
break;
case event is StatusUpdateErrorEvent && StatusUpdateErrorEvent.UPDATE_ERROR:
//3
break;
case event is StatusUpdateErrorEvent && StatusUpdateErrorEvent.UPDATE_ERROR == type:
//4
break;
}
You need to use "break;" after every case. If not, all other breaks after will be executed. It can e also "return;" if you just want to exit function after break.
Other thing is that you use "case" in a very weird way, just like they are if's. Don't put boolean comparison there like that. It's place for values.
Related
I have the following code and I get the error 'Duplicate Declaration query_url'.
switch(condition) {
case 'complex':
const query_url = `something`;
break;
default:
const query_url = `something`;
break;
}
I understand that query_url is getting declared twice which isn't right. But i don't know how to resolve this. Can someone please help on what should be the correct way to make this work?
Try wrapping the cases in blocks:
switch(condition) {
case 'complex': {
const query_url = `something`;
… // do something
break;
}
default: {
const query_url = `something`;
… // do something else
break;
}
}
I personally prefer (and tend to abuse) the following in these sorts of cases:
const query_url = (()=>
{
switch(condition)
case 'complex': return 'something';
default : return 'something-else';
})();
(this requires ES6 or declaring "use-strict" in Node 4.x though)
Update: Alternatively, much more compact depending on if there is any logic there or if it's a simple assignment:
const query_url = {complex : 'something'}[condition] || 'something-else';
Also, of course, depends on the amount of outside-logic embedded in those switch statements!
if you need to redeclare the same variable in each case see #Bergi 's answer bellow
if query_url can have multiple values depending on the switch branch obviously you need a variable ( declare either with var or let ).
const is set once and stays that way.
example usage with let
let query_url = '';
switch(condition) {
case 'complex':
query_url = `something`;
break;
default:
query_url = `something`;
break;
}
You can use {} to scope your switch case.
For your case, you need to return the variable as long as the var exists and is accessible between curly braces:
switch(condition) {
case 'complex': {
const query_url = `something`;
return query_url;
}
default: {
const query_url = `something`;
return query_url;
}
}
If you won't use return, you must declare a let query_url above your switch statement.
Just put your switch in a function with some return statements :
var condition;
function aSwitch(condition){
switch(condition) {
case 'complex':
return 'something';
default:
return 'something';
}
}
const query_url = aSwitch(condition);
const query_url={
complex:'something complex',
other:'other thing'
}[condition]
The drawback is,you can't have default with object,you need to have addition check of condition.
I am using Angular UI-grid to display data in tabular form and i also added a functionality to export the visible data in CSV file but my problem is that in exported file all the string are enclose with double quotes.
Can anyone tell me how to remove those unnecessary double-quotes ?
Any help is appreciated
The behavior that you are referring to comes from the function formatFieldAsCsv(field) within the uiGridExporterService service. There is no API that will allow you to change this with a setting.
What we can do however is use a decorator to override this default behavior without having to modify the ui-grid module itself.
I have demonstrated this in a working plunker.
In the snippet below, I have assigned qualifier to replace the quotations that were initially in use. With this, you can either leave the function as is and have no qualifier at all, or you can change it's value to whatever you like, and that will become the prefix/suffix of each field.
app.config(['$provide', function ($provide) {
$provide.decorator('uiGridExporterService', [
'$delegate',
function myServiceDecorator($delegate) {
$delegate.formatFieldAsCsv = formatFieldAsCsv;
return $delegate;
}
]);
function formatFieldAsCsv(field) {
var qualifier = '';
if (field.value === null) { // we want to catch anything null-ish, hence just == not ===
return '';
}
if (typeof(field.value) === 'number') {
return field.value;
}
if (typeof(field.value) === 'boolean') {
return (field.value ? 'TRUE' : 'FALSE');
}
if (typeof(field.value) === 'string') {
return qualifier + field.value.replace(/"/g, '""') + qualifier;
}
return JSON.stringify(field.value);
}
}]);
http://plnkr.co/edit/8qskcFt7EHSlTQFo4ZUG?p=preview
I simply insert following codes in a clean base(at the final of HelloWorld::init()) produced by cocos new:
auto kl = EventListenerKeyboard::create();
kl->onKeyPressed = [](EventKeyboard::KeyCode keyCode, Event* event) {
CCLOG("%s> keyCode=%d",__FUNCTION__,keyCode);
};
auto ed = Director::getInstance()->getEventDispatcher();
ed->addEventListenerWithSceneGraphPriority(kl,this);
On windows, it worked well. But nothing happened on android.
Log with value of keyCode should be left in logcat, I think.
Do I miss anything?
Approach One:
If you just need to handle keyboard as key-event, It's as easy as these below lines of code:
HelloWorld::init()
{
...
auto keyboardListener = EventListenerKeyboard::create();
keyboardListener->onKeyPressed = [](EventKeyboard::KeyCode keyCode, Event* event)
{
switch (keyCode)
{
case EventKeyboard::KeyCode::KEY_UP_ARROW: /*Jump maybe*/ break;
case EventKeyboard::KeyCode::KEY_DOWN_ARROW: /*Crouch maybe*/ break;
case EventKeyboard::KeyCode::KEY_RIGHT_ARROW: /*Move Right maybe*/ break;
case EventKeyboard::KeyCode::KEY_LEFT_ARROW: /*Move Left maybe*/ break;
}
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(keyboardListener, this);
...
return true;
}
I think it's clear enough not to need any extra description.
Approach Two: if you need an input box that user/player can enter string with keyboard and you get what is entered, I recommend to use TextField which is available in cocos2d v3 ( and with some difficulty in v2) and has a full functionality. You can create and initial one of them as:
auto textField = cocos2d::ui::TextField::create("hint: enter here","Arial" , 30);
textField->setTextHorizontalAlignment(cocos2d::TextHAlignment::CENTER);
textField->setTextVerticalAlignment(cocos2d::TextVAlignment::CENTER);
textField->setColor(Color3B(100,100,100));
textField->setMaxLength(10);
textField->setMaxLengthEnabled(true);
textField->setTouchAreaEnabled(true);
textField->setTouchSize(Size(200,400));
textField->setPosition(...);
textField->addEventListener(CC_CALLBACK_2(HelloWorld::textFieldEvent, this));
this->addChild(textField, 10);
You can get entered data any time with std::string enteredData= textField->getString();
You can also do something when user entering text with two event as :
void HelloWorld::textFieldEvent(Ref *pSender, cocos2d::ui::TextField::EventType type)
{
switch (type)
{
case cocos2d::ui::TextField::EventType::ATTACH_WITH_IME:
{
textField->setColor(Color3B::BLACK);
// or whatever elese
break;
}
case cocos2d::ui::TextField::EventType::DETACH_WITH_IME:
{
textField->setColor(Color3B(100,100,100));
// or whatever elese
break;
}
}
}
Enjoy !
I am new to ActionScripting but I have done some Java. I was told they are kinda similar. I am coding my swf file with some AS3 integrated.
function init():void{
// do something
}
function init(var string:String):String{
// do something else
}
is this not allowed in AS? If not, is there another way of handling it besides?
Thanks in advance.
Yes, you can override functions. But the example you gave is not overriding - it's overloading. For overriding a function, you basically just create a function with the same signature and everything in a subclass and add the word "override" right before it.
You can't directly overload a function though. If you want a variable number of parameters, you have to use optional parameters instead. Like this:
function init(str:String = null):String
{
if (str == null)
{
// do one thing
return null;
}
else
{
// do another thing
return "someString";
}
}
And that's about the best you're going to be able to do in AS3. The inability to overload functions, at least strictly speaking, is a fairly common complaint and obvious shortcoming of the language.
Do you mean method overloading? Actionscript, sadly, does not support this.
To get around it, you can use default parameters, or just make your parameters a bit less constraining. This answer has some details on that.
You could try this:
function init(var string:String = "Default value"):String{
// do something
}
Actionscript does not support method overloading. However, based on the answer to this question you have other options.
If you just want to be able to accept any type, you can use * to
allow any type:
function someFunction( xx:*, yy:*, flag:Boolean = true )
{
if (xx is Number) {
...do stuff...
} else if (xx is String) {
...do stuff...
} else {
...do stuff...
}
}
If you have a large number of various parameters where order is
unimportant, use an options object:
function someFunction( options:Object )
{
if (options.foo) doFoo();
if (options.bar) doBar();
baz = options.baz || 15;
...etc...
}
If you have a variable number of parameters, you can use the ...
(rest) parameter:
function someFunction( ... args)
{
switch (args.length)
{
case 2:
arr = args[0];
someBool = args[1];
xx = arr[0];
yy = arr[1];
break;
case 3:
xx = args[0];
yy = args[1];
someBool = args[2];
break;
default:
throw ...whatever...
}
...do more stuff...
}
For cases where you need to call a common function to a number of
classes, you should specify the interface common to each class:
function foo( bar:IBazable, flag:Boolean )
{
...do stuff...
baz = bar.baz()
...do more stuff...
}
This AS3 function works for normal methods and getter methods:
public function MyClassTestAPI(functionName:String, ...rest):* {
var value:*;
try {
switch(rest.length) {
case 0:
value = myObj[functionName];
break;
case 1:
value = myObj[functionName].call(functionName, rest[0]);
break;
case 2:
value = myObj[functionName].call(functionName, rest[0],rest[1]);
break;
default:
throw("Cannot pass more than 2 parameters (passed " + rest.length + ")");
}
}
return value;
}
Sample usage:
this.MyClassTestAPI("Foo", "arg1"); // tests function Foo(arg1:String):String
this.MyClassTestAPI("MyProperty"); // tests function get MyProperty():String
this.MyClassTestAPI("MyProperty", "new value");// tests function set MyProperty(val:String):void
The third call does not work (throws exception).
How can I make it work for setter methods as well?
Thanks!
edit:
This is a version that works, except with getter and setter that have additional parameters.
It is ok for my needs:
public function MyClassTestAPI(functionName:String, ...rest):* {
var value:*;
try {
if (typeof(this.mediaPlayer[functionName]) == 'function') {
switch(rest.length) {
case 0:
value = myObj[functionName].call(functionName);
break;
case 1:
value = myObj[functionName].call(functionName, rest[0]);
break;
case 2:
value = myObj[functionName].call(functionName, rest[0],rest[1]);
break;
default:
throw("Cannot pass more than 2 parameters (passed " + rest.length + ")");
}
} else {
switch(rest.length) {
case 0:
value = myObj[functionName];
break;
case 1:
myObj[functionName] = rest[0];
break;
default:
throw("Cannot pass parameter to getter or more than one parameter to setter (passed " + rest.length + ")");
}
}
}
return value;
}
Setter functions works as variables, so you can't use it in this way:
myProperty.call( "new value" );
Your function for variables is pointless, because you just have to do a value assignment:
myProperty = "new value";
By the way you can include it in your function in two ways:
create a third parameter what tells your function it is a function or variable
create the value assignment in the catch section
You are currently passing only one string with value "new value"
This should do the trick:
this.MyClassTestAPI("MyProperty", "new","value");
For more information on this matter check the Adobe LiveDocs at:
http://livedocs.adobe.com/flex/3/html/help.html?content=03_Language_and_Syntax_19.html
Cheers