facebooker-rails3 1.0.64

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 (117) hide show
  1. data/README.textile +44 -0
  2. data/Rakefile +54 -0
  3. data/generators/facebook/facebook_generator.rb +14 -0
  4. data/generators/facebook/templates/config/facebooker.yml +49 -0
  5. data/generators/facebook/templates/public/javascripts/facebooker.js +332 -0
  6. data/generators/facebook_controller/USAGE +33 -0
  7. data/generators/facebook_controller/facebook_controller_generator.rb +40 -0
  8. data/generators/facebook_controller/templates/controller.rb +7 -0
  9. data/generators/facebook_controller/templates/functional_test.rb +11 -0
  10. data/generators/facebook_controller/templates/helper.rb +2 -0
  11. data/generators/facebook_controller/templates/view.fbml.erb +2 -0
  12. data/generators/facebook_controller/templates/view.html.erb +2 -0
  13. data/generators/facebook_publisher/facebook_publisher_generator.rb +14 -0
  14. data/generators/facebook_publisher/templates/create_facebook_templates.rb +15 -0
  15. data/generators/facebook_publisher/templates/publisher.rb +3 -0
  16. data/generators/facebook_scaffold/USAGE +27 -0
  17. data/generators/facebook_scaffold/facebook_scaffold_generator.rb +118 -0
  18. data/generators/facebook_scaffold/templates/controller.rb +93 -0
  19. data/generators/facebook_scaffold/templates/facebook_style.css +2579 -0
  20. data/generators/facebook_scaffold/templates/functional_test.rb +89 -0
  21. data/generators/facebook_scaffold/templates/helper.rb +2 -0
  22. data/generators/facebook_scaffold/templates/layout.fbml.erb +6 -0
  23. data/generators/facebook_scaffold/templates/layout.html.erb +17 -0
  24. data/generators/facebook_scaffold/templates/style.css +74 -0
  25. data/generators/facebook_scaffold/templates/view_edit.fbml.erb +13 -0
  26. data/generators/facebook_scaffold/templates/view_edit.html.erb +18 -0
  27. data/generators/facebook_scaffold/templates/view_index.fbml.erb +24 -0
  28. data/generators/facebook_scaffold/templates/view_index.html.erb +24 -0
  29. data/generators/facebook_scaffold/templates/view_new.fbml.erb +12 -0
  30. data/generators/facebook_scaffold/templates/view_new.html.erb +17 -0
  31. data/generators/facebook_scaffold/templates/view_show.fbml.erb +10 -0
  32. data/generators/facebook_scaffold/templates/view_show.html.erb +10 -0
  33. data/generators/publisher/publisher_generator.rb +14 -0
  34. data/generators/xd_receiver/templates/xd_receiver.html +10 -0
  35. data/generators/xd_receiver/templates/xd_receiver_ssl.html +10 -0
  36. data/generators/xd_receiver/xd_receiver_generator.rb +10 -0
  37. data/lib/facebooker.rb +242 -0
  38. data/lib/facebooker/adapters/adapter_base.rb +89 -0
  39. data/lib/facebooker/adapters/bebo_adapter.rb +77 -0
  40. data/lib/facebooker/adapters/facebook_adapter.rb +64 -0
  41. data/lib/facebooker/admin.rb +42 -0
  42. data/lib/facebooker/application.rb +37 -0
  43. data/lib/facebooker/attachment.rb +51 -0
  44. data/lib/facebooker/batch_request.rb +45 -0
  45. data/lib/facebooker/data.rb +57 -0
  46. data/lib/facebooker/feed.rb +78 -0
  47. data/lib/facebooker/logging.rb +44 -0
  48. data/lib/facebooker/mobile.rb +20 -0
  49. data/lib/facebooker/mock/service.rb +50 -0
  50. data/lib/facebooker/mock/session.rb +18 -0
  51. data/lib/facebooker/model.rb +139 -0
  52. data/lib/facebooker/models/affiliation.rb +10 -0
  53. data/lib/facebooker/models/album.rb +11 -0
  54. data/lib/facebooker/models/applicationproperties.rb +39 -0
  55. data/lib/facebooker/models/applicationrestrictions.rb +10 -0
  56. data/lib/facebooker/models/comment.rb +9 -0
  57. data/lib/facebooker/models/cookie.rb +10 -0
  58. data/lib/facebooker/models/education_info.rb +11 -0
  59. data/lib/facebooker/models/event.rb +28 -0
  60. data/lib/facebooker/models/family_relative_info.rb +7 -0
  61. data/lib/facebooker/models/friend_list.rb +16 -0
  62. data/lib/facebooker/models/group.rb +36 -0
  63. data/lib/facebooker/models/info_item.rb +10 -0
  64. data/lib/facebooker/models/info_section.rb +10 -0
  65. data/lib/facebooker/models/location.rb +8 -0
  66. data/lib/facebooker/models/message_thread.rb +89 -0
  67. data/lib/facebooker/models/notifications.rb +17 -0
  68. data/lib/facebooker/models/page.rb +46 -0
  69. data/lib/facebooker/models/photo.rb +19 -0
  70. data/lib/facebooker/models/tag.rb +12 -0
  71. data/lib/facebooker/models/user.rb +722 -0
  72. data/lib/facebooker/models/video.rb +9 -0
  73. data/lib/facebooker/models/work_info.rb +10 -0
  74. data/lib/facebooker/parser.rb +951 -0
  75. data/lib/facebooker/rails/backwards_compatible_param_checks.rb +31 -0
  76. data/lib/facebooker/rails/controller.rb +370 -0
  77. data/lib/facebooker/rails/cucumber.rb +28 -0
  78. data/lib/facebooker/rails/cucumber/world.rb +40 -0
  79. data/lib/facebooker/rails/extensions/action_controller.rb +48 -0
  80. data/lib/facebooker/rails/extensions/action_view.rb +21 -0
  81. data/lib/facebooker/rails/extensions/rack_setup.rb +17 -0
  82. data/lib/facebooker/rails/extensions/routing.rb +15 -0
  83. data/lib/facebooker/rails/facebook_form_builder.rb +141 -0
  84. data/lib/facebooker/rails/facebook_pretty_errors.rb +22 -0
  85. data/lib/facebooker/rails/facebook_request_fix.rb +28 -0
  86. data/lib/facebooker/rails/facebook_request_fix_2-3.rb +17 -0
  87. data/lib/facebooker/rails/facebook_session_handling.rb +68 -0
  88. data/lib/facebooker/rails/facebook_url_helper.rb +156 -0
  89. data/lib/facebooker/rails/facebook_url_rewriting.rb +60 -0
  90. data/lib/facebooker/rails/helpers.rb +835 -0
  91. data/lib/facebooker/rails/helpers/fb_connect.rb +161 -0
  92. data/lib/facebooker/rails/helpers/stream_publish.rb +22 -0
  93. data/lib/facebooker/rails/integration_session.rb +38 -0
  94. data/lib/facebooker/rails/profile_publisher_extensions.rb +42 -0
  95. data/lib/facebooker/rails/publisher.rb +600 -0
  96. data/lib/facebooker/rails/routing.rb +49 -0
  97. data/lib/facebooker/rails/test_helpers.rb +68 -0
  98. data/lib/facebooker/rails/utilities.rb +22 -0
  99. data/lib/facebooker/railtie.rb +34 -0
  100. data/lib/facebooker/server_cache.rb +24 -0
  101. data/lib/facebooker/service.rb +103 -0
  102. data/lib/facebooker/service/base_service.rb +19 -0
  103. data/lib/facebooker/service/curl_service.rb +44 -0
  104. data/lib/facebooker/service/net_http_service.rb +12 -0
  105. data/lib/facebooker/service/typhoeus_multi_service.rb +27 -0
  106. data/lib/facebooker/service/typhoeus_service.rb +17 -0
  107. data/lib/facebooker/session.rb +771 -0
  108. data/lib/facebooker/stream_post.rb +19 -0
  109. data/lib/facebooker/version.rb +9 -0
  110. data/lib/net/http_multipart_post.rb +123 -0
  111. data/lib/rack/facebook.rb +89 -0
  112. data/lib/rack/facebook_session.rb +21 -0
  113. data/lib/tasks/facebooker.rake +19 -0
  114. data/lib/tasks/facebooker.rb +2 -0
  115. data/lib/tasks/tunnel.rake +46 -0
  116. data/rails/init.rb +1 -0
  117. metadata +178 -0
