Tag Archives: jQuery

Award Firework Alternative with jquery.imgExplosion

Don’t ask me why, but I needed a way to explode some stars in a fancy animation on a page. At first I found Fireworks.js, which was kinda cool at first–but I quickly realized a few things:

1. It’s using raw javascript, which is a pity if you are already loading the power of jquery and jquery.ui
2. It wasn’t what I really wanted. I wanted STARS!

So, I bring you, jquery.imgExplosion:

Although, the default implementation uses a star graphic I whipped up in Illustrator:

You can still attach the plugin to any image–either on the page or not. Soccer balls? Severed heads? I don’t care what you do with it but FORK the code if you’ve got improvement ideas.
Check out the Demos Page for examples.

Download/Fork on Github

https://github.com/atomantic/jquery.imgExplosion

Demos

http://atomantic.github.com/jquery.imgExplosion/

follow on Twitter

Inline Code Assistance for Form Fields with jquery.codeassist

I’m working on a project that required some apparently previously unexpected UI controls. One of them, I decided should be made into a jQuery plugin and get some feedback from the community. I call it jquery.codeassist.

OK… so what the hell does it do?

The plugin creates a code assist menu within textarea and input fields, which allows users to select from a list of suggested values. This effect is triggered by the entry of a key character such as %, $ or [

So far, only %, $ and [ (with an optional closing key of ]) are supported–though, with some tweaks, I know I can get it to accept any input.

OK… but really, what the hell does it do?

It was built for the purpose of allowing users to enter dynamically replaceable code bits into textareas and input fields. A use case example would be if you are allowing users to create a page template or message template that will need to be filtered for the audience or some other situation involving different values for different pieces of data at a time. A user can enter in the code bits, which you can replace behind the scenes in the template.

OK… so is there a real world example?

Since the impetus for this plugin comes from a proprietary and as of yet unseen stealthy startup, I’m not at liberty to show the awesome reason why I found it necessary to create this plugin. But here’s a totally crappy and simple demo so you can see what the hell I’m actually talking about:
Crappy, Simple Demo

And you can download, fork and whatnot on github:
Source on GitHub

Issues I had with the implementation

Mouse position

The thing that is bugging me most at the moment is that I wanted the menu to appear where the mouse is. Simple enough, right? Just take a look at the triggered event pageX and pageY, right? Well, that would work if I was attaching to a mouse event–but the trigger for the menu is a key event, which doesn’t care about the position of the mouse. So to get around this, I’ve got a listener that’s caching the mouse coordinates so we can look at it when we need to:

// this is stupid but I can't find a better way to get the current mouse position
// since the key events don't contain the pageX and pageY 
// so following it around and caching the position :(
$(document).mousemove(function(e){
	codeassist.pageX = e.pageX;
	codeassist.pageY = e.pageY;
});

I am genuinely annoyed about this.

Cursor position

For sane browsers, you can simply access element.selectionStart to get the index that the cursor is positioned within the text. However, for IE, you have to hack up a nasty solution:

... // up here, we've defined el as the input, v as the current value of the input, and t = $(this), etc..
var before = ''; // text before cursor
if (el.selectionStart!==undefined){ // sane browser
	before = v.substring(0,el.selectionStart);
}else{ // IE
	t.focus();
	var range = document.selection.createRange();
	range.moveStart ('character', -v.length);
	before = v.substring(0,range.text.length);
}

follow on Twitter

Dynamic Filterable Life Plan / Timeline (PHP, jQuery, CSS)

I just created my life plan (or the start of one anyway–I’ll be editing this thing for a while) and I figured I’d share with you the code used to make it.
My live updated version is on my Portfolio: The Future as I See It.

Demo


$maxYear){
$diffYears = $year – $maxYear;
$year = $maxYear; // this is what we will use in mktime() then we can add seconds to that output
$addtime = $diffYears * 31536000; // years of seconds
}

// count leap years
$numYears = $year – date(‘Y’);
$leaps = floor($numYears/4);
$addtime -= $leaps * 86400; // subtract these excess days (to get accurate year count)

