Switch case statement in coffee script - if-statement

I have a few different buttons that are calling the same function and I would like to have them wrapped in a switch statement instead of using a bunch of else if conditions. Any help would be great!!!
events:
"click .red, .blue, #black, #yellow" : "openOverlay"
openOverlay: (e) ->
e.preventDefault()
e.stopPropagation()
target = $(e.currentTarget)
# the view should be opened
view =
if target.hasClass 'red' then new App.RedView
else if target.hasClass 'blue' then new App.BlueView
else if target.is '#black' then new App.BlackView
else
null
# Open the view
App.router.overlays.add view: view if view?

There are two forms of switch in CoffeeScript:
switch expr
when expr1 then ...
when expr2 then ...
...
else ...
and:
switch
when expr1 then ...
when expr2 then ...
...
else ...
The second form might help you:
view = switch
when target.hasClass 'red' then new App.RedView
when target.hasClass 'blue' then new App.BlueView
when target.is '#black' then new App.BlackView
else null
You could leave out the else null if undefined is an acceptable value for view. You could also wrap the logic in an (explicit) function:
viewFor = (target) ->
# There are lots of ways to do this...
return new App.RedView if(target.hasClass 'red')
return new App.BlueView if(target.hasClass 'blue')
return new App.BlackView if(target.is '#black')
null
view = viewFor target
Giving your logic a name (i.e. wrapping it in a function) is often useful for clarifying your code.

In addition to the details in the accepted answer, switch statements in CoffeeScript also supports , to provide multiple match results:
switch someVar
when val3, val4 then ...
else ...
or (if your statements has multiple lines):
switch someVar
when val3, val4
...
else
...

Related

In SwiftUI creating buttons as per different cases

