vj-sdk 0.2.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  log/*
2
2
  core-fixtures.yml
3
3
  pkg/*
4
- .DS_Store
4
+ .DS_Store
5
+ *.tmproj
data/README.markdown CHANGED
@@ -0,0 +1,105 @@
1
+ Videojuicer Core SDK
2
+ ====================
3
+
4
+ The Videojuicer Core SDK is a library for conveniently working with the [Videojuicer](http://videojuicer.com) Core API service.
5
+
6
+ Drop-in Rails/Merb compatibility
7
+ --------------------------------
8
+
9
+ The models in this SDK present a familiar ORM-style interface onto all the objects in the remote API. Users of ActiveRecord or DataMapper should feel right at home:
10
+
11
+ presentation = Videojuicer::Presentation.new(:title=>"Hello World")
12
+ presentation.valid? #=> true
13
+ presentation.save #=> true
14
+
15
+ Validations, creation, updates and deleting records all behave as you'd expect from these libraries.
16
+
17
+ Getting started
18
+ ===============
19
+
20
+ Getting started is easy. First off, you'll need to be a Videojuicer customer with access to a Videojuicer Seed. You'll also need to [register for a consumer key](http://api.videojuicer.com/oauth/consumers).
21
+
22
+ The Core API uses [OAuth](http://oauth.net) as a security and authorisation mechanism, and the SDK acts as an OAuth client.
23
+
24
+ To get started you will need:
25
+
26
+ * Your seed name
27
+ * Your username and password
28
+ * Your consumer key
29
+ * Your consumer secret
30
+
31
+ Authorizing the SDK to work with your account
32
+ ---------------------------------------------
33
+
34
+ require 'rubygems'
35
+ require 'videojuicer'
36
+
37
+ #
38
+ @seed_name = your_seed_name
39
+ @consumer_key = your_consumer_key
40
+ @consumer_secret = your_consumer_secret
41
+ #
42
+ # ----------------------
43
+ # OAuth Stage 1
44
+ # ----------------------
45
+ #
46
+ # Create a VJ Session
47
+ @api_session = Videojuicer::Session.new(
48
+ :seed_name=>@seed_name,
49
+ :consumer_key=>@consumer_key,
50
+ :consumer_secret=>@consumer_secret
51
+ )
52
+ # Get the OAuth Request token
53
+ @request_token = @api_session.get_request_token
54
+ # Get the authorization URL for your token
55
+ @auth_url = @api_session.authorize_url(
56
+ "oauth_token" => @request_token["oauth_token"],
57
+ "oauth_token_secret" => @request_token["oauth_token_secret"],
58
+ "oauth_callback" => a_url_where_to_which_you_want_the_user_directed_after_authorization
59
+ )
60
+ #
61
+ # ----------------------
62
+ # OAuth Stage 2
63
+ # Direct the user to the @auth_url - they will be asked for their username and password.
64
+ # ----------------------
65
+ #
66
+ # ----------------------
67
+ # OAuth Stage 3
68
+ # Exchange the Request token for an Access token
69
+ # ----------------------
70
+ #
71
+ @access_token = @api_session.exchange_request_token(
72
+ "oauth_token" => @request_token["oauth_token"],
73
+ "oauth_token_secret" => @request_token["oauth_token_secret"]
74
+ )
75
+ #
76
+ # ----------------------
77
+ # Authorization complete
78
+ # Store the access token for later use
79
+ # ----------------------
80
+
81
+ Working with the authorized access token
82
+ ----------------------------------------
83
+
84
+ @api_session = Videojuicer::Session.new(
85
+ :seed_name=>@seed_name,
86
+ :consumer_key=>@consumer_key,
87
+ :consumer_secret=>@consumer_secret,
88
+ :token=>@access_token["oauth_token"],
89
+ :token_secret=>@access_token["oauth_token_secret"]
90
+ )
91
+ # The session is now properly configured and authorized. You can just work within it like so:
92
+ @api_session.scope do
93
+ Videojuicer::User.all #=> [<Videojuicer::User ................. >]
94
+ end
95
+
96
+ You may also do one-off setup of the SDK as follows:
97
+
98
+ Videojuicer.configure!(
99
+ :seed_name=>@seed_name,
100
+ :consumer_key=>@consumer_key,
101
+ :consumer_secret=>@consumer_secret,
102
+ :token=>@access_token["oauth_token"],
103
+ :token_secret=>@access_token["oauth_token_secret"]
104
+ )
105
+ Videojuicer::User.all #=> [<Videojuicer::User ................. >]
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
+ :minor: 4
3
+ :patch: 0
2
4
  :major: 0
3
- :minor: 2
4
- :patch: 1
data/lib/videojuicer.rb CHANGED
@@ -29,11 +29,13 @@ require 'videojuicer/resource/property_registry'
29
29
  require 'videojuicer/resource/base'
30
30
  require 'videojuicer/session'
31
31
  # Frontend models
32
+ require 'videojuicer/seed'
32
33
  require 'videojuicer/user'
33
34
  require 'videojuicer/campaign'
34
35
  require 'videojuicer/campaign_policy'
35
36
  require 'videojuicer/presentation'
36
37
  require 'videojuicer/asset/audio'
38
+ require 'videojuicer/asset/document'
37
39
  require 'videojuicer/asset/flash'
38
40
  require 'videojuicer/asset/image'
39
41
  require 'videojuicer/asset/text'
@@ -31,6 +31,7 @@ module Videojuicer
31
31
 
32
32
  # - access control / workflow
33
33
  base.property :url, String, :writer => :private
34
+ base.property :http_url, String, :writer => :private
34
35
  base.property :state, String, :writer => :private
35
36
  base.property :state_changed_at, DateTime, :writer => :private
36
37
  base.property :state_changed_url, String
@@ -0,0 +1,8 @@
1
+ require File.join(File.dirname(__FILE__), "base")
2
+
3
+ module Videojuicer
4
+ module Asset
5
+ class Document < Base
6
+ end
7
+ end
8
+ end
@@ -191,7 +191,7 @@ module Videojuicer
191
191
  # with the proxy configuration to produce a set of parameters that will be accepted
192
192
  # by the OAuth provider.
193
193
  def authify_params(method, path, params)
194
- params = {
194
+ defaults = {
195
195
  :oauth_consumer_key=>consumer_key,
196
196
  :oauth_token=>token,
197
197
  :api_version=>api_version,
@@ -200,8 +200,9 @@ module Videojuicer
200
200
  :oauth_signature_method=>"HMAC-SHA1",
201
201
  :seed_name=>seed_name,
202
202
  :user_id=>user_id
203
- }.merge(params)
204
- params.delete_if {|k,v| (!v) or (v.to_s.empty?) }
203
+ }
204
+ defaults.delete_if {|k,v| (!v) or (v.to_s.empty?) }
205
+ params = defaults.merge(params)
205
206
  params[:oauth_signature] = signature(method, path, params)
206
207
  return params
207
208
  end
@@ -48,7 +48,7 @@ module Videojuicer
48
48
  end
49
49
 
50
50
  # Parse and handle response
51
- return validate_response(response)
51
+ return validate_committed_response(response)
52
52
  end
53
53
 
54
54
  # Attempts to validate this object with the remote service. Returns TRUE on success,
@@ -74,6 +74,13 @@ module Videojuicer
74
74
  def errors; @errors ||= Videojuicer::Resource::Errors.new({}); end
75
75
  def errors_on(key); errors.on(key); end
76
76
 
77
+ # Takes a *change-making* response from the API and cleans the dirty attributes if it was successful.
78
+ def validate_committed_response(response)
79
+ result = validate_response(response)
80
+ clean_dirty_attributes! if result
81
+ return result
82
+ end
83
+
77
84
  # Takes a response from the API and performs the appropriate actions.
78
85
  def validate_response(response)
79
86
  body = response.body
@@ -104,7 +111,7 @@ module Videojuicer
104
111
  def reload
105
112
  raise NoResource, "Cannot load remote attributes for new records" if new_record?
106
113
  response = proxy_for(config).get(resource_path(nil, :nested=>false))
107
- return validate_response(response)
114
+ return validate_committed_response(response)
108
115
  end
109
116
 
110
117
  # Attempts to delete this record. Will raise an exception if the record is new
@@ -134,6 +141,7 @@ module Videojuicer
134
141
  # Instantiate objects
135
142
  items = items.collect do |attrs|
136
143
  o = new; o.attributes = attrs
144
+ o.clean_dirty_attributes!
137
145
  o
138
146
  end
139
147
  return (op.is_a?(Hash))? Videojuicer::Resource::Collection.new(items, op["count"], op["offset"], op["limit"]) : items
@@ -31,10 +31,9 @@ module Videojuicer
31
31
  v = "@attributes"
32
32
  subclass.instance_variable_set(v, instance_variable_get(v))
33
33
  end
34
-
35
34
 
36
35
  def initialize(attrs={})
37
- self.attributes = default_attributes
36
+ set_default_attributes
38
37
  self.attributes = attrs
39
38
  end
40
39
 
@@ -50,14 +49,63 @@ module Videojuicer
50
49
  end
51
50
  end
52
51
 
52
+ # Sets the attributes to their default values, marking only those values with defaults as being dirty.
53
+ def set_default_attributes
54
+ self.attributes = default_attributes
55
+ self.attributes.each do |key, value|
56
+ # Scrub the attributes if there's no value
57
+ attr_clean!(key) unless value
58
+ end
59
+ end
60
+
53
61
  def default_attributes
54
62
  d = {}
55
63
  self.class.attributes.each do |key, props|
56
- d[key] = props[:default] || nil
64
+ d[key] = props[:default] || nil
57
65
  end
58
66
  return d
59
67
  end
60
68
 
69
+ # Returns the hash of currently-dirty attributes complete with values
70
+ def dirty_attributes
71
+ o = {}
72
+ @dirty_attribute_keys ||= []
73
+ @dirty_attribute_keys.each do |key|
74
+ o[key] = attr_get(key)
75
+ end
76
+ o
77
+ end
78
+
79
+ # Clears the array of dirty attribute keys
80
+ def clean_dirty_attributes!
81
+ @dirty_attribute_keys = []
82
+ end
83
+
84
+ # Returns an array of keys for attributes that are currently dirty
85
+ def dirty_attribute_keys
86
+ @dirty_attribute_keys ||= []
87
+ @dirty_attribute_keys
88
+ end
89
+
90
+ # Returns true if the specified attribute is currently dirty
91
+ def attr_dirty?(key)
92
+ @dirty_attribute_keys ||= []
93
+ @dirty_attribute_keys.include?(key.to_sym)
94
+ end
95
+
96
+ # Mark the specified attribute as dirty.
97
+ def attr_dirty!(key)
98
+ @dirty_attribute_keys ||= []
99
+ @dirty_attribute_keys << key.to_sym
100
+ @dirty_attribute_keys.uniq!
101
+ end
102
+
103
+ # Mark the specified attribute as no longer being dirty.
104
+ def attr_clean!(key)
105
+ @dirty_attribute_keys ||= []
106
+ @dirty_attribute_keys.delete_if {|k| k == key.to_sym }
107
+ end
108
+
61
109
  def attr_get(key)
62
110
  key = key.to_sym
63
111
  attributes[key]
@@ -65,6 +113,7 @@ module Videojuicer
65
113
 
66
114
  def attr_set(key, value)
67
115
  key = key.to_sym
116
+ attr_dirty!(key)
68
117
  attributes[key] = coerce_value(key, value)
69
118
  end
70
119
 
@@ -103,7 +152,7 @@ module Videojuicer
103
152
  # Returns a hash of the attributes for this object, minus the
104
153
  # private attributes that should not be included in the response.
105
154
  def returnable_attributes
106
- attrs = attributes.dup
155
+ attrs = dirty_attributes.dup
107
156
  self.class.attributes.select {|name, props| props[:writer] != :public}.each do |name, props|
108
157
  attrs.delete name
109
158
  end
@@ -0,0 +1,19 @@
1
+ module Videojuicer
2
+ class Seed
3
+ include Videojuicer::Resource
4
+ include Videojuicer::Exceptions
5
+
6
+ property :name, String
7
+ property :provider_name, String
8
+ property :provider_url, String
9
+ property :google_analytics_id, String
10
+
11
+ # Returns the currently-configured seed
12
+ def self.current
13
+ proxy = Videojuicer::OAuth::RequestProxy.new
14
+ jobj = JSON.parse(proxy.get("/seeds/current.json").body)
15
+ new(jobj)
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ require File.join(File.dirname(__FILE__), "..", "helpers", "spec_helper")
2
+
3
+ describe Videojuicer::Asset::Document do
4
+
5
+ before(:all) do
6
+ @klass = Videojuicer::Asset::Document
7
+ configure_test_settings
8
+ end
9
+
10
+ describe "instantiation" do
11
+ it_should_behave_like "a configurable"
12
+ end
13
+
14
+ describe "general interface:" do
15
+ before(:all) do
16
+ @singular_name = "asset"
17
+ @plural_name = "assets/document"
18
+ end
19
+
20
+ it_should_behave_like "a RESTFUL resource model"
21
+ end
22
+
23
+ it_should_behave_like "an asset"
24
+ end
@@ -0,0 +1,311 @@
1
+ /*
2
+ Videojuicer Management Panel Core JS
3
+ This file contains the standard presentational and interactive JS for the Management Panel.
4
+
5
+ Dependencies: jQuery 1.3, jQuery Easing
6
+ */
7
+
8
+ // Document Boot
9
+ // ==============================================================================
10
+
11
+ $(document).ready(function() {
12
+
13
+ // Cosmetic - Add .has-js to the <body> so that Markup can be styled for when the user has or doesnt have JS
14
+ $("body").addClass("has-js");
15
+
16
+ // Cosmetic - Add the correct wrapper to links that require it.
17
+ $(".btn, nav > a").wrapInner("<span></span>").append("<i></i>");
18
+
19
+ // Cosmetic - Move the tooltip class to the parent element for wrapping DL items.
20
+ $(".tool-tip-container").closest("dd").addClass("has-msg");
21
+ // Cosmetic - If the fields within a DT/DD pair are in an error state, pass the error class
22
+ // around to stabilise the display.
23
+ $(".error:input").closest("dd").addClass("has-error");
24
+
25
+ // Interactivity - Allow tooltip icons to toggle the display of the element they reference.
26
+ $(".tool-tip-icon").click(function() {
27
+ $this = $(this);
28
+ t = $($this.attr("href"));
29
+
30
+ if($this.hasClass('active')) {
31
+ t.fadeOut('fast');
32
+ $this.removeClass('active');
33
+ } else {
34
+ remove_all_tooltips();
35
+ $this.addClass('active');
36
+ t.fadeIn('fast');
37
+ };
38
+ return false;
39
+ })
40
+
41
+ // Cosmetic - add wrapper elements to help boxes that don't have them.
42
+ $("div.help:not(div:has(.help-content))").wrapInner("<div class=\"help-content\"></div>");
43
+ $("div.help:not(div:has(.help-top))").prepend('<span class="help-top"><span class="help-R"></span></span>');
44
+ $("div.help:not(div:has(.help-bottom))").append('<span class="help-bottom"><span class="help-R"></span></span>');
45
+
46
+ // Interactivity - Register selection event on all select-all checkboxes. These
47
+ // checkboxes will toggle all other checkboxes within the same fieldset as themselves.
48
+ $("input.select-all").bind("change", function() {
49
+ $this = $(this);
50
+ checked = $this.is(":checked");
51
+ $("input", $this.closest("fieldset")).each(function() {
52
+ this.checked = checked;
53
+ });
54
+ });
55
+
56
+ // Interactivity - Confirmation dialogues get appended to destructive links.
57
+ $(".dangerous").click(function(event) {
58
+ code = (new String(Math.random())).substr(2,4);
59
+ msg = "This action cannot be undone. Please enter the code "+code+" to confirm your decision, or press 'Cancel' if you do not wish to continue.";
60
+ return (prompt(msg)==code);
61
+ });
62
+ $(".destructive").click(function(event) {
63
+ msg = $(this).attr("data-confirmation-msg") || "This action cannot be undone. Please confirm that you wish to continue.";
64
+ return confirm(msg);
65
+ });
66
+
67
+ // Interactivity - The markup contains nested lists that act like dropdown menus.
68
+ // This makes them work good. The interactivity causes the click on the root
69
+ // link to pop the menu open, and a click on either the button or one of the nested
70
+ // links to close it again.
71
+ $(".btn-select-parent a").bind("click", function() {
72
+ $this = $(this);
73
+ $this.closest(".btn-select-parent").toggleClass("open");
74
+ $this.closest(".btn-select-parent").toggleClass("closed");
75
+ return false;
76
+ })
77
+
78
+ // Interactivity - Make active all nav-tab arrays.
79
+ $("ul.nav-tabbed a").make_nav_tab();
80
+ $("ul.nav-tabbed a:first").activate_nav_tab();
81
+
82
+
83
+ // Interactivity - Hide All Tooltips whenever an input, textarea or select focuses
84
+ $('textarea, input, select').focus(function() {
85
+ remove_all_tooltips();
86
+ });
87
+
88
+ // Interactivity - Expandable fieldsets
89
+ $('fieldset.expandable legend a').click(function() {
90
+ $a = $(this);
91
+ $a.closest("fieldset").toggleClass("open");
92
+ $a.closest("fieldset").toggleClass("closed");
93
+ });
94
+
95
+ // Interactivity - Any link with .dismisser as the class will hide the element it
96
+ // references in the href attribute.
97
+ $("a.dismisser").click(function() {
98
+ $($(this).attr("href")).fadeOut("slow");
99
+ return false;
100
+ });
101
+
102
+ // Make necessary corrections for IE
103
+ // Buttons need inline syles applied to the span and i elements to make them appear correctly
104
+ if($.browser.msie) {
105
+ style_buttons_for_ie();
106
+
107
+ } else {
108
+ // Do Nothing!
109
+ }
110
+ });
111
+
112
+ // Tiny Extensions to jQuery (major extensions should get their own files)
113
+ // ==============================================================================
114
+
115
+ // Used on a link within a nav-tab controller bar to give it all the right interactivity.
116
+ $.fn.make_nav_tab = function(options) {
117
+ return this.each(function() { $link = $(this);
118
+ $link.click(function() {
119
+ $(this).activate_nav_tab();
120
+ return false;
121
+ })
122
+ });
123
+ }
124
+ // Used on a tab bar nav-tab to activate it and display the content it relates to.
125
+ $.fn.activate_nav_tab = function(options) {
126
+ return this.each(function() { $link = $(this); $ul = $link.closest("ul"); $li = $link.closest("li");
127
+ // Mark all containing LIs in the controller as inactive
128
+ $("li", $ul).removeClass("active");
129
+ // Mark this link's containing LI as active
130
+ $li.addClass("active");
131
+ // Hide all content blocks owned by this controller block
132
+ $(".tabbed-content[data-group="+$ul.attr("data-controls")+"]").collapse();
133
+ // Show the specific content block we're activating
134
+ $($link.attr("href")).expand();
135
+ });
136
+ }
137
+
138
+ // Animate the closing of all matched elements.
139
+ // Used to keep animation settings consistent.
140
+ $.fn.collapse = function(options) {
141
+ this.slideUp(250, 'easeOutQuad');
142
+ }
143
+ // Animate the opening of all matched elements.
144
+ // Used to keep animation settings consistent.
145
+ $.fn.expand = function(options) {
146
+ this.slideDown(250, 'easeOutQuad');
147
+ }
148
+
149
+
150
+ // Tabbed Navigation
151
+ // FOR: Switching between different tabs on the page
152
+ // ==============================================================================
153
+
154
+ function TabbedNavigation(num_tabs, tab_handle, content_handle, classname, default_tab) {
155
+
156
+ this.num_tabs = num_tabs; // -> number of tabs on page
157
+ this.tab_handle = tab_handle; // -> name of tab IDs minus number (e.g. "tab1" would be "tab")
158
+ this.content_handle = content_handle; // -> name of content box IDs minus number (e.g. "content1" would be "content")
159
+ this.classname = classname; // -> css class to be applied to open tab
160
+ this.default_tab = default_tab; // -> which tab is open by default
161
+
162
+ TabbedNavigation.prototype.hide_all_content_boxes_except = function(num, fade) {
163
+ var css = { display:'none'}
164
+ for(i = 1; i <= this.num_tabs; i++) {
165
+ $(this.content_handle + i).css(css);
166
+ }
167
+ if(!fade) {
168
+ var css = { display:'block'}
169
+ $(this.content_handle + num).css(css);
170
+ } else {
171
+ $(this.content_handle + num).fadeIn(750);
172
+ }
173
+ }
174
+
175
+ TabbedNavigation.prototype.set_current_tab_to = function(num) {
176
+ for(i = 1; i <= this.num_tabs; i++) {
177
+ $(this.tab_handle + i).removeClass(this.classname);
178
+ }
179
+ $(this.tab_handle + num).addClass(this.classname);
180
+ }
181
+
182
+ TabbedNavigation.prototype.set_tab_to = function(num) {
183
+ this.set_current_tab_to(num);
184
+ this.hide_all_content_boxes_except(num);
185
+ }
186
+
187
+ this.set_tab_to(this.default_tab);
188
+ }
189
+
190
+ // Tooltips
191
+ // FOR: Showing & Hiding the relevant tooltips when the user clicks tooltip icon
192
+
193
+ function remove_all_tooltips() {
194
+ $('.tool-tip-msg').fadeOut('fast');
195
+ $('.tool-tip-icon').removeClass('active');
196
+ };
197
+
198
+ // Expandable Fieldset
199
+ // FOR: Allowing the user to expand or contract a fieldset
200
+ function close_expandable_fieldsets() {
201
+ $('fieldset.expandable').addClass('closed');
202
+ };
203
+
204
+ function trigger_fieldset(id) {
205
+ if(id) {
206
+ var fieldset = id + '-parent'
207
+ if ($(fieldset).hasClass('closed')) {
208
+ close_expandable_fieldsets();
209
+ $(fieldset).removeClass('closed').addClass('open');
210
+ } else {
211
+ close_expandable_fieldsets();
212
+ };
213
+ };
214
+ };
215
+
216
+ // Submit forms
217
+ // FOR: Fake Submitting forms
218
+ /*
219
+ function submit_form(id, submitted_by) {
220
+ var frm = document.forms[id];
221
+
222
+ // If we passed a submitted_by array then add the elements to the form
223
+ if (submitted_by !== undefined) {
224
+
225
+ for(var key in submitted_by){
226
+ ff = document.createElement("INPUT");
227
+ ff.type = "hidden";
228
+ ff.name = key;
229
+ ff.value = submitted_by[key];
230
+ frm.appendChild(ff);
231
+ }
232
+
233
+ // Make the form revalidate so that the new values are passed
234
+ if (frm.normalize) {frm.normalize();}
235
+ }
236
+
237
+ frm.submit();
238
+ return false;
239
+ }
240
+
241
+ function reset_form(id) {
242
+ document.forms[id].reset();
243
+ return false;
244
+ }
245
+ */
246
+
247
+ // Convert Buttons
248
+ // FOR: Convert button.btn to a.btn in ie6
249
+
250
+
251
+
252
+ function highlight_links(id) {
253
+
254
+ $('tr').removeClass('highlight');
255
+ for(var i = 0; i<id.length; i++) {
256
+ //alert(id[i]);
257
+ $(id[i]).addClass('highlight');
258
+ };
259
+ };
260
+
261
+ var verbose_output = (document.location.toString().indexOf(".dev") > 0);
262
+ function trace(text) {
263
+ if (verbose_output && window.console != null) console.log(text);
264
+ }
265
+
266
+
267
+ // Style Buttons in ie
268
+ // FOR: adding inline styles to buttons to make them work in IE 6 + 7 (but not 8, ie8 is fine)
269
+
270
+ function style_buttons_for_ie() {
271
+
272
+ $('button.btn').each(function() {
273
+
274
+ // i X Positioning
275
+ var spanW = $(this).children('span').width();
276
+ var iW = $(this).children('i').width();
277
+ var XPos = spanW+iW;
278
+ var XPosNum = '-' + XPos + 'px';
279
+
280
+
281
+ // i Y Positioning
282
+ var iH = $(this).children('i').height();
283
+ var iYPos = '-' + iH + 'px'
284
+
285
+ // Button Width
286
+ var bW = spanW+iW + 'px'
287
+
288
+ if (Object.prototype.toString.call(self.JSON) === "[object JSON]"){
289
+ // IE8: Dont fix anything
290
+ }
291
+
292
+ else if (typeof document.body.style.maxHeight === "undefined") {
293
+ // ie6: Add inline styles
294
+ $(this).each(function() {
295
+ $(this).children('i').css({'position' : 'relative', 'right' : XPosNum, 'top' : iYPos});
296
+ $(this).css({'height' : iH, 'width' : bW, 'overflow' : 'hidden'});
297
+ })
298
+
299
+ } else {
300
+ // ie7 (same fix as ie6 fix)
301
+
302
+ $(this).each(function() {
303
+ $(this).children('i').css({'position' : 'relative', 'right' : XPosNum, 'top' : iYPos});
304
+ $(this).css({'height' : iH, 'width' : bW, 'overflow' : 'hidden'})
305
+ })
306
+
307
+ }
308
+
309
+ });
310
+
311
+ };
@@ -199,6 +199,19 @@ module Videojuicer
199
199
  }}