$date = mktime(0,0,0,$month,$day,$year) + $addtime;
$now = time();
$days = ceil(($date – $now)/86400);
if($days < 365){ return 'in '.$days .' day'.($days==1?'':'s'); }else{ $years = floor($days/365); $days = $days%365; return 'in '.$years.' year'.($years==1?'':'s').', '.$days.' day'.($days==1?'':'s'); } } $events = array( array( 'yyyy'=>‘2010’,’mm’=>’01’,’dd’=>’20’,
‘name’=>’Move to Magdeburg, Deutschland’,
‘info’=>’My family will be moving to Magdeburg to experience living in Germany and to strenghten our deutsche Sprachfähigkeiten.’,
‘type’=>’travel’
),
array(
‘yyyy’=>’2010′,’mm’=>’06’,’dd’=>’15’,
‘name’=>’Produce an iPhone App’,
‘info’=>’This might get done before I move to Magdeburg but this is my personal deadline for a v1.0 release.’,
‘type’=>’work’
),
array(
‘yyyy’=>’2011′,’mm’=>’01’,’dd’=>’20’,
‘name’=>’Move Back to Seattle, WA USA’,
‘info’=>’Unless we decide to stay in Germany or move elsewhere’,
‘type’=>’travel’
),
array(
‘yyyy’=>’2013′,’mm’=>’07’,’dd’=>’15’,
‘name’=>’Accomplish a Free-Standing Backflip’,
‘info’=>’I\’ve done it on a trampoline and with spotters but never alone without aid. This is a life-long goal.’,
‘type’=>’fitness’
),
array(
‘yyyy’=>’2017′,’mm’=>’09’,’dd’=>’01’,
‘name’=>’Publish First Novel’,
‘info’=>’Contact me if you want to be one of my pre-publication reviewers’,
‘type’=>’creative’
),
array(
‘yyyy’=>’2021′,’mm’=>’07’,’dd’=>’22’,
‘name’=>’Give First TED Talk’,
‘info’=>’On what topic? Web, security, social media, nano-technology, engineering, the future, productivity in an age of overabundance? I\’m not sure yet–but it will be awesome.’,
‘url’=>’http://ted.com’,
‘type’=>’social’
),
array(
‘yyyy’=>’2026′,’mm’=>’07’,’dd’=>’22’,
‘name’=>’Engineering Degree from MIT’,
‘info’=>’Oh, yes, I will be going back to school. Probably many times in my life.’,
‘type’=>’education’
),
array(
‘yyyy’=>’2044′,’mm’=>’11’,’dd’=>’17’,
‘name’=>’Undergo First Major Rejuvination Treatments’,
‘info’=>’Certainly there will be many improvements to personal health management before this date, but this is the anticipated date of my first major operation (or likely, full system nanobot integration)’,
‘type’=>’fitness’
),
array(
‘yyyy’=>’2079′,’mm’=>’11’,’dd’=>’05’,
‘name’=>’Engage Dyson Sphere’,
‘url’=>’http://en.wikipedia.org/wiki/Dyson_sphere’,
‘info’=>’If not on the team that deploys it, I will at least be celebrating the event :)’,
‘type’=>’social’
)
);

$types = array();
foreach($events as $event){
if(empty($types[$event[‘type’]])) $types[$event[‘type’]] = 1;
else $types[$event[‘type’]]++;
}
ksort($types);
$typeLinks = ”;
foreach($types as $key=>$val){
$typeLinks .= ‘‘.$key.’ (‘.$val.’)‘;
}
?>

The PHP/HTML

Of course, you will need to make sure you include jQuery. I recommend using the Google Hosted Ajax Library rather than hosting it yourself. There are many good reasons to do this (blog post soon to come).
Just place this either in your HTML head or just before your closing body tag:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>

I’ve used PHPDoc blocks to supply inline documentation throughout the code. Post a comment with any questions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<?php 
$pageName = 'plan';
$pageTitle = 'The Future as I See It';
include('header.php'); 
 
/**
 * get the years and days until a date
 * this function is a bit of a hack until my server supports PHP 5.3.0
 * which has date_diff, alias of DateTime::diff (http://www.php.net/manual/en/datetime.diff.php)
 */
