lanalytics-rails 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +43 -0
  4. data/app/assets/javascripts/lanalytics.js +17 -0
  5. data/app/assets/javascripts/lanalytics/lanalytics.framework.js.coffee +128 -0
  6. data/app/assets/javascripts/lanalytics/model/lanalytics.model.exp_api_statement.js.coffee +41 -0
  7. data/app/assets/javascripts/lanalytics/model/lanalytics.model.stmt_component.js.coffee +8 -0
  8. data/app/assets/javascripts/lanalytics/model/lanalytics.model.stmt_resource.js.coffee +16 -0
  9. data/app/assets/javascripts/lanalytics/model/lanalytics.model.stmt_user.js.coffee +14 -0
  10. data/app/assets/javascripts/lanalytics/model/lanalytics.model.stmt_verb.js.coffee +12 -0
  11. data/app/assets/javascripts/lanalytics/plugins/lanalytics.plugins.example.html5videoplayer.js.coffee +25 -0
  12. data/app/assets/javascripts/lanalytics/plugins/lanalytics.plugins.newplugintemplate.js.coffee +23 -0
  13. data/app/assets/javascripts/lanalytics/plugins/lanalytics.plugins.pageviewplugin.js.coffee +42 -0
  14. data/app/assets/javascripts/lanalytics/plugins/lanalytics.plugins.statichtmlevent.js.coffee +31 -0
  15. data/app/controllers/lanalytics/tracking_controller.rb +28 -0
  16. data/config/routes.rb +17 -0
  17. data/lib/lanalytics-rails.rb +10 -0
  18. data/lib/lanalytics/engine.rb +11 -0
  19. data/lib/lanalytics/lanalytics_controller_filter.rb +24 -0
  20. data/lib/lanalytics/version.rb +3 -0
  21. data/lib/tasks/lanalytics_tasks.rake +4 -0
  22. data/spec/controllers/tracking_controller_spec.rb +45 -0
  23. data/spec/dummy/README.rdoc +28 -0
  24. data/spec/dummy/Rakefile +6 -0
  25. data/spec/dummy/app/assets/javascripts/application.js +14 -0
  26. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  27. data/spec/dummy/app/controllers/application_controller.rb +9 -0
  28. data/spec/dummy/app/controllers/welcome_controller.rb +10 -0
  29. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  30. data/spec/dummy/app/helpers/welcome_helper.rb +2 -0
  31. data/spec/dummy/app/views/layouts/application.html.erb +15 -0
  32. data/spec/dummy/app/views/welcome/index.html.erb +5 -0
  33. data/spec/dummy/bin/bundle +3 -0
  34. data/spec/dummy/bin/rails +4 -0
  35. data/spec/dummy/bin/rake +4 -0
  36. data/spec/dummy/config.ru +4 -0
  37. data/spec/dummy/config/application.rb +24 -0
  38. data/spec/dummy/config/boot.rb +5 -0
  39. data/spec/dummy/config/database.yml +25 -0
  40. data/spec/dummy/config/environment.rb +5 -0
  41. data/spec/dummy/config/environments/development.rb +37 -0
  42. data/spec/dummy/config/environments/production.rb +82 -0
  43. data/spec/dummy/config/environments/test.rb +39 -0
  44. data/spec/dummy/config/initializers/assets.rb +8 -0
  45. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  46. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  47. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  48. data/spec/dummy/config/initializers/inflections.rb +16 -0
  49. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  50. data/spec/dummy/config/initializers/session_store.rb +3 -0
  51. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  52. data/spec/dummy/config/locales/en.yml +23 -0
  53. data/spec/dummy/config/routes.rb +59 -0
  54. data/spec/dummy/config/secrets.yml +22 -0
  55. data/spec/dummy/public/404.html +67 -0
  56. data/spec/dummy/public/422.html +67 -0
  57. data/spec/dummy/public/500.html +66 -0
  58. data/spec/dummy/public/favicon.ico +0 -0
  59. data/spec/dummy/spec/controllers/welcome_controller_spec.rb +12 -0
  60. data/spec/dummy/spec/helpers/welcome_helper_spec.rb +15 -0
  61. data/spec/dummy/spec/javascripts/support/jasmine.yml +50 -0
  62. data/spec/dummy/spec/views/welcome/index.html.erb_spec.rb +5 -0
  63. data/spec/factories/exp_api_statement_factory.rb +7 -0
  64. data/spec/javascripts/foo.js.coffee +8 -0
  65. data/spec/javascripts/lanlaytics/model/exp_api_statement_spec.js.coffee +157 -0
  66. data/spec/javascripts/support/jasmine.yml +50 -0
  67. data/spec/rails_helper.rb +50 -0
  68. data/spec/spec_helper.rb +98 -0
  69. metadata +298 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bccfc3e4db4ed376314e8f978c475749316f58dc
