From b3e8fbb7df16773d9482fe194bdc36c75bb28fa2 Mon Sep 17 00:00:00 2001 From: Marcin Kulik Date: Sat, 3 Mar 2012 18:38:11 +0100 Subject: [PATCH] Load asciicast data via ajax --- Gemfile | 1 + Gemfile.lock | 2 ++ .../javascripts/player/asciicast.js.coffee | 4 +++ app/assets/javascripts/player/movie.js.coffee | 22 ++++++++++++--- .../javascripts/player/player_view.js.coffee | 7 +++-- app/controllers/asciicasts_controller.rb | 2 ++ app/helpers/asciicasts_helper.rb | 27 ++++--------------- app/models/asciicast.rb | 23 ++++++++++++++++ app/views/asciicasts/show.html.erb | 2 +- config/application.rb | 2 ++ 10 files changed, 64 insertions(+), 28 deletions(-) create mode 100644 app/assets/javascripts/player/asciicast.js.coffee diff --git a/Gemfile b/Gemfile index 0fac63f..a94b1f7 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,7 @@ gem 'confstruct' gem 'omniauth' gem 'omniauth-twitter' gem 'omniauth-github' +gem 'bzip2-ruby' # Gems used only for assets and not required # in production environments by default. diff --git a/Gemfile.lock b/Gemfile.lock index 8a0a087..262750a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -33,6 +33,7 @@ GEM arel (3.0.0) awesome_print (0.4.0) builder (3.0.0) + bzip2-ruby (0.2.7) capybara (1.1.2) mime-types (>= 1.16) nokogiri (>= 1.3.3) @@ -204,6 +205,7 @@ PLATFORMS DEPENDENCIES awesome_print + bzip2-ruby capybara carrierwave coffee-rails diff --git a/app/assets/javascripts/player/asciicast.js.coffee b/app/assets/javascripts/player/asciicast.js.coffee new file mode 100644 index 0000000..ceaf97a --- /dev/null +++ b/app/assets/javascripts/player/asciicast.js.coffee @@ -0,0 +1,4 @@ +class AsciiIo.Asciicast extends Backbone.Model + + url: -> + "/asciicasts/#{@get('id')}.json" diff --git a/app/assets/javascripts/player/movie.js.coffee b/app/assets/javascripts/player/movie.js.coffee index 8314d84..6e335e1 100644 --- a/app/assets/javascripts/player/movie.js.coffee +++ b/app/assets/javascripts/player/movie.js.coffee @@ -2,13 +2,20 @@ class AsciiIo.Movie MIN_DELAY: 0.01 SPEED: 1.0 - constructor: (@data, @timing) -> + constructor: (@model) -> @frameNo = 0 @dataIndex = 0 @currentTime = 0 @processedFramesTime = 0 _.extend(this, Backbone.Events) + isLoaded: -> + @model.get('escaped_stdout_data') != undefined + + load: -> + @model.fetch + success: => @play() + play: -> @nextFrame() @@ -21,13 +28,22 @@ class AsciiIo.Movie seek: (percent) -> # TODO + timing: -> + @model.get('stdout_timing_data') + + data: -> + unless @_data + @_data = eval "'" + @model.get('escaped_stdout_data') + "'" + + @_data + nextFrame: () -> # return if @currentData.length > 100 - if frame = @timing[@frameNo++] # @frameNo += 1 + if frame = @timing()[@frameNo++] # @frameNo += 1 [delay, count] = frame - frameData = @data.slice(@dataIndex, @dataIndex + count) + frameData = @data().slice(@dataIndex, @dataIndex + count) @dataIndex += count if delay <= @MIN_DELAY diff --git a/app/assets/javascripts/player/player_view.js.coffee b/app/assets/javascripts/player/player_view.js.coffee index 7784a19..b235d9a 100644 --- a/app/assets/javascripts/player/player_view.js.coffee +++ b/app/assets/javascripts/player/player_view.js.coffee @@ -1,7 +1,9 @@ class AsciiIo.PlayerView extends Backbone.View initialize: (options) -> - @movie = new AsciiIo.Movie(options.data, options.timing) + @movie = new AsciiIo.Movie(@model) + @movie.load() + @terminalView = new AsciiIo.TerminalView( cols: this.options.cols lines: this.options.lines @@ -39,4 +41,5 @@ class AsciiIo.PlayerView extends Backbone.View @terminalView.stopCursorBlink() play: -> - @movie.play() + if @movie.isLoaded() + @movie.play() diff --git a/app/controllers/asciicasts_controller.rb b/app/controllers/asciicasts_controller.rb index 783e707..c1d2f57 100644 --- a/app/controllers/asciicasts_controller.rb +++ b/app/controllers/asciicasts_controller.rb @@ -1,4 +1,5 @@ class AsciicastsController < ApplicationController + respond_to :html, :json def index @asciicasts = Asciicast.order("created_at DESC") @@ -6,6 +7,7 @@ class AsciicastsController < ApplicationController def show @asciicast = Asciicast.find(params[:id]) + respond_with @asciicast end end diff --git a/app/helpers/asciicasts_helper.rb b/app/helpers/asciicasts_helper.rb index 8ccdc2d..c9753c6 100644 --- a/app/helpers/asciicasts_helper.rb +++ b/app/helpers/asciicasts_helper.rb @@ -1,31 +1,14 @@ module AsciicastsHelper - def player_data(asciicast) - data = `bzip2 -d -c #{asciicast.stdout.path}` - 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(',')}]" - - < - var data = #{var_data}; - var time = #{j var_time}; - var cols = #{asciicast.terminal_columns}; - var lines = #{asciicast.terminal_lines}; $(function() { window.player = new AsciiIo.PlayerView({ el: $('.player'), - cols: cols, - lines: lines, - data: data, - timing: time + cols: #{asciicast.terminal_columns}, + lines: #{asciicast.terminal_lines}, + model: new AsciiIo.Asciicast({ id: #{asciicast.id} }) }); window.player.play(); diff --git a/app/models/asciicast.rb b/app/models/asciicast.rb index 9d8e2e1..c289a04 100644 --- a/app/models/asciicast.rb +++ b/app/models/asciicast.rb @@ -20,4 +20,27 @@ class Asciicast < ActiveRecord::Base self.terminal_columns = data['term']['columns'] self.terminal_type = data['term']['type'] 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 diff --git a/app/views/asciicasts/show.html.erb b/app/views/asciicasts/show.html.erb index 5bdd903..2ca69ea 100644 --- a/app/views/asciicasts/show.html.erb +++ b/app/views/asciicasts/show.html.erb @@ -13,4 +13,4 @@

But like anything else with Vim, there are always multiple ways of accomplishing the very same thing, so I make no guarantees that there aren’t 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.

-<%= player_data(@asciicast) %> +<%= player_script(@asciicast) %> diff --git a/config/application.rb b/config/application.rb index d37c20e..b11b261 100644 --- a/config/application.rb +++ b/config/application.rb @@ -54,3 +54,5 @@ module AsciiIo config.assets.version = '1.0' end end + +ActiveRecord::Base.include_root_in_json = false