http://meta.discourse.org/t/is-it-better-for-discourse-to-use-javascript-or-coffeescript/3153
170 lines
4.6 KiB
JavaScript
170 lines
4.6 KiB
JavaScript
|
|
/* We use this class to track how long posts in a topic are on the screen.
|
|
*/
|
|
|
|
|
|
/* This could be a potentially awesome metric to keep track of.
|
|
*/
|
|
|
|
|
|
(function() {
|
|
|
|
window.Discourse.ScreenTrack = Ember.Object.extend({
|
|
/* Don't send events if we haven't scrolled in a long time
|
|
*/
|
|
|
|
PAUSE_UNLESS_SCROLLED: 1000 * 60 * 3,
|
|
/* After 6 minutes stop tracking read position on post
|
|
*/
|
|
|
|
MAX_TRACKING_TIME: 1000 * 60 * 6,
|
|
totalTimings: {},
|
|
/* Elements to track
|
|
*/
|
|
|
|
timings: {},
|
|
topicTime: 0,
|
|
cancelled: false,
|
|
track: function(elementId, postNumber) {
|
|
this.timings["#" + elementId] = {
|
|
time: 0,
|
|
postNumber: postNumber
|
|
};
|
|
},
|
|
guessedSeen: function(postNumber) {
|
|
if (postNumber > (this.highestSeen || 0)) {
|
|
this.highestSeen = postNumber;
|
|
}
|
|
},
|
|
/* Reset our timers
|
|
*/
|
|
|
|
reset: function() {
|
|
this.lastTick = new Date().getTime();
|
|
this.lastFlush = 0;
|
|
this.cancelled = false;
|
|
},
|
|
/* Start tracking
|
|
*/
|
|
|
|
start: function() {
|
|
var _this = this;
|
|
this.reset();
|
|
this.lastScrolled = new Date().getTime();
|
|
this.interval = setInterval(function() {
|
|
return _this.tick();
|
|
}, 1000);
|
|
},
|
|
/* Cancel and eject any tracking we have buffered
|
|
*/
|
|
|
|
cancel: function() {
|
|
this.cancelled = true;
|
|
this.timings = {};
|
|
this.topicTime = 0;
|
|
clearInterval(this.interval);
|
|
this.interval = null;
|
|
},
|
|
/* Stop tracking and flush buffered read records
|
|
*/
|
|
|
|
stop: function() {
|
|
clearInterval(this.interval);
|
|
this.interval = null;
|
|
return this.flush();
|
|
},
|
|
scrolled: function() {
|
|
this.lastScrolled = new Date().getTime();
|
|
},
|
|
flush: function() {
|
|
var highestSeenByTopic, newTimings, topicId,
|
|
_this = this;
|
|
if (this.cancelled) {
|
|
return;
|
|
}
|
|
/* We don't log anything unless we're logged in
|
|
*/
|
|
|
|
if (!Discourse.get('currentUser')) {
|
|
return;
|
|
}
|
|
newTimings = {};
|
|
Object.values(this.timings, function(timing) {
|
|
if (!_this.totalTimings[timing.postNumber])
|
|
_this.totalTimings[timing.postNumber] = 0;
|
|
|
|
if (timing.time > 0 && _this.totalTimings[timing.postNumber] < _this.MAX_TRACKING_TIME) {
|
|
_this.totalTimings[timing.postNumber] += timing.time;
|
|
newTimings[timing.postNumber] = timing.time;
|
|
}
|
|
timing.time = 0;
|
|
});
|
|
topicId = this.get('topic_id');
|
|
highestSeenByTopic = Discourse.get('highestSeenByTopic');
|
|
if ((highestSeenByTopic[topicId] || 0) < this.highestSeen) {
|
|
highestSeenByTopic[topicId] = this.highestSeen;
|
|
}
|
|
if (!Object.isEmpty(newTimings)) {
|
|
jQuery.ajax('/topics/timings', {
|
|
data: {
|
|
timings: newTimings,
|
|
topic_time: this.topicTime,
|
|
highest_seen: this.highestSeen,
|
|
topic_id: topicId
|
|
},
|
|
cache: false,
|
|
type: 'POST',
|
|
headers: {
|
|
'X-SILENCE-LOGGER': 'true'
|
|
}
|
|
});
|
|
this.topicTime = 0;
|
|
}
|
|
this.lastFlush = 0;
|
|
},
|
|
tick: function() {
|
|
/* If the user hasn't scrolled the browser in a long time, stop tracking time read
|
|
*/
|
|
|
|
var diff, docViewBottom, docViewTop, sinceScrolled,
|
|
_this = this;
|
|
sinceScrolled = new Date().getTime() - this.lastScrolled;
|
|
if (sinceScrolled > this.PAUSE_UNLESS_SCROLLED) {
|
|
this.reset();
|
|
return;
|
|
}
|
|
diff = new Date().getTime() - this.lastTick;
|
|
this.lastFlush += diff;
|
|
this.lastTick = new Date().getTime();
|
|
if (this.lastFlush > (Discourse.SiteSettings.flush_timings_secs * 1000)) {
|
|
this.flush();
|
|
}
|
|
/* Don't track timings if we're not in focus
|
|
*/
|
|
|
|
if (!Discourse.get("hasFocus")) {
|
|
return;
|
|
}
|
|
this.topicTime += diff;
|
|
docViewTop = jQuery(window).scrollTop() + jQuery('header').height();
|
|
docViewBottom = docViewTop + jQuery(window).height();
|
|
return Object.keys(this.timings, function(id) {
|
|
var $element, elemBottom, elemTop, timing;
|
|
$element = jQuery(id);
|
|
if ($element.length === 1) {
|
|
elemTop = $element.offset().top;
|
|
elemBottom = elemTop + $element.height();
|
|
/* If part of the element is on the screen, increase the counter
|
|
*/
|
|
|
|
if (((docViewTop <= elemTop && elemTop <= docViewBottom)) || ((docViewTop <= elemBottom && elemBottom <= docViewBottom))) {
|
|
timing = _this.timings[id];
|
|
timing.time = timing.time + diff;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
}).call(this);
|