Findings on change listener in react

I ran into a strange issue testing a react 16 page with zombie. I was using zombie to fire a change event on a checkbox. Totally legit. But it was not calling the event listener. Knowing react uses a synthetic event system I began a long voyage into debugging this. What I found was a little strange and can be tied to this single comment.

1
2
3
4
Function shouldUseClickEvent(elem) {
// Use the `click` event to detect changes to checkbox and radio inputs.
// This approach works across all browsers, whereas `change` does not fire
// until `blur` in IE8.

So react swallows browser change events for checkboxes and relies on the fact that in order to achieve the change, a click must happen.

It listens to the click, decides its a checkbox, attaches its own change event, finds event listeners registered to onChange and goes on about its business.

Fine.

But why is react making exceptions for ie8!????

Vim javascript cucumber functionality

Cucumber is great. Human readable steps that can power different testing frameworks.

One of the main pain points is finding the step definition from a feature file. My primary text editor is vim. A plugin does exist to provide this functionality but it is geared towards ruby cucumber. I am usingĀ vim-cucumber. I already have this installed for syntax highlighting but it was not easily configurable forĀ cucumber-js. Below are a few snippets to have a key combo find and open the corresponding step definition from a feature file.

Rate limiting promises

You have a bunch of requests to make and you want to do them in the most efficient way possible.
Unfortunately your api is rate limited.
This lets you define a cool down period after a batch is sent.

Example:
100 requests to make
5 per second rate limit
20 batches each with a 5 second cool down period

1. create a promise for each batch
2. resolve that promise once the models xhr were executed and returned their own promises
3. repeat until all batches are done
4. return array of all the promises generated by the xhrs

button type=button can be important

While dealing with a bizarre MS edge/ie bug I found how important defining the type of your buttons can be.
Scenario:
In MS edge when hitting return while focused on and text input field, the submit event would fail to fire for the correct submit button. Instead it would find the next enabled button (in this case the cancel button) and fire that event. Not ideal.

Specific Issue:
Form with both an input type=submit and a button with no defined type for canceling.
Input type=submit is initially set with a disabled attribute of true.

I found that if this submit input was not disabled submitting via enter key behaved as expected.
But as soon as the submit input was disabled any button after the disabled submit input would receive the event.

Applying the type=button to the cancel button allowed me to keep the type=submit input disabled and still prevent behavior from the cancel button.

While one could argue this is bad markup, all other browsers were able to suck it up and behave normally.

Have watch compile only changed sass

I recently started using browsersync. With an app that takes on average 10 seconds to browserify all of the javascript trivial css changes can take a lot of time because of refreshing. This piece of code further saves time by telling grunt-sass to compile only the changed scss file using grunt eventing.

It takes the path that changed and replaces the grunt-sass src param with it saving upwards of three seconds for me. The only caveat is if you are editing sass includes. Grunt-sass has no idea which index file needs to be compiled. In the end I wasn’t able to use this time saver but someone else might be able to.

grunt-watch config

module.exports = (grunt, options) ->
grunt.event.on('watch', (action, filepath) ->
grunt.config('sass.dist.files.2', '[<%='+ filepath+ ' %>]')
)
return scripts:
files: "stylesheets/**/*.scss"
tasks: ['css']
options:
debounceDelay: 250
event: ['changed']
spawn: false

grunt-sass config

dist:
options:
imagePath : path.join("/", Asset.STATIC_PATH, "images")
includePaths : [ "lib/assets/stylesheets/" ]
outputStyle : (if options.environment is "development" then "nested" else "compressed")

files: [
expand : true
cwd : "lib/assets/stylesheets/"
src : [ "**/*.scss" ]
dest : "public/static/"
ext : ".css"
]

Access your local host from your virtualbox

This is a follow up to setting up virtual box on a mac.

The whole reason for windows on a mac is to test web sites. I needed to access the local host.

It is as simple as using your ip address. I had to dig a bit to find mine because my router assigns me one.

Open terminal and run:

ifconfig

copy the inet setting and paste it into virtualbox browser.

Thats it, you now have access to your local host from virtualbox.

Set up windows with virtualbox on a mac for free

I just recently found the joy of virtualbox. Now I can quickly test web sites in any version of IE with the click of a button. No more finding a pc, struggling with giving it access to my local network and wasting time switching between the two computers. I keep an instance of virtual box running in a desktop space on my mac so it is always just a swipe away. Lets get started.

Downloads:

After you download a copy of virtualbox from here, head over to modern.ie

You will want to spend a bit of time here discovering best practices and ways to tackle older versions of ie. The real gold here are the virtual machines you can download.

You will most likely want a couple combinations of windows and IE. Follow the instructions. It took me a couple tries due to errors compiling the .rar files.

Once those are all downloaded, which may take a minute since they are about a gig a piece, run the source command on the .sfx file and create your virtual box image.

Congratulations, you now have a free windows virtual machine. A double click on the image will open virtualbox. You can run the machine right now but I wanted to do some configurations to make things run smoother.

Configuration:
1. More memory
Select your machine in virtual box and click on the settings tab. Go to system and select more memory. THe default was 8mb. Give it all you can spare. I gave it 4gb. You might want to bump up the processor while you are there.

2. Fire up the machine and install guest additions
While in the virtual machine, click on devices on the menu bar. Choose install guest additions. This will start a prompt in windows. Follow the instructions and restart. This is important because it now allows windows to utilize the full resolution of your screen. It also seemed to help with performance.

3. Caveats
After I installed the guest additions my internet stopped working in windows. I struggled to find the answer.
Solution:
In the virtualbox application click on your machine, and click settings(same area for setting up more ram and processor power). Click on network. Choose NAT. It is very important to check the box “cable connected”. My internet was back!

Rinse and repeat for other combinations of IE and windows.

Alternatives:
Browser stack is amazing if you have the budget.
Parallels
Book camp
vmware fustion

South Migrations foreign key name change

Data migration is confusing. Here are a few south migrations I needed to change the name of a foreign key. For any of this to make sense you need a pretty good understanding of south.

Old model:

class CustomField(models.Model):
    name = models.ForeignKey('CustomFieldName', null=True, blank=True)
    politician = models.ForeignKey(Candidate, null=True, blank=True)

New model:

class CustomField(models.Model):
    name = models.ForeignKey('CustomFieldName', null=True, blank=True)
    candidate = models.ForeignKey(Candidate, null=True, blank=True,help_text='choose a candidate for a field specific to this race or elections')
    politician = models.ForeignKey('legislators.Politician',null=True, blank=True,default=None,help_text='Choose a politician for fields to persist through multiple elections and races')

I was able to do this pretty easily with rename_column()

Now that I had renamed my field to candidate, politician was freed up to use for a new column, or so I thought. I ran a typical schema migration after adding politician and kept getting an error that politician_id already existed. Where was it coming from? South adds an index to the table. I needed to run

db.delete_index('elections_customfield', 'politician_id')

Only after that was I able to re-add politician as a field. Took me a few hours of struggle so I thought I’d write about.

Final migrations:

change name:

    def forwards(self, orm):
        "Write your forwards methods here."
        # Note: Don't use "from appname.models import ModelName". 
        # Use orm.ModelName to refer to models in this application,
        # and orm['appname.ModelName'] for models in other applications.
        db.delete_foreign_key('elections_customfield', 'politician_id')
        db.delete_index('elections_customfield', 'politician_id')
        db.rename_column('elections_customfield', 'politician_id','candidate_id')
        db.alter_column('elections_customfield', 'candidate_id', models.ForeignKey(to=orm['elections.Candidate']))
   
    def backwards(self, orm):
        "Write your backwards methods here."
        db.rename_column('elections_customfield', 'candidate_id','politician_id')

Re-add politician as a differnt field:


    def forwards(self, orm):
        # Adding field 'CustomField.politician'
        db.add_column('elections_customfield', 'politician',
                      self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['legislators.Politician'], null=True, blank=True),
                      keep_default=False)

In my case i needed to migrate the old politician data to the new politician field:

    def forwards(self, orm):
        "Write your forwards methods here."
        # Note: Don't use "from appname.models import ModelName". 
        # Use orm.ModelName to refer to models in this application,
        # and orm['appname.ModelName'] for models in other applications.
        for custom_field in orm.CustomField.objects.all():
            candidate = custom_field.candidate.politician
            custom_field.politician = candidate
            #custom_field.candidate = None
            custom_field.save()

goodbye

Jquery delegate and IOS with .on()

I encountered a very annoying bug in IOS today. It appears IOS will not respect the delegate feature of the jQuery.on() function. After spending and hour trouble shooting I found this stackoverflow.

The simplest solution seems to be setting the element in question to cursor:pointer with css. Why this works I do not know!

Example:

    $('body').on('click','.icon-close',function(){
        $("#popup-content, .sidebar").fadeOut();
    });
    .icon-close{ cursor:pointer; }

trains

“it’s like a bunch of fucking people trying to figure out how to drive a train, and don’t realize the engine needs to be on rails”
-dev