I have swiftUI scene for Error.
That error can be uses for Network , login etc anything.
Buttons and their actions on that screen varies as per the errortype.
enum ErrorItem: String {
case subscriptionError = "Subscription"
case networkError = "NetworkError"
}
init(errorType: ErrorItem) {
super.init()
if errorType == ErrorItem.subscriptionError {
titleString = "Login Error"
numOfButton = 1 // I do not want to use this . I want to create some closure and enum of buttons and create array of buttons
}
else {
titleString = "Something Went Wrong"
numOfButton = 2
}
}
I am handling number of buttons display by "numofButtons".
But for each case number of buttons, their titles and their actions will also be different.
What are the best approach to handle that ?
Can i create something like this and have array of ErrorButtonTypes. So if one screen contain 2 buttons i.e close and action button i can use both and if one screen contain 1button only close button i can use only 1 button
enum ErrorButtonType {
case close(String) // String = title
case action(String, (() -> Void) // String = title, function = action to take with that button
}
The easy and efficient way to declare var inside the enum and set value for each case. Like this
enum ErrorItem: String {
case subscriptionError = "Subscription"
case networkError = "NetworkError"
var title: String {
switch self {
case .subscriptionError:
return "Login Error"
case .networkError:
return "Something Went Wrong"
}
}
var numOfButton: Int {
switch self {
case .subscriptionError:
return 1
case .networkError:
return 2
}
}
}
And your init is
init(errorType: ErrorItem) {
super.init()
titleString = errorType.title
numOfButton = errorType.numOfButton
}
EDIT
As per your edited question, you can use enum with action like this.
Your enum
enum ErrorButtonType {
case close(String) // String = title
case action(String, (() -> Void)) // String = title, function = action to take with that button
}
Declare your enum
var errorType: ErrorButtonType = ErrorButtonType.close("Close")
set enum value
let action: (() -> Void) = {
// Your button action
}
errorType = ErrorButtonType.action("Action", action)
Get enum value
switch errorType {
case .close(let title):
print(title)
case .action(let title, let action):
print(title)
action() // Assign this action to button
}

Assign a string value to a toggle switch in swiftui

i have a form that works correctly but would like to add a toggle to indicated if a garment is used or new. if it is new toggle on, if its used a condtion box will show where the user can input the garments condition.
when then toggle is on, i would like to set the value to static string value of "New"
code i have tried:
Form{
VStack {
Toggle(isOn: self.$itemNew) {
Text("is the item new?")
self.$Cond == "New"
}
if !itemNew {
TextField("Item Condition:", text: self.$Cond) {}
}
}
}
that code didnt seem to work, any pointers on where i should be looking to solve this one?
Thanks
You don't have to use a $, you can create a Binding manually like this:
Toggle(isOn: Binding(get: {self.cond == "New" ? true : false},
set: {
if newValue == true{
self.cond == "New"
}else{
self.cond == "Not really new"
}
})) {
Text("is the item new?")
}
And the self.cond is still must be a #State variable to trigger View update its visual presentation.
But your case isn't look very ordinary for that instrument. Is there other possible values of the string?

Testing ViewModel in RxSwift

I would like to perform a test in one of my ViewModels that contains a BehaviorRelay object called "nearByCity" that it is bind to BehaviorRelay called "isNearBy". That's how my view model looks like.
class SearchViewViewModel: NSObject {
//MARK:- Properties
//MARK: Constants
let disposeBag = DisposeBag()
//MARK: Vars
var nearByCity:BehaviorRelay<String?> = BehaviorRelay(value: nil)
var isNearBy = BehaviorRelay(value: true)
//MARK:- Constructor
init() {
super.init()
setupBinders()
}
}
//MARK:- Private methods
private extension SearchViewViewModel{
func setupBinders(){
nearByCity
.asObservable()
.distinctUntilChanged()
.map({$0 ?? ""})
.map({$0 == ""})
.bind(to: isNearBy)
.disposed(by: disposeBag)
}
}
The test that i want to perform is to actually verify that when the string is accepted, the bool value also changes according to the function setupBinders().
Any Idea?
Thank you
Here's one way to test:
class RxSandboxTests: XCTestCase {
func testBinders() {
let scheduler = TestScheduler(initialClock: 0)
let source = scheduler.createColdObservable([.next(5, "hello"), .completed(10)])
let sink = scheduler.createObserver(Bool.self)
let disposeBag = DisposeBag()
let viewModel = SearchViewViewModel(appLocationManager: StubManager())
source.bind(to: viewModel.nearByCity).disposed(by: disposeBag)
viewModel.isNearBy.bind(to: sink).disposed(by: disposeBag)
scheduler.start()
XCTAssertEqual(sink.events, [.next(0, true), .next(5, false)])
}
}
Some other points:
Don't make your subject properties var use let instead because you don't want anybody to be able to replace them with unbound versions.
The fact that you have to use the AppLocationManager in this code that has no need of it implies that the object is doing too much. There is nothing wrong with having multiple view models in a view controller that each handle different parts of the view.
Best would be to avoid using Subjects (Relays) at all in your view model code, if needed, they are better left in the imperative side of the code.
At minimum, break up your setupBinders function so that the parts are independently testable. Your above could have been written as a simple, easily tested, free function:
func isNearBy(city: Observable<String?>) -> Observable<Bool> {
return city
.distinctUntilChanged()
.map {$0 ?? ""}
.map {$0 == ""}
}

Reference a class name as a variable

I'm wondering if there is a better way to write this block of code. It's extremely redundant and before i did it this way i was thinking there should be a way to do it with variables as the class names but ran into many issues and eventually ended up doing it this way. Now every time i look at it it bothers me. I did quite a bit of research on this topic and did not come up with anything. Possibly because i'm not sure what doing something like this would be called.
For sake of argument, assume the following code is in a function that is called when a SKSpriteNode is tapped. Each "button" is named for the scene that it will be transitioning to. There are actually 12 more of these case statements.
let name = sender.name
switch(name){
case "newGame":
defaults.set(true,forKey: "isFirstRun")
defaults.set(true,forKey: "isNewGame")
let transition = SKTransition.crossFade(withDuration: 1.0)
let nextScene = Setup(fileNamed:"Setup")
nextScene?.scaleMode = .aspectFill
scene?.view?.presentScene(nextScene!, transition: transition)
break
case "IceFishing":
defaults.set(2, forKey: "currentLocation")
let transition = SKTransition.crossFade(withDuration: 1.0)
let nextScene = IceFishing(fileNamed:"IceFishing")
nextScene?.scaleMode = .aspectFill
scene?.view?.presentScene(nextScene!, transition: transition)
break
case "OpeningScene":
let transition = SKTransition.crossFade(withDuration: 1.0)
let nextScene = OpeningScene(fileNamed:"OpeningScene")
nextScene?.scaleMode = .aspectFill
scene?.view?.presentScene(nextScene!, transition: transition)
break
case "House":
let transition = SKTransition.crossFade(withDuration: 1.0)
let nextScene = SodHouse(fileNamed:"House")
nextScene?.scaleMode = .aspectFill
scene?.view?.presentScene(nextScene!, transition: transition)
break
default:
break
}
I would think (or hope) there is a way to do something like...
let name = sender.name
let _Class = name as! SKScene //Not right, but i was guessing
let transition = SKTransition.crossFade(withDuration: 1.0)
let nextScene = _Class(fileNamed:name)
nextScene?.scaleMode = .aspectFill
scene?.view?.presentScene(nextScene!, transition: transition)
All of the sks files and Swift classes are named the same.
You basically want to have the code look like this (I added some guards for you):
let name = sender.name
let transition = SKTransition.crossFade(withDuration: 1.0)
guard let nextScene = SKScene(fileNamed:sender.name) else {fatalError("unable to find next scene")}
guard let scene = scene else {fatalError("unable to find scene")}
guard let view = scene.view else {fatalError("unable to find view")}
nextScene.scaleMode = .aspectFill
case "newGame":
//I would avoid using defaults unless you plan on saving when the app exits
defaults.set(true,forKey: "isFirstRun")
defaults.set(true,forKey: "isNewGame")
case "IceFishing":
defaults.set(2, forKey: "currentLocation")
default: break
}
view.presentScene(nextScene!, transition: transition)
Basically what we are doing is relying on the custom class field in the sks file to load the custom class for us.
Edit: Now to clean up the code even more, I would ditch using defaults. You should only have to use this when you want to save data across gaming sessions, not across plays.
let name = sender.name
let transition = SKTransition.crossFade(withDuration: 1.0)
guard let nextScene = SKScene(fileNamed:sender.name) else {fatalError("unable to find next scene")}
guard let scene = scene else {fatalError("unable to find scene")}
guard let view = scene.view else {fatalError("unable to find view")}
nextScene.scaleMode = .aspectFill
nextScene.userData += scene.userData
//Move these to the SKS file under UserData section, then you can pull it using scene.userData?
// defaults.set(2, forKey: "currentLocation")
// defaults.set(true,forKey: "isFirstRun")
// defaults.set(true,forKey: "isNewGame")
view.presentScene(nextScene!, transition: transition)