@@ -0,0 +1,44 @@
1
+ h2. Facebooker
2
+
3
+ The original Facebooker gem is here: http://github.com/mmangino/facebooker
4
+
5
+ This here is only my fork:
6
+
7
+ * Forked and modified the original 2010 at http://github.com/funkensturm/facebooker
8
+ * achieving rails 3 compability from http://github.com/joren/facebooker/tree/rails3
9
+ * and the new api cookies code was taken and modified from http://github.com/cbaclig/facebooker
10
+
11
+ I also took the freedom to delete lots of files I don't need anyway. Like gems and test (haha, just kidding - they are important. I took them out though, because it would take weeks to work with rails 3 and the new FB API, so I just use this whole thing as a plugin which is continuously changing)
12
+
13
+ Note that something was fishy with the manual signature check. I'm relying on the Rack to do this now, but I don't know whether that's a good idea: http://rails.brentsowers.com/2009/12/signature-verification-does-not-work.html
14
+
15
+ h2. ORIGINAL LICENSE
16
+
17
+ (The MIT License)
18
+
19
+ Copyright (c) 2008-2009:
20
+
21
+ * Chad Fowler
22
+ * Patrick Ewing
23
+ * Mike Mangino
24
+ * Shane Vitarana
25
+ * Corey Innis
26
+
27
+ Permission is hereby granted, free of charge, to any person obtaining
28
+ a copy of this software and associated documentation files (the
29
+ 'Software'), to deal in the Software without restriction, including
30
+ without limitation the rights to use, copy, modify, merge, publish,
31
+ distribute, sublicense, and/or sell copies of the Software, and to
32
+ permit persons to whom the Software is furnished to do so, subject to
33
+ the following conditions:
34
+
35
+ The above copyright notice and this permission notice shall be
36
+ included in all copies or substantial portions of the Software.
37
+
38
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
39
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
40
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
41
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
42
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
43
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
44
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,54 @@
1
+ # -*- ruby -*-
2
+ #
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ begin
6
+ require 'load_multi_rails_rake_tasks'
7
+ rescue LoadError
8
+ $stderr.puts "Install the multi_rails gem to run tests against multiple versions of Rails"
9
+ end
10
+
11
+ require 'lib/facebooker/version'
12
+
13
+ NAME = 'facebooker-rails3'
14
+
15
+ begin
16
+ gem 'jeweler'
17
+ require 'jeweler'
18
+ Jeweler::Tasks.new do |spec|
19
+ spec.name = NAME
20
+ spec.version = Facebooker::VERSION::STRING
21
+ spec.summary = "Facebooker for Rails 3"
22
+ spec.description = spec.summary
23
+ spec.homepage = "http://github.com/tarsolya/facebooker-rails3"
24
+ spec.authors = ["chad@chadfowler.com", "tarsolya@gmail.com"]
25
+ spec.email = "tarsolya@gmail.com"
26
+
27
+ spec.files = FileList['[A-Z]*', File.join(*%w[{generators,lib,rails} ** *]).to_s]
28
+ end
29
+ Jeweler::GemcutterTasks.new
30
+ rescue LoadError
31
+ puts "Jeweler - or one of its dependencies - is not available. " <<
32
+ "Install it with: sudo gem install jeweler -s http://gemcutter.org"
33
+ end
34
+
35
+ begin
36
+ require 'rcov/rcovtask'
37
+
38
+ namespace :test do
39
+ namespace :coverage do
40
+ desc "Delete aggregate coverage data."
41
+ task(:clean) { rm_f "coverage.data" }
42
+ end
43
+ desc 'Aggregate code coverage for unit, functional and integration tests'
44
+ Rcov::RcovTask.new(:coverage) do |t|
45
+ t.libs << "test"
46
+ t.test_files = FileList["test/**/*_test.rb"]
47
+ t.output_dir = "coverage/"
48
+ t.verbose = true
49
+ t.rcov_opts = ['--exclude', 'test,/usr/lib/ruby,/Library/Ruby,/System/Library', '--sort', 'coverage']
50
+ end
51
+ end
52
+ rescue LoadError
53
+ $stderr.puts "Install the rcov gem to enable test coverage analysis"
54
+ end
@@ -0,0 +1,14 @@
1
+ class FacebookGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ m.file 'config/facebooker.yml', 'config/facebooker.yml'
5
+ m.file 'public/javascripts/facebooker.js', 'public/javascripts/facebooker.js'
6
+ end
7
+ end
8
+
9
+ protected
10
+
11
+ def banner
12
+ "Usage: #{$0} facebooker"
13
+ end
14
+ end
@@ -0,0 +1,49 @@
1
+ # The api key, secret key, and canvas page name are required to get started
2
+ # Tunnel configuration is only needed if you are going to use the facebooker:tunnel Rake tasks
3
+ # Your callback url in Facebook should be set to http://public_host:public_port
4
+ # If you're building a Facebook connect site,
5
+ # change the value of set_asset_host_to_callback_url to false
6
+ # To develop for the new profile design, add the following key..
7
+ # api: new
8
+ # remove the key or set it to anything else to use the old facebook design.
9
+ # This should only be necessary until the final version of the new profile is released.
10
+
11
+ development:
12
+ api_key:
13
+ secret_key:
14
+ canvas_page_name:
15
+ callback_url:
16
+ pretty_errors: true
17
+ set_asset_host_to_callback_url: true
18
+ tunnel:
19
+ public_host_username:
20
+ public_host:
21
+ public_port: 4007
22
+ local_port: 3000
23
+ server_alive_interval: 0
24
+
25
+ test:
26
+ api_key:
27
+ secret_key:
28
+ canvas_page_name:
29
+ callback_url:
30
+ set_asset_host_to_callback_url: true
31
+ tunnel:
32
+ public_host_username:
33
+ public_host:
34
+ public_port: 4007
35
+ local_port: 3000
36
+ server_alive_interval: 0
37
+
38
+ production:
39
+ api_key:
40
+ secret_key:
41
+ canvas_page_name:
42
+ callback_url:
43
+ set_asset_host_to_callback_url: true
44
+ tunnel:
45
+ public_host_username:
46
+ public_host:
47
+ public_port: 4007
48
+ local_port: 3000
49
+ server_alive_interval: 0
@@ -0,0 +1,332 @@
1
+ function $(element) {
2
+ if (typeof element == "string") {
3
+ element=document.getElementById(element);
4
+ }
5
+ if (element)
6
+ extendInstance(element,Element);
7
+ return element;
8
+ }
9
+
10
+ function getElementsByName(elementName) {
11
+ var matcher = function(element) {
12
+ return (element.getName() === elementName);
13
+ };
14
+ return domCollect(document.getRootElement(), matcher);
15
+ }
16
+ function getElementsByClass(classname) {
17
+ var matcher = function(element) {
18
+ return (element.getClassName() === classname);
19
+ };
20
+ return domCollect(document.getRootElement(), matcher);
21
+ }
22
+ //function getElementsByTagName(tagName) -> native to FJBS
23
+
24
+ extendInstance(Ajax, { //Extends the native Facebook Ajax object
25
+ /*
26
+ * Make a request to a remote server. Call the 'success' callback with the result.
27
+ * Ex: Ajax.Load('JSON','http://...',{ success: function(result){console.log(result.toSource())} }, {'json':test_content})
28
+ */
29
+ Load: function(response_type, action_path, callbacks, post_parameters) {
30
+ callbacks = Ajax.checkCallbacks(callbacks);
31
+ var ajax = new Ajax();
32
+ switch(response_type) {
33
+ case 'FBML':
34
+ ajax.responseType = Ajax.FBML;
35
+ break;
36
+ case 'JSON':
37
+ ajax.responseType = Ajax.JSON;
38
+ break;
39
+ case 'RAW':
40
+ ajax.responseType = Ajax.RAW;
41
+ break;
42
+ default:
43
+ console.error("Unknow respons format requested. You supplied %s. Supported: 'FBML', 'RAW'", response_type);
44
+ return;
45
+ }
46
+ ajax.ondone = function(result){
47
+ callbacks.success(result);
48
+ callbacks.complete();
49
+ }
50
+ ajax.onerror = function(error_string) {
51
+ callbacks.failure(error_string);
52
+ callbacks.complete();
53
+ }
54
+
55
+ post_parameters = post_parameters || {}
56
+ post_parameters['authenticity_token'] = _token;
57
+
58
+ if(action_path.indexOf('http') == -1) {
59
+ action_path = _hostname + action_path;
60
+ }
61
+
62
+ callbacks.begin();
63
+ ajax.post(action_path,post_parameters);
64
+ },
65
+ /*
66
+ * Make a request to a remote server. Update target_element with result. Calls the 'success' callback with the result
67
+ * Ex: Ajax.Update('test1', 'FBML', 'http://...',{ success: function(result){console.log(result)} })
68
+ */
69
+ Update: function(target_element, response_type, action_path, callbacks, post_parameters) {
70
+ callbacks = Ajax.checkCallbacks(callbacks);
71
+ var update_element = function(content) {
72
+ switch(response_type) {
73
+ case 'FBML':
74
+ $(target_element).setInnerFBML(content);
75
+ break;
76
+ case 'RAW':
77
+ $(target_element).setTextValue(content);
78
+ break;
79
+ default:
80
+ console.log("Unsupported response type "+response_type);
81
+ break;
82
+ }
83
+ };
84
+
85
+ var onsuccess = (callbacks.success == null)?
86
+ update_element :
87
+ chainMethods([update_element,callbacks.success]);
88
+
89
+ callbacks.success = onsuccess;
90
+ Ajax.Load(response_type, action_path, callbacks, post_parameters);
91
+ },
92
+
93
+
94
+ InPlaceInputEditor: function(target_element, action_path, post_parameters) {
95
+ var classname = $(target_element).getClassName() || "";
96
+
97
+ this.edit = function() {
98
+ var target = $(target_element);
99
+ var wrapper = target.getParentNode();
100
+ var dimensions = $(target_element).getDimensions();
101
+ var value = $(target_element+'__value').getValue();
102
+
103
+ var editArea = document.createElement('input');
104
+ editArea.setType($(target_element+'__value').getType());
105
+ editArea.setId(target_element+"__editor");
106
+ editArea.setValue(value);
107
+ //editArea.focus();
108
+ //editArea.setStyle("width",dimensions.width+"px");
109
+ //editArea.setStyle("height", dimensions.height+'px');
110
+
111
+ $(target_element+'__value').remove();
112
+ wrapper.removeChild(target);
113
+ wrapper.appendChild(editArea);
114
+ }
115
+ this.save = function(callbacks){
116
+ var newValue = $(target_element + "__editor").getValue();
117
+ var wrapper = $(target_element + "__editor").getParentNode();
118
+ callbacks = Ajax.checkCallbacks(callbacks);
119
+ Ajax.Load("RAW", action_path + "?raw=" + escape(newValue), {
120
+ success: chainMethods([
121
+ callbacks.success,
122
+ function(result){
123
+ wrapper.setInnerXHTML('<span>'+
124
+ '<input id="'+target_element+'__value" name="'+target_element+'__value" style="display:none;" type="text" value="'+unescape(result)+'" />'+
125
+ '<span><span id="'+target_element+'" class="'+classname+'" type="text">'+unescape(result)+'</span></span></span>');
126
+ }
127
+ ])
128
+ }, post_parameters)
129
+ };
130
+ },
131
+ InPlaceTextAreaEditor: function(target_element, action_path, post_parameters) {
132
+ var classname = $(target_element).getClassName() || "";
133
+
134
+ this.edit = function() {
135
+ var target = $(target_element);
136
+ var wrapper = target.getParentNode();
137
+ var dimensions = $(target_element).getDimensions();
138
+ var value = $(target_element+'__value').getValue();
139
+
140
+ var editArea = document.createElement('textarea');
141
+ editArea.setId(target_element+"__editor");
142
+ editArea.setValue(value.replace(/<br \/>|<br\/>/g,'\n').replace(/<p>|<\/p>/g,''));
143
+ editArea.addEventListener('keyup', function() {
144
+ autoExpandTextarea(editArea);
145
+ });
146
+ //editArea.focus();
147
+ editArea.setStyle("width",dimensions.width+"px");
148
+ //editArea.setStyle("height", dimensions.height+'px');
149
+
150
+ $(target_element+'__value').remove();
151
+ wrapper.removeChild(target);
152
+ wrapper.appendChild(editArea);
153
+ autoExpandTextarea(editArea);
154
+ }
155
+ this.save = function(callbacks){
156
+ var newValue = $(target_element + "__editor").getValue();
157
+ var wrapper = $(target_element + "__editor").getParentNode();
158
+ callbacks = Ajax.checkCallbacks(callbacks);
159
+ Ajax.Load("RAW", action_path + "?raw=" + escape(newValue), {
160
+ success: chainMethods([
161
+ callbacks.success,
162
+ function(result){
163
+ wrapper.setInnerXHTML('<span>'+
164
+ '<textarea id="'+target_element+'__value" name="'+target_element+'__value" style="display:none;">'+unescape(result.replace(/<br \/>|<br\/>/g,'\n').replace(/<p>|<\/p>/g,''))+'</textarea>'+
165
+ '<div><div id="'+target_element+'" class="'+classname+'" type="text">'+unescape(result)+'</div></div></span>');
166
+ }
167
+ ])
168
+ }, post_parameters)
169
+ };
170
+ },
171
+ /*
172
+ * Pass the data inside of a form to a target url and place the result inside target_element.
173
+ * Calls the 'success' callback with the result
174
+ */
175
+ UpdateRemoteForm: function(form_element, target_element, response_type, target_action, callbacks) {
176
+ callbacks = callbacks || {};
177
+ Ajax.Update(target_element, response_type, target_action, callbacks, $(form_element).serialize());
178
+ },
179
+ checkCallbacks:function(callbacks) {
180
+ callbacks = callbacks || {};
181
+ var donothing = function(){};
182
+ return callbacks = {
183
+ success: callbacks.success || donothing,
184
+ failure: callbacks.failure || donothing,
185
+ begin: callbacks.begin || donothing,
186
+ complete: callbacks.complete || donothing
187
+ };
188
+ }
189
+ });
190
+
191
+ /*
192
+ * Displays a confirmation dialog. If the user clicks "continue" then callback will be evaluated.
193
+ * title and message can be strings or fb:js-string objects
194
+ */
195
+ function confirm(title,message,callback) {
196
+ dialog = new Dialog(Dialog.DIALOG_POP);
197
+
198
+ dialog.showChoice(
199
+ title,
200
+ message, // Content
201
+ 'Continue',
202
+ 'Cancel');
203
+
204
+ dialog.onconfirm = function() {
205
+ callback();
206
+ };
207
+ }
208
+
209
+ function chainMethods(callbacks) {
210
+ return function(par1,par2,par3,par4,par5,par6) {
211
+ for (var i = 0, l = callbacks.length; i < l; i++) {
212
+ callbacks[i](par1, par2, par3, par4, par5, par6);
213
+ }
214
+ }
215
+ }
216
+
217
+ function extendInstance(instance,hash) {
218
+ for (var name in hash) {
219
+ instance[name] = hash[name];
220
+ }
221
+ }
222
+
223
+ var Element = {
224
+ visible: function() {
225
+ return (this.getStyle('display') != 'none');
226
+ },
227
+ toggle: function() {
228
+ if (this.visible()) {
229
+ this.hide();
230
+ } else {
231
+ this.show();
232
+ }
233
+ },
234
+ hide: function() {
235
+ this.setStyle({
236
+ display:'none'
237
+ });
238
+ return this;
239
+ },
240
+ show: function(element) {
241
+ this.setStyle({
242
+ display:''
243
+ });
244
+ return this;
245
+ },
246
+ remove: function() {
247
+ this.getParentNode().removeChild(this);
248
+ return null;
249
+ },
250
+ /*
251
+ * Returns calculated element size
252
+ */
253
+ getDimensions: function() {
254
+ var display = this.getStyle('display');
255
+ if (display != 'none' && display != null) // Safari bug
256
+ return {
257
+ width: this.getOffsetWidth(),
258
+ height: this.getOffsetHeight()
259
+ };
260
+
261
+ // All *Width and *Height properties give 0 on elements with display none,
262
+ // so enable the element temporarily
263
+ var originalVisibility = this.getStyle("visibility");
264
+ var originalDisplay = this.getStyle("display");
265
+ var originalPosition = this.getStyle("position");
266
+ this.setStyle('visibility','none');
267
+ this.setStyle('display','block');
268
+ this.setStyle('position','absolute');
269
+ var originalWidth = this.getClientWidth();
270
+ var originalHeight = this.getClientHeight();
271
+ this.setStyle('visibility',originalVisibility);
272
+ this.setStyle('display',originalDisplay);
273
+ this.setStyle('position',originalPosition);
274
+
275
+ return {
276
+ width: originalWidth,
277
+ height: originalHeight
278
+ };
279
+ }
280
+ }
281
+
282
+ function encodeURIComponent(str) {
283
+ if (typeof(str) == "string") {
284
+ return str.replace(/=/g,'%3D').replace(/&/g,'%26');
285
+ }
286
+ //checkboxes and radio buttons return objects instead of a string
287
+ else if(typeof(str) == "object"){
288
+ for (prop in str)
289
+ {
290
+ return str[prop].replace(/=/g,'%3D').replace(/&/g,'%26');
291
+ }
292
+ }
293
+ return "";
294
+ }
295
+
296
+ /*
297
+ * Applies block to all elements of an array. Return the array itself.
298
+ */
299
+ function map(array, block){
300
+ results = [];
301
+ for (var i=0,l=array.length;i<l;i++){
302
+ results.push(block(array[i]));
303
+ }
304
+ return results;
305
+ }
306
+
307
+ /*
308
+ * Collects all elements within the 'element' tree that 'matcher' returns true for
309
+ * For an example, see selectElementsByClass
310
+ */
311
+ function domCollect(element, matcher) {
312
+ collection = [];
313
+ var recurse = function(subelement){
314
+ var nodes = subelement.getChildNodes();
315
+ map(nodes, function(node){
316
+ if (matcher(node)) {
317
+ extendInstance(node,Element)
318
+ collection.push(node);
319
+ }
320
+ if (node.getFirstChild()) {
321
+ recurse(node);
322
+ }
323
+ });
324
+ };
325
+ recurse(element);
326
+ return collection;
327
+ }
328
+
329
+ PeriodicalExecuter = function (callback, frequency) {
330
+ setTimeout(callback, frequency *1000);
331
+ setTimeout(function() { new PeriodicalExecuter(callback,frequency); }, frequency*1000);
332
+ };