Archive

Archive for May, 2012

backbone.js learning note [3]

May 14, 2012 Leave a comment

[ update 5/14/2012 ] This single page app is now available at http://whatsmyspeed.appspot.com/. Decided to go (back) with google app engine instead of heroku due to (initial start) performance reason.

I am definitely addicted to backbone.js and I just threw some backbone into the running speed calculator I wrote some time ago (with node.js):

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>Speed Calculator</title>
	<style type="text/css">
		body { padding: 50px; font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; }
		a { color: #00B7FF; }
		label {width:100px;font-weight:bold;display:block;float:left;}
		input[type="text"] {width:120px;margin-right:5px;}
	</style>
</head>
<body>
	<div id="container">
	   <p> 
		  <label>Distance</label>
		  <input id="distance" type="text" placeholder="distance in miles">
		</p>
		<p>
		  <label>Time</label>
		  <input id="time" type="text" placeholder="ex: 24:25, 01:45:17">
		</p>
		<p>
		  <label>Speed</label>
		  <input id="speed" type="text">
		</p>
	</div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
    <script src="http://documentcloud.github.com/backbone/backbone-min.js"></script>
	<script>
		var Speed=Backbone.Model.extend({
			defaults: {
				distance:0,
				time:0
			}
		});
		var SpeedView=Backbone.View.extend({
			el:$('body'),
			events: {
				'blur input#time': 'update_model',
				'blur input#distance': 'update_model'
			},
			initialize: function() {
				_.bindAll(this, 'render');
				this.model.bind('change', this.render);
			},
			update_model: function() {
				this.model.set({
					time: $('#time').val()
					,distance: $('#distance').val()
				});	
			},
			render: function() {
				$('#speed').val('');
				var dist_str=this.model.get('distance')
					, time_str=this.model.get('time')
				if( dist_str!='' && time_str!='' && !isNaN(dist_str) ) {
					var speed=this._calc_speed(dist_str, time_str);
					if(speed!=null) {
						$('#speed').val(speed.toFixed(3));
					}
				}
				return false;
			},
			_calc_speed: function(dist_str, time_str) {
				var dist_reg=/^([0-9]+(?:\.[0-9]+)?)$/
					, dist_res=dist_reg.exec( dist_str )
					, time_reg=/^(?:(?:(2[0-3]|[0-1]?[0-9])[:])?([0-5]?[0-9])[:])?([0-5]?[0-9](?:\.[0-9]+)?)$/
					, time_res=time_reg.exec( time_str );
				if(dist_res && time_res) {
					var hours=(time_res[1]||0)*1
						, minutes=(time_res[2]||0)*1
						, seconds=(time_res[3]||0)*1
					total_seconds=hours*3600+minutes*60+seconds;
					if(total_seconds>0) {
						return 3600*dist_res[1]/total_seconds;
					} else {
						return null;
					}
				}
				return null;
			}
		});
		var speed=new Speed();
		var speedview=new SpeedView({model:speed});
	</script>
</body>
</html>
Categories: backbone.js, javascript

backbone.js study note [2]

May 13, 2012 Leave a comment

Here’s an improved and complete example to the first learning note on backbone.js

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>stock price simple demo</title>
</head>
<body>
    <div id="data"></div>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
    <script src="http://documentcloud.github.com/backbone/backbone-min.js"></script>

    <script>
        var Stock=Backbone.Model.extend({
            defaults: {
                price: 123
            }
        });

        var StockList=Backbone.Collection.extend({
            model: Stock
        });

        var ItemView=Backbone.View.extend({
            tagName: 'li',
            initialize: function() {
                _.bindAll(this, 'render');
                this.model.bind('change:price', this.render);
            },
            render: function() {
                $(this.el).html('<span>'+this.model.get('price')+'</span>');
                return this;
            }
        });

        var stock1=new Stock({price:333});
        var stock2=new Stock({price:555.667});

        var StockView=Backbone.View.extend({
            el: $('#data'),
            initialize: function() {
                _.bindAll(this, 'render');
                this.collection=new StockList();
                this.collection.add(stock1);
                this.collection.add(stock2);
                this.render();
            },
            render: function() {
                $(this.el).append('<ul></ul>');
                _(this.collection.models).each( function(item) {
                    var itemview=new ItemView({model:item});
                    $('ul', this.el).append(itemview.render().el);
                }, this);
            }
        });
        var stockview=new StockView();
    </script>
</body>
</html>

To test what it does (so far this is the most impressive feature of backbone, the rendering is actually linked directly to the change of model), open a Javascript console (in Chrome or with Firebug in Firefox), and type

stock1.set({ price: 10 })
stock2.set({ price: 999 })

, pay attention to the changes on the page.

References:
http://arturadib.com/hello-backbonejs/docs/5.html

Categories: backbone.js, javascript

How to make an Ajax form without capturing key press event on the input element

May 13, 2012 Leave a comment

OK this is a very common task: build a form, collect user input and send to server for processing (through Ajax therefore upon response the page should remain the same). One of the ways to accomplish this is to bind the ajax handling function to both the submit button (or an anchor link)’s click event and the input field’s key press event (only when Enter key is pressed):

<!DOCTYPE html> 
<html>
<head>                  
    <meta charset="utf-8">                                               
    <title>submit test using onclick and onkeydown event</title>
</head>             
<body>
    Name:   <input type="text" name="user_name" value="" id="user_name" onkeydown="kp_handler();">
    <p><input type="button" value="Continue &rarr;" onclick="handle_submit();"></p>
    <script type="text/javascript">
        function kp_handler(evt) {
                if(!evt && window.event) evt=window.event;
                if(evt.keyCode==13) {
                    handle_submit();
                }   
        }           
        function handle_submit() {                      
            // you might want to do ajax here to submit data to the server
            // as a demo I just print the data to the client's browser
            var msg='You have entered '+ document.getElementById('user_name').value;
            try {
                console.log(msg);
            } catch (e) {
                alert(msg);
            }
        }
    </script>
</body>
</html>

However, a better approach is to do it through a dummy form enclosing the text input and submit button. The benefit of of this is the Enter key event is automatically handled by form’s onsubmit attribute hence there’s no need to capture the onkeydown event on the text input element (figuring whether the Enter key is pressed is messy as you can see from the first approch):

<!DOCTYPE html> 
<html>
<head>                  
    <meta charset="utf-8">                                               
    <title>submit test using only onsubmit event</title>
</head>             
<body>
    <form id="some_form" onsubmit="javascript: handle_submit(); return false;">
        Name:   <input type="text" name="user_name" value="" id="user_name">
    <p><input type="submit" value="Continue &rarr;" ></p>
    </form>
    <script type="text/javascript">
        function handle_submit() {
            // you might want to do ajax here to submit data to the server
            // as a demo I just print the data to the client's browser
            var msg='You have entered '+ document.getElementById('user_name').value;
            try {
                console.log(msg);
            } catch (e) {
                alert(msg);
            }
        }
    </script>
</body>
</html>

It’s worth noting that the return false statement has to be put at the end of the onsubmit attribute (moving it into handle_submit will result in the form submitting to the page itself).
Comments and feedbacks are welcome.

Categories: javascript

A simple password generator written in node.js

Probably not a very advanced password generator but should be adequate for general purpose, see https://github.com/midnightcodr/gen_pass for details.

Simple html to text converter

May 3, 2012 2 comments

This is follow-up post on sending html email using swift mailer [ see previous post here ].

Since it’s never fun to have to write the same (or similar) stuff twice, the other morning I started to look for something than can do some basic html to text conversion, that is, turn br, p into newline, at the minimum. Through googling I discovered this handy php script to do the job. For example, html2text is able to convert the following html

    Dear Customer,
    <p>blah blah...</p>
    <p />
    Sincerely,<br />
    ABC Company Service Dept<br />
    <a href="http://example.com">A link</a>

into plain text

    Dear Customer,

    blah blah...


    Sincerely,
    ABC Company Service Dept
    [A link](http://example.com)

To use the code can’t be easier:

...
require_once 'path/to/html2text.php';
$html="<p>some html text here</p>";  // original html message
$plain=convert_html_to_text($html);   // converted plain text
...

Here’s a complete example on how to use it with swift mailer to send out html email (at a low SPAM score):

<?php
        require_once 'lib/swift_required.php'; // or absolute path if swift mailer library is not under current directory
        require_once 'path/to/html2text.php';
        define('mailhost', 'localhost'); // change if using external smtp server
        $to='some_recipient@email.address';
        $subject='HTML msg sending test';
        $body_html='<p>This is a <strong>test</strong>.</p>';
        $plain=convert_html_to_text($body_html); 
        $transport=Swift_SmtpTransport::newInstance(mailhost, 25);
        $mailer=Swift_Mailer::newInstance($transport);
        $message=Swift_Message::newInstance($subject)
            ->setFrom( array('noreply@yourcompany.com'=>'Your Company Name') )
            ->setTo( array($to) )
            ->setBody($plain)
            ->addPart($body_html, 'text/html');
        $result = $mailer->send($message);
Categories: html2text, php, swift_mailer