Twitter Bootstrap Tooltips playing nice with SVG

First, read about Bootstrap tooltips and popovers on Bootstrap’s website.


Want to add a tooltip to an svg object?

Check out this question on Stack Overflow:

How do I show a bootstrap tooltip with an svg object.

Or, just jump right on ahead to the jsfiddle.

The essence of it boils down to using $('svg -whatever-').tooltip(-options-).

For example, if all you elements have class cells, then you would use something like


// title: compulsary if you want a non-empty tooltip
d3.selectAll('.cells').attr('title','This is my tooltip title');

// content: popovers only. 
d3.selectAll('.cells').attr('data-content','This is some content');

// set the options – read more on the Bootstrap page linked to above
$('svg .cells').popover({
   'trigger':'hover'
   ,'container': 'body'
   ,'placement': 'top'
   ,'white-space': 'nowrap'
   ,'html':'true'
});


Confused about how to add tooltips in general? Or just want to make your life easier and deal with them all at once?

Read this answer on Stack Overflow: Bootstrap 3.0 Popovers and Tooltips.

The gist of it:

$('[data-toggle="tooltip"]').tooltip({
    'placement': 'top'
});
$('[data-toggle="popover"]').popover({
    trigger: 'hover'
    ,'placement': 'top'
});

Functions with variable number of input arguments in Java

static public final float myMax(float... input) {
    -- code for finding max of an array --
}

Java automatically transforms your input into an array which you can traverse like an array.
This means that you only need to define a single function and it will be able to deal with all of these scenarios

myMax(1,2);
myMax(1,2,-1,2,20000000,9,3); 
myMax(new float[]{1,2,-1,2,20000000,9,3});

You’re not constrained to just the float type though. Any class will do, from Strings, to booleans, to custom classes you’ve created yourself.

Wish I’d known this when I first began using Java.

Things I wish someone had told me when I first started learning Meteor.js

Here’s to hoping I don’t make the same mistake twice.


When using iron-router for your meteor project, do not use ‘link’ in any of your handlebar templates. For example, say you have a loop that looks something like this:

{{#each list_items}}
  <div>{{username}}
    <a href="{{link}}">Click here!</a>
  </div>
{{/each}}

and the JSON object for each list_item looks something like this:

{
  user: 'Chuck Norris',
  link: 'http://YouDontFindChuckNorrisHeFindsYou.com/'
}

The inclusion of {{link}} in the code above will cause iron-router to give you this error:

You called Router.path for a route named undefined but that that route doesn't seem to exist.
This is because under the hood Iron-Router registers handlebars helper:

Handlebars.registerHelper('link', 
    function (options) {   ...   }); 

By specifying something else as link, you’re interfering with that magic so use something else. Like url or my_link, or, if you want to be really descriptive, potato.
Reference: Handlebars + Meteor + iron-router on Stack Overflow


Reading in data from a csv file into your Meteor app database.

This assumes you’ve already googled it and you’re now on page 3 of your search results, slowly yet surely giving up hope (but also knowledgeable enough to at least follow along with what I’m about to say).
Steps:
1. Navigate to your app folder in terminal and start your app like so.

cd myapp
meteor

2. Place your data-file in the same folder as your app. For simplicity, just place it in the main folder for now, not in any of the sub-sub-sub-sub-directories. I’m going to call the file data.csv just to keep things simple.
Directory Structure

3.I’m going to assume you have a Meteor Collection named ‘links’:

Links = new Meteor.Collection('links')

Now, Go back to terminal and open another tab. Type this:

mongoimport -h localhost:3001 --db meteor --collection links --type csv --file data.csv --fields url,name --headerline

Your ‘links’ collection should now contain the relevant data from your csv file.
There’s a wealth of info on the above in this mongo docs page. This youtube video also goes over the steps pretty clearly.

Briefly:

  • -h = the host (or server) name.
  • --port = specifies the port on the host that the MongoDB database is listening on. By default, Meteor uses port 3000 so we use 3001 for the Mongo db.
  • --db = the name of your database, in this case, meteor.
  • -collection = the name of the collection to import the CSV file into. You can also use --c for short.
  • In the above, my collection is called ‘links’.

  • --type The format of the file to be imported. In our case, it’s a csv but it can also be a json, or a tsv (and potentially some other format too. I haven’t checked).
  • --file The physical location of the file. Since we placed it in the main directory, we didn’t have to include any pathnames. If you have it somewhere else, like in a subdirectory, or in your documents folder, or even on your Desktop, just type the correct filepath and you’re good to go.
  • --fields What columns of your csv file you’d like to use. I’m pulling the columns labeled ‘url’ and ‘name’.
  • --headerline This simply tells MongoDB to disregard the first line of the CSV file.

If you’re doing all this and it’s still not working, try creating a new test.csv file in a text-editor, copy-pasting the contents of your data.csv file into it, then importing that new test.csv file instead to see if the problem lies in your data file. For some reason, I always have a problem reading my csv files in unless I do that (took me half the night to figure it out too. Fun times).


A few more useful links:

  • Calling server methods client-side? This excellent gist by nachiket-p should get you going.

  • Need to know more about iron-router? Read Manuel Schoebel’s blog entry on it.

  • Want better bootstrap headers? Go no further than alanning’s list of examples on github.

  • Get all ‘url’ fields from your Links Collection using underscore.js:
    var theArray = _.pluck( .find().fetch(), '' );
    So, if your collection is named links,
    Links = new Meteor.Collection('links'),
    has fields
    {id, name, url},
    and you want to get an array containing just the url fields, you would write
    var urlArray = _.pluck( Links.find().fetch(), 'url' );

  • Add a field to your Collection:

    function addAField(){
        <The-Collection>.find().fetch().forEach(function (elem) {
            <The-Collection>.update(elem._id, 
                   {$set:{'<new-field-name>':<new-field-value>}} );  
        });
    } 
    

    For example, say you want to add a field containing a random number into your Links Collection. You could use something like this
    Links = new Meteor.Collection('links'),
    combined with a call to the addAField function,

    function addAField(){
        Links.find().fetch().forEach(function (elem) {
    	Links.update(elem._id, 
                 {$set:{'rand':Math.random()}} );  
        });
    } 
    

Your Processing applet is damaged and can’t be opened. You should move it to the trash.

Your friend just spent the better part of a weekend making an applet for you to do some crazy awesome kickass thing but every time you try to open it, you get this error message “The .app is damaged and can’t be opened. You should move it to the trash.

Uh Oh.

Bah! But it worked fine on her computer! In fact, she even emailed it to herself, downloaded it, and reran it without any problem!

Fret not! Salvation is near! You know it’s true because I’m overusing exclamation marks! (!)

Here’s how to fix it (on a Mac):

  1. Go to System Preferences
  2. Click on Security & Privacy
  3. Change your Gatekeeping settings to “Allow applications downloaded from *ANYWHERE*”.

System Prefs --> Security --> Allow applications downloaded from *ANYWHERE*[Click for a larger image]

There. It should work now.

And if it doesn’t, I guess you’re S.O.L….

Using javascript to parse your URL into parts

Problem: Your site has a url that looks something like this: http://www.bart.gov/schedules/quickplanner?orig=12TH&addr1=&dest=16TH&addr2=&type=departure&date=2013-12-21&time=9%3A00%20am&tab=2

You want to break it down into parts, for reasons that I’ll leave to your imagination.

Turns out that all the info you need is conveniently stored in the window.location object. Here’s the keys stored in the window.location object:

ancestorOrigins
constructor
hash
host
hostname
href
origin
pathname
port
protocol
search

You can find out what each of them hold using this simple for loop:

//print out all window.location variables.
var loc = window.location;
for(var aKey in loc){
 console.log(aKey+":",loca[aKey]);
}

For example, if the url of the site is http://www.bart.gov/schedules/quickplanner
you’ll find that

window.location.protocol = "http"
window.location.host = "www.bart.gov"
window.location.pathname = "schedules/quickplanner

The window.location.search variable holds the part of the string that’s after the pathname.
That is, in the BART url above,

window.location.search = ?orig=12TH&addr1=&dest=16TH&addr2=&type=departure&date=2013-12-21&time=9%3A00%20am&tab=2;

You can parse it into parts like so:

function get_search_from_url  (query) {
  if(!query || query.length==0) return query; // empty query string was input.
  var query_string = {};
  // get rid of the '?' at the beginning
  query = query.chartAt(0)=='?' ? query.substring(1,query.length) : query;
  // get the different parts
  var vars = query.split("&");
  for (var i=0;i<vars.length;i++) {
    var pair = vars[i].split("=");
    pair[0] = decodeURIComponent(pair[0]);
    pair[1] = decodeURIComponent(pair[1]);
    	// If first entry with this name
    if (typeof query_string[pair[0]] === "undefined") {
      query_string[pair[0]] = pair[1];
    	// If second entry with this name
    } else if (typeof query_string[pair[0]] === "string") {
      var arr = [ query_string[pair[0]], pair[1] ];
      query_string[pair[0]] = arr;
    	// If third or later entry with this name
    } else {
      query_string[pair[0]].push(pair[1]);
    }
  } 
  return query_string;
};

It basically does the opposite of jquery’s .param function.

Exporting data from a web browser to a csv file using javascript.

If you want to skip all this text and just download a working example, go ahead and scroll to the end of this post. Otherwise, read on.


There is a comprehensive answer from Terry Young on Stack Overflow with accompanying fiddle here.

Works as you’d expect on Firefox 20 and Google Chrome 26. The file exports fine in Safari 6.0.5 but won’t name the file. Instead, it’ll save your file as ‘unknown’ (no file extension) so you’ll need to go in and rename it yourself if you’re constrained to Safari.

And then there’s this answer on Stack Overflow by adeneo. It’s a little less comprehensive but equally helpful depending on what you’re looking for. Here’s the fiddle. A rough idea of what the code looks like is shown below.

var A = [['n','sqrt(n)']];  // initialize array of rows with header row as 1st item
	 
for(var j=1;j<10;++j){ A.push([j, Math.sqrt(j)]) }

var csvRows = [];
for(var i=0,l=A.length; i<l; ++i){
	    csvRows.push(A[i].join(','));   // unquoted CSV row
}
var csvString = csvRows.join('\n');

var a = document.createElement('a');
a.href     = 'data:attachment/csv,' + csvString;
a.target   ='_blank';
a.download = 'myFile.csv,' + encodeURIComponent(csvString); ;
a.innerHTML = "Click me to download the file.";
document.body.appendChild(a);

Finally, here’s a link to a downloadable gist on GitHub if you want to just get up and running straight away. It’s based on Terry Young‘s answer but modified to include table headers, and refactored so anything that gets done more than once gets its own function.

Listing all files in a folder [java]

From here.

public File[] listf(String directoryName) {

    // .............list file
    File directory = new File(directoryName);

    // get all the files from a directory
    File[] fList = directory.listFiles(); 

    for (File file : fList) {
        if (file.isFile()) {
            System.out.println(file.getAbsolutePath());
        } else if (file.isDirectory()) {
            listf(file.getAbsolutePath());
        }
    }
    System.out.println(fList);
    return fList;
}