4
+ data.tar.gz: 5e311be19936df67cf1028f9ed4b15694d8fa90a
5
+ SHA512:
6
+ metadata.gz: c5cde7057286068c228fd7bc03ebdb5a0ee09ab9672aab058fdadbe32b50c613820439fdaadfbd257f1bfce84ce9cff182d16fcacf4b91957cf80c61ceae10db
7
+ data.tar.gz: 218af978189ca12381fdc77a3f5d813aef704dd65a48a303f4df51e9d74d014e8a366c5ba1d5d2f8c45ffacd325e0f1a2c9e8861bf3a0c0c7cf4e2ebdbe268ff
@@ -0,0 +1,20 @@
1
+ Copyright 2014 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,43 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'geminabox/rake'
8
+ Geminabox::Rake.install host: 'https://gemuser:K6c1mcRWtrTQepS6aI8HRXc7DPoRYXbG@dev.xikolo.de/gems/',
9
+ dir: '.',
10
+ namespace: 'lanalytics-rails'
11
+
12
+ require 'rdoc/task'
13
+
14
+ RDoc::Task.new(:rdoc) do |rdoc|
15
+ rdoc.rdoc_dir = 'rdoc'
16
+ rdoc.title = 'Lanalytics'
17
+ rdoc.options << '--line-numbers'
18
+ rdoc.rdoc_files.include('README.rdoc')
19
+ rdoc.rdoc_files.include('lib/**/*.rb')
20
+ end
21
+
22
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
23
+ load 'rails/tasks/engine.rake'
24
+
25
+ Bundler::GemHelper.install_tasks
26
+
27
+ require 'rspec/core'
28
+ require 'rspec/core/rake_task'
29
+
30
+ desc "Run all specs in spec directory (excluding plugin specs)"
31
+ RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
32
+
33
+ # require 'jasmine'
34
+ # load 'jasmine/tasks/jasmine.rake'
35
+
36
+ begin
37
+ require 'jasmine'
38
+ load 'jasmine/tasks/jasmine.rake'
39
+ rescue LoadError
40
+ task :jasmine do
41
+ abort "Jasmine is not available. In order to run jasmine, you must: (sudo) gem install jasmine"
42
+ end
43
+ end
@@ -0,0 +1,17 @@
1
+ // Including the files necessary for the Lanalytics service
2
+
3
+ //= require jquery
4
+
5
+ //= require ./lanalytics/model/lanalytics.model.stmt_component.js.coffee
6
+ //= require ./lanalytics/model/lanalytics.model.stmt_resource.js.coffee
7
+ //= require ./lanalytics/model/lanalytics.model.stmt_verb.js.coffee
8
+ //= require ./lanalytics/model/lanalytics.model.stmt_user.js.coffee
9
+ //= require ./lanalytics/model/lanalytics.model.exp_api_statement.js.coffee
10
+ //= require ./lanalytics/lanalytics.framework.js.coffee
11
+ //= require_directory ./lanalytics/plugins
12
+
13
+ // Files that we do not want to release
14
+ //= stub ./lanalytics/plugins/lanalytics.plugins.newplugintemplate.js.coffee
15
+ //= stub ./lanalytics/plugins/lanalytics.plugins.example.html5videoplayer.js.coffee
16
+
17
+ lanalytics = new Lanalytics.Framework();
@@ -0,0 +1,128 @@
1
+ # Turning on debug mode for development
2
+ # DEBUG = true if typeof DEBUG is "undefined"
3
+ # Turning off debug mode for development
4
+ DEBUG = false if typeof DEBUG is "undefined"
5
+
6
+ window.Lanalytics or= {};
7
+
8
+ class window.Lanalytics.Framework
9
+
10
+ constructor: ->
11
+ @eventQueue = [];
12
+ @plugins = []
13
+
14
+ addPlugin: (plugin) ->
15
+ # if plugin instanceof throw "Plugin is not a Lanalytics.Plugin
16
+ @plugins.push(plugin)
17
+
18
+ currentUser: ->
19
+ if gon?.lanalytics?.current_user?
20
+ return new Lanalytics.Model.StmtUser(gon.lanalytics.current_user.id)
21
+ else
22
+ return new Lanalytics.Model.AnonymousUser()
23
+
24
+ track: (user, verb, resource, withResult = {}, inContext = {}) ->
25
+
26
+ # If a verb is key, we will replace it with the verb that we need to transmit
27
+ verb = Lanalytics.VerbDictionary.getVerb(verb) if typeof verb is "string"
28
+ now = new Date()
29
+
30
+ experienceStmt = new Lanalytics.Model.ExpApiStatement(user, verb, resource, now, withResult, inContext)
31
+
32
+ @eventQueue.push(experienceStmt)
33
+
34
+ @processEventQueue()
35
+
36
+ console.debug("New event was tracked:", experienceStmt) if (DEBUG)
37
+
38
+ # Verb can a key or an js object
39
+ # Resource should be an object that contains the resource type and the resource key
40
+ trackCurrentUserDoing: (verb, resource, withResult = {}, inContext = {}) ->
41
+
42
+ user = @currentUser()
43
+ @track(user, verb, resource, withResult, inContext)
44
+
45
+ processEventQueue: ->
46
+
47
+ # if eventQueue < 10
48
+
49
+ experienceStatement = @eventQueue.shift()
50
+
51
+ $.ajax("/lanalytics/log", {
52
+ type: 'POST',
53
+ cache: false,
54
+ dataType: 'JSON',
55
+ data: experienceStatement.params() ,
56
+ success: (response_data, text_status, jqXHR) ->
57
+ # Do nothing for now
58
+ error: (jqXHR, textStatus, errorThrown) =>
59
+ @eventQueue.push(experienceStatement)
60
+ })
61
+
62
+
63
+ class window.Lanalytics.VerbDictionary
64
+
65
+ @_verbDict = {
66
+ "video-play": {
67
+ verb_key: "video_play",
68
+ verb_id: "http://lanalytics.open.hpi.de/expapi/verbs/video-play"
69
+ },
70
+ "video-pause": {
71
+ verb_key: "video_pause",
72
+ verb_id: "http://lanalytics.open.hpi.de/expapi/verbs/video-stop"
73
+ },
74
+ "video-seek": {
75
+ verb_key: "video_seek",
76
+ verb_id: 'http://lanalytics.open.hpi.de/expapi/verbs/quiz-submitted'
77
+ },
78
+ "video-change-speed": {
79
+ verb_key: "video_change_speed",
80
+ verb_id: 'http://lanalytics.open.hpi.de/expapi/verbs/video-change-speed'
81
+ },
82
+ "quiz-submitted": {
83
+ verb_key: "quiz_submitted",
84
+ verb_id: 'http://lanalytics.open.hpi.de/expapi/verbs/quiz-submitted'
85
+ },
86
+ "video-change-size": {
87
+ verb_key: "video_change_size",
88
+ verb_id: 'http://lanalytics.open.hpi.de/expapi/verbs/video-change-size'
89
+ },
90
+ "video-fullscreen": {
91
+ verb_key: "video_fullscreen",
92
+ verb_id: 'http://lanalytics.open.hpi.de/expapi/verbs/video-fullscreen'
93
+ }
94
+
95
+ }
96
+
97
+ @_undefinedVerbTemplate = {
98
+ verb_key: "undefined",
99
+ id: "http://lanalytics.open.hpi.de/expapi/verbs/undefined"
100
+ }
101
+
102
+ @getVerb: (id) ->
103
+
104
+ if VerbDictionary._verbDict[id]?
105
+ return new Lanalytics.Model.StmtVerb(VerbDictionary._verbDict[id].verb_key)
106
+ else
107
+ return new Lanalytics.Model.StmtVerb(id)
108
+
109
+
110
+
111
+ class window.Lanalytics.Plugin
112
+ constructor: (@lanalytics) ->
113
+
114
+ @newInstance: (lanalyticsTracker) ->
115
+ throw "This function has to be implemented in the subclass."
116
+
117
+ # The plugin are supposed to be defined under this namesspace
118
+ window.Lanalytics.Plugins or= {};
119
+
120
+ $ ->
121
+ for pluginClassName in Object.keys(Lanalytics.Plugins)
122
+ try
123
+ plugin = Lanalytics.Plugins[pluginClassName].newInstance(lanalytics)
124
+ lanalytics.addPlugin(plugin)
125
+ console.log("Lanalytics.Plugins.#{pluginClassName} found, created and added") if (DEBUG)
126
+ catch error
127
+ console.log("Lanalytics.Plugins.#{pluginClassName} found, but could not be instantiated") if (DEBUG)
128
+ console.log(error.stack) if (DEBUG)
@@ -0,0 +1,41 @@
1
+ window.Lanalytics or= {};
2
+ window.Lanalytics.Model or= {};
3
+
4
+ class window.Lanalytics.Model.ExpApiStatement
5
+
6
+ constructor: (user, verb, resource, timestamp = new Date(), @with_result = {}, @in_context = {}) ->
7
+ # ::TODO Some assertions to ensure the datamodel
8
+ throw "'user' argument cannot be nil and should be Lanalytics::Model::StmtUser" unless user instanceof Lanalytics.Model.StmtUser
9
+ @user = user
10
+
11
+ throw "'verb' argument cannot be nil and should be Lanalytics::Model::StmtVerb" unless verb instanceof Lanalytics.Model.StmtVerb
12
+ @verb = verb
13
+
14
+ throw "'resource' argument cannot be nil and should be Lanalytics::Model::StmtResource" unless resource instanceof Lanalytics.Model.StmtResource
15
+ @resource = resource
16
+
17
+ timestamp ||= DateTime.now
18
+ throw "'timestamp' argument should be DateTime or String" unless timestamp instanceof Date or timestamp instanceof String
19
+ timestamp = new Date(timestamp) if timestamp instanceof String
20
+ @timestamp = timestamp
21
+
22
+
23
+ # This is the serialization
24
+ serialize: ->
25
+ return JSON.stringify(@params)
26
+
27
+ params: ->
28
+ return {
29
+ user: @user.params(),
30
+ verb: @verb.params(),
31
+ resource: @resource.params(),
32
+ timestamp: @timestamp,
33
+ with_result: @with_result,
34
+ in_context: @in_context
35
+ }
36
+
37
+
38
+
39
+
40
+
41
+
@@ -0,0 +1,8 @@
1
+ window.Lanalytics or= {};
2
+ window.Lanalytics.Model or= {};
3
+
4
+ class window.Lanalytics.Model.StmtComponent
5
+
6
+ constructor: (type) ->
7
+ throw "'type' argument cannot be nil and or empty" if !type? || !type.trim().length
8
+ @type = type.toString()
@@ -0,0 +1,16 @@
1
+ window.Lanalytics or= {};
2
+ window.Lanalytics.Model or= {};
3
+
4
+ class window.Lanalytics.Model.StmtResource extends Lanalytics.Model.StmtComponent
5
+
6
+ constructor: (type, uuid) ->
7
+ super(type)
8
+
9
+ throw "'uuid' argument cannot be nil or empty" if !uuid? || !uuid.trim().length
10
+ @uuid = uuid.toString()
11
+
12
+ params: ->
13
+ return {
14
+ type: @type,
15
+ uuid: @uuid
16
+ }
@@ -0,0 +1,14 @@
1
+ window.Lanalytics or= {};
2
+ window.Lanalytics.Model or= {};
3
+
4
+ class window.Lanalytics.Model.StmtUser extends window.Lanalytics.Model.StmtResource
5
+
6
+ constructor: (uuid) ->
7
+ super("User", uuid)
8
+
9
+
10
+
11
+ class window.Lanalytics.Model.AnonymousUser extends window.Lanalytics.Model.StmtUser
12
+
13
+ constructor: ->
14
+ super("User", "ANONYMOUS")
@@ -0,0 +1,12 @@
1
+ window.Lanalytics or= {};
2
+ window.Lanalytics.Model or= {};
3
+
4
+ class window.Lanalytics.Model.StmtVerb extends window.Lanalytics.Model.StmtComponent
5
+
6
+ constructor: (type) ->
7
+ super(type)
8
+
9
+ params: ->
10
+ return {
11
+ type: @type,
12
+ }
@@ -0,0 +1,25 @@
1
+ # This plugin was created for the xikolo-web application in order to track the events from the (custom) video player
2
+ # This is exactly the situation for which a olugin is designed for ...
3
+ class window.Lanalytics.Plugins.Html5VideoPlayerTracker extends Lanalytics.Plugin
4
+
5
+ # This is the interface method expected by Lanalytics
6
+ # Should return a valid instance of the plugin
7
+ @newInstance: (lanalytics) ->
8
+ return new Lanalytics.Plugins.Html5VideoPlayerTracker(lanalytics)
9
+
10
+ constructor: (lanalytics) ->
11
+ super(lanalytics)
12
+ this._init()
13
+
14
+ _init: ->
15
+ $(document).on("video-play", @trackVideoPlay)
16
+ $(document).on("video-pause", @trackVideoPause)
17
+
18
+ # It is important to use '=>' because then 'this' will be binded to StaticHtmlEventTracker instance (in order to access lanalytics)
19
+ trackVideoPlay: (event, videoPlayerData) =>
20
+ stmtResource = new Lanalytics.Model.StmtResource("Item", videoPlayerData.resource)
21
+ @lanalytics.track("video-play", stmtResource)
22
+
23
+ trackVideoPause: (event, videoPlayerData) =>
24
+ stmtResource = new Lanalytics.Model.StmtResource("Item", videoPlayerData.resource)
25
+ @lanalytics.trackCurrentUserDoing("video-pause", stmtResource)
@@ -0,0 +1,23 @@
1
+
2
+ class window.Lanalytics.Plugins.NewLanalyticsPlugin extends Lanalytics.Plugin
3
+
4
+ # This is the interface method expected by Lanalytics
5
+ # Should return a valid instance of the plugin
6
+ @newInstance: (lanalytics) ->
7
+ return new Lanalytics.Plugins.NewLanalyticsPlugin(lanalytics)
8
+
9
+ constructor: (lanalytics) ->
10
+ super(lanalytics)
11
+ this._init()
12
+
13
+ _init: ->
14
+ # Do something
15
+ # Register to some events in the DOM, e.g. $(document).on("video-play", @trackVideoPlay)
16
+ $(document).on("video-pause", @trackVideoPause)
17
+
18
+ # Handler for the event in the DOM
19
+ # It is important to use '=>' because then 'this' will be binded to NewLanalyticsPlugin instance (in order to access lanalytics)
20
+ # trackVideoPlay: (event, videoPlayerData) =>
21
+ # @lanalytics.trackCurrentUserDoing("video-play", {
22
+ # resource_id: videoPlayerData.resource
23
+ # })
@@ -0,0 +1,42 @@
1
+
2
+ class window.Lanalytics.Plugins.PageViewPlugin extends Lanalytics.Plugin
3
+
4
+ # This is the interface method expected by Lanalytics
5
+ # Should return a valid instance of the plugin
6
+ @newInstance: (lanalytics) ->
7
+ return new Lanalytics.Plugins.PageViewPlugin(lanalytics)
8
+
9
+ constructor: (lanalytics) ->
10
+ super(lanalytics)
11
+ this._init()
12
+ @windowLoadTimestamp = undefined
13
+
14
+ _init: ->
15
+ $(window).load(@enterPage);
16
+
17
+ # $(window).unload(@leavePage);
18
+
19
+ enterPage: (event, data) =>
20
+ @windowLoadTimestamp = @currentTime()
21
+
22
+ # Do nothing if there is no user logged in
23
+ return if @lanalytics.currentUser() instanceof Lanalytics.Model.AnonymousUser
24
+
25
+ inContext =
26
+ user_os: navigator?.platform
27
+ user_agent: navigator?.userAgent
28
+ user_app_version: navigator?.appVersion
29
+
30
+ urlPathLocation = window?.location?.pathname
31
+ stmtResource = new Lanalytics.Model.StmtResource("PAGE", urlPathLocation)
32
+ @lanalytics.trackCurrentUserDoing("viewed_page", stmtResource, {}, inContext)
33
+
34
+
35
+ # leavePage: (event, videoPlayerData) =>
36
+ # @windowLoadTimestamp
37
+ # timeOnPage = @currentTime() - @windowLoadTimestamp
38
+ # console.log(data)
39
+ # @lanalytics.trackCurrentUserDoing("observed", stmtResource)
40
+
41
+ currentTime: ->
42
+ return new Date().getTime()
@@ -0,0 +1,31 @@
1
+
2
+
3
+ class window.Lanalytics.Plugins.StaticHtmlEventTracker extends Lanalytics.Plugin
4
+
5
+ # This is the interface method expected by Lanalytics
6
+ # Should return a valid instance of the plugin
7
+ @newInstance: (lanalytics) ->
8
+ return new Lanalytics.Plugins.StaticHtmlEventTracker(lanalytics)
9
+
10
+ constructor: (lanalytics) ->
11
+ super(lanalytics)
12
+ this._init()
13
+
14
+ _init: ->
15
+ $("*[data-lanalytics-event]").on("click", @processStaticHtmlEvent)
16
+
17
+ # It is important to use '=>' because then 'this' will be binded to StaticHtmlEventTracker instance (in order to access lanalytics)
18
+ processStaticHtmlEvent: (event) =>
19
+
20
+ clickedElement = event.target
21
+ lanalyticsParentsOfElement = $(clickedElement).parents("[data-lanalytics-resource]")
22
+ if lanalyticsParentsOfElement.length == 0
23
+ throw "No 'data-lanalytics-resource' field could be found in the parents of #{$(clickedElement).html().trim()}."
24
+
25
+ eventData = $(clickedElement).data("lanalytics-event")
26
+ stmtVerb = new Lanalytics.Model.StmtVerb(eventData['verb'])
27
+
28
+ eventResourceData = lanalyticsParentsOfElement.first().data("lanalytics-resource");
29
+ stmtResource = new Lanalytics.Model.StmtResource(eventResourceData['type'], eventResourceData['uuid'])
30
+
31
+ @lanalytics.trackCurrentUserDoing(stmtVerb, stmtResource)