function getUntil($year,$month,$day){
	$year = intval($year);
	$maxYear = 2035;
	$addtime = 0;
	if($year > $maxYear){
		$diffYears = $year - $maxYear;
		$year = $maxYear;
		$addtime = $diffYears * 31536000; // years of seconds
	}
 
	// count leap years
	$numYears = $year - date('Y');
	$leaps = floor($numYears/4);
	$addtime -= $leaps * 86400; // subtract these excess days (to get accurate year count)
 
	$date = mktime(0,0,0,$month,$day,$year) + $addtime;
	$now = time();
	$days = ceil(($date - $now)/86400);
	if($days < 365){
		return 'in '.$days .' day'.($days==1?'':'s');
	}else{
		$years = floor($days/365);
		$days = $days%365;
		return 'in '.$years.' year'.($years==1?'':'s').', '.$days.' day'.($days==1?'':'s');
	}
}
$events = array(
	array(
		'yyyy'=>'2010','mm'=>'01','dd'=>'20',
		'name'=>'Move to Magdeburg, Deutschland',
		'info'=>'My family will be moving to Magdeburg to experience living in Germany and to strenghten our deutsche Sprachfähigkeiten.',
		'type'=>'travel'
	),
	array(
		'yyyy'=>'2010','mm'=>'06','dd'=>'15',
		'name'=>'Produce an iPhone App',
		'info'=>'This might get done before I move to Magdeburg but this is my personal deadline for a v1.0 release.',
		'type'=>'work'
	),
	array(
		'yyyy'=>'2013','mm'=>'07','dd'=>'15',
		'name'=>'Accomplish a Free-Standing Backflip',
		'info'=>'I\'ve done it on a trampoline and with spotters but never alone without aid. This is a life-long goal.',
		'type'=>'fitness'
	),
	array(
		'yyyy'=>'2017','mm'=>'09','dd'=>'01',
		'name'=>'Publish First Novel',
		'info'=>'Contact me if you want to be one of my pre-publication reviewers',
		'type'=>'creative'
	),
	array(
		'yyyy'=>'2021','mm'=>'07','dd'=>'22',
		'name'=>'Give First TED Talk',
		'info'=>'On what topic? Web, security, social media, nano-technology, engineering, the future, productivity in an age of overabundance? I\'m not sure yet--but it will be awesome.',
		'url'=>'http://ted.com',
		'type'=>'social'
	),
	array(
		'yyyy'=>'2026','mm'=>'07','dd'=>'22',
		'name'=>'Engineering Degree from MIT',
		'info'=>'Oh, yes, I will be going back to school. Probably many times in my life.',
		'type'=>'education'
	),
	array(
		'yyyy'=>'2044','mm'=>'11','dd'=>'17',
		'name'=>'Undergo First Major Rejuvination Treatments',
		'info'=>'Certainly there will be many improvements to personal health management before this date, but this is the anticipated date of my first major operation (or likely, full system nanobot integration)',
		'type'=>'fitness'
	),
	array(
		'yyyy'=>'2079','mm'=>'11','dd'=>'05',
		'name'=>'Engage Dyson Sphere',
		'url'=>'http://en.wikipedia.org/wiki/Dyson_sphere',
		'info'=>'If not on the team that deploys it, I will at least be celebrating the event :)',
		'type'=>'social'
	)
);
?>
 
<h1><?=$pageTitle?></h1>
<div id="pageFilter">
<a href="javascript:pageFilter('all')" class="active all" title="Show All">show all</a><?php
$types = array();
foreach($events as $event){
	if(empty($types[$event['type']])) $types[$event['type']] = 1;
	else	$types[$event['type']]++;
}
ksort($types);
 
foreach($types as $key=>$val){
	echo '<a href="javascript:pageFilter(\''.$key.'\')" class="'.$key.'" title="Show '.ucfirst($key).'">'.$key.' ('.$val.')</a>';
}
?>
</div>
<ul class="timeline">
<?php
foreach($events as $event){
	?>
    <li class="<?=$event['type']?>">
    	<div class="head">
            <span class="date"><?=$event['yyyy'].'.'.$event['mm'].'.'.$event['dd']?></span>
            <span class="name"><?=$event['name']?></span>
			<?
            if(!empty($event['url'])) echo '[<span class="url"><a href="'.$event['url'].'">more info</a></span>]';
            ?>
            <span class="until"><?=getUntil($event['yyyy'],$event['mm'],$event['dd'])?></span>
        </div>
        <div class="body">
            <div class="info"><?=$event['info']?></div>
            <div class="type"><?=$event['type']?></div>
        </div>
    </li>
    <?
}
?>
</ul>
 
<script type="text/javascript">
function pageFilter(type){
	$('#pageFilter a').removeClass('active');
	$('#pageFilter .'+type).addClass('active');
	if(type=='all'){
		$('.timeline li').slideDown();
	}else{
		$('.timeline li').slideUp();
		$('li.'+type).slideDown();
	}
}
$('.type').bind('click',function(){
	pageFilter($(this).html());					 
});
</script>
 
<?php include('footer.php'); ?>

The CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#pageFilter {
	font-size:.8em;
	text-align:right;
	margin-top:10px;
}
#pageFilter a{
	border:1px solid #dde;
	padding:3px 5px;
	margin-left:5px;
}
.timeline {
	list-style:none;
	font-size:.8em;
}
.timeline li{
	margin-top:10px;
	border:1px solid #9cf;
}
.timeline .head {
	background-color:#def;
	padding:3px 5px;
}
.timeline .body {
	padding:10px;
	position:relative;
}
.timeline .date{
	color:#036;
	font-weight:bold;
	margin-right:10px;
}
.timeline .name{
	color:#666;
}
.timeline .until{
	float:right;
}
.timeline .info{
	padding-bottom:15px;
}
.timeline .type{
	position:absolute;
	bottom:0;
	right:0;
	border:1px solid #dde;
	background-color:#ffe;
	padding:3px 3px 3px 5px;
	cursor:pointer;
}
a.all, .timeline .all .type{
	background-color:#FFFFFF;
}
a.creative, .timeline .creative .type{
	background-color:#F0FFFD;
}
a.education, .timeline .education .type{
	background-color:#EEF4FF;
}
a.fitness, .timeline .fitness .type{
	background-color:#F2EEFE;
}
a.social, .timeline .social .type{
	background-color:#FDF5F5;
}
a.travel, .timeline .travel .type{
	background-color:#FFFDED;
}
a.work, .timeline .work .type{
	background-color:#F3FFEB;
}

follow on Twitter