|
Jun, 10
2010
|
Download My Attempt at a Bokeh Wallpaper [PSD] |
Read |
|
Jun, 10
2010
|
Download My Attempt at a Bokeh Wallpaper [PSD] |
Read |
I was messing around with Photoshop tutorials and came across the very famous abduzeedo.com. I wanted to create a bokeh style wallpaper and he has a fantastic tutorial on how to do it. Linky
I ran with it and came up with what you see below. I’m including the PSD in case you want to change the colors. All you have to do is change the gradient layer style and you’re set.
I’m including a 1920×1200 wallpaper png, an iPhone wallpaper png, and the original PSD in this post.
Let me know what you think and enjoy!
Here’s an example of what you can do in 2 seconds with the PSD. HDR effects and all…
|
Jun, 2
2010
|
Quick Fix: xFBML not rendering in IE [RESOLVED]! |
Read |
I was having a problem where using xFBML and the facebook javascript API would not render elements in IE (but they worked in all other browsers).
This was resolved by fixing the DOCTYPE in the header.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:fb="http://www.facebook.com/2008/fbml">
Now everything renders fine within the site AND it also renders in an iFrame Facebook App!
|
Apr, 29
2010
|
Show Popular Stories Using Google Analytics and ASP.net C# and Sort the Results [How To] |
Read |
Recently, I needed to be able to get a list of popular pages for a site that I manage and display that information. I figured, rather than building a database and code hit tracking and page views from scratch, I would just tap into my Google Analytics data.
Requirements:
All of the articles have the path format “/articles/[ category ]/[ article-title ]/” and all articles have unique titles. First stop, create the article class:
class ArticleInfo
{
public string title { get; set; }
public string path { get; set; }
public string hits { get; set; }
}
This is what I will use to sort by title after sorting by hits. Granted, this could probably be optimized a bit more but I’m really tired…
Basically, this creates a class of titles, paths, and hits which I will be pulling from later to create the HTML.
Here is the rest of the code-behind for the user control which will display the data. I will go through this piece by piece
protected void Page_Load(object sender, EventArgs e)
{
try
{
clsDBGet db = new clsDBGet();
DataTable dt = db.GetDTfromProc("[STORED PROCEDURE - GET]", null);//Stored procedure to pull from the DB
if (dt.Rows.Count > 0)
ga.Text = dt.Rows[0]["DATA"].ToString();
else
{
try
{
ReportRequestor rr = new ReportRequestor("[gmail account email]", "[password]");
AnalyticsAccountInfo ainfo = new AnalyticsAccountInfo();
IEnumerable(AnalyticsAccountInfo) accounts = rr.GetAccounts();
string analyticsTitle = "V2 Live";//Title of Profile where I want to grab the data
AnalyticsAccountInfo account = accounts.First(a => a.Title == analyticsTitle);
DateTime from = DateTime.Now.AddDays(-2);//last 24 hours (data is always a day behind)
DateTime to = DateTime.Now;
IEnumerable(GenericEntry) report = rr.RequestReport(account, new Dimension[] { Dimension.pagePath, Dimension.pageTitle }, new Metric[] { Metric.pageviews }, from, to, 1000);
string myString = string.Empty;
int x = 0;
string[] articleTitles = new string[22]; //To only grab unique titles
ArticleInfo[] articleData = new ArticleInfo[22];
bool unique = true;
report = report.OrderByDescending(myReport => Convert.ToInt32(myReport.Metrics.First().Value));
foreach (GenericEntry myReport in report)
{
Regex isArticle = new Regex("/articles/.+/.+/");
string path = myReport.Dimensions.First().Value;
string title = myReport.Dimensions.Last().Value;
string hits = myReport.Metrics.First().Value;
if (x < 22 && isArticle.IsMatch(path))
{
if (!path.Contains("/page_") && !path.Contains("/search/") && title.Trim() != "(not set)")
{
//Add to array of article titles then check to see if it exists in the array
for (int y = 0; y < articleTitles.Length; y++)
{
if (articleTitles[y] != null && title.Trim().ToLower() == articleTitles[y].ToLower())
{
unique = false;
break;
}
else
unique = true;
}
if (unique)
{
articleData[x] = new ArticleInfo { path = Server.UrlDecode(path).Trim(), title = title.Trim(), hits = hits };
x++;
}
}
}
}
IEnumerable(ArticleInfo) articles = articleData.OrderBy(article => article.title);
foreach (ArticleInfo article in articles)
{
myString += "<li><a class=\"gaHits\" href=\"" + article.path + "\" title=\"" + article.title + "\" data=\"" + article.hits + "\"></a ></li>";
}
if (x < 10)
{
panelGA.Visible = false;
}
else
{
clsDBPost dbp = new clsDBPost();
string proc = "[STORED PROCEDURE - INSERT]";
Hashtable ht = new Hashtable();
ht.Add("data", myString);
bool inserted = dbp.ExecuteProcedure(proc, ht);
}
ga.Text = myString;
}
catch (Exception EX)
{
//Response.Write(EX.ToString());
panelGA.Visible = false;
}
}
}
catch (Exception ex2)
{
//Response.Write(ex2.ToString());
panelGA.Visible = false;
}
}
Let's break this up into parts.
The first thing I want to do is query my database to see if I already have the latest Google Analytics data for today. If it's there, render the data outright. This allows me to only query Google Analytics once per day, instead of on every page load. This is important because Google limits the amount of requests you can make per day and because we are requesting data for the previous day, there's no need to pull up to the minute results.
clsDBGet db = new clsDBGet();
DataTable dt = db.GetDTfromProc("[STORED PROCEDURE - GET]", null);
if (dt.Rows.Count > 0)
ga.Text = dt.Rows[0]["DATA"].ToString();
This sis where we tap into Reimer's reader. Further explanation can be found in the link at the top of this article but for now let's focus on some key points. I'm pulling data from Google from 2 days ago, through today. I'm also pulling the pagePath, pageTitle and using the metric pageViews. This will translate into the URL of the post, the title of the post and the hits. The last thing to note is that I'm pulling the top 1000 results because not every page on the site is an article and I want to make sure I get at least 10 articles in the data I'm pulling back. This number is arbitrary but I think it defaults at 1000 anyway.
ReportRequestor rr = new ReportRequestor("[gmail account email]", "[password]");
AnalyticsAccountInfo ainfo = new AnalyticsAccountInfo();
IEnumerable(AnalyticsAccountInfo) accounts = rr.GetAccounts();
string analyticsTitle = "V2 Live";//Title of Profile where I want to grab the data
AnalyticsAccountInfo account = accounts.First(a => a.Title == analyticsTitle);
DateTime from = DateTime.Now.AddDays(-2);//last 24 hours (data is always a day behind)
DateTime to = DateTime.Now;
IEnumerable(GenericEntry) report = rr.RequestReport(account, new Dimension[] { Dimension.pagePath, Dimension.pageTitle }, new Metric[] { Metric.pageviews }, from, to, 1000);
In this next part I'm setting my variables that I will be using later in the loops to filter the rows.
string myString = string.Empty; int x = 0; string[] articleTitles = new string[22]; //To only grab unique titles ArticleInfo[] articleData = new ArticleInfo[22]; bool unique = true; report = report.OrderByDescending(myReport => Convert.ToInt32(myReport.Metrics.First().Value));
I'm also creating an array of ArticleInfo's called articleData which will hold 22 elements as I only want to display the top 22 articles. Lastly, I'm ordering the report data by hits (pageViews) because the report data comes from Google sorted by URL path. This is bad because I want to get the top articles, not a list ordered alphabetically by URL. Without this sort, I would be getting articles in a certain category only (because the URL lists the category before the title) and it would not be a true representation of site activity.
Here come the loops:
foreach (GenericEntry myReport in report)
{
Regex isArticle = new Regex("/articles/.+/.+/");
string path = myReport.Dimensions.First().Value;
string title = myReport.Dimensions.Last().Value;
string hits = myReport.Metrics.First().Value;
if (x < 22 && isArticle.IsMatch(path))
{
if (!path.Contains("/page_") && !path.Contains("/search/") && title.Trim() != "(not set)")
{
//Add to array of article titles then check to see if it exists in the array
for (int y = 0; y < articleTitles.Length; y++)
{
if (articleTitles[y] != null && title.Trim().ToLower() == articleTitles[y].ToLower())
{
unique = false;
break;
}
else
unique = true;
}
if (unique)
{
articleTitles[x] = title.Trim();
articleData[x] = new ArticleInfo { path = Server.UrlDecode(path).Trim(), title = title.Trim(), hits = hits };
x++;
}
}
}
}
Lots of stuff is going on here. The first thing I'm doing is creating a filter to filter through the results and only pull back pages that are articles by doing "isArticle.IsMatch(path)". I also don't want to do this loop more than I need to, hence the "x < 22" part. The next "IF" statement is arbitrary and required for the site.
The next FOR LOOP is to make sure I'm only grabbing unique articles. This is important because sometimes users include capital letters in the URL and this will make Google Analytics display multiple rows for the same page and split up the numbers. There's a way to counter this in GA but for today's purposes, I'm assuming that your results might have the same page split across different URLS. I take the title of the article and check to see if it's in the articleTitles array. If it isn't already in there, I add it to the array and set the "unique" flag to true and move on. If it is, I skip that row altogether by setting the "unique" flag to false. (This method will probably produce some skewed results if you are splitting page views across URLs).
In this last part, I'm creating another enumerable list of articleInfo's and sorting it by title. This way the bar graph that I display won't just look like a linearly decreasing graph. I also create the HTML list item and append it to the full list of items in myString. This is what will be rendered out on the page and also what will be placed in the database using the stored procedure, "V2_INSERT_GOOGLE_DATA".
If there are less than 10 results, or if for some reason I cannot communicate with either Google or the database, I hide the panel altogether.
IEnumerable(ArticleInfo) articles = articleData.OrderBy(article => article.title);
foreach (ArticleInfo article in articles)
{
myString += "<li><a class=\"gaHits\" href=\"" + article.path + "\" title=\"" + article.title + "\" data=\"" + article.hits + "\"></a ></li>";
}
if (x < 10)
{
panelGA.Visible = false;
}
else
{
clsDBPost dbp = new clsDBPost();
string proc = "[STORED PROCEDURE - INSERT]";
Hashtable ht = new Hashtable();
ht.Add("data", myString);
bool inserted = dbp.ExecuteProcedure(proc, ht);
}
ga.Text = myString;
I hope this helps some of you who are trying to implement this method of pulling data from Google. I used jQuery to have the list animate as a bar graph with the article titles appearing on hover. This is the final result:
|
Apr, 23
2010
|
Protect Images Online using PHP and jQuery [How To] |
Read |
Ever go to a website and think to yourself, “Wow, those are some nice photos. I wonder if I can download them and [insert personal use line here]“?
The issue of protecting images online is quite a challenge, and borderline impossible. Using Flash is a good way to do it, but now you’ve just limited your audience. Even with Flash, it’s not 100% secure. In safari, users can go to the activity window and see what resources are being downloaded and from where. Other more advanced users often use Firebug or something of the like to grab the actual URL of the image and subsequently access that file directly.
Ultimately, users can always just take a screen shot of the page, but this will also include any of the text that is above the image (unless they use Firebug to hide it). You can’t stop that without the user agreeing to download a 3rd party plugin, so might as well deal with that fact.
In lieu of all this, I still wanted to use Pablo Yanez’s images as wallpapers for my new site design. He wanted them protected. I completely agree… and out of that need, came this project.
Theory behind the process: (I’m not going to go into too much detail for, hopefully, obvious reasons)
Here’s the trick: The encoder.php file gets the initial “Build me the URL of where the image is” request. This URL has a time stamp generated and encoded in it. Make sure the time stamp that is being generated adds or subtracts a large number of time, in this example I will say 12304 seconds get added. This part is key because if users figure out that the encoded parameter is a base_64 encoded time stamp, they can write a script to generate one too, totally defeating the purpose of the time stamp. That’s the first part of the encoder. The second part is to read the directory where the images are and, in my case, put the entire list into an array and pick a random number that is no less than 0 and no larger than the length of the array -1. This is important because in image.php, we will be doing the same lookup in the directory, except this time, we are using that random number to select the file name of the file we want to display. Also, image.php also creates a time stamp (important) and adds 12304 seconds to it. If image.php’s time stamp is within, say, 5 seconds of the encoded.php timestamp, the script continues. Otherwise, the script dies and in my case, renders out “clear.gif” to confuse people.
*Important note at this point: Using the time stamp technique disables caching of the images, but because we don’t want users to retain a copy at all, that’s fine.
This is my encoder.php file (secure parts omitted):
function getRan()
{
$dir_array = array();
if ($handle = opendir('Secure images directory, relative to site root')) {
while (false !== ($file = readdir($handle))) {
if($file!="." && $file!=".."){
$dir_array[] = $file;
}
}
closedir($handle);
}
return rand(0,count($dir_array)-1);
}
function getRanAJAX()
{
$dir_array = array();
if ($handle = opendir('Secure images directory, relative this')) {
while (false !== ($file = readdir($handle))) {
if($file!="." && $file!=".."){
$dir_array[] = $file;
}
}
closedir($handle);
}
return rand(0,count($dir_array)-1);
}
function getBGParams()
{
$r = getRan();
$t = time();//use math to change time - add or subtract in seconds
$tenc = base64_encode($t);
$tdir = bloginfo('template_directory'); //wordpress
$style= $tdir."/image.php?u=".$tenc."&p=".$r;
echo $style;
}
function getU()
{
$ref = $_SERVER['HTTP_REFERER'];
//make sure requests are coming from me
$pattern = '/^(http:\/\/www.gmtaz.com)|(http:\/\/gmtaz.com)/';
if(preg_match($pattern,$ref)){
$r = getRanAJAX();
$t = time();//use math to change time - add or subtract in seconds
$tenc = base64_encode($t);
echo '{"u":"'.$tenc.'", "d" : "' . $tdir . '/image.php", "r" : "'.$r.'", "ref" : "'.$ref.'"}';
}
}
function getR()
{
$r = rand(0, 1);
echo '{"r":"'.$r.'"}';
}
$op = $_GET['o'];
if($op=='u')
getU();
if($op == 'r')
{
getR();
}
Hopefully that all makes sense. The first AJAX request using jQuery looks like this:
< ?php include 'encoder.php' ?>
$(function(){
gmtaz.setBG('< ?php getBGParams() ?>');
setInterval(function(){
var u = '';
var url = '';
var r = '';
var dt = new Date();
var time = dt.getTime();
//for wordpress
var td = "< ?php bloginfo('template_directory'); ?>/encoder.php";
$.getJSON(td,
{o:'u', t: time},
function(d){
u = d.u;
url = d.d;
r = d.r;
var dd = '' + url + '?u='+ u +'&p=' + r;
//alert(dd +''+ '');
gmtaz.setBG(dd);
});
}, 12000);
});
setBG(dd) is actually this function:
setBG : function(url){
var url = url + gmtaz.getResolution();
$('< img />')
.attr('src', url)
.load(function(){
var src = $(this).attr('src');
$('#bg').css({
'backgroundImage':'url('+src+')',
'backgroundRepeat':'no-repeat',
'backgroundAttachment':'fixed'})
.fadeIn('slow',function(){
$('body').css({
'backgroundImage':'url('+src+')',
'backgroundRepeat':'no-repeat',
'backgroundAttachment':'fixed'
});
$(this).fadeOut('fast');
});
});
},
getResolution : function(){
return '&w='+screen.width+"&h="+screen.height;
},
All this is doing is using some jQuery to grab that image URL which is being passed in and set it as the background. I actually have two bg layers to allow for the fade effect.
Here’s image.php:
< ?php
$dir_array = array();
if ($handle = opendir('Secure Images Directory')) {
while (false !== ($file = readdir($handle))) {
if($file!="." && $file!=".."){
$dir_array[] = $file;
}
}
closedir($handle);
}
$images = $dir_array;
$t = time();//same mathematical algorithm as in encoder.php
$tdec = base64_decode($_GET['u']);
$diffT = $t-$tdec;
if($diffT > 5 || $diffT < 0)//if older than 5 seconds - die
{
die('clear.gif');
}
//Disable caching
header("Expires: Tue, 03 Jul 2001 06:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Content-type: image/jpeg");
while (@ob_end_clean());
$PATH = urldecode($_GET['p']);
$File = 'secret directoy'.$images[$PATH];
if (($FileInfos= stat($File)) or die("File not found!"));
$FileExt= substr($File, -3);
$FileTypeMIME= array("jpg" => "image/jpeg",
"png" => "image/png",
"gif" => "image/gif",
"ico" => "image/x-icon");
$ContentType= $FileTypeMIME[$FileExt];
if (empty($ContentType)) die("You are not allowed to access this file!");
$h = $_GET['h'];
$w = $_GET['w'];
$im = @imagecreatefromjpeg($File);
$width = 1920;
$height = 1200;
$NewThumb= ImageCreateTrueColor($w,$h);
// check if ratios match
$_ratio=array($width/$height,$w/$h);
if ($_ratio[0] != $_ratio[1]) { // crop image
// find the right scale to use
$_scale=min((float)($width/$w),(float)($height/$h));
// coords to crop
$cropX=(float)($width-($_scale*$w));
$cropY=(float)($height-($_scale*$h));
// cropped image size
$cropW=(float)($width-$cropX);
$cropH=(float)($height-$cropY);
$crop = ImageCreateTrueColor($cropW,$cropH);
// crop the middle part of the image to fit proportions
ImageCopy(
$crop,
$im,
0,
0,
(int)($cropX/2),
(int)($cropY/2),
$cropW,
$cropH
);
}
// do the thumbnail
if (isset($crop)) { // been cropped
ImageCopyResampled(
$NewThumb,
$crop,
0,
0,
0,
0,
$w,
$h,
$cropW,
$cropH
);
ImageDestroy($crop);
} else { // ratio match, regular resize
ImageCopyResampled(
$NewThumb,
$im,
0,
0,
0,
0,
$w,
$h,
$width,
$height
);
}
$q=60;//final output quality
ImageJpeg($NewThumb,null,$q);
ImageDestroy($NewThumb);
ImageDestroy($im);
?>
You may notice that I’m doing some cropping here. Actually what I’m doing is sizing the image to the full resolution of the visitor. I crop it to fit the dimension ratio first, then I resize it. This should make the image always look the same no matter what computer you’re on. Handy for dynamically creating wallpapers as well.. I might expand on this and include that function in my wallpaper gallery.
Let me know if anyone knows a way around this. I’m interested in tightening this up!
|
Nov, 5
2009
|
Using Bit.ly, prettySociable, and jQuery to share shortened links |
Read |
So I went ahead and made some script modifications to the already awesome PrettySociable jQuery plugin. These modifications allow for the use of your bit.ly account api to shorten urls.
By default, the prettySociable plugin takes the url supplied and submits that to the share service (twitter, facebook, etc.). I just made a simple change to allow for the developers to include a bit.ly api and username when calling $.prettySociable() by passing those in as parameters.
$.prettySociable({bitly_api: 'api here', bitly_user:'your username'});
If these options aren’t set, the plugin will use the default url. If they are, the plugin will automatically call the bit.ly api to shorten the url and use that shortened url instead.
I probably need to test a bit more, but here is the jquery.prettysociable.bitly.js script and here it is minified: jquery.prettysociable.bitly.min.js.
Links that helped me with this:
Bit.ly
PrettySociable plugin page
jQuery HowTo @blogspot
|
Aug, 31
2009
|
[Quick Fix] Can’t Use iPhone OS 7A400 in XCODE ? Solved |
Read |
Recently, I began work on an iPhone app and during testing I came across this error:
“The version of iPhone OS on “Gustavo Tandeciarz’s iPhone” does not match any of the versions of iPhone OS supported for development with this copy of Xcode…”
I have the latest version (3.0.1) on my iPhone, which is apparently not supported, yet by Xcode so until then, I need a work around.
Searching Google, I found this little gem:
Open Terminal and run the following:
ln -s /Developer/Platforms/iPhoneOS.platform/DeviceSupport/3.0\ \(7A341\) /Developer/Platforms/iPhoneOS.platform/DeviceSupport/3.0.1
Restart Xcode and try again. This worked perfectly on both of my Macs.
|
Aug, 19
2009
|
How to Upgrade Windows 7 RC Ultimate to RTM Enterprise |
Read |
Yes yes, everyone said it’s unsupported and, technically, it is. This was just an exercise to see if it was possible to do and I can personally verify that it is and, actually really easy.
I’m going to assume that you already have a valid, legal copy of Windows 7 Enterprise and an installed copy of Windows 7 RC Ultimate and they are both the same kernel (either 32bit or 64bit) and that you already backed up all your data.
Within Windows Ultimate:

Now comes the (kind of) tricky part.
See Here (howtogeek.com) for another article describing this process and here (blogs.msdn.com)
That’s it. Enjoy what is, arguably, the best version of Windows yet. I’m assuming that this registry hack will work for versions other than Enterprise although I have not tried any other versions myself.
|
May, 8
2009
|
How to enable Remote Desktop through SSH or Telnet |
Read |
If you have a telnet server already configured (or an SSH server as is my case) but you forgot to, or need to, enable remote desktop to remotely control that computer, you can do this via the terminal.
Just connect to your console session (SSH / Telnet) and run this command:
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
This will make Terminal Services on the remote computer allow for incoming connections. Then, for Windows 7, type in:
net start "Remote Desktop Services"
This will start the listener service on the computer. You should now be able to access the computer using the administrators account (granted, you must have admin access to the ssh or telnet terminal to do any of this).
|
Apr, 16
2009
|
Quickly Trim Text with Regular Expressions and jQuery |
Read |
I ran into an issue ( a while back but finally had time to address it ) where we had lines of text that we could trim down to fit an HTML container. If the text was longer that 37 characters, we stripped off the end and replaced it with ‘…’. The problem with doing this strictly on a character count basis was that the break would usually be mid-word and with some words like, assign, that would could be bad.
A simple way to fix address this is to use regular expressions. Specifically, this regular expression: ^(.){1,37}\b
My solution was to use javascript and css to replace the text on the fly. Applying the ‘white-space:nowrap’ style to the text element allows me to keep everything on one line. Overflow:hidden hides the text that would flow out of the block. This helps me keep a minimum amount of text visible until the javascript function applies the fix. Also, I’m using in-line javascript (big no-no) but it does the job fast.
This is the script:
function trimText(element)
{
var list = $(element);
var regToShow = new RegExp(/^(.){1,37}\b/);
list.each(function(){
var toShow = $(this).text().match(regToShow);
$(this).text(toShow[0]+'...');
});
}
trimText(Selector);
Basically, what I’m doing here is applying the regular expression to the called-in-class’ text. If you know about regular expressions or want to know more about them, check out RegExr. It’s an online and downloadable (Adobe Air) tool for regular expressions testing and design. You can also put in a conditional statement if you don’t to add the ‘…’ at the end unless you are actually trimming the line.
if($(this).text()!=toShow[0])
$(this).text(toShow[0]+'...');
This just checks to see if the final text is the same as the original text (i.e. no trimming) and if so, do not add ‘…’.
It’s quick and dirty but it works. It would work better if you apply the Regular Expression in the code BEFORE the text gets rendered, but sometimes, that’s not a viable option.
|
Mar, 9
2009
|
PHP: Check if current time is between 2 values |
Read |
Here’s a quick and easy script to check if the current time (by timezone) is between 2 predefined values:
function isbetween($s, $e) {
putenv("TZ=US/Eastern"); //Sets the current timezone
$ret = False; //Defaults to false
$n = date("G:i"); //Get current time in 24 hour format
$n = explode(':',$n); //Separate hours and minutes
$s = explode(':',$s);
$e = explode(':',$e);
$nt = $n[0] * 60 + $n[1]; //Convert time to total minutes
$st = $s[0] * 60 + $s[1];
$et = $e[0] * 60 + $e[1];
if($nt > $st && $nt < $et) //Check time
$ret = True;
return $ret;
}
if(isbetween('9:30', '16:00'))
{
echo "It is later than 9:30AM and earlier than 4PM EST";
}