Tuesday, December 20, 2011

Add styles permanently to your Blogger layout

So if you're like me, you probably write posts. These posts contain paragraphs, images, maybe dot-points, and yes, code. What many bloggers do with posted code, is give it a certain style for easier readability.
$ something like this
Up until now, everytime I wanted to do that, I first stated the style that I wanted in the HTML editing way. This was done by putting this at the start of every post that I needed to:
<style type="text/css">
pre.source-code {
  font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;
  color: #000000;
  background-color: #eee;
  font-size: 12px;
  border: 1px dashed #999999;
  line-height: 16px;
  padding: 10px;
  overflow: auto;
  width: 100%
}
</style> 

But now, this part can be skipped and all I have to do now is just wrap the text in the appropriate tags and Blogger will do the rest. But first, the styling above needs to be added to your Blogger settings.

While logged into your Blogger account, navigate to the page that shows you all the info for the blog that you want to customize, in my case "My Natural State...".

With the 'Layout' option on the left selected, click on the 'Template Designer' text just under the blog title.



You should be taken to the template wizard that you would of gone through the first time you made the blog. Select "Advanced" -> then scroll down to "Add CSS" -> and then add you style!


That's all there is to it. Now when you make a new post, you still have to type the with the HTML tab selected up the top, otherwise it will be read as plain text. Oh...and this just means that you only have to remember the tags, luckily I only have 1, heheh.

Enjoy, ciao!

Monday, December 19, 2011

HTML5 FileAPI: Display Drag n Drop image file

Sometimes accidents are great, and as always, something can be learned. Yesterday, while trying to figure out a way to display .csv files in the web browser, I stumbled upon FileAPI, some sort of HTML5 library...or something (can't display .csv files though...I was just distracted :D). One of the uses that has become apparent to me and others is that files can be dropped straight into the web browser, and then you can read the information that it contains.

Quick video here.
FileReader Docs (by Mozilla) here, this is mainly what I will be describing.
Other links here, here and here.

So, for the rest of this post, I'm just going to paste some code so you can do what snowcrashbeta did (Video link above). All you will need is an index.html file and an associated script.js file. You don't really need to know much JS, but it helps find problems. The way I would describe whats going on is that:
  • elements on the website wait for specific actions to occur,
  • when they do (a file is dropped onto it), a js function is called which then (and depending on how you set it up) takes the file and reads the information embedded in it (filename, type, size etc.), 
  • once it is read, you can then display this information or do something else...like display the image. Somewhere along the line, the file is also uploaded, how neat is that!
Below will be the code, and MY interpretation of what's going on. Yes, there is a high chance that I could be wrong, but I did do a little bit of reading...

index.html
<head>
 <title>Drag n Drog</title>
 <meta http-equiv="content-type" content="text/html;charset=utf-8" />
 <meta name="generator" content="Geany 0.20" />
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<style>
 div { border-radius: 20px; margin-bottom: 10px; padding: 15px; }
 #wrapper { margin: 20px auto; max-width: 600px; }
 #dropper { border: 5px dashed #ccc; height: 100px; text-align: center; font-size: 60px; color: #ccc;}
 #fileinfo { border: 5px solid black; height: 30px; }
 #filedata { border: 5px solid black; height: 250px; }
</style>
</head>

<body>
<div id="wrapper">
 <div id="dropper">Drop File Here</div>
 <div id="fileinfo">File Info</div>
 <div id="filedata"><img id="fileimage" src="" alt="Image"/></div>
</div>
 
 <script src="script.js"></script>
 
</body>
</html>

<head></head>: where the title, links to script files and styles are stated
  • <script src="https://ajax.googleapis... the location of the FileAPI (I think?)
  • div#wrapper...#dropper...#fileinfo...#filedata... CSS styles for these tags
<body> </body>: what people will see
  • <div id="dropper">... dropper element. Where users will drop files.
  • <div id="fileinfo">... fileinfo element. Where information about the file is displayed.
  • <div id="filedata">... filedata element. Holds the image since <img> tags do not have a border option (I'm sure there's a work around).
    • <img id="fileimage" src=""... within the <div id="filedata"... tags. This is where the image will be loaded after the user drops it
  •  <script src="script.js">...load our script file. Note: this can be put up the top of file where the other one was, with the effect that this file will be loaded before the rest of the page will be loaded. Also, the <script... up the top can be put here, but will be loaded after everything else.
The website should look like this. And if you drop an image onto the element, it should display in the box below. So what's going on? Read on.

script.js
$(document).ready(function() {
 var dropbox = document.getElementById("dropper");
 
 dropbox.addEventListener("dragover", dragOver, false);
 dropbox.addEventListener("drop", drop, false);
});

function dragOver(evt) {
 evt.stopPropagation();
 evt.preventDefault();
}

function drop(evt) {
 evt.stopPropagation();
 evt.preventDefault();
 
 var files = evt.dataTransfer.files;
 
 if (files.length > 0) handleFileInfo(files);
}

function handleFileInfo(files) {
 var f = files[0];
 var output = [];
 output.push('<strong>', f.name, '</strong> (', f.type || 'n/a', ') - ',
     f.size, ' bytes, last modified: ',
     f.lastModifiedDate.toLocaleDateString());
     
 $("#fileinfo").html(output.join(""));
 
 var reader = new FileReader();

 reader.onload = function (evt) {
  document.getElementById("fileimage").src = evt.target.result
  };
 reader.readAsDataURL(f);
}

$(document)...});
This is where the event listeners (self-explanatory really) for the "dropper" element are defined. Since we have defined an area where we want users to drop files, then we have to link a bit of code to certain events, the code then being called to run. "dragover" and "drop" are predefined options, and I suspect many more exist for us to experiment with :).

