Load asciicast data via ajax

This commit is contained in:
Marcin Kulik 2012-03-03 18:38:11 +01:00
parent a16c10009a
commit b3e8fbb7df
10 changed files with 64 additions and 28 deletions

View File

@ -9,6 +9,7 @@ gem 'confstruct'
gem 'omniauth' gem 'omniauth'
gem 'omniauth-twitter' gem 'omniauth-twitter'
gem 'omniauth-github' gem 'omniauth-github'
gem 'bzip2-ruby'
# Gems used only for assets and not required # Gems used only for assets and not required
# in production environments by default. # in production environments by default.

View File

@ -33,6 +33,7 @@ GEM
arel (3.0.0) arel (3.0.0)
awesome_print (0.4.0) awesome_print (0.4.0)
builder (3.0.0) builder (3.0.0)
bzip2-ruby (0.2.7)
capybara (1.1.2) capybara (1.1.2)
mime-types (>= 1.16) mime-types (>= 1.16)
nokogiri (>= 1.3.3) nokogiri (>= 1.3.3)
@ -204,6 +205,7 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
awesome_print awesome_print
bzip2-ruby
capybara capybara
carrierwave carrierwave
coffee-rails coffee-rails

View File

@ -0,0 +1,4 @@
class AsciiIo.Asciicast extends Backbone.Model
url: ->
"/asciicasts/#{@get('id')}.json"

View File

@ -2,13 +2,20 @@ class AsciiIo.Movie
MIN_DELAY: 0.01 MIN_DELAY: 0.01
SPEED: 1.0 SPEED: 1.0
constructor: (@data, @timing) -> constructor: (@model) ->
@frameNo = 0 @frameNo = 0
@dataIndex = 0 @dataIndex = 0
@currentTime = 0 @currentTime = 0
@processedFramesTime = 0 @processedFramesTime = 0
_.extend(this, Backbone.Events) _.extend(this, Backbone.Events)
isLoaded: ->
@model.get('escaped_stdout_data') != undefined
load: ->
@model.fetch
success: => @play()
play: -> play: ->
@nextFrame() @nextFrame()
@ -21,13 +28,22 @@ class AsciiIo.Movie
seek: (percent) -> seek: (percent) ->
# TODO # TODO
timing: ->
@model.get('stdout_timing_data')
data: ->
unless @_data
@_data = eval "'" + @model.get('escaped_stdout_data') + "'"
@_data
nextFrame: () -> nextFrame: () ->
# return if @currentData.length > 100 # return if @currentData.length > 100
if frame = @timing[@frameNo++] # @frameNo += 1 if frame = @timing()[@frameNo++] # @frameNo += 1
[delay, count] = frame [delay, count] = frame
frameData = @data.slice(@dataIndex, @dataIndex + count) frameData = @data().slice(@dataIndex, @dataIndex + count)
@dataIndex += count @dataIndex += count
if delay <= @MIN_DELAY if delay <= @MIN_DELAY

View File

@ -1,7 +1,9 @@
class AsciiIo.PlayerView extends Backbone.View class AsciiIo.PlayerView extends Backbone.View
initialize: (options) -> initialize: (options) ->
@movie = new AsciiIo.Movie(options.data, options.timing) @movie = new AsciiIo.Movie(@model)
@movie.load()
@terminalView = new AsciiIo.TerminalView( @terminalView = new AsciiIo.TerminalView(
cols: this.options.cols cols: this.options.cols
lines: this.options.lines lines: this.options.lines
@ -39,4 +41,5 @@ class AsciiIo.PlayerView extends Backbone.View
@terminalView.stopCursorBlink() @terminalView.stopCursorBlink()
play: -> play: ->
@movie.play() if @movie.isLoaded()
@movie.play()

View File

@ -1,4 +1,5 @@
class AsciicastsController < ApplicationController class AsciicastsController < ApplicationController
respond_to :html, :json
def index def index
@asciicasts = Asciicast.order("created_at DESC") @asciicasts = Asciicast.order("created_at DESC")
@ -6,6 +7,7 @@ class AsciicastsController < ApplicationController
def show def show
@asciicast = Asciicast.find(params[:id]) @asciicast = Asciicast.find(params[:id])
respond_with @asciicast
end end
end end

View File

@ -1,31 +1,14 @@
module AsciicastsHelper module AsciicastsHelper
def player_data(asciicast) def player_script(asciicast)
data = `bzip2 -d -c #{asciicast.stdout.path}` return <<EOS.html_safe
time = `bzip2 -d -c #{asciicast.stdout_timing.path}`
data_hex_array = data.bytes.map { |b| '\x' + format('%02x', b) }
var_data = "'#{data_hex_array.join}'"
time_lines = time.lines.map do |line|
delay, n = line.split
"[#{delay.to_f}, #{n.to_i}]"
end
var_time = "[#{time_lines.join(',')}]"
<<EOS.html_safe
<script> <script>
var data = #{var_data};
var time = #{j var_time};
var cols = #{asciicast.terminal_columns};
var lines = #{asciicast.terminal_lines};
$(function() { $(function() {
window.player = new AsciiIo.PlayerView({ window.player = new AsciiIo.PlayerView({
el: $('.player'), el: $('.player'),
cols: cols, cols: #{asciicast.terminal_columns},
lines: lines, lines: #{asciicast.terminal_lines},
data: data, model: new AsciiIo.Asciicast({ id: #{asciicast.id} })
timing: time
}); });
window.player.play(); window.player.play();

View File

@ -20,4 +20,27 @@ class Asciicast < ActiveRecord::Base
self.terminal_columns = data['term']['columns'] self.terminal_columns = data['term']['columns']
self.terminal_type = data['term']['type'] self.terminal_type = data['term']['type']
end end
def as_json(opts = {})
super :methods => [:escaped_stdout_data, :stdout_timing_data]
end
def escaped_stdout_data
if data = stdout.read
Bzip2.uncompress(data).bytes.map { |b| '\x' + format('%02x', b) }.join
else
nil
end
end
def stdout_timing_data
if data = stdout_timing.read
Bzip2.uncompress(data).lines.map do |line|
delay, n = line.split
[delay.to_f, n.to_i]
end
else
nil
end
end
end end

View File

@ -13,4 +13,4 @@
<p>But like anything else with Vim, there are always multiple ways of accomplishing the very same thing, so I make no guarantees that there arent simpler ways of getting this done — but I can say that this way gets the job done, and is pretty easy to get working on your own system.</p> <p>But like anything else with Vim, there are always multiple ways of accomplishing the very same thing, so I make no guarantees that there arent simpler ways of getting this done — but I can say that this way gets the job done, and is pretty easy to get working on your own system.</p>
</div> </div>
<%= player_data(@asciicast) %> <%= player_script(@asciicast) %>

View File

@ -54,3 +54,5 @@ module AsciiIo
config.assets.version = '1.0' config.assets.version = '1.0'
end end
end end
ActiveRecord::Base.include_root_in_json = false