Author - Web Developer - Educator
Found 7 results for tag "tutorials"
RSS Feed

HTML API: Intro to Web Notifications API

After taking some time to get back into my craft, I realized that I had missed a lot of advancements in the HTML world, especially the evolution of the HTML API. Yes, there actually is an HTML API.

While researching some of the "new" API, I came across a bunch of articles by Aurelio De Rosa via SitePoint (a lot of good stuff there), and one of the items that caught my attention was the "Web Notifications API." Now, I will say that this stuff is still experimental (see the W3C's Working Draft for Notifications, so it's not widely supported and may even disappear. But for now, it's pretty awesome!)

Anyway, I'm sure you're not here to hear read about my day, so let's get to the point of the matter: HTML API - specifically, the Web Notifications API.

I know a lot of you just want to get to the demo and play with it, so here's a Working Demo (Chrome, Firefox, and Safari 7+ only)


What are "Web Notifications"?


If you use an email system like Gmail or Outlook, chances are you've already seen something like this:
Web Notification in the wild!

Well, those are technically desktop notifications and are usually controlled by software, not browsers. (Prior to HTML5, in order to get Desktop Notifications for Gmail, you had to download the "Gmail Notifier" application, and Outlook is already a software program to begin with).

The main difference is that these notifications (like the one above) are controlled by the browser - yes, the browser can control (certain) desktop notifications, and it's actually quite simple.

How to Use It


In an HTML file, add this bit of Javascript:
var notification = new Notification("New Email Received", { icon: "mail.png" })
That's pretty much it. No external libraries to load, no frameworks to bend around your whim - it's automatically built in to most modern browsers. Now, I know what you're asking: "What? That seems too simple! There has to be more." Don't worry, that was just the extremely core concept (provided by W3C). Technically, there is one more step to do: your application must first ask for permission before doing anything with the visitor's computer. (Yes, I know this seems a bit backwards, but for privacy, I can understand - especially with all of the ActiveX IE vaulnerabilities out there). This seems that the W3C wants to get rid of, but for now, it stays. (W3C says: Warning: In designing the platform notifications are the one instance thus far where asking the user upfront makes sense. Specifications for other APIs should not use this pattern and instead employ one of the many more suitable alternatives. [ref])
Notification.requestPermission(function(){
 
    //we're declaring a new object here
 
    var notification = new Notification(title, options);
 
});
There are 3 states to the "Permission" request: default (equivilant to "denied", because a choice has not been made yet), denied (the user denied the access, and therefore the request cannot proceed), or granted (the green light). This is similiar to when a browser (and/or application) asks to automatically use your physical location to determine items near you, like so:

Geolocation API in use

If you haven't already allowed a site to display desktop notifications (or allowed for geolocation, as the above image), then it will ask you for permission before proceeding:

Asking Permission

Overall, in accordance with "best practices", here's what I have learned/uncovered/researched:

First, you need to check to see if the API is supported. As this is still in the works, it isn't fully supported everywhere (for example, only Chrome, Firefox, and Safari 7+ support this - see http://caniuse.com/#feat=notifications for the full supported range).

In order to detect if the API is supported, add this bit of JS before you go calling Notifications.
//check to see if the API is supported
 
if (!('Notification' in window)){
 
    //API not supported. Show a message or something
 
    ....
 
} else {
 
    // API is supported. Do things
 
    ....
 
}
Therefore, if you have any buttons, links, or other items that make the notifications appear based on calling them, then you can disable them safely (or, if you are basing it off of automatic notifications, like emails, scores, or calendars, you can safety defer the notifications instead of having an error thrown).

Let's get fancy


The above sample is pretty much all you need to know for calling Notifications. If you want to get a little fancy with things, try this:
title = 'Email Received';
 
options = {
 
    body: 'You have a total of 3 unread emails',
 
    tag: 'preset', //The UID of the notification
 
    icon: 'https://mail.google.com/mail/u/0/images/favicon2.ico'
 
};
Before we go into detail about this, let's break it down:

  • title: This is the title of the Notification (duh)

  • options: This outlines a few of the Instance options available in the API
    (technically, everything is optional)

    • dir: This determines the text direction that the notification will be displayed (options are auto, ltr (left to right), or rtl (right to left) (default: auto)

    • lang: The language that the notification should be displayed in (example: 'en' for 'english') - (default: default language for computer)

    • body: The message that is displayed in the notification, like the body of a letter (default: blank)

    • tag: I like to think of this as the UID (Unique IDentifier) of the notification. Examples in the W3C Draft Documentation show usage of multiple instances of notification windows, so if you want one for your Email, Calendar, Reminders, etc, you can name each appropriately instead of just having to fall back on just 1. (default: blank)

    • icon: If you have a jpg, png, ico, or any other image file to show with the notification, you can list it here (I'd recommend the full absolute path of a web file instead of locally) (default: blank)

Those are all of the options available for the Notification API right now. Maybe more will come in the future - it just depends on what the official word is on the development.

FAQ


Can the notification automatically close after a few seconds?

I'd like to say 'yes', but the answer is unfortunately, no - at least, not completely.

I've tested my demo in Chrome and Firefox and had different results. I set up a setTimeout right after the notification is shown and tested it.
notification.onshow = function() { setTimeout(notification.close, 15000) }
However, Firefox displays the notification and automatically dismisses it after 5 seconds, regardless of the timeout, and Chrome will display the notification until you close it. Apparently, the problem is that the drafted Event Handlers don't register in the browsers, yet. I've tried to implement a calling feature of event.type == 'onshow', then call the setTimeout function, but to no avail. I've also tried to match up the event.type prior to the forEach function, but yet again, nothing.

Demo

In case you missed it above, here's the live demo again. It provides a call button that calls the notification on demand. I'm sure you can play around with it and figure out how it works.

References

Mozilla Dev Documentation: https://developer.mozilla.org/en-US/docs/Web/API/Notification W3C Draft: w3.org/TR/notifications/ Articles by Aurelio De Rosa: sitepoint.com/author/aderosa/ Aurelio's Notifications API Demo: http://aurelio.audero.it/demo/web-notifications-api-demo.html "Can I Use" browser feature comparison: http://caniuse.com/#feat=notifications


Tags:#html #api #javascript #w3c #mozilla #demos #tutorials

RSS Feed

Backups and Sync Success!

Backups are important

After many, many months (and many mistakes), we finally have our own backup server!

Let me explain: when we had our data hosted on 3rd party servers, backups were never considered because the services already provided backups (or, so we were told). We only had to use WebsiteSource's backup service once, and the other company said they were creating a backup service, but never put us on it.

When we moved our data to the primary local server back in September, my level of worrying gradually increased over time. We had all of our site data on 1 server - and if that server were (for some reason) to crap out, we'd be in a very large hole with no way out. 8 years of coding. 8 years of projects. 8 years of client work. 8 years of a full portfolio. 8 years of database records. All gone.

Luckily, that hasn't happened yet (and we hope it never will - oh, the horrors if it did). So, in order to fill in this gap, I finally got the courage to make a backup server! (finally, right?)

I was able to salvage a bunch of the spare parts that I had laying around. Some RAM, some hard drives, a few semi-barebones desktop frames, motherboards galore...and all of this stuff was just collecting dust in various areas.

I went through a bunch of combinations of RAM/Hard Drives/Motherboards/CD Drives before I found a combo that worked (a few of the frames that I had required SATA drives, and I only have ATA/IDE drives available).

I finally got some RAM that fit appropriately, a large enough hard drive to hold the information that I needed (not the same size as the main server drive, but big enough), and a CD drive that worked (I had to install the Server OS somehow, right?).

After spending all of today getting the latest Ubuntu Server ISO downloaded and burned, I popped in the CD, ran the install ISO, and had a dedicated backup server ready to go.

I then spent the latter part of the day setting up rsync, cron, and mysqldump to automate the creation and mirroring of backups.

MySQL Dump Script:
#!/bin/bash
 
BACKUP_DATE=$(date +'%F')
 
mysqldump -u [username] -p[password] --all-databases --events > \
 
   /var/www/vhosts/$BACKUP_DATE.sql
--events is here because it was returning an error saying "Skipping mysql.events table"

RSYNC Script:
#!/bin/bash
 
N=$(date +'%F %T')
 
LOG_FILE="$HOME/rsync.log"
 
echo "RSYNC Begin: $N" >> $LOG_FILE
 
rsync -r -a -v -e "ssh -l [username]" --delete \
 
   [source directory from root] [remote_server_ip]:[remote directory from root]  >> $LOG_FILE
 
echo "---------------------------------" >> $LOG_FILE
--delete is to delete any remote files that aren't on the source location. Also, if you want to only sync certain file types, add "--exclude='*' --include='*.[ext]'" after --delete (exclude everything except what is included), or you can just omit --delete altogether if you want. The rest of the script is just log information - completely optional, but makes the log easier to read

Update 2013-12-09: I've updated the script a bit to make it a little more universal after some things were called to my attention

The main part of that was spent trying to get the backup server (which I am calling "Fry" - I'm thinking of going Futurama for a server nomenclature) to automatically SSH into the main server without a password (aka: storing an SSH key). I had to learn a lot in order to do that, but I found out that the problem that eluded me for about 5 hours was that the main server's home directory had the wrong permission settings for the .ssh folder.

Next time the SSH keys aren't being stored right, run [sudo] tail -f /var/log/auth.log and see what the error is. Lesson learned.

So, the overall point of this story:
  • A dedicated backup server, Fry, has been salvaged, installed, and setup
  • There is an rsync script on Fry to automatically sync up the files from the main server (all 40GB+ worth)
  • The Main Server has an automatic cron script to run mysqldump to make a full backup of all of the MySQL database
  • Fry's rsync will keep the latest 6 (daily) copies of the MySQL Dump backups along with the main backup
  • Fry's rsync script creates a custom log to record the output


Now to install a Leela (why not Zoidberg?) server for load balancing (or a production server. I don't know - I've never had more than 1 server running locally at a time).....

....and just because this whole "end of the year" thing is so chaotic, here's a comic I liked which I hope to do (just to get it all over with):
BC


Good Night!


Tags:#bc #xkcd #backup #ubuntu #futurama #rsync #sudo #zoidberg #bash #tutorials

RSS Feed

HTML5 Canvas - Bouncing Ball Example

At this point, I'm trying to stay up with HTML5 programming, and I feel like I'm a little behind the times.

So, because I'm in a Python class (via Coursera by Rice University) learning about interactive programming (more specifically, "Pong" was this week's project) and seeing Google's anniversary edition of Breakout, I felt inspired to learn how innovative HTML5 could be, so I looked up some HTML5 references and thought I'd try my hand at it.

Well, I combined by Python experiences and some HTML5 canvas examples and created some ball-bouncing joy. Want a demo? Here's a demo!

Here's a screenshot of it:
Bouncing Ball
I've taken out the clear() function to show it in motion


Even though this is very simple (as compared to some more advanced HTML5 stuff), I thought I'd go ahead and put this here for others to view/use/learn from.

Here's the HTML:
 
<!DOCTYPE html>
 
<html>
 
	<head>
 
		<meta charset='utf-8'/>
 
		<title>Ball Canvas Test</title>
 
		<link href='main.css' rel='stylesheet'/>
 
		<!--[if lt IE 9]>
 
			<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
 
		<![endif]-->
 
		<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js'></script>
 
		<script src='main.js'></script>
 
	</head>
 

 
	<body>
 
		<div id='debug'></div>
 
		<div id='container'>
 
			<canvas id='scene'></canvas>
 
		</div>
 

 
		<footer>
 
			© 2013 - Kyle Perkins
 
		</footer>
 
	</body>
 
</html>
 


Here's the CSS: (this uses a standard Reset CSS, started by Eric Meyers)
 
@import url("//dev.shadowdev.com/reset.css");
 
html, body{
 
	display: block;
 
	text-align: center;
 
}
 
#debug{
 
	position: absolute;
 
	top: 50px;
 
	right: 50px;
 
}
 
canvas{
 
	margin: auto;
 
	display: block;
 
	border: 5px #000 solid;
 
	background-color: #efefef;
 
}
 


And here's the fancy-smancy Javascript:
var canvas, ctx;
 
var circles = [];
 
var circleCount = 4; 
 
var velocity_set = 2;
 

 
function oneorzero(num){
 
	// simple function to randomly get 0 or 1
 
	if (Math.round(Math.random())==1) num *= -1;
 
	return num;}
 

 
function Circle(x,y,radius, color){
 
	// get the information stored for eac ball
 
	this.x = x;
 
	this.y = y;
 
	this.radius = radius;
 
	this.color = color;
 
	var V1 = oneorzero(velocity_set);
 
	var V2 = oneorzero(velocity_set);
 
	// velocity is set as an array so we can have the [x,y] values
 
	// [5,5] means ^,>
 
	// [-5, -5] means V,<
 
	this.velocity = new Array(V1, V2);
 
}
 

 
function clear(){
 
	// clear the screen (prevent "dirty canvas")
 
	ctx.clearRect(0,0, ctx.canvas.width, ctx.canvas.height);
 
}
 

 
function getrand(){
 
	// function to randomly get a value between 0-255 (one value for R, G, and B each)
 
	return Math.floor((Math.random()*255)+1);
 
}
 

 
function drawCircle(ctx, x, y, radius, color) { // draw circle function
 
//	$('#debug').html("X:"+x+" Y:"+y);
 
//    ctx.fillStyle = 'rgba('+r+', '+g+', '+b+', 1.0)';
 
	ctx.beginPath();
 
	ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
 
	ctx.fillStyle = "rgb("+color+")";
 
	ctx.fill();
 
	ctx.stroke();
 
//    ctx.closePath();
 
}
 

 
function drawScene(){ //main draw function
 
	clear(); //clear the canvas
 
	// this is only for additional draw functionality (testing only)
 
/*	ctx.beginPath();
 
      ctx.arc(canvas.width/2, canvas.height/2, 70, 0, 2 * Math.PI, false);
 
      ctx.fillStyle = 'blue';
 
      ctx.fill();
 
      ctx.lineWidth = 5;
 
      ctx.strokeStyle = '#fc0';
 
      ctx.stroke();
 
*/
 
	
 
	var ball_info ="";
 
	for (var i=0; i 0)
 
		$('#debug').html(ball_info);
 
}
 

 
////////////////////////////////////////
 

 
$(function(){
 
	// call these setup properties upon load
 
	canvas = document.getElementById("scene");
 
	ctx = canvas.getContext('2d');
 

 
	// this is to make sure the canvas spreads across the screen
 
	ctx.canvas.width = window.innerWidth-10; // the canvas has a 5px border
 
	ctx.canvas.height = window.innerHeight-50; // 50 is only for the footer info
 

 
	var circleRadius = 25;
 
	var width = canvas.width;
 
	var height = canvas.height;
 

 
	for (var i = 0; i < circleCount; i++){
 
		// start at random position
 
		var x = Math.random()*(width*.9);
 
		var y = Math.random()*(height*.9);
 
		var r = getrand();
 
		var g = getrand();
 
		var b = getrand();
 
		ballColor = r+","+g+","+b;
 
		// add circle to array
 
		circles.push(new Circle(x,y,circleRadius, ballColor));
 
	}
 
	setInterval(drawScene, 1); // loop drawScene - aka: "draw handler"
 
});
 

 
function animate(ball, canvas, context) {
 
	// this is for adding (aka: "move") the ball based on the velocity increase/decrease
 
	// velocity is an array
 
        ball.x += ball.velocity[0];
 
	ball.y += ball.velocity[1];
 
	
 
        if( (ball.x > (canvas.width - ball.radius)) || (ball.x < (0 + ball.radius))) {
 
		// bounce off left or right wall
 
		ball.velocity[0] *= -1;
 
        }
 
	if ( (ball.y > (canvas.height - ball.radius)) || (ball.y < (0 + ball.radius))){
 
		// bounce off top or bottom wall
 
		ball.velocity[1] *= -1;
 
	}
 

 
	// draw the circles with on the (canvas, x position, y position, radius, color)
 
        drawCircle(ctx, ball.x, ball.y, ball.radius, ball.color);
 
      }


I hope this works for some people learning how to use HTML5 and the "velocity effect"


Tags:#html5 #css #javascript #python #tutorials

RSS Feed

Python Progress: Coin Flip

Based on a conversation I had earlier today with Keat's brother, I took another whack at Python. I've been working on learning Python for a while, but never really got the hang of it since I'm mainly a PHP guy.

Anyway, based on some tutorials I learned today, I wrote a pretty nice Python script for calculating coin flips and reporting the outcome. Some of my Python-skilled friends may laugh, but I enjoyed writing this and testing my (limited) skills.

 
#!/usr/bin/python
 
import time, random, os
 

 
#clear the screen
 
os.system('clear')
 

 
#define H and T, making them floats
 
H=T=0.0
 

 
#begin input
 

 
max_num = raw_input("How many times do you want to flip a coin? ")
 

 
if len(max_num)==0:
 
	#if no input, make 10 the default
 
	max_num = 10 
 
	print "No number specificed. Defalting to 10"
 

 
max_num = int(max_num) #convert to integer to make the calcualtions work 
 

 
#little helpful tip
 
if max_num >= 300:
 
	unit = str(round((max_num*.2)/60,2))+" minutes"
 
else:
 
	unit = str(round(max_num*.2,2))+" seconds"
 

 
print "It will take "+unit+" to complete"
 

 
#flip the "coin" max_num times
 
for x in range(0,max_num):
 
	coin = random.randrange(2)
 
	if coin == 0:
 
		print "Heads" #report
 
		H+=1 #record
 
	else:
 
		print "Tails" #report
 
		T+=1 #record
 
	time.sleep(.15) #take a small break
 

 
#simple function to calcualte the percentage and report it, 
 
# instead of having to write this out more than once
 
def report(text,side):
 
	perc = round((side/max_num)*100, 2)
 
	print text+": "+str(perc)+"%"
 

 
#debugging
 
#print "Heads: "+str(H)+" | Tails: "+str(T)
 

 
#finalize the reports
 
report("Heads", H)
 
report("Tails", T)
 

 

 
#Print the winning side
 
#print "\n"
 
if H>T:
 
	print '\033[1m'+"Heads Win!"+'\033[0m'
 
elif T>H:
 
	print '\033[1m'+"Tails Win!"+'\033[0m'
 
elif T==H:
 
	print "It's a tie!"
 


I've been trying to work on getting Python to work on the web, but my server doesn't really like WSGI or mod_python. I also tried TurboGears, but that didn't quite work as expected. I may be able to work on that better and get it incoroprated to to some Dynamic programming and offer that to clients.

Also, things may be changing at Shadow Development - could be for the worse or better. Personally, I think it will be for the better because I really enjoyed pushing my skillset and coding practices, so we'll see where it goes.


Tags:#python #php #coins #heads #tails #percent #tutorials

RSS Feed

Simple but effective: <label for=''>

It's amazing how something so simple can go a long ways, especially when most people don't know about it.

I'm talking about labels. Specifically, the <label for=''> attribute.

Common sense says "If you have a radio button or a checkbox on an HTML form, give it a label so people know what it is for."

Experience says "Make sure that each item has an id and name so it's universally accepted."

Better experience says "Add the for attribute to the label so your visitors don't require a microscope to click in the teeny-tiny little circle/box."

I will admit that Matt Inman (The Oatmeal) said it best:
The Oatmeal describes what [for] is for


If you don't code, here's what it looks like (click the label - doesn't do anything):

<label>Check Me</label> 
 
<input type='checkbox' name='ckbx'/>


Here's what the difference is (click the label, see the difference?):

<label for='ck_box'>Check Me</label> 
 
<input type='checkbox' name='ckbx' id='ck_box'/>


I just wanted to get that out in the open.

In summary, if you hand-code forms (like me), use the for attribute in your labels. It makes everybody's lives easier.


Tags:#label #for #labelfor #html #oatmeal #rant #tutorials

RSS Feed

Find text in files with GREP

I needed to reference this quite frequently, so I thought I'd post it here.

Ever had the frustration of needing to find a certain string inside files on a Linux OS via a terminal/command line? It'd be nice to have something like the Windows File Finder (when it works) to search for text inside of a file and report the file back.

You could cat each file and use grep [string] to spit back each line, then write down the filename. But there is an easier way.

Use grep first instead of piping it!

All you need to do is type in

grep -lir "[phrase]" [directory]
and that's all there is to it (the quotations are optional). By using the command grep instead of using it after a pipe "|", this can search through files in an instant instead of having to manually search through each file. The -l (that's a lowercase "L") puts out files that match (as opposed to -v which shows all files that don't match). The i makes the search query case insensitive. Lastly, the r makes grep recursive in folders. Simple as that. Of course, you can have the results spit back to you if you just press Enter, or you can output it to a file by using the > operator, like so:
grep -lir "cout" . > output.txt
(my VB and C++ friends should like this)


Tags:#linux #commandline #terminal #grep #search #tutorials

RSS Feed

Milestone 3: Complete!

YAY! I've successfully completed Milestone 3 of the Accelerator. It was a bit of a challenge, since I'm still learning jQuery, but I accept challenges for coding - especially when using a language that I barely know anything about and am willing to learn. Just to recap: M3 was to successfully remove a dynamically inserted row. Using a combination of .empty() .remove(), .parent(), and .live(), I was able to successfully remove dyanmicaly inserted rows using the .append() function and the tableDnD library.
$('.remove_box').live('click', function() { 
    /* get parent (td), then parent again (tr), and empty the tr */ 
    $(this).parent().parent().remove();  
});
Edit: 2010-11-14 20:12:35 .empty() was replaced by .remove() since the latter keeps the tableDnD library in place and requires the DOM features to be kept for the move features Now on to Milestone 4: field submission with database structure building rules - let's see how that goes....
Business Accelerator Progress - Form Builder: 60%


Tags:#milestone #accelerator #jquery #tracker #tutorials