You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@labs.apache.org by fa...@apache.org on 2009/08/30 18:30:39 UTC
svn commit: r809371 [2/10] - in /labs/consite/trunk/conferences: ./
app/views/admin/con/dashboard/ app/views/layouts/ db/ db/migrate/ lib/
lib/tasks/ public/images/conferences/ vendor/plugins/active_scaffold/
vendor/plugins/active_scaffold/.git/ vendor...
Added: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/CHANGELOG
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/active_scaffold/CHANGELOG?rev=809371&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/active_scaffold/CHANGELOG (added)
+++ labs/consite/trunk/conferences/vendor/plugins/active_scaffold/CHANGELOG Sun Aug 30 16:30:26 2009
@@ -0,0 +1,152 @@
+= 1.2RC1
+
+== FEATURES
+
+- Added view helpers (active_scaffold_javascripts, active_scaffold_stylesheets, active_scaffold_ie_stylesheets) to help with asset cacheing (Alexander Semyonov)
+- Works with Rails 2.1 (2.0 / 1.2.x will continue to be supported by version 1.1)
+
+== FIXES
+
+- Javascript compatibility with FF3 / Safari 3.1 (Mike Dalessio)
+ see http://groups.google.com/group/activescaffold/browse_thread/thread/d37afa3f2ac687f2/b34ebf62d767bee3
+- Avoid ruby deprecation warning in config/list.rb (Dustin Sallings)
+- Fixes bug where template overrides are ignored when placed in Engines plugins (Mike Dalessio)
+- Fixed in_place_editor to work with latest control.js
+- Fixed infinite recursion bug when creating a new record with a new association
+- Subform action name conflict fix
+- Helpful warning message if record_select is not on a column with an association
+
+= 1.1.1
+
+== FIXES
+
+* rendering for rails 1.2.x
+
+= 1.1.0
+
+== FEATURES
+
+* `render :super' now accepts a :locals option
+* parameter-based conditions now support arrays of values (e.g. users?name[]=bob&name[]=fred becomes "name IN ('bob', 'fred')")
+
+== FIXES
+
+* `render :super' now works from active_scaffold_overrides without endlessly looping
+* `render :super' no longer assumes that the *immediate* caller was the override template file
+* `render :super' works better with windows file names (e.g. c:/...)
+* reload_if_empty() javascript now uses GET
+* inplace_edit now uses POST instead of GET
+* adding time and date fields to ignore list for determining whether subform row is empty. previously only datetime was ignored.
+* closed a potential internet explorer security issue in dhtml_history.js library
+
+= 1.1.0 RC1
+
+== FEATURES
+
+=== LIST
+* row class: new helper method (list_row_class) gets called for each record in the list and returns a CSS class.
+* automatically link to the :show action of singular associations. this is similar to the nested scaffolds for plural associations.
+* column.list_ui: good for when you want to render multiple columns the same way.
+* * built-in list interface options:
+* * * for inplace edits - checkbox
+* Support :joins_for_collection in column_calculation
+* inplace_edit option on list columns. currently works for text boxes and booleans
+
+=== CREATE/UPDATE
+* file uploads - largely taken care of by file_column bridge.
+* * automatically detects if FileColumn is installed. If so, uses it, and sets the form_ui for file columns to be file upload fields
+* * sets multipart? on config.create and config.update if file_columns are used on the target model
+* * Posts through iframe to give ajax-style file uploads
+* * Image columns are recognized and previewed as such
+* * Ability to delete a file
+* form_ui
+* * form interface options are now supported through helper method named active_scaffold_input_#{form_ui}. if you want a different form interface than activescaffold normally provides, you may configure the form_ui for that column to use one of these methods. you can easily define your own, too.
+* * built-in form interface options:
+* * * for associations - singular_association, plural_association, select, record_select
+* * * others - select, checkbox, country, password, textarea, usa_state, virtual, boolean
+* * subforms respect form_ui settings. but if form_ui is empty, it will be set to :select to disable subform nesting.
+* boolean columns: when the database column allows nil, we now add a third option to the dropdown so you don't *have* to pick true or false.
+* new :params option for a column lets you specify additional parameters to accept when the given column is on the form. this is for when a column needs to submit multiple values to work.
+* improved support for associations in parameters. for simply selecting/deselecting associations, activescaffold will now recognize `:user => 5' or `:users => [1, 2, 5]'.
+* Supply a unique id from active_scaffold_input_options for form fields.
+* added after_update_save controller override method
+
+=== EMBEDDING
+* `render :active_scaffold' now accepts a :conditions option, which is a weaker but more flexible variation of :constraints
+* active_scaffold_includes now accepts a frontend name. this is necessary so you can include the proper assets even if active_scaffold isn't configured on the current controller (it's embedded).
+* polymorphic constraints are now supported, assuming params[:parent_model].to_s is the proper content for the polymorphic _type field.
+* Beefing up the constraint system so it can handle has_one/belongs_to. Specifically, it can now disassociate a previous relationship before setting a new one. For example, Bear has_one Den. If creating a new Den, constrained to a certain Bear, the constraints system will now disassociate any previous Den from the Bear before associating the new one.
+
+=== NESTING
+* :through associations may now be nested
+* nested#shallow_delete
+
+=== SEARCH
+* fieldsearch module handles booleans better - provides third option so you don't *have* to search on a boolean column
+* In field search lock_version is the only magic column. May want to search by :id or date fields.
+
+=== GENERAL
+* use #human_name for the column label when possible.
+* merge_conditions now supports hash conditions (and should forever support every conditions style that ActiveRecord supports)
+* action links may now remove an action link with #clear_link
+* action links have a new :controller option, so you don't have to sneak it into :params anymore
+* dhtml history may now be disabled
+* authorized_for? in ActiveRecordPermissions now calls respond_to? only as much as needed
+* removing an assert_valid_keys? call in active_record_permissions#authorized_for?. it just wasn't worth the CPU time.
+* render :super is now extension-agnostic. ex: `render :super` in list.html.erb will properly find list.rhtml as the "parent" template.
+* Auto-bridge loading mechanism. Bridges integrated into core.
+* inherited_view_paths: ability to specify other folders to look for if missing view occurs
+
+== FIXES
+
+=== LIST
+* the calculation row now updates on edit/create/destroy.
+* list now returns to page 1 if the current page has no records.
+* list will now try to reload the scaffold on a previous page if you delete the last entry on the current page.
+* if there were no end-of-line record actions, then any column actions would not use ajax. this was because the loading indicator was missing, which messed up the action link javascript.
+* theme == :default no longer attempts to use Rico.Corner
+* column_empty? now treats any values equal to list.empty_field_text as empty, too.
+* better :method handling for action links.
+* the ' ' fix for ie6 was failing for value types that weren't nil and didn't respond to empty?
+* if someone sets singular columns to link to the 'nested' action, the link will now render with the appropriate id parameter.
+* do not propagate params[:search] through action links that link to other controllers. closes issue #447.
+* reworked rendering of pagination links for IE
+
+=== CREATE/UPDATE
+* constraints are now applied to a record during the #new action, in case any custom form rendering depends on the constrained column
+* the default options_for_association_conditions now returns nil for :through associations
+* will not update a record attribute if the value hasn't changed. this is a workaround for an activerecord bug with has_one associations.
+* attributes_hash_is_empty? didn't handle multi-parameter attribute names like 'created_at(5i)', which resulted in extra records being created from subforms.
+* Hide hidden column header labels - like lock_version - in sub-forms.
+* configuring url_for to not escape ampersands for the add_new_url in association footers (the 'create another' button's url)
+* attribute_params.rb#attributes_hash_is_empty now checks defaults by converting them to strings to match the parameter values.
+
+=== NESTING
+* no longer trying to nest a polymorphic association (there's no consistent model to list)
+* fixed :conditions generation for nested/embedded scaffolds - was causing a bind variable mismatch.
+
+=== SEARCH
+* search/livesearch should no longer choke on virtual columns
+* the search/live_search forms will now ignore params[:search] when generating the submit url
+
+=== GENERAL
+* no longer blow up on data strings with unintentional % characters. as_() was sprintf'ing too frequently.
+* link_to no longer blows up on controller symbols
+* activescaffold no longer loses information on columns - `config.columns.add', `config.columns = [...]', and `config.columns.exclude' all now affect the *inheritability* of a column by the other modules (list, create, update, etc.), but all columns remain in config.columns. this also makes _id columns behave better.
+* dhtml history no longer saves null:null:null history bookmark.
+* if there aren't any columns to search on, then activescaffold no longer creates an empty WHERE clause
+* render :update was failing in some cases because activescaffold wasn't expecting blocks to the render call.
+* quoting the scaffold id for report_500_response()
+* adding :update_column => :post to the RESTful routing. closes issue #448.
+
+== MISC
+
+* reorganized the helpers and extensions
+* ui_type is now only an alias for form_ui
+* improvements to exception messages
+* when initializing in production mode, activescaffold now recovers gracefully if it can't copy asset files
+* RESTful routing is now accomplished in a way that'll let other add-ons extend the meaning of :active_scaffold => true.
+* fixes for edge rails compatibility
+* small improvements for localization accessibility
+* minor string renaming (will affect localization tables, though)
+* closed a few XSS holes
\ No newline at end of file
Added: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/MIT-LICENSE
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/active_scaffold/MIT-LICENSE?rev=809371&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/active_scaffold/MIT-LICENSE (added)
+++ labs/consite/trunk/conferences/vendor/plugins/active_scaffold/MIT-LICENSE Sun Aug 30 16:30:26 2009
@@ -0,0 +1,20 @@
+Copyright (c) 2006 Richard White
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Added: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/README
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/active_scaffold/README?rev=809371&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/active_scaffold/README (added)
+++ labs/consite/trunk/conferences/vendor/plugins/active_scaffold/README Sun Aug 30 16:30:26 2009
@@ -0,0 +1,31 @@
+**********************************************************************************
+** For all documentation see the project website: http://www.ActiveScaffold.com **
+**********************************************************************************
+
+ActiveScaffold plugin by Scott Rutherford (scott@caronsoftware.com), Richard White (rrwhite@gmail.com), Lance Ivy (lance@cainlevy.net), Ed Moss, and Tim Harper
+
+Uses DhtmlHistory by Brad Neuberg (bkn3@columbia.edu)
+http://codinginparadise.org
+
+Uses Querystring by Adam Vandenberg
+http://adamv.com/dev/javascript/querystring
+
+Uses Paginator by Bruce Williams
+http://paginator.rubyforge.org/
+
+Supports RecordSelect by Lance Ivy
+http://code.google.com/p/recordselect/
+
+== Version Information
+
+Please note the following list of Active Scaffold branches and Rails versions. Master will not work with Rails < 2.2
+
+Rails master (edge): Active Scaffold master
+Rails 2.2.*: Active Scaffold rails-2.2
+Rails 2.1.*: Active Scaffold rails-2.1
+Rails < 2.1: Active Scaffold 1-1-stable (no guarantees)
+
+Since Rails 2.3, render_component plugin is needed for nested and embbeded scaffolds. It works with rails-2.3 branch from ewildgoose repository:
+script/plugin install git://github.com/ewildgoose/render_component.git -r rails-2.3
+
+Released under the MIT license (included)
Propchange: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/README
------------------------------------------------------------------------------
svn:eol-style = native
Added: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/Rakefile
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/active_scaffold/Rakefile?rev=809371&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/active_scaffold/Rakefile (added)
+++ labs/consite/trunk/conferences/vendor/plugins/active_scaffold/Rakefile Sun Aug 30 16:30:26 2009
@@ -0,0 +1,24 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/packagetask'
+require 'rake/rdoctask'
+require 'find'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test ActiveScaffold.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for ActiveScaffold.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'ActiveScaffold'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
Added: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/environment.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/active_scaffold/environment.rb?rev=809371&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/active_scaffold/environment.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/active_scaffold/environment.rb Sun Aug 30 16:30:26 2009
@@ -0,0 +1,17 @@
+require 'active_scaffold'
+
+# TODO: clean up extensions. some could be organized for autoloading, and others could be removed entirely.
+Dir["#{File.dirname __FILE__}/lib/extensions/*.rb"].each { |file| require file }
+
+ActionController::Base.send(:include, ActiveScaffold)
+ActionController::Base.send(:include, RespondsToParent)
+ActionController::Base.send(:include, ActiveScaffold::Helpers::ControllerHelpers)
+ActionView::Base.send(:include, ActiveScaffold::Helpers::ViewHelpers)
+
+ActionController::Base.class_eval {include ActiveRecordPermissions::ModelUserAccess::Controller}
+ActiveRecord::Base.class_eval {include ActiveRecordPermissions::ModelUserAccess::Model}
+ActiveRecord::Base.class_eval {include ActiveRecordPermissions::Permissions}
+
+require 'bridges/bridge.rb'
+
+I18n.load_path += Dir[File.join(File.dirname(__FILE__), 'lib', 'active_scaffold', 'locale', '*.{rb,yml}')]
Propchange: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/environment.rb
------------------------------------------------------------------------------
svn:eol-style = native
Added: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/add.gif
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/add.gif?rev=809371&view=auto
==============================================================================
Binary file - no diff available.
Propchange: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/add.gif
------------------------------------------------------------------------------
svn:mime-type = image/gif
Added: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/arrow_down.gif
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/arrow_down.gif?rev=809371&view=auto
==============================================================================
Binary file - no diff available.
Propchange: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/arrow_down.gif
------------------------------------------------------------------------------
svn:mime-type = image/gif
Added: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/arrow_up.gif
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/arrow_up.gif?rev=809371&view=auto
==============================================================================
Binary file - no diff available.
Propchange: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/arrow_up.gif
------------------------------------------------------------------------------
svn:mime-type = image/gif
Added: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/close.gif
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/close.gif?rev=809371&view=auto
==============================================================================
Binary file - no diff available.
Propchange: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/close.gif
------------------------------------------------------------------------------
svn:mime-type = image/gif
Added: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/cross.png
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/cross.png?rev=809371&view=auto
==============================================================================
Binary file - no diff available.
Propchange: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/cross.png
------------------------------------------------------------------------------
svn:mime-type = image/png
Added: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/indicator-small.gif
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/indicator-small.gif?rev=809371&view=auto
==============================================================================
Binary file - no diff available.
Propchange: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/indicator-small.gif
------------------------------------------------------------------------------
svn:mime-type = image/gif
Added: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/indicator.gif
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/indicator.gif?rev=809371&view=auto
==============================================================================
Binary file - no diff available.
Propchange: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/indicator.gif
------------------------------------------------------------------------------
svn:mime-type = image/gif
Added: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/magnifier.png
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/magnifier.png?rev=809371&view=auto
==============================================================================
Binary file - no diff available.
Propchange: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/images/magnifier.png
------------------------------------------------------------------------------
svn:mime-type = image/png
Added: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/javascripts/active_scaffold.js
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/javascripts/active_scaffold.js?rev=809371&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/javascripts/active_scaffold.js (added)
+++ labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/javascripts/active_scaffold.js Sun Aug 30 16:30:26 2009
@@ -0,0 +1,434 @@
+if (typeof Prototype == 'undefined')
+{
+ warning = "ActiveScaffold Error: Prototype could not be found. Please make sure that your application's layout includes prototype.js (e.g. <%= javascript_include_tag :defaults %>) *before* it includes active_scaffold.js (e.g. <%= active_scaffold_includes %>).";
+ alert(warning);
+}
+if (Prototype.Version.substring(0, 3) != '1.6')
+{
+ warning = "ActiveScaffold Error: Prototype version 1.6.x is required. Please update prototype.js (rake rails:update:javascripts).";
+ alert(warning);
+}
+
+/*
+ * Simple utility methods
+ */
+
+var ActiveScaffold = {
+ records_for: function(tbody_id) {
+ var rows = [];
+ var child = $(tbody_id).down('.record');
+ while (child) {
+ rows.push(child);
+ child = child.next('.record');
+ }
+ return rows;
+ },
+ stripe: function(tbody_id) {
+ var even = false;
+ var rows = this.records_for(tbody_id);
+ for (var i = 0; i < rows.length; i++) {
+ var child = rows[i];
+ //Make sure to skip rows that are create or edit rows or messages
+ if (child.tagName != 'SCRIPT'
+ && !child.hasClassName("create")
+ && !child.hasClassName("update")
+ && !child.hasClassName("inline-adapter")
+ && !child.hasClassName("active-scaffold-calculations")) {
+
+ if (even) child.addClassName("even-record");
+ else child.removeClassName("even-record");
+
+ even = !even;
+ }
+ }
+ },
+ hide_empty_message: function(tbody, empty_message_id) {
+ if (this.records_for(tbody).length != 0) {
+ $(empty_message_id).hide();
+ }
+ },
+ reload_if_empty: function(tbody, url) {
+ var content_container_id = tbody.replace('tbody', 'content');
+ if (this.records_for(tbody).length == 0) {
+ new Ajax.Updater($(content_container_id), url, {
+ method: 'get',
+ asynchronous: true,
+ evalScripts: true
+ });
+ }
+ },
+ removeSortClasses: function(scaffold_id) {
+ $$('#' + scaffold_id + ' td.sorted').each(function(element) {
+ element.removeClassName("sorted");
+ });
+ $$('#' + scaffold_id + ' th.sorted').each(function(element) {
+ element.removeClassName("sorted");
+ element.removeClassName("asc");
+ element.removeClassName("desc");
+ });
+ },
+ decrement_record_count: function(scaffold_id) {
+ // decrement the last record count, firsts record count are in nested lists
+ count = $$('#' + scaffold_id + ' span.active-scaffold-records').last();
+ count.innerHTML = parseInt(count.innerHTML) - 1;
+ },
+ increment_record_count: function(scaffold_id) {
+ // increment the last record count, firsts record count are in nested lists
+ count = $$('#' + scaffold_id + ' span.active-scaffold-records').last();
+ count.innerHTML = parseInt(count.innerHTML) + 1;
+ },
+
+ server_error_response: '',
+ report_500_response: function(active_scaffold_id) {
+ messages_container = $(active_scaffold_id).down('td.messages-container');
+ new Insertion.Top(messages_container, this.server_error_response);
+ }
+}
+
+/*
+ * DHTML history tie-in
+ */
+function addActiveScaffoldPageToHistory(url, active_scaffold_id) {
+ if (typeof dhtmlHistory == 'undefined') return; // it may not be loaded
+
+ var array = url.split('?');
+ var qs = new Querystring(array[1]);
+ var sort = qs.get('sort')
+ var dir = qs.get('sort_direction')
+ var page = qs.get('page')
+ if (sort || dir || page) dhtmlHistory.add(active_scaffold_id+":"+page+":"+sort+":"+dir, url);
+}
+
+/*
+ * Add-ons/Patches to Prototype
+ */
+
+/* patch to support replacing TR/TD/TBODY in Internet Explorer, courtesy of http://dev.rubyonrails.org/ticket/4273 */
+Element.replace = function(element, html) {
+ element = $(element);
+ if (element.outerHTML) {
+ try {
+ element.outerHTML = html.stripScripts();
+ } catch (e) {
+ var tn = element.tagName;
+ if(tn=='TBODY' || tn=='TR' || tn=='TD')
+ {
+ var tempDiv = document.createElement("div");
+ tempDiv.innerHTML = '<table id="tempTable" style="display: none">' + html.stripScripts() + '</table>';
+ element.parentNode.replaceChild(tempDiv.getElementsByTagName(tn).item(0), element);
+ }
+ else throw e;
+ }
+ } else {
+ var range = element.ownerDocument.createRange();
+ /* patch to fix <form> replaces in Firefox. see http://dev.rubyonrails.org/ticket/8010 */
+ range.selectNodeContents(element.parentNode);
+ element.parentNode.replaceChild(range.createContextualFragment(html.stripScripts()), element);
+ }
+ setTimeout(function() {html.evalScripts()}, 10);
+ return element;
+};
+
+/*
+ * URL modification support. Incomplete functionality.
+ */
+Object.extend(String.prototype, {
+ append_params: function(params) {
+ url = this;
+ if (url.indexOf('?') == -1) url += '?';
+ else if (url.lastIndexOf('&') != url.length) url += '&';
+
+ url += $H(params).collect(function(item) {
+ return item.key + '=' + item.value;
+ }).join('&');
+
+ return url;
+ }
+});
+
+/*
+ * Prototype's implementation was throwing an error instead of false
+ */
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ var t = Element._attributeTranslations;
+ attribute = (t.names && t.names[attribute]) || attribute;
+ // Return false if we get an error here
+ try {
+ return $(element).getAttributeNode(attribute).specified;
+ } catch (e) {
+ return false;
+ }
+ }
+};
+
+/**
+ * A set of links. As a set, they can be controlled such that only one is "open" at a time, etc.
+ */
+ActiveScaffold.Actions = new Object();
+ActiveScaffold.Actions.Abstract = function(){}
+ActiveScaffold.Actions.Abstract.prototype = {
+ initialize: function(links, target, loading_indicator, options) {
+ this.target = $(target);
+ this.loading_indicator = $(loading_indicator);
+ this.options = options;
+ this.links = links.collect(function(link) {
+ return this.instantiate_link(link);
+ }.bind(this));
+ },
+
+ instantiate_link: function(link) {
+ throw 'unimplemented'
+ }
+}
+
+/**
+ * A DataStructures::ActionLink, represented in JavaScript.
+ * Concerned with AJAX-enabling a link and adapting the result for insertion into the table.
+ */
+ActiveScaffold.ActionLink = new Object();
+ActiveScaffold.ActionLink.Abstract = function(){}
+ActiveScaffold.ActionLink.Abstract.prototype = {
+ initialize: function(a, target, loading_indicator) {
+ this.tag = $(a);
+ this.url = this.tag.href;
+ this.method = 'get';
+ if(this.url.match('_method=delete')){
+ this.method = 'delete';
+ } else if(this.url.match('_method=post')){
+ this.method = 'post';
+ }
+ this.target = target;
+ this.loading_indicator = loading_indicator;
+ this.hide_target = false;
+ this.position = this.tag.getAttribute('position');
+ this.page_link = this.tag.getAttribute('page_link');
+
+ this.onclick = this.tag.onclick;
+ this.tag.onclick = null;
+ this.tag.observe('click', function(event) {
+ this.open();
+ Event.stop(event);
+ }.bind(this));
+
+ this.tag.action_link = this;
+ },
+
+ open: function() {
+ if (this.is_disabled()) return;
+
+ if (this.tag.hasAttribute( "dhtml_confirm")) {
+ if (this.onclick) this.onclick();
+ return;
+ } else {
+ if (this.onclick && !this.onclick()) return;//e.g. confirmation messages
+ this.open_action();
+ }
+ },
+
+ open_action: function() {
+ if (this.position) this.disable();
+
+ if (this.page_link) {
+ window.location = this.url;
+ } else {
+ if (this.loading_indicator) this.loading_indicator.style.visibility = 'visible';
+ new Ajax.Request(this.url, {
+ asynchronous: true,
+ evalScripts: true,
+ method: this.method,
+ onSuccess: function(request) {
+ if (this.position) {
+ this.insert(request.responseText);
+ if (this.hide_target) this.target.hide();
+ } else {
+ request.evalResponse();
+ }
+ }.bind(this),
+
+ onFailure: function(request) {
+ ActiveScaffold.report_500_response(this.scaffold_id());
+ if (this.position) this.enable()
+ }.bind(this),
+
+ onComplete: function(request) {
+ if (this.loading_indicator) this.loading_indicator.style.visibility = 'hidden';
+ }.bind(this)
+ });
+ }
+ },
+
+ insert: function(content) {
+ throw 'unimplemented'
+ },
+
+ close: function() {
+ this.enable();
+ this.adapter.remove();
+ if (this.hide_target) this.target.show();
+ },
+
+ register_cancel_hooks: function() {
+ // anything in the insert with a class of cancel gets the closer method, and a reference to this object for good measure
+ var self = this;
+ this.adapter.select('.cancel').each(function(elem) {
+ elem.observe('click', this.close_handler.bind(this));
+ elem.link = self;
+ }.bind(this))
+ },
+
+ reload: function() {
+ this.close();
+ this.open();
+ },
+
+ get_new_adapter_id: function() {
+ var id = 'adapter_';
+ var i = 0;
+ while ($(id + i)) i++;
+ return id + i;
+ },
+
+ enable: function() {
+ return this.tag.removeClassName('disabled');
+ },
+
+ disable: function() {
+ return this.tag.addClassName('disabled');
+ },
+
+ is_disabled: function() {
+ return this.tag.hasClassName('disabled');
+ },
+
+ scaffold_id: function() {
+ return this.tag.up('div.active-scaffold').id;
+ }
+}
+
+/**
+ * Concrete classes for record actions
+ */
+ActiveScaffold.Actions.Record = Class.create();
+ActiveScaffold.Actions.Record.prototype = Object.extend(new ActiveScaffold.Actions.Abstract(), {
+ instantiate_link: function(link) {
+ var l = new ActiveScaffold.ActionLink.Record(link, this.target, this.loading_indicator);
+ l.refresh_url = this.options.refresh_url;
+ if (link.hasClassName('delete')) {
+ l.url = l.url.replace(/\/delete(\?.*)?$/, '$1');
+ l.url = l.url.replace(/\/delete\/(.*)/, '/destroy/$1');
+ }
+ if (l.position) l.url = l.url.append_params({adapter: '_list_inline_adapter'});
+ l.set = this;
+ return l;
+ }
+});
+
+ActiveScaffold.ActionLink.Record = Class.create();
+ActiveScaffold.ActionLink.Record.prototype = Object.extend(new ActiveScaffold.ActionLink.Abstract(), {
+ close_previous_adapter: function() {
+ this.set.links.each(function(item) {
+ if (item.url != this.url && item.is_disabled() && item.adapter) item.close();
+ }.bind(this));
+ },
+
+ insert: function(content) {
+ this.close_previous_adapter();
+
+ if (this.position == 'replace') {
+ this.position = 'after';
+ this.hide_target = true;
+ }
+
+ if (this.position == 'after') {
+ new Insertion.After(this.target, content);
+ this.adapter = this.target.next();
+ }
+ else if (this.position == 'before') {
+ new Insertion.Before(this.target, content);
+ this.adapter = this.target.previous();
+ }
+ else {
+ return false;
+ }
+
+ this.adapter.down('a.inline-adapter-close').observe('click', this.close_handler.bind(this));
+ this.register_cancel_hooks();
+
+ new Effect.Highlight(this.adapter.down('td'));
+ },
+
+ close_handler: function(event) {
+ this.close_with_refresh();
+ if (event) Event.stop(event);
+ },
+
+ /* it might simplify things to just override the close function. then the Record and Table links could share more code ... wouldn't need custom close_handler functions, for instance */
+ close_with_refresh: function() {
+ new Ajax.Request(this.refresh_url, {
+ asynchronous: true,
+ evalScripts: true,
+ method: this.method,
+ onSuccess: function(request) {
+ Element.replace(this.target, request.responseText);
+ var new_target = $(this.target.id);
+ if (this.target.hasClassName('even-record')) new_target.addClassName('even-record');
+ this.target = new_target;
+ this.close();
+ }.bind(this),
+
+ onFailure: function(request) {
+ ActiveScaffold.report_500_response(this.scaffold_id());
+ }
+ });
+ },
+
+ enable: function() {
+ this.set.links.each(function(item) {
+ if (item.url != this.url) return;
+ item.tag.removeClassName('disabled');
+ }.bind(this));
+ },
+
+ disable: function() {
+ this.set.links.each(function(item) {
+ if (item.url != this.url) return;
+ item.tag.addClassName('disabled');
+ }.bind(this));
+ }
+});
+
+/**
+ * Concrete classes for table actions
+ */
+ActiveScaffold.Actions.Table = Class.create();
+ActiveScaffold.Actions.Table.prototype = Object.extend(new ActiveScaffold.Actions.Abstract(), {
+ instantiate_link: function(link) {
+ var l = new ActiveScaffold.ActionLink.Table(link, this.target, this.loading_indicator);
+ if (l.position) l.url = l.url.append_params({adapter: '_list_inline_adapter'});
+ return l;
+ }
+});
+
+ActiveScaffold.ActionLink.Table = Class.create();
+ActiveScaffold.ActionLink.Table.prototype = Object.extend(new ActiveScaffold.ActionLink.Abstract(), {
+ insert: function(content) {
+ if (this.position == 'top') {
+ new Insertion.Top(this.target, content);
+ this.adapter = this.target.immediateDescendants().first();
+ }
+ else {
+ throw 'Unknown position "' + this.position + '"'
+ }
+
+ this.adapter.down('a.inline-adapter-close').observe('click', this.close_handler.bind(this));
+ this.register_cancel_hooks();
+
+ new Effect.Highlight(this.adapter.down('td'));
+ },
+
+ close_handler: function(event) {
+ this.close();
+ if (event) Event.stop(event);
+ }
+});
Propchange: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/javascripts/active_scaffold.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/javascripts/dhtml_history.js
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/javascripts/dhtml_history.js?rev=809371&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/javascripts/dhtml_history.js (added)
+++ labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/javascripts/dhtml_history.js Sun Aug 30 16:30:26 2009
@@ -0,0 +1,867 @@
+/*
+Copyright (c) 2007 Brian Dillard and Brad Neuberg:
+Brian Dillard | Project Lead | bdillard@pathf.com | http://blogs.pathf.com/agileajax/
+Brad Neuberg | Original Project Creator | http://codinginparadise.org
+
+SVN r113 from http://code.google.com/p/reallysimplehistory
++ Changes by Ed Wildgoose - MailASail
++ Changed EncodeURIComponent -> EncodeURI
++ Changed DecodeURIComponent -> DecodeURI
++ Changed 'blank.html?' -> '/blank.html?'
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
+(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+ dhtmlHistory: An object that provides history, history data, and bookmarking for DHTML and Ajax applications.
+
+ dependencies:
+ * the historyStorage object included in this file.
+
+*/
+window.dhtmlHistory = {
+
+ /*Public: User-agent booleans*/
+ isIE: false,
+ isOpera: false,
+ isSafari: false,
+ isKonquerer: false,
+ isGecko: false,
+ isSupported: false,
+
+ /*Public: Create the DHTML history infrastructure*/
+ create: function(options) {
+
+ /*
+ options - object to store initialization parameters
+ options.blankURL - string to override the default location of blank.html. Must end in "?"
+ options.debugMode - boolean that causes hidden form fields to be shown for development purposes.
+ options.toJSON - function to override default JSON stringifier
+ options.fromJSON - function to override default JSON parser
+ options.baseTitle - pattern for title changes; example: "Armchair DJ [@@@]" - @@@ will be replaced
+ */
+
+ var that = this;
+
+ /*Set up the historyStorage object; pass in options bundle*/
+ window.historyStorage.setup(options);
+
+ /*Set up our base title if one is passed in*/
+ if (options && options.baseTitle) {
+ if (options.baseTitle.indexOf("@@@") < 0 && historyStorage.debugMode) {
+ throw new Error("Programmer error: options.baseTitle must contain the replacement parameter"
+ + " '@@@' to be useful.");
+ }
+ this.baseTitle = options.baseTitle;
+ }
+
+ /*set user-agent flags*/
+ var UA = navigator.userAgent.toLowerCase();
+ var platform = navigator.platform.toLowerCase();
+ var vendor = navigator.vendor || "";
+ if (vendor === "KDE") {
+ this.isKonqueror = true;
+ this.isSupported = false;
+ } else if (typeof window.opera !== "undefined") {
+ this.isOpera = true;
+ this.isSupported = true;
+ } else if (typeof document.all !== "undefined") {
+ this.isIE = true;
+ this.isSupported = true;
+ } else if (vendor.indexOf("Apple Computer, Inc.") > -1) {
+ this.isSafari = true;
+ this.isSupported = (platform.indexOf("mac") > -1);
+ } else if (UA.indexOf("gecko") != -1) {
+ this.isGecko = true;
+ this.isSupported = true;
+ }
+
+ /*Create Safari/Opera-specific code*/
+ if (this.isSafari) {
+ this.createSafari();
+ } else if (this.isOpera) {
+ this.createOpera();
+ }
+
+ /*Get our initial location*/
+ var initialHash = this.getCurrentLocation();
+
+ /*Save it as our current location*/
+ this.currentLocation = initialHash;
+
+ /*Now that we have a hash, create IE-specific code*/
+ if (this.isIE) {
+ /*Optionally override the URL of IE's blank HTML file*/
+ if (options && options.blankURL) {
+ var u = options.blankURL;
+ /*assign the value, adding the trailing ? if it's not passed in*/
+ this.blankURL = (u.indexOf("?") != u.length - 1
+ ? u + "?"
+ : u
+ );
+ }
+ this.createIE(initialHash);
+ }
+
+ /*Add an unload listener for the page; this is needed for FF 1.5+ because this browser caches all dynamic updates to the
+ page, which can break some of our logic related to testing whether this is the first instance a page has loaded or whether
+ it is being pulled from the cache*/
+
+ var unloadHandler = function() {
+ that.firstLoad = null;
+ };
+
+ this.addEventListener(window,'unload',unloadHandler);
+
+ /*Determine if this is our first page load; for IE, we do this in this.iframeLoaded(), which is fired on pageload. We do it
+ there because we have no historyStorage at this point, which only exists after the page is finished loading in IE*/
+ if (this.isIE) {
+ /*The iframe will get loaded on page load, and we want to ignore this fact*/
+ this.ignoreLocationChange = true;
+ } else {
+ if (!historyStorage.hasKey(this.PAGELOADEDSTRING)) {
+ /*This is our first page load, so ignore the location change and add our special history entry*/
+ this.ignoreLocationChange = true;
+ this.firstLoad = true;
+ historyStorage.put(this.PAGELOADEDSTRING, true);
+ } else {
+ /*This isn't our first page load, so indicate that we want to pay attention to this location change*/
+ this.ignoreLocationChange = false;
+ this.firstLoad = false;
+ /*For browsers other than IE, fire a history change event; on IE, the event will be thrown automatically when its
+ hidden iframe reloads on page load. Unfortunately, we don't have any listeners yet; indicate that we want to fire
+ an event when a listener is added.*/
+ this.fireOnNewListener = true;
+ }
+ }
+
+ /*Other browsers can use a location handler that checks at regular intervals as their primary mechanism; we use it for IE as
+ well to handle an important edge case; see checkLocation() for details*/
+ var locationHandler = function() {
+ that.checkLocation();
+ };
+ setInterval(locationHandler, 100);
+ },
+
+ /*Public: Initialize our DHTML history. You must call this after the page is finished loading. Optionally, you can pass your listener in
+ here so you don't need to make a separate call to addListener*/
+ initialize: function(listener) {
+
+ /*save original document title to plug in when we hit a null-key history point*/
+ this.originalTitle = document.title;
+
+ /*IE needs to be explicitly initialized. IE doesn't autofill form data until the page is finished loading, so we have to wait*/
+ if (this.isIE) {
+ /*If this is the first time this page has loaded*/
+ if (!historyStorage.hasKey(this.PAGELOADEDSTRING)) {
+ /*For IE, we do this in initialize(); for other browsers, we do it in create()*/
+ this.fireOnNewListener = false;
+ this.firstLoad = true;
+ historyStorage.put(this.PAGELOADEDSTRING, true);
+ }
+ /*Else if this is a fake onload event*/
+ else {
+ this.fireOnNewListener = true;
+ this.firstLoad = false;
+ }
+ }
+ /*optional convenience to save a separate call to addListener*/
+ if (listener) {
+ this.addListener(listener);
+ }
+ },
+
+ /*Public: Adds a history change listener. Only one listener is supported at this time.*/
+ addListener: function(listener) {
+ this.listener = listener;
+ /*If the page was just loaded and we should not ignore it, fire an event to our new listener now*/
+ if (this.fireOnNewListener) {
+ this.fireHistoryEvent(this.currentLocation);
+ this.fireOnNewListener = false;
+ }
+ },
+
+ /*Public: Change the current HTML title*/
+ changeTitle: function(historyData) {
+ var winTitle = (historyData && historyData.newTitle
+ /*Plug the new title into the pattern*/
+ ? this.baseTitle.replace('@@@', historyData.newTitle)
+ /*Otherwise, if there is no new title, use the original document title. This is useful when some
+ history changes have title changes and some don't; we can automatically return to the original
+ title rather than leaving a misleading title in the title bar. The same goes for our "virgin"
+ (hashless) page state.*/
+ : this.originalTitle
+ );
+ /*No need to do anything if the title isn't changing*/
+ if (document.title == winTitle) {
+ return;
+ }
+
+
+ /*Now change the DOM*/
+ document.title = winTitle;
+ /*Change it in the iframe, too, for IE*/
+ if (this.isIE) {
+ this.iframe.contentWindow.document.title = winTitle;
+ }
+
+ /*If non-IE, reload the hash so the new title "sticks" in the browser history object*/
+ if (!this.isIE && !this.isOpera) {
+ var hash = decodeURI(document.location.hash);
+ if (hash != "") {
+ var encodedHash = encodeURI(this.removeHash(hash));
+ document.location.hash = encodedHash;
+ } else {
+ //document.location.hash = "#";
+ }
+ }
+ },
+
+ /*Public: Add a history point. Parameters available:
+ * newLocation (required):
+ This will be the #hash value in the URL. Users can bookmark it. It will persist across sessions, so
+ your application should be able to restore itself to a specific state based on just this value. It
+ should be either a simple keyword for a viewstate or else a pseudo-querystring.
+ * historyData (optional):
+ This is for complex data that is relevant only to the current browsing session. It will be available
+ to your application until the browser is closed. If the user comes back to a bookmarked history point
+ during a later session, this data will no longer be available. Don't rely on it for application
+ re-initialization from a bookmark.
+ * historyData.newTitle (optional):
+ This will swap out the html <title> attribute with a new value. If you have set a baseTitle using the
+ options bundle, the value will be plugged into the baseTitle by swapping out the @@@ replacement param.
+ */
+ add: function(newLocation, historyData) {
+
+ var that = this;
+
+ /*Escape the location and remove any leading hash symbols*/
+ var encodedLocation = encodeURI(this.removeHash(newLocation));
+
+ if (this.isSafari) {
+
+ /*Store the history data into history storage - pass in unencoded newLocation since
+ historyStorage does its own encoding*/
+ historyStorage.put(newLocation, historyData);
+
+ /*Save this as our current location*/
+ this.currentLocation = encodedLocation;
+
+ /*Change the browser location*/
+ window.location.hash = encodedLocation;
+
+ /*Save this to the Safari form field*/
+ this.putSafariState(encodedLocation);
+
+ this.changeTitle(historyData);
+
+ } else {
+
+ /*Most browsers require that we wait a certain amount of time before changing the location, such
+ as 200 MS; rather than forcing external callers to use window.setTimeout to account for this,
+ we internally handle it by putting requests in a queue.*/
+ var addImpl = function() {
+
+ /*Indicate that the current wait time is now less*/
+ if (that.currentWaitTime > 0) {
+ that.currentWaitTime = that.currentWaitTime - that.waitTime;
+ }
+
+ /*IE has a strange bug; if the encodedLocation is the same as _any_ preexisting id in the
+ document, then the history action gets recorded twice; throw a programmer exception if
+ there is an element with this ID*/
+ if (document.getElementById(encodedLocation) && that.debugMode) {
+ var e = "Exception: History locations can not have the same value as _any_ IDs that might be in the document,"
+ + " due to a bug in IE; please ask the developer to choose a history location that does not match any HTML"
+ + " IDs in this document. The following ID is already taken and cannot be a location: " + newLocation;
+ throw new Error(e);
+ }
+
+ /*Store the history data into history storage - pass in unencoded newLocation since
+ historyStorage does its own encoding*/
+ historyStorage.put(newLocation, historyData);
+
+ /*Indicate to the browser to ignore this upcomming location change since we're making it programmatically*/
+ that.ignoreLocationChange = true;
+
+ /*Indicate to IE that this is an atomic location change block*/
+ that.ieAtomicLocationChange = true;
+
+ /*Save this as our current location*/
+ that.currentLocation = encodedLocation;
+
+ /*Change the browser location*/
+ window.location.hash = encodedLocation;
+
+ /*Change the hidden iframe's location if on IE*/
+ if (that.isIE) {
+ that.iframe.src = that.blankURL + encodedLocation;
+ }
+
+ /*End of atomic location change block for IE*/
+ that.ieAtomicLocationChange = false;
+
+ that.changeTitle(historyData);
+
+ };
+
+ /*Now queue up this add request*/
+ window.setTimeout(addImpl, this.currentWaitTime);
+
+ /*Indicate that the next request will have to wait for awhile*/
+ this.currentWaitTime = this.currentWaitTime + this.waitTime;
+ }
+ },
+
+ /*Public*/
+ isFirstLoad: function() {
+ return this.firstLoad;
+ },
+
+ /*Public*/
+ getVersion: function() {
+ return this.VERSIONNUMBER;
+ },
+
+ /*- - - - - - - - - - - -*/
+
+ /*Private: Constant for our own internal history event called when the page is loaded*/
+ PAGELOADEDSTRING: "DhtmlHistory_pageLoaded",
+
+ VERSIONNUMBER: "0.8",
+
+ /*
+ Private: Pattern for title changes. Example: "Armchair DJ [@@@]" where @@@ will be relaced by values passed to add();
+ Default is just the title itself, hence "@@@"
+ */
+ baseTitle: "@@@",
+
+ /*Private: Placeholder variable for the original document title; will be set in ititialize()*/
+ originalTitle: null,
+
+ /*Private: URL for the blank html file we use for IE; can be overridden via the options bundle. Otherwise it must be served
+ in same directory as this library*/
+ blankURL: "/blank.html?",
+
+ /*Private: Our history change listener.*/
+ listener: null,
+
+ /*Private: MS to wait between add requests - will be reset for certain browsers*/
+ waitTime: 200,
+
+ /*Private: MS before an add request can execute*/
+ currentWaitTime: 0,
+
+ /*Private: Our current hash location, without the "#" symbol.*/
+ currentLocation: null,
+
+ /*Private: Hidden iframe used to IE to detect history changes*/
+ iframe: null,
+
+ /*Private: Flags and DOM references used only by Safari*/
+ safariHistoryStartPoint: null,
+ safariStack: null,
+ safariLength: null,
+
+ /*Private: Flag used to keep checkLocation() from doing anything when it discovers location changes we've made ourselves
+ programmatically with the add() method. Basically, add() sets this to true. When checkLocation() discovers it's true,
+ it refrains from firing our listener, then resets the flag to false for next cycle. That way, our listener only gets fired on
+ history change events triggered by the user via back/forward buttons and manual hash changes. This flag also helps us set up
+ IE's special iframe-based method of handling history changes.*/
+ ignoreLocationChange: null,
+
+ /*Private: A flag that indicates that we should fire a history change event when we are ready, i.e. after we are initialized and
+ we have a history change listener. This is needed due to an edge case in browsers other than IE; if you leave a page entirely
+ then return, we must fire this as a history change event. Unfortunately, we have lost all references to listeners from earlier,
+ because JavaScript clears out.*/
+ fireOnNewListener: null,
+
+ /*Private: A variable that indicates whether this is the first time this page has been loaded. If you go to a web page, leave it
+ for another one, and then return, the page's onload listener fires again. We need a way to differentiate between the first page
+ load and subsequent ones. This variable works hand in hand with the pageLoaded variable we store into historyStorage.*/
+ firstLoad: null,
+
+ /*Private: A variable to handle an important edge case in IE. In IE, if a user manually types an address into their browser's
+ location bar, we must intercept this by calling checkLocation() at regular intervals. However, if we are programmatically
+ changing the location bar ourselves using the add() method, we need to ignore these changes in checkLocation(). Unfortunately,
+ these changes take several lines of code to complete, so for the duration of those lines of code, we set this variable to true.
+ That signals to checkLocation() to ignore the change-in-progress. Once we're done with our chunk of location-change code in
+ add(), we set this back to false. We'll do the same thing when capturing user-entered address changes in checkLocation itself.*/
+ ieAtomicLocationChange: null,
+
+ /*Private: Generic utility function for attaching events*/
+ addEventListener: function(o,e,l) {
+ if (o.addEventListener) {
+ o.addEventListener(e,l,false);
+ } else if (o.attachEvent) {
+ o.attachEvent('on'+e,function() {
+ l(window.event);
+ });
+ }
+ },
+
+
+ /*Private: Create IE-specific DOM nodes and overrides*/
+ createIE: function(initialHash) {
+ /*write out a hidden iframe for IE and set the amount of time to wait between add() requests*/
+ this.waitTime = 400;/*IE needs longer between history updates*/
+ var styles = (historyStorage.debugMode
+ ? 'width: 800px;height:80px;border:1px solid black;'
+ : historyStorage.hideStyles
+ );
+ var iframeID = "rshHistoryFrame";
+ var iframeHTML = '<iframe frameborder="0" id="' + iframeID + '" style="' + styles + '" src="' + this.blankURL + initialHash + '"></iframe>';
+ document.write(iframeHTML);
+ this.iframe = document.getElementById(iframeID);
+ },
+
+ /*Private: Create Opera-specific DOM nodes and overrides*/
+ createOpera: function() {
+ this.waitTime = 400;/*Opera needs longer between history updates*/
+ var imgHTML = '<img src="javascript:location.href=\'javascript:dhtmlHistory.checkLocation();\';" style="' + historyStorage.hideStyles + '" />';
+ document.write(imgHTML);
+ },
+
+ /*Private: Create Safari-specific DOM nodes and overrides*/
+ createSafari: function() {
+ var formID = "rshSafariForm";
+ var stackID = "rshSafariStack";
+ var lengthID = "rshSafariLength";
+ var formStyles = historyStorage.debugMode ? historyStorage.showStyles : historyStorage.hideStyles;
+ var stackStyles = (historyStorage.debugMode
+ ? 'width: 800px;height:80px;border:1px solid black;'
+ : historyStorage.hideStyles
+ );
+ var lengthStyles = (historyStorage.debugMode
+ ? 'width:800px;height:20px;border:1px solid black;margin:0;padding:0;'
+ : historyStorage.hideStyles
+ );
+ var safariHTML = '<form id="' + formID + '" style="' + formStyles + '">'
+ + '<textarea style="' + stackStyles + '" id="' + stackID + '">[]</textarea>'
+ + '<input type="text" style="' + lengthStyles + '" id="' + lengthID + '" value=""/>'
+ + '</form>';
+ document.write(safariHTML);
+ this.safariStack = document.getElementById(stackID);
+ this.safariLength = document.getElementById(lengthID);
+ if (!historyStorage.hasKey(this.PAGELOADEDSTRING)) {
+ this.safariHistoryStartPoint = history.length;
+ this.safariLength.value = this.safariHistoryStartPoint;
+ } else {
+ this.safariHistoryStartPoint = this.safariLength.value;
+ }
+ },
+
+ /*TODO: make this public again?*/
+ /*Private: Get browser's current hash location; for Safari, read value from a hidden form field*/
+ getCurrentLocation: function() {
+ var r = (this.isSafari
+ ? this.getSafariState()
+ : this.getCurrentHash()
+ );
+ return r;
+ },
+
+ /*TODO: make this public again?*/
+ /*Private: Manually parse the current url for a hash; tip of the hat to YUI*/
+ getCurrentHash: function() {
+ var r = window.location.href;
+ var i = r.indexOf("#");
+ return (i >= 0
+ ? r.substr(i+1)
+ : ""
+ );
+ },
+
+ /*Private: Safari method to read the history stack from a hidden form field*/
+ getSafariStack: function() {
+ var r = this.safariStack.value;
+ return historyStorage.fromJSON(r);
+ },
+ /*Private: Safari method to read from the history stack*/
+ getSafariState: function() {
+ var stack = this.getSafariStack();
+ var state = stack[history.length - this.safariHistoryStartPoint - 1];
+ return state;
+ },
+ /*Private: Safari method to write the history stack to a hidden form field*/
+ putSafariState: function(newLocation) {
+ var stack = this.getSafariStack();
+ stack[history.length - this.safariHistoryStartPoint] = newLocation;
+ this.safariStack.value = historyStorage.toJSON(stack);
+ },
+
+ /*Private: Notify the listener of new history changes.*/
+ fireHistoryEvent: function(newHash) {
+ var decodedHash = decodeURI(newHash)
+ /*extract the value from our history storage for this hash*/
+ var historyData = historyStorage.get(decodedHash);
+ this.changeTitle(historyData);
+ /*call our listener*/
+ this.listener.call(null, decodedHash, historyData);
+ },
+
+ /*Private: See if the browser has changed location. This is the primary history mechanism for Firefox. For IE, we use this to
+ handle an important edge case: if a user manually types in a new hash value into their IE location bar and press enter, we want to
+ to intercept this and notify any history listener.*/
+ checkLocation: function() {
+
+ /*Ignore any location changes that we made ourselves for browsers other than IE*/
+ if (!this.isIE && this.ignoreLocationChange) {
+ this.ignoreLocationChange = false;
+ return;
+ }
+
+ /*If we are dealing with IE and we are in the middle of making a location change from an iframe, ignore it*/
+ if (!this.isIE && this.ieAtomicLocationChange) {
+ return;
+ }
+
+ /*Get hash location*/
+ var hash = this.getCurrentLocation();
+
+ /*Do nothing if there's been no change*/
+ if (hash == this.currentLocation) {
+ return;
+ }
+
+ /*In IE, users manually entering locations into the browser; we do this by comparing the browser's location against the
+ iframe's location; if they differ, we are dealing with a manual event and need to place it inside our history, otherwise
+ we can return*/
+ this.ieAtomicLocationChange = true;
+
+ if (this.isIE && this.getIframeHash() != hash) {
+ this.iframe.src = this.blankURL + hash;
+ }
+ else if (this.isIE) {
+ /*the iframe is unchanged*/
+ return;
+ }
+
+ /*Save this new location*/
+ this.currentLocation = hash;
+
+ this.ieAtomicLocationChange = false;
+
+ /*Notify listeners of the change*/
+ this.fireHistoryEvent(hash);
+ },
+
+ /*Private: Get the current location of IE's hidden iframe.*/
+ getIframeHash: function() {
+ var doc = this.iframe.contentWindow.document;
+ var hash = String(doc.location.search);
+ if (hash.length == 1 && hash.charAt(0) == "?") {
+ hash = "";
+ }
+ else if (hash.length >= 2 && hash.charAt(0) == "?") {
+ hash = hash.substring(1);
+ }
+ return hash;
+ },
+
+ /*Private: Remove any leading hash that might be on a location.*/
+ removeHash: function(hashValue) {
+ var r;
+ if (hashValue === null || hashValue === undefined) {
+ r = null;
+ }
+ else if (hashValue === "") {
+ r = "";
+ }
+ else if (hashValue.length == 1 && hashValue.charAt(0) == "#") {
+ r = "";
+ }
+ else if (hashValue.length > 1 && hashValue.charAt(0) == "#") {
+ r = hashValue.substring(1);
+ }
+ else {
+ r = hashValue;
+ }
+ return r;
+ },
+
+ /*Private: For IE, tell when the hidden iframe has finished loading.*/
+ iframeLoaded: function(newLocation) {
+ /*ignore any location changes that we made ourselves*/
+ if (this.ignoreLocationChange) {
+ this.ignoreLocationChange = false;
+ return;
+ }
+
+ /*Get the new location*/
+ var hash = String(newLocation.search);
+ if (hash.length == 1 && hash.charAt(0) == "?") {
+ hash = "";
+ }
+ else if (hash.length >= 2 && hash.charAt(0) == "?") {
+ hash = hash.substring(1);
+ }
+ /*Keep the browser location bar in sync with the iframe hash*/
+ window.location.hash = hash;
+
+ /*Notify listeners of the change*/
+ this.fireHistoryEvent(hash);
+ }
+
+
+};
+
+/*
+ historyStorage: An object that uses a hidden form to store history state across page loads. The mechanism for doing so relies on
+ the fact that browsers save the text in form data for the life of the browser session, which means the text is still there when
+ the user navigates back to the page. This object can be used independently of the dhtmlHistory object for caching of Ajax
+ session information.
+
+ dependencies:
+ * json2007.js (included in a separate file) or alternate JSON methods passed in through an options bundle.
+*/
+window.historyStorage = {
+
+ /*Public: Set up our historyStorage object for use by dhtmlHistory or other objects*/
+ setup: function(options) {
+
+ /*
+ options - object to store initialization parameters - passed in from dhtmlHistory or directly into historyStorage
+ options.debugMode - boolean that causes hidden form fields to be shown for development purposes.
+ options.toJSON - function to override default JSON stringifier
+ options.fromJSON - function to override default JSON parser
+ */
+
+ /*process init parameters*/
+ if (typeof options !== "undefined") {
+ if (options.debugMode) {
+ this.debugMode = options.debugMode;
+ }
+ if (options.toJSON) {
+ this.toJSON = options.toJSON;
+ }
+ if (options.fromJSON) {
+ this.fromJSON = options.fromJSON;
+ }
+ }
+
+ /*write a hidden form and textarea into the page; we'll stow our history stack here*/
+ var formID = "rshStorageForm";
+ var textareaID = "rshStorageField";
+ var formStyles = this.debugMode ? historyStorage.showStyles : historyStorage.hideStyles;
+ var textareaStyles = (historyStorage.debugMode
+ ? 'width: 800px;height:80px;border:1px solid black;'
+ : historyStorage.hideStyles
+ );
+ var textareaHTML = '<form id="' + formID + '" style="' + formStyles + '">'
+ + '<textarea id="' + textareaID + '" style="' + textareaStyles + '"></textarea>'
+ + '</form>';
+ document.write(textareaHTML);
+ this.storageField = document.getElementById(textareaID);
+ if (typeof window.opera !== "undefined") {
+ this.storageField.focus();/*Opera needs to focus this element before persisting values in it*/
+ }
+ },
+
+ /*Public*/
+ put: function(key, value) {
+
+ var encodedKey = encodeURI(key);
+
+ this.assertValidKey(encodedKey);
+ /*if we already have a value for this, remove the value before adding the new one*/
+ if (this.hasKey(key)) {
+ this.remove(key);
+ }
+ /*store this new key*/
+ this.storageHash[encodedKey] = value;
+ /*save and serialize the hashtable into the form*/
+ this.saveHashTable();
+ },
+
+ /*Public*/
+ get: function(key) {
+
+ var encodedKey = encodeURI(key);
+
+ this.assertValidKey(encodedKey);
+ /*make sure the hash table has been loaded from the form*/
+ this.loadHashTable();
+ var value = this.storageHash[encodedKey];
+ if (value === undefined) {
+ value = null;
+ }
+ return value;
+ },
+
+ /*Public*/
+ remove: function(key) {
+
+ var encodedKey = encodeURI(key);
+
+ this.assertValidKey(encodedKey);
+ /*make sure the hash table has been loaded from the form*/
+ this.loadHashTable();
+ /*delete the value*/
+ delete this.storageHash[encodedKey];
+ /*serialize and save the hash table into the form*/
+ this.saveHashTable();
+ },
+
+ /*Public: Clears out all saved data.*/
+ reset: function() {
+ this.storageField.value = "";
+ this.storageHash = {};
+ },
+
+ /*Public*/
+ hasKey: function(key) {
+
+ var encodedKey = encodeURI(key);
+
+ this.assertValidKey(encodedKey);
+ /*make sure the hash table has been loaded from the form*/
+ this.loadHashTable();
+ return (typeof this.storageHash[encodedKey] !== "undefined");
+ },
+
+ /*Public*/
+ isValidKey: function(key) {
+ return (typeof key === "string");
+ //TODO - should we ban hash signs and other special characters?
+ },
+
+ /*- - - - - - - - - - - -*/
+
+ /*Private - CSS strings utilized by both objects to hide or show behind-the-scenes DOM elements*/
+ showStyles: 'border:0;margin:0;padding:0;',
+ hideStyles: 'left:-1000px;top:-1000px;width:1px;height:1px;border:0;position:absolute;',
+
+ /*Private - debug mode flag*/
+ debugMode: false,
+
+ /*Private: Our hash of key name/values.*/
+ storageHash: {},
+
+ /*Private: If true, we have loaded our hash table out of the storage form.*/
+ hashLoaded: false,
+
+ /*Private: DOM reference to our history field*/
+ storageField: null,
+
+ /*Private: Assert that a key is valid; throw an exception if it not.*/
+ assertValidKey: function(key) {
+ var isValid = this.isValidKey(key);
+ if (!isValid && this.debugMode) {
+ throw new Error("Please provide a valid key for window.historyStorage. Invalid key = " + key + ".");
+ }
+ },
+
+ /*Private: Load the hash table up from the form.*/
+ loadHashTable: function() {
+ if (!this.hashLoaded) {
+ var serializedHashTable = this.storageField.value;
+ if (serializedHashTable !== "" && serializedHashTable !== null) {
+ this.storageHash = this.fromJSON(serializedHashTable);
+ this.hashLoaded = true;
+ }
+ }
+ },
+ /*Private: Save the hash table into the form.*/
+ saveHashTable: function() {
+ this.loadHashTable();
+ var serializedHashTable = this.toJSON(this.storageHash);
+ this.storageField.value = serializedHashTable;
+ },
+ /*Private: Bridges for our JSON implementations - both rely on 2007 JSON.org library - can be overridden by options bundle*/
+ toJSON: function(o) {
+ return o.toJSONString();
+ },
+ fromJSON: function(s) {
+ return s.parseJSON();
+ }
+};
+
+
+/*******************************************************************/
+/** QueryString Object from http://adamv.com/dev/javascript/querystring */
+/* Client-side access to querystring name=value pairs
+ Version 1.3
+ 28 May 2008
+
+ License (Simplified BSD):
+ http://adamv.com/dev/javascript/qslicense.txt
+*/
+function Querystring(qs) { // optionally pass a querystring to parse
+ this.params = {};
+
+ if (qs == null) qs = location.search.substring(1, location.search.length);
+ if (qs.length == 0) return;
+
+// Turn <plus> back to <space>
+// See: http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4.1
+ qs = qs.replace(/\+/g, ' ');
+ var args = qs.split('&'); // parse out name/value pairs separated via &
+
+// split out each name=value pair
+ for (var i = 0; i < args.length; i++) {
+ var pair = args[i].split('=');
+ var name = decodeURI(pair[0]);
+
+ var value = (pair.length==2)
+ ? decodeURI(pair[1])
+ : name;
+
+ this.params[name] = value;
+ }
+}
+
+Querystring.prototype.get = function(key, default_) {
+ var value = this.params[key];
+ return (value != null) ? value : default_;
+}
+
+Querystring.prototype.contains = function(key) {
+ var value = this.params[key];
+ return (value != null);
+}
+
+/*******************************************************************/
+/* Added by Ed Wildgoose - MailASail */
+/* Initialise the library and add our history callback */
+/*******************************************************************/
+window.dhtmlHistory.create({
+ toJSON: function(o) {
+ return Object.toJSON(o);
+ }
+ , fromJSON: function(s) {
+ return s.evalJSON();
+ }
+
+ // Enable this to assist with debugging
+// , debugMode: true
+
+ // dhtmlHistory has been modified not to need the next line
+ // But left in for robustness when updating dhtmlHistory
+ , blankURL: '/blank.html?'
+});
+
+/** Our callback to receive history
+ change events. */
+var handleHistoryChange = function(pageId, pageData) {
+ if (!pageData) return;
+ var info = pageId.split(':');
+ var id = info[0];
+ pageData += '&_method=get';
+ new Ajax.Updater(id+'-content', pageData, {asynchronous:true, evalScripts:true, method: 'get', onLoading:function(request){Element.show(id+'-pagination-loading-indicator');}});
+}
+
+window.onload = function() {
+ dhtmlHistory.initialize(handleHistoryChange);
+};
+
Propchange: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/javascripts/dhtml_history.js
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/javascripts/dhtml_history.js
------------------------------------------------------------------------------
svn:executable = *
Added: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/javascripts/form_enhancements.js
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/javascripts/form_enhancements.js?rev=809371&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/javascripts/form_enhancements.js (added)
+++ labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/javascripts/form_enhancements.js Sun Aug 30 16:30:26 2009
@@ -0,0 +1,114 @@
+
+// TODO Change to dropping the name property off the input element when in example mode
+TextFieldWithExample = Class.create();
+TextFieldWithExample.prototype = {
+ initialize: function(inputElementId, defaultText, options) {
+ this.setOptions(options);
+
+ this.input = $(inputElementId);
+ this.name = this.input.name;
+ this.defaultText = defaultText;
+ this.createHiddenInput();
+
+ this.checkAndShowExample();
+
+ Event.observe(this.input, "blur", this.onBlur.bindAsEventListener(this));
+ Event.observe(this.input, "focus", this.onFocus.bindAsEventListener(this));
+ Event.observe(this.input, "select", this.onFocus.bindAsEventListener(this));
+ Event.observe(this.input, "keydown", this.onKeyPress.bindAsEventListener(this));
+ Event.observe(this.input, "click", this.onClick.bindAsEventListener(this));
+ },
+ createHiddenInput: function() {
+ this.hiddenInput = document.createElement("input");
+ this.hiddenInput.type = "hidden";
+ this.hiddenInput.value = "";
+ this.input.parentNode.appendChild(this.hiddenInput);
+ },
+ setOptions: function(options) {
+ this.options = { exampleClassName: 'example' };
+ Object.extend(this.options, options || {});
+ },
+ onKeyPress: function(event) {
+ if (!event) var event = window.event;
+ var code = (event.which) ? event.which : event.keyCode
+ if (this.isAlphanumeric(code)) {
+ this.removeExample();
+ }
+ },
+ onBlur: function(event) {
+ this.checkAndShowExample();
+ },
+ onFocus: function(event) {
+ if (this.exampleShown()) {
+ this.removeExample();
+ }
+ },
+ onClick: function(event) {
+ this.removeExample();
+ },
+ isAlphanumeric: function(keyCode) {
+ return keyCode >= 40 && keyCode <= 90;
+ },
+ checkAndShowExample: function() {
+ if (this.input.value == '') {
+ this.input.value = this.defaultText;
+ this.input.name = null;
+ this.hiddenInput.name = this.name;
+ Element.addClassName(this.input, this.options.exampleClassName);
+ }
+ },
+ removeExample: function() {
+ if (this.exampleShown()) {
+ this.input.value = '';
+ this.input.name = this.name;
+ this.hiddenInput.name = null;
+ Element.removeClassName(this.input, this.options.exampleClassName);
+ }
+ },
+ exampleShown: function() {
+ return Element.hasClassName(this.input, this.options.exampleClassName);
+ }
+}
+
+Form.disable = function(form) {
+ var elements = this.getElements(form);
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i];
+ try { element.blur(); } catch (e) {}
+ element.disabled = 'disabled';
+ Element.addClassName(element, 'disabled');
+ }
+ }
+Form.enable = function(form) {
+ var elements = this.getElements(form);
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i];
+ element.disabled = '';
+ Element.removeClassName(element, 'disabled');
+ }
+ }
+
+DraggableLists = Class.create({
+ initialize: function(list) {
+ list = $(list).addClassName('draggable-list');
+ var list_selected = list.cloneNode(false).addClassName('selected');
+ list_selected.id += '_seleted';
+ list.select('input[type=checkbox]').each(function(item) {
+ var li = item.up('li');
+ li.down('label').htmlFor = null;
+ new Draggable(li, {revert: 'failure', ghosting: true});
+ if (item.checked) list_selected.insert(li.remove());
+ });
+ list.insert({after: list_selected});
+ Droppables.add(list, {hoverclass: 'hover', containment: list_selected.id, onDrop: this.drop_to_list});
+ Droppables.add(list_selected, {hoverclass: 'hover', containment: list.id, onDrop: this.drop_to_list});
+ list.undoPositioned(); // undo positioned to fix dragging from elements with overflow auto
+ list_selected.undoPositioned();
+ },
+
+ drop_to_list: function(draggable, droppable, event) {
+ droppable.insert(draggable.remove());
+ draggable.setStyle({left: '0px', top: '0px'});
+ draggable.down('input').checked = droppable.hasClassName('selected');
+ }
+});
Propchange: labs/consite/trunk/conferences/vendor/plugins/active_scaffold/frontends/default/javascripts/form_enhancements.js
------------------------------------------------------------------------------
svn:eol-style = native
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org