It is recommended that you watch that video I linked to above, that's really how I learnt this.

function dragOver(evt) {...}
This is to prevent the default action from occurring when a user drops a file into the web browser. If you try this, then the browser will try to display the file. But we want to do much more than display the image.

function drop(evt) {...}
Same as above. But, when the user drops the file, we want to do something. We can call the handleFileInfo() straight away, but what I've done here is do a quick if() statement to check that there is something in the file to process.

function handleFileInfo(files) {...} This file processor.
  • output.push(..html(output.join("")); this takes the file the user has dropped, and reads certain parameters the belong to it. It then concatenates these and sends it to "fileinfo" - which we defined in index.html.
  • var reader... not sure, but calls FileAPI and gets it ready, if it isn't already :S.
  • reader.onload...readAsDataURL(f); ... more unknown :S. But in html speak, finds the "fileimage" element and then changes its' .src to evt.target.result (which is probably where the file was uploaded to)
    • readAsDataURL(f) VI!!. This is the method in which reader. reads the files. See FileReader for more info, scroll about half way down.
Done!  There is a lot of stuff here that I don't know about, but it has definitely given me a primer for HTML5 capabilities...and some ideas for my website (which is pretty dull to say the least!).

If you would like to download these two files and give it a go, get them here:
FileAPI_DnD_example.tar.gz
Many thanks! Till next time, Ciao!

Tuesday, December 13, 2011

Mv folders with spaces

So something has happened to my 320GB external HDD and I've started to get corrupt files :(. Not good. It is a few years old but I think that my best bet would be to remove everything and reformat it. This also gives me a chance to clean up all the shit and solve problems like how to move folders that have spaces in them - since spaces tend to cause a bit of trouble for programmers.

My solution is fairly simple, probably not the best and/or shortest, but the job is now done, and I can reformat my HDD.

The steps can be summarized as follows:

1) ls the directory with all the folders that you need to move and send the output to a .txt file. Before you ask why didn't I just move the parent folder? Well, to put simply, I had errors of some sort...so I had to do it the long way
2) Using 9 lines of python and the 'os' library, read the output.txt file and add "s to the start and end of every line. Close output.txt
3) Use nawk to read the updated output.txt file and move the folders (with spaces...grr) to the desired location.

Let's get started!

So here's the code and how I've done it. For the purpose of this example, I will compare the Music folder on my media drive and the Music folder on my desktop - each of which contain several sub-folders of artists. But if you want to just mv folders, then just skip some of the steps.

1)
~$ ls ~/Music > ~/computer-ls.txt

1a)
This is optional. Since I want to compare the contents of ~/Music to /media/Music and move only those files that are in ~/Music but not in /media/Music, do this step - use diff to compare the .txt files, grep > or <, cut off the > and < (to match folder names), and then send the output to a file:
~$ ls /media/Music > ~/media-ls.txt

