Skip to content

Commit

Permalink
Minor refactor; Centralizes the options in js and adds relative times
Browse files Browse the repository at this point in the history
Signed-off-by: Akash Manohar J <akash@akash.im>
  • Loading branch information
HashNuke committed Apr 12, 2012
1 parent 96c096d commit e868f93
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 26 deletions.
7 changes: 0 additions & 7 deletions app/assets/javascripts/application.js
Expand Up @@ -19,10 +19,3 @@
//= require backbone/kandan
//= require_tree .

$(function(){
$('.user_menu_link').click(function(e){
e.preventDefault();
$('.user_menu').toggle();
return false;
});
});
Expand Up @@ -2,7 +2,7 @@ class Kandan.Helpers.Channels

@options:
autoScrollThreshold: 0.90
maxActivities: <%= Kandan::Config.options[:per_page] %>
maxActivities: Kandan.options.perPage

@pastAutoScrollThreshold: (channelId)->
currentPosition = @currentScrollPosition channelId
Expand Down
Expand Up @@ -16,6 +16,13 @@ window.Kandan =
Data: {}
Plugins: {}

options:
broadcaster: "<%= Kandan::Config.options[:broadcaster][:name] %>"
perPage : <%= Kandan::Config.options[:per_page] %>
nowThreshold: 3000
timestampRefreshInterval: 2000


# TODO this is a helper method to register plugins
# in the order required until we come up with plugin management
registerPlugins: ->
Expand Down Expand Up @@ -50,32 +57,32 @@ window.Kandan =


initBroadcasterAndSubscribe: ()->
Kandan.broadcaster = new Kandan.Broadcasters.FayeBroadcaster()
Kandan.broadcaster = eval "new Kandan.Broadcasters.#{@options.broadcaster}Broadcaster()"
Kandan.broadcaster.subscribe "/channels/*"
@registerAppEvents()

initTabs: ()->
$('#kandan').tabs({
select: (event, ui)->
$(document).data('active-channel-id',
Kandan.Helpers.Channels.getChannelIdByTabIndex(ui.index))
Kandan.Helpers.Channels.getChannelIdByTabIndex(ui.index))
Kandan.Data.Channels.runCallbacks('change')
add: (event, ui) ->
$('.header .ui-tabs-panel:last').detach().appendTo('#channels')
$('#kandan').tabs('option', 'disabled', [])
})

$("#kandan").tabs 'option', 'tabTemplate', '''
<li>
<a href="#{href}" class="show_channel">
<span class="tab_right"></span>
<span class="tab_left"></span>
<span class="tab_content">
<cite>#{label}</cite>
<cite class="close_channel" title="close channel">x</cite>
</span>
</a>
</li>
<li>
<a href="#{href}" class="show_channel">
<span class="tab_right"></span>
<span class="tab_left"></span>
<span class="tab_content">
<cite>#{label}</cite>
<cite class="close_channel" title="close channel">x</cite>
</span>
</a>
</li>
'''

initChatArea: (channels)->
Expand Down Expand Up @@ -104,6 +111,17 @@ window.Kandan =
name: "#{currentUser.first_name} #{currentUser.last_name}"
})

registerUtilityEvents: ()->
window.setInterval(=>
for el in $(".posted_at")
$(el).text (new Date($(el).data("timestamp"))).toRelativeTime(@options.nowThreshold)
, @options.timestampRefreshInterval)

$(".user_menu_link").click (e)->
e.preventDefault()
$(".user_menu").toggle()
false

init: ->
@setCurrentUser()
channels = new Kandan.Collections.Channels()
Expand All @@ -113,3 +131,4 @@ window.Kandan =
activeUsers = new Kandan.Collections.ActiveUsers()
activeUsers.fetch({success: @onFetchActiveUsers(channelsCollection)})
})
@registerUtilityEvents()
8 changes: 5 additions & 3 deletions app/assets/javascripts/backbone/views/show_activity.js.coffee
Expand Up @@ -5,7 +5,6 @@ class Kandan.Views.ShowActivity extends Backbone.View

render: ()->
activity = @options.activity.toJSON()
activity.created_at = Kandan.Helpers.Utils.timeToString(new Date(activity.created_at))
if activity.action != "message"
@compiledTemplate = JST['user_notification']({activity: activity})
else
Expand All @@ -15,7 +14,10 @@ class Kandan.Views.ShowActivity extends Backbone.View
else
@compiledTemplate = Kandan.Helpers.Activities.buildFromMessageTemplate $.extend(activity, {content: _.escape(activity.content)})

$(@el).data('activity-id', activity.id)
$(@el).attr('id', "activity-#{activity.id}")
$(@el).data("activity-id", activity.id)
$(@el).attr("id", "activity-#{activity.id}")
$(@el).html(@compiledTemplate)

