I'd like to take a minute and not talk about software. My wife and I recently had a successful home birth and I would like to share my story to remember what happened while it's fresh, as well as help others who are considering a home birth feel more at ease about the potential risks they could run into for their births.
You might be thinking, "big deal, babies get born all the time". But the unusual things about our home birth were that the baby was born 30 minutes after contractions started and the baby was born early Christmas Morning and nobody arrived in time.
<disclaimer>
Births are messy and I am going to talk about things that are unpleasant for people to listen to. So if you can't stomach medical terms about nether regions or you are a current or future employer of mine, this blog post is not for you. Also, I am not a hippy. I'm just a guy that wanted to have a uneventful and safe home birth with his wife.
</disclaimer>
My wife's water broke around 1pm. She got up to use the rest room, but soon realized that she was not peeing, but instead leaking amniotic fluid. I was woken up by her telling me that she thought things were starting. I was skeptical because she claimed that things "might be starting" on previous nights. So instead, I woke up to change our toddler, who was screaming at the time.
After finishing that, I tried to go back to bed. My wife said I should call the midwife and notify her. When we called her, she advised us to try and sleep and call back when contractions start. This is a standard thing to do because lots of labors last a very long time even after water breaks. So, we tried to get back in bed. After a few seconds of her lying down, she immediately got up and said that it was not working.
She went back to the bathroom and remained there for the rest of the labor. Like I said, labor is messy and the rest room is a very safe place to be when you might not be prepared for things. She pretty much evacuated all her waste at this point in time. This is a pretty good sign that you are in labor when this happens. Other things happened around this time like a "bloody show", which happens due to the cervix opening up.
Once active labor starts for my wife, she pretty much can't go anywhere. This is unfortunate because we wanted to have a water birth. Water births are where the mother tries to deliver the baby in a pool of water. Usually this involves some sort of tub or bath. We had a tub set up for our previous home birth, but like I said, my wife probably couldn't even be convinced to move into the tub. That being said, my wife wasn't in a condition to be moved even to the car. So if we even tried to go to the hospital, the baby would probably have been delivered in our car.
So, after we were in the bathroom and situated, my wife eventually mentioned she was going through contractions. But the issue here was that she thought they were the wrong kind of contractions. If you have taken any birth classes, or watch any videos on the stages of birth, you usually see sections where they say "When contractions last for X minutes and are Y minutes apart, you are probably in the Z stage of labor". Well, my wife thought that because she was having short contractions with short intervals, she wasn't in Active Labor. Most of the terminology says that your contractions are longer when in Active Labor. So we called up the midwife and let her know things were gearing up.
Since we knew the midwife and her backup were on the way, I tried to call up nearby relatives who said they were going to help take care of our son. We had a plan where we wanted our son to be around and at least know about the birth happening. But we didn't want him to interfere or get in the way. We were expecting the labor to last at least as long as the last labor (about 4 hours). So we figured that was enough time to merit having someone look after our kid. One of the stressful things about this was that it was late at night (around 1:30 am) and no one we called answered the phone. It took at least 10 tries to get ahold of someone. After everyone was contacted, the relatives were thirty minutes away and the midwife was 15-20 minutes away, so I had to play the stalling game.
We were prepared to have a home birth, and had supplies set aside for when labor started, so I decided it would be a good idea to go through it. This box was in our toddler's room, so I woke him up while stumbling around in the dark. I also got a Pilates ball, so I could sit with my wife in the restroom.
I remembered from the last birth that the midwives tried to make sure pain around the opening was managed. You can apply things that ease burning sensations, or just help lubricate or stretch the area. Also I remembered that they also tried to monitor the baby's heart rate to make sure we didn't need emergency intervention, like a hospital c-section.
So, I tried to use some oils to help with stretching, but most of my efforts were met with disapproval from my wife. Since I don't have much experience, nothing helpful resulted. I then resorted to massage her hands to help calm her down. But, because of her labor pains, even touching her hands was not what she wanted. Which was different from my first home birth, where I absorbed her pain in each contraction when she clenched her hands.
Her general demeanor was not too good at one point, and I realized that we weren't calming down. I remembered that we did some breathing exercises whenever my wife started feeling like she wasn't in control. So at one contraction, I just started breathing low and she followed me. She immediately remembered she needed to relax and we got through the contraction. At one point, I remember trying to tell her that she was in control. She was parroting me back, but I actually thought she said "I'm not in control", which was a mis-heard downer, but I didn't let it effect me.
Around this point, we made so much noise that at one point I looked behind myself and saw my child watching us. He wasn't afraid, just curious why we were making so much noise. He definitely witnessed his mom in a poor state. We were happy that he was able to see what it means to have a baby. Being 22 months old, he wasn't able to verbalize much, but we kept reassuring him and telling him that a baby was coming out of mommies tummy. We wanted him to know as much as a baby can comprehend about what was happening.
I eventually started to wonder where everyone was. I looked down at her area and saw that the baby was crowning. This is when the head starts to be visible. I ran to the front door of our house and looked out and saw no one and immediately ran back. I ran past my child happily jumping on our bed. I figured that we should make sure the baby was ok and I put my head against my wife's belly to see if I could hear a heart beat. I remember that we did a bunch of heart monitoring in the previous birth. When I put my head on the belly, I got a gentle kick to the face and decided that that was good enough and said, "the baby is still alive", with a grin.
We went through a couple more contractions and then I realized even more that the baby was fully crowned. I figured that we were going to have to deliver the baby right there ourselves. We both had a moment where we realized this together and came to accept it pretty fast. I asked my wife if she would stand up, trying to keep her legs somewhat apart, and she did. In a split second, the baby's head got through the opening. The rest of the body was slippery and came right out. I caught the baby pretty easily and gave the child directly to its mom so she could bond and feed it. There has been research that shows that children need to have bonding time with their mom immediately after the birth, and I was eager to help with that.
I got up and went to the front door of the house and saw the backup midwife outside. I opened the door and said, "The baby's already come!" Here's a recap of what happened: Water broke around 1 am, noticeable contractions started around 1:30. Baby was born at 2:05.
Most people don't expect a half hour labor. Looking back, I wish I knew ways to slow the labor down. I thought, maybe if I made her stay lying down in bed, she would have had less time pushing because its harder to give birth when reclined. I also wished that I was able to help slow down the crowning baby. Afterwards I asked the midwife and she says there are pushing techniques that can be done to do this. But I still feel like I'm not qualified to do that next time. Most people reassure me saying that when a baby is ready to come out of mom, you can't stop it. So maybe I couldn't have done much anyway.
You may think the story ends here, but after the midwives came ( and eventually the relatives to take care of our toddler :-p ), we went through the post birth things, like birthing the placenta and cutting the cord. Then they tried to assess what damage happened. I could tell by how they were acting that they didn't think that they would be able to repair it easily. So, we decided to go to the hospital around 3 am. on Christmas day.
We left our child with the backup midwife, then my wife, our midwife, and I drove to the hospital. Unfortunately, since it was really early and Christmas, we were received pretty slowly at the hospital. Also much time was taken just rounding up all the doctors and deciding how the procedure should be done. The surgery was fast, but we weren't in a state of being able to leave until noon. Finally we were reunited and ate breakfast, opened a few Christmas presents, and finally passed out for most of the day. (and got "take out" from a local Chinese restaurant since it was the only one open that day)
One fun thing about the experience was that I got interviewed by a local newspaper. Someone I knew tipped off the newspaper that we had a home birth with no assistance. And since it was Christmas and not much news happens around those days, there was a mushy story the next day on the local front page about a dad delivering a baby on Xmas. I left out the part about the hospital in the newspaper, but wanted retell the whole experience in this blog to be for people who are thinking about having a home birth. I want potential home birth people to understand what a "worst case" situation looks like and that it really wasn't that bad. I think we did as much as we could and we were definitely prepared and had supplies. We had help that was on the way and we were committed to having a home birth.
I feel very lucky to have gone through this experience and that both my wife and child came out of the situation in good health. This birth wasn't as scary birthing my first child (who was breached, but that's another story). At most it was inconvenient to deal with an unhelpful hospital on christmas morning.
I never thought of having a home birth, but my wife was insistent on having one. I remained positive about her decision and despite everything that's happened, I still believe home births are a great experience. Above all, do what is most comfortable for your spouse. Trust in your spouse's ability to give birth and you will be amazed at how strong they are. Be there for them when they feel afraid of pain. Never make her feel like she is doing something wrong, or doesn't know what she is doing.
Monday, December 31, 2012
Thursday, December 13, 2012
Silicon Valley Hold 'Em
— Kenny Rogers, "The Gambler"
I've recently been exposed to the world of resume screening and other hiring processes.
I realized that you can have a candidate where you think the on site interview will go great but it doesn't end well and you did a full day of interviewing. Using a Texas Holdem poker analogy, this is when you fall in love with the cards you are holding, but refuse to believe the bad cards that are being revealed to you in the hopes that the card you want is going to come out in the end. But the problem with this strategy is that if you don't fold your hand, you could bet a lot of money and lose big. In an interview process the thing that you lose the most when you have an unwanted candidate is time. So you really would rather let the candidate go early than let them take up the whole day.
Because of this realization I thought it would be fun to try and make several analogies of the hiring process and Hold 'Em and use this as a mantra to help ensure bad candidates get rejected earlier.
In Texas Hold Em, you have a few rules of game. You have the cards, some chips to bet, and turns of betting. Each turn another card or cards gets revealed. These new cards can help you make an informed decision about your next move. Sometimes cards you don't want appear. In that case you want to quit playing so that you don't lose too many chips.
So, using an interview analogy, the candidate's resume is the card that you hold in hand. This card is used throughout the process by interviewers to double check the candidate. In Hold Em, people like to look at their hand several times during the round. The same thing happens during each step of the interview process by the interviewers when they print out and look at the resume before starting their interview with the candidate.
The first round of Hold Em is the initial betting round. At this point, no one knows if their hand will win. The same thing happens in the resume screening process. You have to look at the resume and convince yourself this resume will go through the whole process. In the betting part of the round you have 3 options (well sometimes 4), pay the initial bet, raise the bet, or fold. When resume screening you can do the same thing. You can fold (reject the resume), pay the initial bet (set aside time to phone screen the candidate), or raise the bet (bring the candidate on site). The 4th option that happens in poker is a reraise, but this doesn't really apply to resume screening.
The second round of Hold Em is "the flop". In this phase, enough cards are revealed to make a 5 card poker hand. I am going to venture and say that the hiring flop is when you have your first encounter with the candidate. So assuming you didn't raise, you then set up a phone screen and talk to the candidate. You learn a little about them. Most of the time this is not enough, so you could even throw in a separate quiz to make sure the candidate can code. But even after receiving the quiz, this all adds up as your initial encounter. At this step, you have 3 options again. 'Check' (continue without raising and schedule a half day interview), bet (schedule a full day interview), or fold (reject the candidate).
You might want to rethink your hand after the flop
The final two rounds of Hold em reveal one card per round, totaling 5 cards visible. These rounds are "the turn", and finally "the river". The turn is the initial half day of the interview. Whoever you choose to interview the candidate must give you a result. This result is your card. If you don't like the card, you should fold. Don't waste any more time with a bad candidate. Keep in mind the whole time you are betting your time for the candidate. Don't let your candidate know the full format of the interview so that you have the option to fold. Revealing the full schedule to the interview candidate is like having a bad poker face. Some interviews have a runaway train effect that just waste time even though everyone knows the candidate will not pass.
The river card is your second half of the day. The candidate made it this far, we didn't reject them, but there is still a chance. The game is over at this point. Its time to reveal your hand. Once you are done with the interviews, you can have an objective conversation about the day, where everyone who interviewed the candidate gives their opinions/reservations. If you reject an interviewee at the halfway mark, its not very constructive to dwell over a bad candidate. Just like in poker, if you fold early, you don't have to reveal your hand to everyone.
Finding good people is hard. But don't let bad candidates waste your time.
Friday, December 7, 2012
HTML ids and javascript
I randomly stumbled upon an article online that did this:
I fired up my javascript debugger on any random page and sure enough, if I saw html like this:
And then in the javascript console did this:
One caveat was that if the id had dashes, for example: my-id, the name wouldn't show up. This is the same problem you see when you try to create an object:
I figured this was the same problem with the variables I was seeing. The way to access ids with a dash is to use the window object because all the variables are really put on the window object.
Wow, I felt like I found out some great secret of javascript. It even gave me multiple elements when there were more than one. But then I did these actions, and they made me lose all hope in this feature:
So, in conclusion, you can clobber these variables pretty bad and not recover from the issue unless you do something like this:
*whew* back to normal. Also this is a fun thing to try out:
This is a neat feature of javascript. However, I'm wondering if this could actually cause bugs in your code where you name a variable the same as the id of your element and then reference the variable outside of the scope of the function. There's kind of too much magic and gotchas you need to pay attention to.
<script> function fnChangeText(){ var oTextNode = document.createTextNode("New List Item 1"); var oReplaceNode = oItem1.firstChild.replaceNode(oTextNode); } </script> <ul onclick = "fnChangeText()"> <li id = "oItem1">List Item 1</li> </ul>And I thought to myself, "Hey, they didn't access the LI element with document.getElementById!"
I fired up my javascript debugger on any random page and sure enough, if I saw html like this:
<div id="super_sweet_id"> ... </div>
And then in the javascript console did this:
> super_sweet_id ▶ <div id="super_sweet_id"> ... </div>I thought to myself this couldn't be true. Maybe chrome was doing something fancy. But I was able to do the same thing in firefox and IE.
One caveat was that if the id had dashes, for example: my-id, the name wouldn't show up. This is the same problem you see when you try to create an object:
// this isn't allowed in javascript var obj = {my-id: 1}; ▶ SyntaxError: Unexpected token - // instead you have add keys with the associative array setter: var obj = {}; obj['my-id'] = 1;
I figured this was the same problem with the variables I was seeing. The way to access ids with a dash is to use the window object because all the variables are really put on the window object.
> window['lame-dashed-id'] ▶ <span id="lame-dashed-id"> ... </span> // here is an example using the dot operator instead: > window.awesome_id ▶ <div id="awesome_id"> ... </div>Heck, you could even use this idea in anonymous functions, where the this variable is bound to the window object:
> (function() { return this.your_id; })(); ▶ <body id="your_id"> ... </body>Ok so, after figuring all that out, I wanted to find out if I could trick this. I went to some random page with jQuery and said, "What if I add two elements with the same id, heh heh heh (with a sneaky laugh)"
> $('body').append('<div id="a" />') > $('body').append('<div id="a" />') > a [ <div id="a"></div>, <div id="a"></div> ]
Wow, I felt like I found out some great secret of javascript. It even gave me multiple elements when there were more than one. But then I did these actions, and they made me lose all hope in this feature:
> a = 'what?' > a 'what?' > $('body').append('<div id="a" />') ... > a 'what?' > (function() { return this.a; })(); 'what?' // noooooooooo!!!!
So, in conclusion, you can clobber these variables pretty bad and not recover from the issue unless you do something like this:
> delete a true > a [ <div id="a"></div>, <div id="a"></div> ]
*whew* back to normal. Also this is a fun thing to try out:
> b <div id="b">Texty Text</div> > b.id = 'foo'; // muhuhahahahah! 'foo' > b ▶ ReferenceError: b is not defined > foo <div id="foo">Texty Text</div>
This is a neat feature of javascript. However, I'm wondering if this could actually cause bugs in your code where you name a variable the same as the id of your element and then reference the variable outside of the scope of the function. There's kind of too much magic and gotchas you need to pay attention to.
Wednesday, September 19, 2012
The trouble with downloading files
Imagine this scenario. You have QA and some customers complaining that you have this link where a file download is slow. You look at the code and see that the link is serving a dynamic file. The basic use case is that the user wants to generate a file on demand and save it to their local disk.
But you look again at the code and you see that we are using the same code to serve a dynamic file as we do to serve a static file. Anyone that has worked with HTTP and downloading a file knows that the way to tell a user to download a file is by sending special headers to a browser:
What this does is tell the browser that the link you are downloading is an attachment and gives the browser a hint on what the file should be named. The user will get a nice message asking them to save or open the file. This is great and what you want. But when you look at the code, most of the time is wasted generating the file.
So how do you fix this? Lots of people say, "Well, we don't need to generate the file on demand, we could pre-generate the file on the server"
This is a possible solution, but in some applications, disk space is very sacred and should not be wasted. So, what do you do when you must download the file on-demand?
The thing that I tried to do was send the content-disposition header early to the web browser so that the user would be prompted to save as soon as possible, and when they click save/open the file continues to download.
Here is a mod_perl example of accomplishing this with a flush operation:
On apache with mod_perl, this worked for me on firefox, but didn't work with IE and even chrome :-(
If the user clicked on the link, they would have to wait awhile until feedback about the file download showed (a save/open dialog or any indication that something was happening).
This led to someone pointing out that if you click this link many times (because you think nothing is happening), you get a hosed server at 100% cpu utilization processing your dynamic file generation.
Doh!
So how can you solve the problem of giving the user immediate feedback that something is actually downloading and eventually going to have a save/open dialog? Product managers and even other developers started suggesting, "Hey, why don't you just disable the link with javascript until the file downloads?". Other solutions involved showing an AJAX loading image in place of the link.
So, I humored them. I went down the rabbit hole of implementing AJAX file downloading. And from what I can see, it doesn't exist. I found many crappy solutions. Most of them didn't give the correct user experience across all browsers. The jquery solution I found was implemented by creating a hidden iframe. But the onSuccess function didn't get fired at the same place for all browsers.
My workflow was this:
1. onclick for the anchor, replace the anchor with a ajax loading image and start the jquery file download
2. onSuccess show the anchor again.
This worked in firefox, but in IE and chrome the onsuccess fired too early. This didn't solve the problem of preventing the user from clicking the link many times, but it did give the user the idea that something did happen. It felt like we traded one problem for another.
My product manager suggested we open a new window and show the ajax loading gif. Then close the window when the user is prompted to download the file (or the browser is showing download progress).
We tried this out, using the jquery.Download module, but when we tried closing the window in the onsuccess method, we ran into cross browser issues. Firefox window.close() was a no-op. Chrome window.close() worked. IE window.close() asked the user if they wanted to close the window.
This was a crappy solution since it flat out didn't work in firefox.
Back to the drawing board, one developer suggested we open in a new tab using an anchor target:
<a href="/my_dynamic_download?id=123" target="_blank" >Downlod file!</a>
This did work cross browser. It opened a new tab in each browser. The tab would be blank, but the browser would show some sort of loading image progress somewhere in the tab name: .
And when the file was ready to prompt the user to save/open, the tab would close automatically!
So the most elegant solution that overcame many different obstacles was actually a one line fix.
Its not perfect, but you don't have to write lots of hacky javascript.
Just know that if you ever have to deal with downloading dynamic files you will get lots of opinions. There will be lots of crappy solutions out there that aren't cross browser. You have to really think about how the user will react to no feedback. I don't think my solution is perfect but I appreciate its simplicity and how it prevented me from checking in lots of crappy code that was a major javascript hack (and the many solutions even made my perl code hacky as well).
As a side note, I do feel that if I had more control over the HTTP connection on the server side, I really believe that just flushing the content disposition to the web browser immediately should have solved everything. But since mod_perl's rflush didn't work as advertised, I had to resort to this crazy rabbit hole.
But you look again at the code and you see that we are using the same code to serve a dynamic file as we do to serve a static file. Anyone that has worked with HTTP and downloading a file knows that the way to tell a user to download a file is by sending special headers to a browser:
Content-Disposition: attachment; filename=yourfile
What this does is tell the browser that the link you are downloading is an attachment and gives the browser a hint on what the file should be named. The user will get a nice message asking them to save or open the file. This is great and what you want. But when you look at the code, most of the time is wasted generating the file.
So how do you fix this? Lots of people say, "Well, we don't need to generate the file on demand, we could pre-generate the file on the server"
This is a possible solution, but in some applications, disk space is very sacred and should not be wasted. So, what do you do when you must download the file on-demand?
The thing that I tried to do was send the content-disposition header early to the web browser so that the user would be prompted to save as soon as possible, and when they click save/open the file continues to download.
Here is a mod_perl example of accomplishing this with a flush operation:
$request->headers_out('Content-Disposition', 'attachment; filename=yourfile.pdf'); $request->content_type('application/pdf'); $request->rflush; # continue with your possibly long operation...
On apache with mod_perl, this worked for me on firefox, but didn't work with IE and even chrome :-(
If the user clicked on the link, they would have to wait awhile until feedback about the file download showed (a save/open dialog or any indication that something was happening).
This led to someone pointing out that if you click this link many times (because you think nothing is happening), you get a hosed server at 100% cpu utilization processing your dynamic file generation.
Doh!
So how can you solve the problem of giving the user immediate feedback that something is actually downloading and eventually going to have a save/open dialog? Product managers and even other developers started suggesting, "Hey, why don't you just disable the link with javascript until the file downloads?". Other solutions involved showing an AJAX loading image in place of the link.
So, I humored them. I went down the rabbit hole of implementing AJAX file downloading. And from what I can see, it doesn't exist. I found many crappy solutions. Most of them didn't give the correct user experience across all browsers. The jquery solution I found was implemented by creating a hidden iframe. But the onSuccess function didn't get fired at the same place for all browsers.
My workflow was this:
1. onclick for the anchor, replace the anchor with a ajax loading image and start the jquery file download
2. onSuccess show the anchor again.
This worked in firefox, but in IE and chrome the onsuccess fired too early. This didn't solve the problem of preventing the user from clicking the link many times, but it did give the user the idea that something did happen. It felt like we traded one problem for another.
My product manager suggested we open a new window and show the ajax loading gif. Then close the window when the user is prompted to download the file (or the browser is showing download progress).
We tried this out, using the jquery.Download module, but when we tried closing the window in the onsuccess method, we ran into cross browser issues. Firefox window.close() was a no-op. Chrome window.close() worked. IE window.close() asked the user if they wanted to close the window.
This was a crappy solution since it flat out didn't work in firefox.
Back to the drawing board, one developer suggested we open in a new tab using an anchor target:
<a href="/my_dynamic_download?id=123" target="_blank" >Downlod file!</a>
And when the file was ready to prompt the user to save/open, the tab would close automatically!
So the most elegant solution that overcame many different obstacles was actually a one line fix.
Its not perfect, but you don't have to write lots of hacky javascript.
Just know that if you ever have to deal with downloading dynamic files you will get lots of opinions. There will be lots of crappy solutions out there that aren't cross browser. You have to really think about how the user will react to no feedback. I don't think my solution is perfect but I appreciate its simplicity and how it prevented me from checking in lots of crappy code that was a major javascript hack (and the many solutions even made my perl code hacky as well).
As a side note, I do feel that if I had more control over the HTTP connection on the server side, I really believe that just flushing the content disposition to the web browser immediately should have solved everything. But since mod_perl's rflush didn't work as advertised, I had to resort to this crazy rabbit hole.
Wednesday, August 8, 2012
Interesting perl foreach behavior
My co-workers were surprised by this perl behavior and shared this problem so I thought it would be a fun post.
This code is trying to edit a hash, and normally, you would iterate over the keys and then change the looked up value somewhat like this:
You can also change an items value for an array as well:
What is happening here is that the for-loop variable is an alias for each list item. Since its an alias, Perl does not copy the list item's value just to hand $v to you (it's efficient).
The modification of hash values happens in the example because values() itself returns a list of hash values. This below wouldn't work because it introduces an intermediate copy:
And the following example is also illegal because we are trying to modify read-only values:
my %hash = ( a => 1, b => 2, ); foreach my $v (values %hash) { $v = 99; } warn Data::Dumper->Dump([\%hash], [qw(hash)]); # This was the output: $hash = { a => 99, b => 99 };
This code is trying to edit a hash, and normally, you would iterate over the keys and then change the looked up value somewhat like this:
foreach my $k (keys %hash) { $hash[$k] = 99; }
You can also change an items value for an array as well:
my @test = qw(a b c); foreach my $v (@test) { $v = 'zzz'; } warn Data::Dumper->Dump([\@test], [qw(test)]); # This was the output: $test = [ 'zzz', 'zzz', 'zzz' ];
What is happening here is that the for-loop variable is an alias for each list item. Since its an alias, Perl does not copy the list item's value just to hand $v to you (it's efficient).
The modification of hash values happens in the example because values() itself returns a list of hash values. This below wouldn't work because it introduces an intermediate copy:
my %hash = ( a => 1, b => 2, ); my @hash_values = values %hash; # make copies of hash value aliases foreach my $v (@hash_values) { $v = 99; }
And the following example is also illegal because we are trying to modify read-only values:
foreach my $v (qw[ a b c ]) { $v = 'zzz'; }So now you know the power of the foreach loop.
Saturday, June 16, 2012
SSH bookmarklet
When developing server software for a company, you might be troubleshooting an issue on a development server other than your own and you want to login to that server. Specifically I'm talking about when you are looking at say a QA person's issue in a web browser and you want to login to their box and see what's wrong.
I found out recently that my MacBook has the ssh protocol registerred already where if you click on a link with this scheme: ssh://user@host.name, then that executes ssh user@host.name. I wanted to figure out a way to utilize this in a bookmarklet. I also wanted it to be easy enough such that you could enter a different username, like root or the QA person's username if you have certain access restrictions on that server.
Here is my attempt to create that bookmarklet. Just drag it to your browser's toolbar:
Run SSH
Here is my breakdown of what happens:
This works great, but I really want to figure out how to make multiple programs that register the ssh:// protocol for any operating system or browser. Something like this link explains: http://kb.mozillazine.org/Register_protocol
Windows is pretty easy to create a batch script that adds registry keys for an ssh protocol to run putty (or even cygwin ssh). I would like to know how to do the same on Ubuntu (or any Linux). I'm pretty stoked that the Macbook already has it. I don't know if its related to me installing mac developer tools, but I'm pretty satisfied.
Anyway, Hope this bookmarklet helps!
I found out recently that my MacBook has the ssh protocol registerred already where if you click on a link with this scheme: ssh://user@host.name, then that executes ssh user@host.name. I wanted to figure out a way to utilize this in a bookmarklet. I also wanted it to be easy enough such that you could enter a different username, like root or the QA person's username if you have certain access restrictions on that server.
Here is my attempt to create that bookmarklet. Just drag it to your browser's toolbar:
Run SSH
Here is my breakdown of what happens:
// prompt for a user to ssh as, save that in the window for next time window.sshuser = prompt('Login to ' + window.location.hostname + ' as', window.sshuser || ''); // construct the user@ string user = (window.sshuser ? window.sshuser + '@' : ''); // construct the url and execute it window.location = 'ssh://' + user + window.location.hostname
This works great, but I really want to figure out how to make multiple programs that register the ssh:// protocol for any operating system or browser. Something like this link explains: http://kb.mozillazine.org/Register_protocol
Windows is pretty easy to create a batch script that adds registry keys for an ssh protocol to run putty (or even cygwin ssh). I would like to know how to do the same on Ubuntu (or any Linux). I'm pretty stoked that the Macbook already has it. I don't know if its related to me installing mac developer tools, but I'm pretty satisfied.
Anyway, Hope this bookmarklet helps!
Weird jQuery bug
My software was recently upgraded from jQuery 1.5.2 to 1.7.2.
Luckily we had a bunch of automated tests for our ui code and we found a lot of issues with our code that toggles checkboxes or the disabled state of a tag. Previously you could say
The fixes we found were to either use a boolean value instead of a string, or you could use the removeAttr function:
So because of this we tried to enforce using booleans. But you could run into issues where you didn't know the type of the second parameter to attr.
<rant>
I have to say that I'm pretty unimpressed with jQuery since no one caught this. Changing apis that are so important, like attr, is bad mojo and will cause many developers to curse your name late at night as they debug these unexpected api upgrade bugs. jQuery is supposed to be so awesome because it is easy going and does what you expect. This is a step backwards for all of us.
</ rant>
Luckily we had a bunch of automated tests for our ui code and we found a lot of issues with our code that toggles checkboxes or the disabled state of a tag. Previously you could say
$('#my_checkbox').attr('checked', 'checked'); // check the checkbox $('#my_checkbox').attr('checked', ''); // uncheck the checkbox $('#my_input').attr('disabled', 'disabled'); // disable the input $('#my_input').attr('disabled', ''); // enable the inputWe had code all over the place that did this. But when we used empty string, attr didn't enable or uncheck the elements.
The fixes we found were to either use a boolean value instead of a string, or you could use the removeAttr function:
$('#my_checkbox').attr('checked', true); // check the checkbox $('#my_checkbox').attr('checked', false); // uncheck the checkbox $('#my_checkbox').removeAttr('checked'); // alternative to uncheck the checkbox $('#my_input').attr('disabled', true); // disable the input $('#my_input').attr('disabled', false); // enable the input $('#my_input').removeAttr('disabled'); // alternative to enable the inputWe needed to figure out the best way to change our code with little impact and it looked like using removeAttr would cause more code since you would have to litter your code with if/else statements to figure out whether to use the attr or the removeAttr case.
So because of this we tried to enforce using booleans. But you could run into issues where you didn't know the type of the second parameter to attr.
var checked = $('#my_checkbox').attr('checked'); // get the checkbox state: // 'checked' or '' //... $('#other_checkbox').attr('checked', checked); // set another checkbox to the same state // same thing appplies to disabledI did some digging and found that jQuery 1.6.2 had a fix to change attr('checked') to return the actual html value of checked instead of a boolean value:
<input id="my_checkbox" type="checkbox" checked="checked" /> ... var checkState = $('#my_checkbox').attr('checked'); // returns 'checked' as of jQuery 1.6.2 instead of true. When it is unchecked, you get undefined returned. // See this link for a list of more quirks: // http://blog.jquery.com/2011/06/30/jquery-162-released/#comment-526605So, to remedy this, we decided to always ensure you pass a boolean to the attr function for disabled or checked. Don't use empty string to uncheck or enable your element. If you still want to rely on the return string of the attr function, you can booleanize it like this:
var check_state = $('#my_checkbox').attr('checked'); // get the checkbox state: // 'checked' or undefined //... $('#other_checkbox').attr('checked', !!check_state); // set another checkbox to the same state using a boolean // !!undefined yields false, // !!'checked' yields true // same thing applies to disabledNow you know, and knowing is half the battle.
<rant>
I have to say that I'm pretty unimpressed with jQuery since no one caught this. Changing apis that are so important, like attr, is bad mojo and will cause many developers to curse your name late at night as they debug these unexpected api upgrade bugs. jQuery is supposed to be so awesome because it is easy going and does what you expect. This is a step backwards for all of us.
</ rant>
Wednesday, April 11, 2012
dev=1
Sometimes you want to be able to toggle dev=1 on a url. This can easily be done with javascript.
You can create a link on a page with href="javascript:..." then right-click->save this link as a bookmark in your bookmark toolbar.
The following link is my attempt to write this, you can click it now, or bookmark it --> Toggle Dev
Let's read it line by line:
You have to make sure you don't forget the window.location.hash, or else you will get the dev=1 in the wrong part of the url.
=====================
I also wanted a way to toggle my web server from live apache(https) to a single threaded dev server (8080)
Here is my attempt: Toggle 8080
Again, here it is line by line
Hope this helps.
The following link is my attempt to write this, you can click it now, or bookmark it --> Toggle Dev
Let's read it line by line:
var alocation = window.location.search.toString(); // save the ?query string // determine if when we add dev=1 if we need a ? or an & var questoramp = alocation.indexOf('?') != -1 ? '&' : '?'; // if dev=1 exists, remove it, otherwise add it var next = alocation.match(/[\?&]dev=1/) ? alocation.replace(/[\?&]dev=1/,'') : alocation + questoramp + 'dev=1'; // handle special case where dev=1 is at the beginning of the url next = alocation.match(/\?dev=1&/) ? alocation.replace(/dev=1&/,'') : next; // update the window location window.location.href=window.location.pathname + next + window.location.hash;
You have to make sure you don't forget the window.location.hash, or else you will get the dev=1 in the wrong part of the url.
=====================
I also wanted a way to toggle my web server from live apache(https) to a single threaded dev server (8080)
Here is my attempt: Toggle 8080
Again, here it is line by line
// save the whole url var alocation = window.location.href.toString(); // if you see 8080 in the url, remove it and change the protocol to https, otherwise add it var next = window.location.port == '8080' ? alocation.replace(/:8080/,'').replace(/http/,'https') : 'http://' + window.location.host + ':8080' + window.location.pathname + window.location.search + window.location.hash; // update the window location window.location = next;
Hope this helps.
Friday, March 9, 2012
Logic chains in javascript and python
Let's talk about javascript. What happens when you have a function like this:
function(x) { x = x || 'default' ... }
This is useful when you want to have a function where x is optional. When you don't pass a value to your function x is treated as undefined and the statement is read as x = undefined || 'default'. Whenever you have:
somevariable = statement || statement || statement ... || statement
the variable will get assigned the first true value from left to right or the last false value.
But what happens when you do this?
x = [] || 'kittens'
you would think that [] evaluates as a false value, but in javascript an empty list is true so x becomes []
lets try this in python
x = [] or 'kittens'This evaluates the way you think, x becomes 'kittens'.
Now, I'm not saying anyone would have statements like this, but I just wanted you to think about the little differences that languages have and how they can cause unforeseen bugs.
The same thing applies to empty objects:
in javascript:
x = {} || 'yarg' /* yields {} */
in python
x = {} or 'yarg' /* yields yarg */
Complimentary to the 'or' examples, 'and's behave the opposite. If you have:
somevariable = statement && statement && ... && statement
your variable will get the first false statement or the last true statement.
This works pretty well in javascript/python
x = 'lol' and 'heh' and 'doh' x = 'lol' && 'heh' && 'doh' /* x has doh */
but again, try this:
// javascript x = 'lol' && [] && 'doh' /* yields 'doh' */ # python x = 'lol' and [] and 'doh' /* yields [] */Now you know; and knowing is half the battle.
Thursday, March 1, 2012
Fun Emacs Prank
I noticed while using emacs you can use this handy program called emacsclient to perhaps open a file or run a command on emacs. I took this as an opportunity to have fun with my co-workers.
They like to run emacs with X-Forwarding on remote hosts that are the development hosts. Its easy to log into their remote host and do something like this:
This would open the file on their currently running emacs. Sounds great right? You could make some ascii picture of something nsfw and then just run good old emacsclient to turn their day around!
Anywho, this wasn't enough for me. I wanted to make it so the file would change and maybe scroll across the screen saying something like "LOL Kittens!". Or even you could try and make it invert the ascii art and then invert it back. Somewhat like you are flashing the text.
I first tried to get it so you could scroll the art across the screen (from left to right)
Example:
first iteration
LOL
CAT
second iteration
OL
AT
final iteration
L
T
I started out trying this:
This didn't work as expected. Emacs kept asking if I wanted to refresh the modified buffers.
I did some digging and it didn't seem like an easy solution. I wanted this to be something that would just appear on my co-worker's screen and cause mayhem.
After some more digging I found the handy emacs command: zone.
It does all fun stuff like scrolling your current buffer, or even dripping the text like the movie The Matrix.
I couldn't wait to find out that emacsclient came with --eval as an option. This allows you to run lisp on your emacs server. Checkmate.
I created this script:
This script ran fine. But sometimes emacsclient blocked when you ran zone. This wasn't ideal. So I added this to the beginning to kill the emacsclient every time you run zone:
They like to run emacs with X-Forwarding on remote hosts that are the development hosts. Its easy to log into their remote host and do something like this:
emacsclient --no-wait ~/prank-file
This would open the file on their currently running emacs. Sounds great right? You could make some ascii picture of something nsfw and then just run good old emacsclient to turn their day around!
Anywho, this wasn't enough for me. I wanted to make it so the file would change and maybe scroll across the screen saying something like "LOL Kittens!". Or even you could try and make it invert the ascii art and then invert it back. Somewhat like you are flashing the text.
I first tried to get it so you could scroll the art across the screen (from left to right)
Example:
first iteration
LOL
CAT
second iteration
OL
AT
final iteration
L
T
I started out trying this:
columns=`head -n 1 /tmp/ascii-art-file | wc -c`; # get the number of columns in the text file for x in seq 1 $columns; do cut -c $x-$columns /tmp/ascii-art-file > /tmp/scroll; emacsclient --no-wait /tmp/scroll; sleep 5; done;
This didn't work as expected. Emacs kept asking if I wanted to refresh the modified buffers.
I did some digging and it didn't seem like an easy solution. I wanted this to be something that would just appear on my co-worker's screen and cause mayhem.
After some more digging I found the handy emacs command: zone.
It does all fun stuff like scrolling your current buffer, or even dripping the text like the movie The Matrix.
I couldn't wait to find out that emacsclient came with --eval as an option. This allows you to run lisp on your emacs server. Checkmate.
I created this script:
/tmp/zone #!/bin/sh emacsclient --no-wait $1 emacsclient -e '(with-current-buffer "'`basename $1`'" (zone))' sleep 5
This script ran fine. But sometimes emacsclient blocked when you ran zone. This wasn't ideal. So I added this to the beginning to kill the emacsclient every time you run zone:
ps -ef | grep emacsclient | grep -v grep | awk '{print $2}' | xargs --no-run-if-empty kill -9Finally, to get this to run over and over, just put zone in a while loop:
while true; do /tmp/zone /tmp/ascii-art-file; done;Happy pranking!
Subscribe to:
Posts (Atom)