~$ diff ~/computer-ls.txt ~/media.txt | grep "<" | cut -b3- > move.txt
~$ diff ~/computer-ls.txt ~/media.txt | grep "<" | cut -b3- > move2.txt

When using diff, the output is read such that which ever way the arrow is pointing, then that indicates that the string is in that .txt file but not in the other, i.e. using the code above, if I get output < Ramones, then I know that the Ramones folder is in ~/computer-ls.txt but not in media-ls.txt.

Two move.txt files need to be created because later, python cannot read from a file opened with the 'w' permission and vice versa.

If you wish, review the .txt files and the folders themselves to see if it is true about which folders are missing.

2) Skip this step - python not needed.
The python bit. Python should come installed on your Linux flavour, if not, apt-get install python :). Open a python cli, then run the following command using the .txt files we just created.
~$ python
>>> fread = open('~/move.txt', 'r')
>>> fwrite = open('~/move2.txt', 'w')
>>> for line in fread:
>>>     fwrite.writelines(str("\""+line[:-1]+"\"\n"))
>>> 
>>> fread.close()
>>> fwrite.close()
>>> quit()

The move2.txt file should now have the same folder names as move.txt, but will have "s at the start and end of ever line. "like this"

3) See update below.
Nawk bit. You should have done all this in the same directory, just don't forget to clean up :P. The last command uses nawk (a file scanner which can do a lot more!) to read the move2.txt file, and then run the mv command.

~$ nawk '{ system("mv -v " $0 " /media/Music/") }' ~/move2.txt

Make sure to give the correct file - the one that we changed.

Simple break-down (since I'm still an amateur) - if easier, maybe imagine nawk is like a 'for i in array/file/variable' command:
  • nawk > the nawk app
  • '{ command }' > everything inside the single quotes and curlies is what you want to do, spacing is critical here
  • system() > tells nawk to run it in termina
  • $0 > tells nawk to get the whole line. $1, $2, $3 etc. can be used to read only a single component of a line where the components may be separated by a space (grr). i.e. if the code above used $1 and a folder was called "Black Sabbath", then the output would be Black and we would fail to mv the folder.
Done! Since we used mv -verbose, we should be able to see the files being moved over.

Hope this helps! Till next time, Ciao!

Update:
Step 2) not needed. "s can be inserted in the nawk step as follows:
~$ nawk '{ system("mv -v \"" $0 "\" /media/Music/") }' ~/move.txt

Tuesday, December 6, 2011

Installing TweetDeck on Ubuntu Linux

This one is for all the Twitts out there looking to use a dedicated Twitter client for viewing their subs/lists/trends etc. While there are several clients available and native for Ubuntu (though I am yet to try them), TweetDeck gives a great interface with easy personalization. It also has an inbuilt URL shortener and update notification which can be set to show in the top-right corner...although this can be annoying if you follow a lot of Twit-a-holics (The type I like :D)!

This HowTo will show how to install TweetDeck and the AdobeAir package (which TweetDeck depends on) for Ubuntu. This install was done on kernel version 3.0.0-13.


1) Open up terminal, and direct to a folder where you want to work. I went to my ~/Downloads folder. Then, acquire the AdobeAIRInstaller with wget - it will download to the current directory that you are in. Use ls if you want to check that it is there. Change the permissions so that it can be executed. Execute it - you should get an Adobe window popup and ask you whether you want to install. Follow the options and after about 5 clicks it should be done. Remove the installation file (or keep it). Code is below:
$ wget http://airdownload.adobe.com/air/lin/download/latest/AdobeAIRInstaller.bin
$ chmod +x ./AdobeAIRInstaller.bin
$ sudo ./AdobeAIRInstaller.bin
$ sudo rm -rf AdobeAIRInstaller.bin

If you don't know, AdobeAIR is some sort of installer program. It is used when you want to install certain programs (that run Adobe I suspect...).

Navigate to the TweetDeck website and hit Download. The AdobeAIR window should popup. Follow the prompts and change the installation directory if so desired. Done!

Hope this helped. If AdobeAIR is not installed, then clicking on the TweetDeck Download button will not work, not matter how long you wait.

Happy Tweeting!