TinyMCE Text hightlight with Regular Expression

Just asked a question on regular expression here, basically we need to give an option to people to select some part of text which will be hidden with a MORE button on flash front end, and when some one will click on MORE it will expand it. here is sample text in tinyMCE
some text <start> some inner test </end>
so here is the regular expression to catch this start and end text,
<start>(((?!<(?:\/end|start)>).)+)<\/end>
the above expression will be used to strip this SOME INNER TEST and we will convert this to FLASH friendly MORE button.
My question is, Is there any way to highlight the text inside start & end tags on the fly (while editing) so people will know which part will be hidden for MORE button
Okay guys pat my shoulder on this :D If you don't know what are the code below then learn the basic of TinyMCE initializing. I have done this on jQuery version.
Here is my solution
var highlighter = 1; // A global variable, just to create a toggle for show/hide highlight
added three custom buttons
theme_advanced_buttons1: 'startmore, highlight, endmore, ...';
add setup: to initializing code.
// start highlight, end highlight and show highlight buttons
setup: function(ed) {
ed.addButton('startmore', {
title: 'Start More',
image: 'images/end_s.png',
onclick: function() {
ed.selection.setContent('[start]');
}
});
ed.addButton('endmore', {
title: 'End More',
image: 'images/end_m.png',
onclick: function() {
ed.selection.setContent('[end]');
if (1 == highlighter) {
highlight_tags();
}
}
});
ed.onInit.add(function(ed) {
highlight_tags();
});
ed.onSubmit.add(function(ed, e) {
var html_output = highlight_remove(tinyMCE.activeEditor.getContent());
tinyMCE.activeEditor.setContent(html_output);
});
ed.addButton('highlight', {
title: 'Show collapse selection',
image: 'images/end_highlight.png',
onclick: function() {
if (1 == highlighter) {
var html_output = highlight_remove(tinyMCE.activeEditor.getContent());
tinyMCE.activeEditor.setContent(html_output);
highlighter = 0;
} else {
highlight_tags();
highlighter = 1;
}
}
});
ed.onContextMenu.add(function(ed, e) {
tinymce.dom.Event.cancel(e);
if (1 == highlighter) {
highlight_tags();
}
});
}
onContextMenu is used to show / fix the highlight by right-clicking inside the editor.
There are issue to show highlight on they fly as as soon I setSontent() it moves the cursor at the start of first line.
Below are the regular expression functions to put the highlight around the [start][end] tags.
function highlight_tags() {
var html_output = tinyMCE.activeEditor.getContent();
html_output = highlight_remove(html_output);
var regex = new RegExp(/\[start\](((?!\[(?:end|start)\]).)+)\[end\]/ig);
html_output = html_output.replace(regex,'<span style="background-color:> yellow;">[start]$1[end]</span>');
tinyMCE.activeEditor.setContent(html_output);
}
function highlight_remove(html_output) {
var regex_fix = new RegExp(/<span\sstyle="background-color:\syellow;">(.+?)<\/span>/ig);
return html_output.replace(regex_fix,'$1');
}
Hmm so far it is serving me.
Just onSubmit I am trying to remove the highlight so it wont go in database and for a second I can see that highlight is removed. But it goes in database... so fixing this now.
Let me know if you guys didn't understand any part.
NOTE: If there is any typo in code that might be this stack overflow editor :).
NOTE: I know this code can be improved a lot, so enlighten me please.