#NOTE can only set the data after it's been appended to the DOM
$(@el).find(".posted_at").data("timestamp", activity.created_at)
@
121 changes: 121 additions & 0 deletions app/assets/javascripts/lib/date.extensions.js
@@ -0,0 +1,121 @@
/**
* Returns a description of this date in relative terms.
* Examples, where new Date().toString() == "Mon Nov 23 2009 17:36:51 GMT-0500 (EST)":
*
* new Date().toRelativeTime()
* --> 'Just now'
*
* new Date("Nov 21, 2009").toRelativeTime()
* --> '2 days ago'
*
* new Date("Nov 25, 2009").toRelativeTime()
* --> '2 days from now'
*
* // One second ago
* new Date("Nov 23 2009 17:36:50 GMT-0500 (EST)").toRelativeTime()
* --> '1 second ago'
*
* toRelativeTime() takes an optional argument - a configuration object.
* It can have the following properties:
* - now - Date object that defines "now" for the purpose of conversion.
* By default, current date & time is used (i.e. new Date())
* - nowThreshold - Threshold in milliseconds which is considered "Just now"
* for times in the past or "Right now" for now or the immediate future
* - smartDays - If enabled, dates within a week of now will use Today/Yesterday/Tomorrow
* or weekdays along with time, e.g. "Thursday at 15:10:34"
* rather than "4 days ago" or "Tomorrow at 20:12:01"
* instead of "1 day from now"
*
* If a single number is given as argument, it is interpreted as nowThreshold:
*
* // One second ago, now setting a now_threshold to 5 seconds
* new Date("Nov 23 2009 17:36:50 GMT-0500 (EST)").toRelativeTime(5000)
* --> 'Just now'
*
* // One second in the future, now setting a now_threshold to 5 seconds
* new Date("Nov 23 2009 17:36:52 GMT-0500 (EST)").toRelativeTime(5000)
* --> 'Right now'
*
*/
Date.prototype.toRelativeTime = (function() {

var _ = function(options) {
var opts = processOptions(options);

var now = opts.now || new Date();
var delta = now - this;
var future = (delta <= 0);
delta = Math.abs(delta);

// special cases controlled by options
if (delta <= opts.nowThreshold) {
return future ? 'Right now' : 'Just now';
}
if (opts.smartDays && delta <= 6 * MS_IN_DAY) {
return toSmartDays(this, now);
}

var units = null;
for (var key in CONVERSIONS) {
if (delta < CONVERSIONS[key])
break;
units = key; // keeps track of the selected key over the iteration
delta = delta / CONVERSIONS[key];
}

// pluralize a unit when the difference is greater than 1.
delta = Math.floor(delta);
if (delta !== 1) { units += "s"; }
return [delta, units, future ? "from now" : "ago"].join(" ");
};

var processOptions = function(arg) {
if (!arg) arg = 0;
if (typeof arg === 'string') {
arg = parseInt(arg, 10);
}
if (typeof arg === 'number') {
if (isNaN(arg)) arg = 0;
return {nowThreshold: arg};
}
return arg;
};

var toSmartDays = function(date, now) {
var day;
var weekday = date.getDay(),
dayDiff = weekday - now.getDay();
if (dayDiff == 0) day = 'Today';
else if (dayDiff == -1) day = 'Yesterday';
else if (dayDiff == 1) day = 'Tomorrow';
else day = WEEKDAYS[weekday];
return day + " at " + date.toLocaleTimeString();
};

var CONVERSIONS = {
millisecond: 1, // ms -> ms
second: 1000, // ms -> sec
minute: 60, // sec -> min
hour: 60, // min -> hour
day: 24, // hour -> day
month: 30, // day -> month (roughly)
year: 12 // month -> year
};
var MS_IN_DAY = (CONVERSIONS.millisecond * CONVERSIONS.second * CONVERSIONS.minute * CONVERSIONS.hour * CONVERSIONS.day);

var WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

return _;

})();



/*
* Wraps up a common pattern used with this plugin whereby you take a String
* representation of a Date, and want back a date object.
*/
Date.fromString = function(str) {
return new Date(Date.parse(str));
};
4 changes: 3 additions & 1 deletion app/assets/templates/activity_base.jst.eco
@@ -1,4 +1,6 @@
<span class="posted_at"><%= @activity.created_at %></span>
<span class="posted_at">
<%= new Date(@activity.created_at).toRelativeTime(Kandan.options.nowThreshold) %>
</span>
<img class="avatar" src="http://gravatar.com/avatar/<%= @activity.user.gravatar_hash %>?s=30&d=https://bushi.do/images/profile.png"/>

<div class="readable">
Expand Down
4 changes: 3 additions & 1 deletion app/assets/templates/message.jst.eco
@@ -1,4 +1,6 @@
<span class="posted_at"><%= @activity.created_at %></span>
<span class="posted_at">
<%= new Date(@activity.created_at).toRelativeTime(Kandan.options.nowThreshold) %>
</span>
<img class="avatar" src="http://gravatar.com/avatar/<%= @activity.user.gravatar_hash %>?s=30&d=https://bushi.do/images/profile.png"/>

<div class="readable">
Expand Down
4 changes: 3 additions & 1 deletion app/assets/templates/user_notification.jst.eco
@@ -1,4 +1,6 @@
<span class="posted_at"><%= @activity.created_at %></span>
<span class="posted_at">
<%= new Date(@activity.created_at).toRelativeTime(Kandan.options.nowThreshold) %>
</span>
<img class="avatar" src="http://gravatar.com/avatar/<%= @activity.user.gravatar_hash %>?s=30&d=https://bushi.do/images/profile.png"/>

<div class="readable">
Expand Down

0 comments on commit e868f93

Please sign in to comment.