/** * remy sharp / http://remysharp.com * Twitter / @rem * http://remysharp.com/2007/05/18/add-twitter-to-your-blog-step-by-step/ * * @params * cssIdOfContainer: e.g. twitters * options: * { * id: {String} username, * count: {Int} 1-20, defaults to 1 - max limit 20 * prefix: {String} '%name% said', defaults to blank * clearContents: {Boolean} true, removes contents of element specified in cssIdOfContainer, defaults to true * ignoreReplies: {Boolean}, skips over tweets starting with '@', defaults to false * template: {String} HTML template to use for LI element (see URL above for examples), defaults to predefined template * enableLinks: {Boolean} linkifies text, defaults to true, * newwindow {Boolean} opens links in new window, defaults to false * timeout: {Int} How long before triggering onTimeout, defaults to 10 seconds if onTimeout is set * onTimeoutCancel: {Boolean} Completely cancel twitter call if timedout, defaults to false * onTimeout: {Function} Function to run when the timeout occurs. Function is bound to element specified with * cssIdOfContainer (i.e. 'this' keyword) * callback: {Function} Callback function once the render is complete, doesn't fire on timeout * * CURRENTLY DISABLED DUE TO CHANGE IN TWITTER API: * withFriends: {Boolean} includes friend's status * * } * * @license MIT (MIT-LICENSE.txt) * @version 1.13.3 - ify now supports lists * @date $Date: 2010-11-10 15:05:04 $ */ // to protect variables from resetting if included more than once if (typeof renderTwitters != 'function') (function () { /** Private variables */ // only used for the DOM ready, since IE & Safari require special conditions var browser = (function() { var b = navigator.userAgent.toLowerCase(); // Figure out what browser is being used return { webkit: /(webkit|khtml)/.test(b), opera: /opera/.test(b), msie: /msie/.test(b) && !(/opera/).test(b), mozilla: /mozilla/.test(b) && !(/(compatible|webkit)/).test(b) }; })(); var guid = 0; var readyList = []; var isReady = false; var monthDict = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; /** Global functions */ // based on Dustin Diaz's ify, but with my fixes :-) window.ify = function() { var entities = { '"' : '"', '&' : '&', '<' : '<', '>' : '>' }; //tweetURL = "http://www.gsn.com"; //default can break CSS if there is no URL in tweet coming in twitter_tag_img = ""; return { "tweeturl": function(t) { return t.replace(/[a-z]+:\/\/[a-z0-9-_]+\.[a-z0-9-_:~%&\?#\/.=]+[^:\.,\)\s*$]/ig, function(m) { return '' + ((m.length > 25) ? m.substr(0, 24) + '...' : m) + ''; //tweetURL = m; return ''; }); }, // "urllink": function(t) { // return '' + t + ''; // }, //"at": function(t) { // return t.replace(/(^|[^\w]+)\@([a-zA-Z0-9_]{1,15}(\/[a-zA-Z0-9-_]+)*)/g, function(m, m1, m2) { // return m1 + '@' + m2 + ''; // }); //}, "hashes": function(t) { return t.replace(/(^|[^&\w'"]+)\#([a-zA-Z0-9_]+)/g, function(m, m1, m2) { //return m1 + '#' + m2 + ''; return m1 + '#' + m2 + ''; }); }, "hash_fb": function(t) { return t.replace(/(^|[^&\w'"]+)\#fb/g, function(m, m1, m2) { return ''; }); }, "hash_imgcheck": function(t) { var matchOne = /#Prize/; var matchTwo = /#Sweeps/; var matchThree = /#Buyitnow/; var matchFour = /#Playtowin/; var matchFive = /#Auctions/; if ( matchOne.test(t) ) { twitter_tag_img = "update"; } else if ( matchTwo.test(t) ) { twitter_tag_img = "sweeps"; } else if ( matchThree.test(t) ) { twitter_tag_img = "buyitnow"; } else if ( matchFour.test(t) ) { twitter_tag_img = "playtowin"; } else if ( matchFive.test(t) ) { twitter_tag_img = "auctions"; } return t; }, "imgswap": function(t) { if ( twitter_tag_img != "" ) { var img_tag = twitter_tag_img; twitter_tag_img = ""; //alert(t); return '' + t; } else { return t; } }, //"hash_oodles": function(t) { // return t.replace(/(^|[^&\w'"]+)\#oodles/g, function(m, m1, m2) { return ''; }); //}, "clean": function(tweet) { return this.imgswap( this.hash_imgcheck( this.tweeturl( this.hashes( this.hash_fb( tweet ) ) ) ) ) ; } }; }(); // to create a public function within our private scope, we attach the // the function to the window object window.renderTwitters = function (obj, options) { // private shortcuts function node(e) { return document.createElement(e); } function text(t) { return document.createTextNode(t); } var target = document.getElementById(options.twitterTarget); var data = null; var ul = node('ul'), li, statusSpan, timeSpan, i, max = obj.length > options.count ? options.count : obj.length; var classincrement = 0; for (i = 0; i < max && obj[i]; i++) { data = getTwitterData(obj[i]); if (options.ignoreReplies && obj[i].text.substr(0, 1) == '@') { max++; continue; // skip } matchOne = /#Prize/; matchTwo = /#Sweeps/; matchThree = /#Buyitnow/; matchFour = /#Playtowin/; matchFive = /#Auctions/; if ( matchOne.test(obj[i].text) || matchTwo.test(obj[i].text) || matchThree.test(obj[i].text) || matchFour.test(obj[i].text) || matchFive.test(obj[i].text) ) { classincrement ++ } else { max++; continue; // skip anything NOT prizes } li = node('li'); li.className = 'tweet' + classincrement; //'tweet' + i; if (options.template) { li.innerHTML = options.template.replace(/%([a-z_\-\.]*)%/ig, function (m, l) { var r = data[l] + "" || ""; if (l == 'text' && options.enableLinks) r = ify.clean(r); return r; }); } else { statusSpan = node('span'); statusSpan.className = 'twitterStatus'; timeSpan = node('span'); timeSpan.className = 'twitterTime'; statusSpan.innerHTML = obj[i].text; // forces the entities to be converted correctly if (options.enableLinks == true) { statusSpan.innerHTML = ify.clean(statusSpan.innerHTML); } timeSpan.innerHTML = relative_time(obj[i].created_at); if (options.prefix) { var s = node('span'); s.className = 'twitterPrefix'; s.innerHTML = options.prefix.replace(/%(.*?)%/g, function (m, l) { return obj[i].user[l]; }); li.appendChild(s); li.appendChild(text(' ')); // spacer :-( } li.appendChild(statusSpan); li.appendChild(text(' ')); li.appendChild(timeSpan); } if (options.newwindow) { li.innerHTML = li.innerHTML.replace(/<\/script>"); // Use the defer script hack var script = document.getElementById("__ie_init"); // script does not exist if jQuery is loaded dynamically if (script) { script.onreadystatechange = function() { if ( this.readyState != "complete" ) return; this.parentNode.removeChild( this ); fireReady.call(); }; } // Clear from memory script = null; } else if ( browser.webkit ) { // Continually check to see if the document.readyState is valid var safariTimer = setInterval(function () { // loaded and complete are both valid states if ( document.readyState == "loaded" || document.readyState == "complete" ) { // If either one are found, remove the timer clearInterval( safariTimer ); safariTimer = null; // and execute any waiting functions fireReady.call(); } }, 10); } } function relative_time(time_value) { var values = time_value.split(" "), parsed_date = Date.parse(values[1] + " " + values[2] + ", " + values[5] + " " + values[3]), date = new Date(parsed_date), relative_to = (arguments.length > 1) ? arguments[1] : new Date(), delta = parseInt((relative_to.getTime() - parsed_date) / 1000), r = ''; function formatTime(date) { var hour = date.getHours(), min = date.getMinutes() + "", ampm = 'AM'; if (hour == 0) { hour = 12; } else if (hour == 12) { ampm = 'PM'; } else if (hour > 12) { hour -= 12; ampm = 'PM'; } if (min.length == 1) { min = '0' + min; } return hour + ':' + min + ' ' + ampm; } function formatDate(date) { var ds = date.toDateString().split(/ /), mon = monthDict[date.getMonth()], day = date.getDate()+'', dayi = parseInt(day), year = date.getFullYear(), thisyear = (new Date()).getFullYear(), th = 'th'; // anti-'th' - but don't do the 11th, 12th or 13th if ((dayi % 10) == 1 && day.substr(0, 1) != '1') { th = 'st'; } else if ((dayi % 10) == 2 && day.substr(0, 1) != '1') { th = 'nd'; } else if ((dayi % 10) == 3 && day.substr(0, 1) != '1') { th = 'rd'; } if (day.substr(0, 1) == '0') { day = day.substr(1); } return mon + ' ' + day + th + (thisyear != year ? ', ' + year : ''); } delta = delta + (relative_to.getTimezoneOffset() * 60); if (delta < 5) { r = 'less than 5 seconds ago'; } else if (delta < 30) { r = 'half a minute ago'; } else if (delta < 60) { r = 'less than a minute ago'; } else if (delta < 120) { r = '1 minute ago'; } else if (delta < (45*60)) { r = (parseInt(delta / 60)).toString() + ' minutes ago'; } else if (delta < (2*90*60)) { // 2* because sometimes read 1 hours ago r = 'about 1 hour ago'; } else if (delta < (24*60*60)) { r = 'about ' + (parseInt(delta / 3600)).toString() + ' hours ago'; } else { if (delta < (48*60*60)) { r = formatTime(date) + ' yesterday'; } else { r = formatTime(date) + ' ' + formatDate(date); // r = (parseInt(delta / 86400)).toString() + ' days ago'; } } return r; } })();