200
200
  end
201
201
 
202
+ class Asset::Document
203
+ include FixtureHelper
204
+ set_attribute_proc {{
205
+ :user_id => rand(100) + 1,
206
+ :licensed_at => Time.now,
207
+ :licensed_by => "foo, bar",
208
+ :licensed_under => "CC BY:NC:SA",
209
+ :published_at => Time.now,
210
+ :file => File.open(File.join(File.dirname(__FILE__), "..", "files", "document.js"))
211
+ }}
212
+ end
213
+
214
+
202
215
  class Asset::Video
203
216
  include FixtureHelper
204
217
  set_attribute_proc {{
@@ -76,6 +76,28 @@ describe Videojuicer::Resource::PropertyRegistry do
76
76
  @example_registry.attr_set :string, "987654321"
77
77
  @example_registry.attr_get(:string).should == "987654321"
78
78
  end
79
+
80
+ it "registers an attribute as being dirty when the attribute is set" do
81
+ @r = ::FooAttributeRegistry.new
82
+ @r.attr_set :string, "987654321"
83
+ @r.attr_dirty?(:string).should be_true
84
+ @r.attr_dirty?(:integer).should be_false
85
+ end
86
+
87
+ it "clears the dirty attributes when clean_dirty_attributes! is called" do
88
+ @r = ::FooAttributeRegistry.new
89
+ @r.attr_set :string, "987654321"
90
+ @r.attr_dirty?(:string).should be_true
91
+ @r.clean_dirty_attributes!
92
+ @r.attr_dirty?(:string).should be_false
93
+ end
94
+
95
+ it "provides the dirty attributes for submission as a hash" do
96
+ @r = ::FooAttributeRegistry.new
97
+ @r.integer = 0
98
+ @r.dirty_attribute_keys.should == [:string_with_default, :integer]
99
+ @r.dirty_attributes.should == {:string_with_default=>"this is the default", :integer=>0}
100
+ end
79
101
 
80
102
  it "converts attributes to a date when a string is passed into a datetime object" do
81
103
  @date_registry.date = "2009-07-01 13:14:15"
@@ -92,6 +114,8 @@ describe Videojuicer::Resource::PropertyRegistry do
92
114
  @example_private_prop_registry.returnable_attributes.should_not include(:id)
93
115
  end
94
116
  it "does not include the private attributes in the returnable attributes" do
117
+ @example_private_prop_registry.public_attr = "foo" # dirty the attributes
118
+ @example_private_prop_registry.private_attr = "bar"
95
119
  @example_private_prop_registry.returnable_attributes.should_not include(:private_attr)
96
120
  @example_private_prop_registry.returnable_attributes.should include(:public_attr)
97
121
  end
data/spec/seed_spec.rb ADDED
@@ -0,0 +1,21 @@
1
+ require File.join(File.dirname(__FILE__), "helpers", "spec_helper")
2
+
3
+ describe Videojuicer::Seed do
4
+
5
+ before(:all) do
6
+ @klass = Videojuicer::Seed
7
+ configure_test_settings
8
+ end
9
+
10
+ describe "instantiation" do
11
+ it_should_behave_like "a configurable"
12
+ end
13
+
14
+ describe "getting the current seed" do
15
+ it "should be successful" do
16
+ s = Videojuicer::Seed.current
17
+ s.name.should == Videojuicer.current_scope[:seed_name]
18
+ end
19
+ end
20
+
21
+ end
@@ -33,7 +33,10 @@ shared_examples_for "a RESTFUL resource model" do
33
33
  end
34
34
  it "gets an ID" do
35
35
  @successful.id.should be_kind_of(Integer)
36
- end
36
+ end
37
+ it "resets the dirty attributes" do
38
+ @successful.dirty_attributes.should be_empty
39
+ end
37
40
  end
38
41
  describe "unsuccessfully" do
39
42
  before(:all) do
@@ -58,6 +61,9 @@ shared_examples_for "a RESTFUL resource model" do
58
61
  it "does not get an ID" do
59
62
  @fail.id.should be_nil
60
63
  end
64
+ it "does not reset the dirty attributes" do
65
+ @fail.dirty_attributes.should_not be_empty
66
+ end
61
67
  end
62
68
  end
63
69
  end
@@ -75,6 +81,10 @@ shared_examples_for "a RESTFUL resource model" do
75
81
  attrs = attrs.reject {|k,v| !v}
76
82
  attrs.should_not be_empty
77
83
  end
84
+
85
+ it "has no dirty attributes" do
86
+ @record.dirty_attributes.should be_empty
87
+ end
78
88
  end
79
89
 
80
90
  describe "listing records" do
@@ -82,6 +92,12 @@ shared_examples_for "a RESTFUL resource model" do
82
92
  @list = @klass.all
83
93
  end
84
94
 
95
+ it "returns items with no dirty attributes" do
96
+ @list.each do |i|
97
+ i.dirty_attributes.should be_empty
98
+ end
99
+ end
100
+
85
101
  it "should return a collection object" do
86
102
  @list.should be_kind_of(Videojuicer::Resource::Collection)
87
103
  end
@@ -118,6 +134,16 @@ shared_examples_for "a RESTFUL resource model" do
118
134
  @record.reload.should be_true
119
135
  end
120
136
 
137
+ it "resets the dirty attributes when reloaded" do
138
+ r = @klass.gen
139
+ r = @klass.get(r.id)
140
+ dattr = @klass.attributes.select {|a,props| props[:class] == String || props[:class] == Integer }.map {|a| a.first }.first
141
+ r.send("#{dattr}=", 1)
142
+ r.attr_dirty?(dattr).should be_true
143
+ r.reload
144
+ r.attr_dirty?(dattr).should be_false
145
+ end
146
+
121
147
  it "saves successfully" do
122
148
  saved = @record.save
123
149
  @record.errors.should == {}
data/vj-sdk.gemspec CHANGED
@@ -5,22 +5,20 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{vj-sdk}
8
- s.version = "0.2.1"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["danski", "thejohnny", "knowtheory", "sixones", "btab"]
12
- s.date = %q{2009-10-30}
12
+ s.date = %q{2010-03-04}
13
13
  s.email = %q{dan@videojuicer.com}
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE",
16
- "README.markdown",
17
- "README.rdoc"
16
+ "README.markdown"
18
17
  ]
19
18
  s.files = [
20
19
  ".gitignore",
21
20
  "LICENSE",
22
21
  "README.markdown",
23
- "README.rdoc",
24
22
  "Rakefile",
25
23
  "VERSION.yml",
26
24
  "lib/core_ext/cgi.rb",
@@ -31,6 +29,7 @@ Gem::Specification.new do |s|
31
29
  "lib/videojuicer.rb",
32
30
  "lib/videojuicer/asset/audio.rb",
33
31
  "lib/videojuicer/asset/base.rb",
32
+ "lib/videojuicer/asset/document.rb",
34
33
  "lib/videojuicer/asset/flash.rb",
35
34
  "lib/videojuicer/asset/image.rb",
36
35
  "lib/videojuicer/asset/text.rb",
@@ -57,11 +56,13 @@ Gem::Specification.new do |s|
57
56
  "lib/videojuicer/resource/property_registry.rb",
58
57
  "lib/videojuicer/resource/relationships/belongs_to.rb",
59
58
  "lib/videojuicer/resource/types.rb",
59
+ "lib/videojuicer/seed.rb",
60
60
  "lib/videojuicer/session.rb",
61
61
  "lib/videojuicer/shared/configurable.rb",
62
62
  "lib/videojuicer/shared/exceptions.rb",
63
63
  "lib/videojuicer/user.rb",
64
64
  "spec/assets/audio_spec.rb",
65
+ "spec/assets/document_spec.rb",
65
66
  "spec/assets/flash_spec.rb",
66
67
  "spec/assets/image_spec.rb",
67
68
  "spec/assets/text_spec.rb",
@@ -76,6 +77,7 @@ Gem::Specification.new do |s|
76
77
  "spec/criterion/time_spec.rb",
77
78
  "spec/criterion/week_day_spec.rb",
78
79
  "spec/files/audio.mp3",
80
+ "spec/files/document.js",
79
81
  "spec/files/empty_file",
80
82
  "spec/files/flash.swf",
81
83
  "spec/files/image.jpg",
@@ -92,6 +94,7 @@ Gem::Specification.new do |s|
92
94
  "spec/promos/video_spec.rb",
93
95
  "spec/property_registry_spec.rb",
94
96
  "spec/request_proxy_spec.rb",
97
+ "spec/seed_spec.rb",
95
98
  "spec/session_spec.rb",
96
99
  "spec/shared/asset_spec.rb",
97
100
  "spec/shared/configurable_spec.rb",
@@ -108,10 +111,11 @@ Gem::Specification.new do |s|
108
111
  s.homepage = %q{http://github.com/danski/vj-sdk}
109
112
  s.rdoc_options = ["--charset=UTF-8"]
110
113
  s.require_paths = ["lib"]
111
- s.rubygems_version = %q{1.3.5}
114
+ s.rubygems_version = %q{1.3.6}
112
115
  s.summary = %q{Videojuicer core-sdk}
113
116
  s.test_files = [
114
117
  "spec/assets/audio_spec.rb",
118
+ "spec/assets/document_spec.rb",
115
119
  "spec/assets/flash_spec.rb",
116
120
  "spec/assets/image_spec.rb",
117
121
  "spec/assets/text_spec.rb",
@@ -136,6 +140,7 @@ Gem::Specification.new do |s|
136
140
  "spec/promos/video_spec.rb",
137
141
  "spec/property_registry_spec.rb",
138
142
  "spec/request_proxy_spec.rb",
143
+ "spec/seed_spec.rb",
139
144
  "spec/session_spec.rb",
140
145
  "spec/shared/asset_spec.rb",
141
146
  "spec/shared/configurable_spec.rb",
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vj-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 4
8
+ - 0
9
+ version: 0.4.0
5
10
  platform: ruby
6
11
  authors:
7
12
  - danski
@@ -13,39 +18,50 @@ autorequire:
13
18
  bindir: bin
14
19
  cert_chain: []
15
20
 
16
- date: 2009-10-30 00:00:00 +00:00
21
+ date: 2010-03-04 00:00:00 +00:00
17
22
  default_executable:
18
23
  dependencies:
19
24
  - !ruby/object:Gem::Dependency
20
25
  name: json
21
- type: :runtime
22
- version_requirement:
23
- version_requirements: !ruby/object:Gem::Requirement
26
+ prerelease: false
27
+ requirement: &id001 !ruby/object:Gem::Requirement
24
28
  requirements:
25
29
  - - ">="
26
30
  - !ruby/object:Gem::Version
31
+ segments:
32
+ - 1
33
+ - 0
27
34
  version: "1.0"
28
- version:
35
+ type: :runtime
36
+ version_requirements: *id001
29
37
  - !ruby/object:Gem::Dependency
30
38
  name: ruby-hmac
31
- type: :runtime
32
- version_requirement:
33
- version_requirements: !ruby/object:Gem::Requirement
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
34
41
  requirements:
35
42
  - - ">="
36
43
  - !ruby/object:Gem::Version
44
+ segments:
45
+ - 0
46
+ - 3
47
+ - 2
37
48
  version: 0.3.2
38
- version:
49
+ type: :runtime
50
+ version_requirements: *id002
39
51
  - !ruby/object:Gem::Dependency
40
52
  name: mash
41
- type: :runtime
42
- version_requirement:
43
- version_requirements: !ruby/object:Gem::Requirement
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
44
55
  requirements:
45
56
  - - ">="
46
57
  - !ruby/object:Gem::Version
58
+ segments:
59
+ - 0
60
+ - 0
61
+ - 3
47
62
  version: 0.0.3
48
- version:
63
+ type: :runtime
64
+ version_requirements: *id003
49
65
  description:
50
66
  email: dan@videojuicer.com
51
67
  executables: []
@@ -55,12 +71,10 @@ extensions: []
55
71
  extra_rdoc_files:
56
72
  - LICENSE
57
73
  - README.markdown
58
- - README.rdoc
59
74
  files:
60
75
  - .gitignore
61
76
  - LICENSE
62
77
  - README.markdown
63
- - README.rdoc
64
78
  - Rakefile
65
79
  - VERSION.yml
66
80
  - lib/core_ext/cgi.rb
@@ -71,6 +85,7 @@ files:
71
85
  - lib/videojuicer.rb
72
86
  - lib/videojuicer/asset/audio.rb
73
87
  - lib/videojuicer/asset/base.rb
88
+ - lib/videojuicer/asset/document.rb
74
89
  - lib/videojuicer/asset/flash.rb
75
90
  - lib/videojuicer/asset/image.rb
76
91
  - lib/videojuicer/asset/text.rb
@@ -97,11 +112,13 @@ files:
97
112
  - lib/videojuicer/resource/property_registry.rb
98
113
  - lib/videojuicer/resource/relationships/belongs_to.rb
99
114
  - lib/videojuicer/resource/types.rb
115
+ - lib/videojuicer/seed.rb
100
116
  - lib/videojuicer/session.rb
101
117
  - lib/videojuicer/shared/configurable.rb
102
118
  - lib/videojuicer/shared/exceptions.rb
103
119
  - lib/videojuicer/user.rb
104
120
  - spec/assets/audio_spec.rb
121
+ - spec/assets/document_spec.rb
105
122
  - spec/assets/flash_spec.rb
106
123
  - spec/assets/image_spec.rb
107
124
  - spec/assets/text_spec.rb
@@ -116,6 +133,7 @@ files:
116
133
  - spec/criterion/time_spec.rb
117
134
  - spec/criterion/week_day_spec.rb
118
135
  - spec/files/audio.mp3
136
+ - spec/files/document.js
119
137
  - spec/files/empty_file
120
138
  - spec/files/flash.swf
121
139
  - spec/files/image.jpg
@@ -132,6 +150,7 @@ files:
132
150
  - spec/promos/video_spec.rb
133
151
  - spec/property_registry_spec.rb
134
152
  - spec/request_proxy_spec.rb
153
+ - spec/seed_spec.rb
135
154
  - spec/session_spec.rb
136
155
  - spec/shared/asset_spec.rb
137
156
  - spec/shared/configurable_spec.rb
@@ -157,23 +176,26 @@ required_ruby_version: !ruby/object:Gem::Requirement
157
176
  requirements:
158
177
  - - ">="
159
178
  - !ruby/object:Gem::Version
179
+ segments:
180
+ - 0
160
181
  version: "0"
161
- version:
162
182
  required_rubygems_version: !ruby/object:Gem::Requirement
163
183
  requirements:
164
184
  - - ">="
165
185
  - !ruby/object:Gem::Version
186
+ segments:
187
+ - 0
166
188
  version: "0"
167
- version:
168
189
  requirements: []
169
190
 
170
191
  rubyforge_project:
171
- rubygems_version: 1.3.5
192
+ rubygems_version: 1.3.6
172
193
  signing_key:
173
194
  specification_version: 3
174
195
  summary: Videojuicer core-sdk
175
196
  test_files:
176
197
  - spec/assets/audio_spec.rb
198
+ - spec/assets/document_spec.rb
177
199
  - spec/assets/flash_spec.rb
178
200
  - spec/assets/image_spec.rb
179
201
  - spec/assets/text_spec.rb
@@ -198,6 +220,7 @@ test_files:
198
220
  - spec/promos/video_spec.rb
199
221
  - spec/property_registry_spec.rb
200
222
  - spec/request_proxy_spec.rb
223
+ - spec/seed_spec.rb
201
224
  - spec/session_spec.rb
202
225
  - spec/shared/asset_spec.rb
203
226
  - spec/shared/configurable_spec.rb
data/README.rdoc DELETED
@@ -1,7 +0,0 @@
1
- = vj-sdk
2
-
3
- Description goes here.
4
-
5
- == Copyright
6
-
7
- Copyright (c) 2009 danski. See LICENSE for details.