diff options
author | Louise Crow <louise.crow@gmail.com> | 2013-09-24 11:29:31 +0100 |
---|---|---|
committer | Louise Crow <louise.crow@gmail.com> | 2013-09-24 11:29:31 +0100 |
commit | d8deb8418b4cd26c68eb1301959e156c19b111e2 (patch) | |
tree | 99c346db95d17be9c5105ce47d5f3ac8e943e952 | |
parent | 8459314b691f5b02277035219cd58f510d100a77 (diff) | |
parent | 75542416a1cc36b353ade557b1bc4f729b02423a (diff) |
Merge branch 'release/0.14'0.14
Conflicts:
locale/bg/app.po
locale/fr/app.po
locale/fr_CA/app.po
locale/he_IL/app.po
locale/hr/app.po
locale/it/app.po
locale/nb_NO/app.po
locale/pl/app.po
locale/sv/app.po
locale/vi/app.po
200 files changed, 8513 insertions, 11558 deletions
diff --git a/.gitignore b/.gitignore index 75c348ff9..f328f6705 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ config/httpd.conf alaveteli.sublime* webrat.log /.rbenv-version +/db/development_structure.sql @@ -10,40 +10,42 @@ source 'https://rubygems.org' gem 'rails', '3.1.12' gem 'pg' +# New gem releases aren't being done. master is newer and supports Rails > 3.0 +gem 'acts_as_versioned', :git => 'git://github.com/technoweenie/acts_as_versioned.git' +gem 'capistrano' gem 'charlock_holmes' +gem 'dynamic_form' +gem 'exception_notification' gem 'fastercsv', '>=1.5.5' +gem 'jquery-rails', '~> 2.1' gem 'json' gem 'mahoro' gem 'net-http-local' gem 'net-purge' +gem 'newrelic_rpm' gem 'rack' +gem 'rake', '0.9.2.2' gem 'rails-i18n' gem 'rdoc' gem 'recaptcha', '~> 0.3.1', :require => 'recaptcha/rails' # :require avoids "already initialized constant" warnings gem 'rmagick', :require => 'RMagick' -gem 'rake', '0.9.2.2' gem 'ruby-msg', '~> 1.5.0' +gem "statistics2", "~> 0.54" +gem 'syslog_protocol' gem 'vpim' gem 'will_paginate' # when 1.2.9 is released by the maintainer, we can stop using this fork: gem 'xapian-full-alaveteli', '~> 1.2.9.5' gem 'xml-simple', :require => 'xmlsimple' gem 'zip' -gem 'capistrano' -gem 'syslog_protocol' -gem 'newrelic_rpm' -# Use until this PR is merged: https://github.com/svenfuchs/globalize3/pull/191 -gem 'globalize3', :git => 'git://github.com/henare/globalize3.git', :branch => 'not-null-empty-attributes' -# New gem releases aren't being done. master is newer and supports Rails > 3.0 -gem 'acts_as_versioned', :git => 'git://github.com/technoweenie/acts_as_versioned.git' -gem 'dynamic_form' -gem 'exception_notification' # Gems related to internationalisation gem 'fast_gettext' gem 'gettext_i18n_rails' gem 'gettext' +# Use until this PR is merged: https://github.com/svenfuchs/globalize3/pull/191 +gem 'globalize3', :git => 'git://github.com/henare/globalize3.git', :branch => 'not-null-empty-attributes' gem 'locale' gem 'routing-filter' gem 'unicode' @@ -53,6 +55,7 @@ group :test do gem 'fakeweb' gem 'coveralls', :require => false gem 'webrat' + gem 'nokogiri' end group :development do @@ -68,6 +71,7 @@ group :develop do end group :test, :development do + gem 'factory_girl_rails', '~> 1.7' gem 'rspec-rails' gem 'spork-rails' end diff --git a/Gemfile.lock b/Gemfile.lock index fb83dadd7..4494c2342 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -85,6 +85,11 @@ GEM eventmachine (1.0.3) exception_notification (3.0.1) actionmailer (>= 3.0.4) + factory_girl (2.6.4) + activesupport (>= 2.3.9) + factory_girl_rails (1.7.0) + factory_girl (~> 2.6.0) + railties (>= 3.0.0) fakeweb (1.3.0) fast_gettext (0.7.0) fastercsv (1.5.5) @@ -99,6 +104,9 @@ GEM highline (1.6.19) hike (1.2.2) i18n (0.6.4) + jquery-rails (2.3.0) + railties (>= 3.0, < 5.0) + thor (>= 0.14, < 2.0) json (1.8.0) linecache (0.46) rbx-require-relative (> 0.0.4) @@ -214,6 +222,7 @@ GEM rack (~> 1.0) tilt (~> 1.1, != 1.3.0) sqlite3 (1.3.7) + statistics2 (0.54) syslog_protocol (0.9.2) text (1.2.1) thin (1.5.1) @@ -252,12 +261,14 @@ DEPENDENCIES debugger dynamic_form exception_notification + factory_girl_rails (~> 1.7) fakeweb fast_gettext fastercsv (>= 1.5.5) gettext gettext_i18n_rails globalize3! + jquery-rails (~> 2.1) json locale mahoro @@ -265,6 +276,7 @@ DEPENDENCIES net-http-local net-purge newrelic_rpm + nokogiri pg rack rails (= 3.1.12) @@ -278,6 +290,7 @@ DEPENDENCIES ruby-debug ruby-msg (~> 1.5.0) spork-rails + statistics2 (~> 0.54) syslog_protocol unicode unidecode diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index 0bccd3358..8b606ea85 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb @@ -17,7 +17,7 @@ class AdminController < ApplicationController end # Always give full stack trace for admin interface - def local_request? + def show_rails_exceptions? true end @@ -29,8 +29,7 @@ class AdminController < ApplicationController FileUtils.rm_rf(cache_subpath) # Remove any download zips - download_dir = request_download_zip_dir(info_request) - FileUtils.rm_rf(download_dir) + FileUtils.rm_rf(info_request.download_zip_dir) # Remove the database caches of body / attachment text (the attachment text # one is after privacy rules are applied) diff --git a/app/controllers/admin_general_controller.rb b/app/controllers/admin_general_controller.rb index ec5f95eda..196616ed6 100644 --- a/app/controllers/admin_general_controller.rb +++ b/app/controllers/admin_general_controller.rb @@ -5,7 +5,6 @@ # Email: hello@mysociety.org; WWW: http://www.mysociety.org/ class AdminGeneralController < AdminController - skip_before_filter :authenticate, :only => :admin_js def index # ensure we have a trailing slash @@ -142,9 +141,5 @@ class AdminGeneralController < AdminController @request_env = request.env end - # TODO: Remove this when support for proxy admin interface is removed - def admin_js - render :layout => false, :content_type => "application/javascript" - end end diff --git a/app/controllers/admin_incoming_message_controller.rb b/app/controllers/admin_incoming_message_controller.rb new file mode 100644 index 000000000..6b50d0e36 --- /dev/null +++ b/app/controllers/admin_incoming_message_controller.rb @@ -0,0 +1,80 @@ +class AdminIncomingMessageController < AdminController + + def edit + @incoming_message = IncomingMessage.find(params[:id]) + end + + def update + @incoming_message = IncomingMessage.find(params[:id]) + old_prominence = @incoming_message.prominence + old_prominence_reason = @incoming_message.prominence_reason + @incoming_message.prominence = params[:incoming_message][:prominence] + @incoming_message.prominence_reason = params[:incoming_message][:prominence_reason] + if @incoming_message.save + @incoming_message.info_request.log_event('edit_incoming', + :incoming_message_id => @incoming_message.id, + :editor => admin_current_user(), + :old_prominence => old_prominence, + :prominence => @incoming_message.prominence, + :old_prominence_reason => old_prominence_reason, + :prominence_reason => @incoming_message.prominence_reason) + expire_for_request(@incoming_message.info_request) + flash[:notice] = 'Incoming message successfully updated.' + redirect_to admin_request_show_url(@incoming_message.info_request) + else + render :action => 'edit' + end + end + + def destroy + @incoming_message = IncomingMessage.find(params[:incoming_message_id]) + @info_request = @incoming_message.info_request + incoming_message_id = @incoming_message.id + + @incoming_message.fully_destroy + @incoming_message.info_request.log_event("destroy_incoming", + { :editor => admin_current_user(), :deleted_incoming_message_id => incoming_message_id }) + # expire cached files + expire_for_request(@info_request) + flash[:notice] = 'Incoming message successfully destroyed.' + redirect_to admin_request_show_url(@info_request) + end + + def redeliver + incoming_message = IncomingMessage.find(params[:redeliver_incoming_message_id]) + message_ids = params[:url_title].split(",").each {|x| x.strip} + previous_request = incoming_message.info_request + destination_request = nil + ActiveRecord::Base.transaction do + for m in message_ids + if m.match(/^[0-9]+$/) + destination_request = InfoRequest.find_by_id(m.to_i) + else + destination_request = InfoRequest.find_by_url_title!(m) + end + if destination_request.nil? + flash[:error] = "Failed to find destination request '" + m + "'" + return redirect_to admin_request_show_url(previous_request) + end + + raw_email_data = incoming_message.raw_email.data + mail = MailHandler.mail_from_raw_email(raw_email_data) + destination_request.receive(mail, raw_email_data, true) + + incoming_message_id = incoming_message.id + incoming_message.info_request.log_event("redeliver_incoming", { + :editor => admin_current_user(), + :destination_request => destination_request.id, + :deleted_incoming_message_id => incoming_message_id + }) + + flash[:notice] = "Message has been moved to request(s). Showing the last one:" + end + # expire cached files + expire_for_request(previous_request) + incoming_message.fully_destroy + end + redirect_to admin_request_show_url(destination_request) + end + +end diff --git a/app/controllers/admin_outgoing_message_controller.rb b/app/controllers/admin_outgoing_message_controller.rb new file mode 100644 index 000000000..ec0981677 --- /dev/null +++ b/app/controllers/admin_outgoing_message_controller.rb @@ -0,0 +1,47 @@ +class AdminOutgoingMessageController < AdminController + + def edit + @outgoing_message = OutgoingMessage.find(params[:id]) + end + + def destroy + @outgoing_message = OutgoingMessage.find(params[:outgoing_message_id]) + @info_request = @outgoing_message.info_request + outgoing_message_id = @outgoing_message.id + + @outgoing_message.fully_destroy + @outgoing_message.info_request.log_event("destroy_outgoing", + { :editor => admin_current_user(), :deleted_outgoing_message_id => outgoing_message_id }) + + flash[:notice] = 'Outgoing message successfully destroyed.' + redirect_to admin_request_show_url(@info_request) + end + + def update + @outgoing_message = OutgoingMessage.find(params[:id]) + + old_body = @outgoing_message.body + old_prominence = @outgoing_message.prominence + old_prominence_reason = @outgoing_message.prominence_reason + @outgoing_message.prominence = params[:outgoing_message][:prominence] + @outgoing_message.prominence_reason = params[:outgoing_message][:prominence_reason] + @outgoing_message.body = params[:outgoing_message][:body] + if @outgoing_message.save + @outgoing_message.info_request.log_event("edit_outgoing", + { :outgoing_message_id => @outgoing_message.id, + :editor => admin_current_user(), + :old_body => old_body, + :body => @outgoing_message.body, + :old_prominence => old_prominence, + :old_prominence_reason => old_prominence_reason, + :prominence => @outgoing_message.prominence, + :prominence_reason => @outgoing_message.prominence_reason }) + flash[:notice] = 'Outgoing message successfully updated.' + expire_for_request(@outgoing_message.info_request) + redirect_to admin_request_show_url(@outgoing_message.info_request) + else + render :action => 'edit' + end + end + +end diff --git a/app/controllers/admin_public_body_controller.rb b/app/controllers/admin_public_body_controller.rb index ec2a08dbc..e0da234b0 100644 --- a/app/controllers/admin_public_body_controller.rb +++ b/app/controllers/admin_public_body_controller.rb @@ -14,6 +14,7 @@ class AdminPublicBodyController < AdminController def _lookup_query_internal @locale = self.locale_from_params() + underscore_locale = @locale.gsub '-', '_' I18n.with_locale(@locale) do @query = params[:query] if @query == "" @@ -23,10 +24,10 @@ class AdminPublicBodyController < AdminController if @page == "" @page = nil end - @public_bodies = PublicBody.joins(:translations).where(@query.nil? ? "public_body_translations.locale = '#{@locale}'" : + @public_bodies = PublicBody.joins(:translations).where(@query.nil? ? "public_body_translations.locale = '#{underscore_locale}'" : ["(lower(public_body_translations.name) like lower('%'||?||'%') or lower(public_body_translations.short_name) like lower('%'||?||'%') or - lower(public_body_translations.request_email) like lower('%'||?||'%' )) AND (public_body_translations.locale = '#{@locale}')", @query, @query, @query]).paginate :order => "public_body_translations.name", :page => @page, :per_page => 100 + lower(public_body_translations.request_email) like lower('%'||?||'%' )) AND (public_body_translations.locale = '#{underscore_locale}')", @query, @query, @query]).paginate :order => "public_body_translations.name", :page => @page, :per_page => 100 end @public_bodies_by_tag = PublicBody.find_by_tag(@query) end diff --git a/app/controllers/admin_request_controller.rb b/app/controllers/admin_request_controller.rb index 40ccfb98c..4d45ced8b 100644 --- a/app/controllers/admin_request_controller.rb +++ b/app/controllers/admin_request_controller.rb @@ -106,39 +106,6 @@ class AdminRequestController < AdminController redirect_to admin_request_list_url end - def edit_outgoing - @outgoing_message = OutgoingMessage.find(params[:id]) - end - - def destroy_outgoing - @outgoing_message = OutgoingMessage.find(params[:outgoing_message_id]) - @info_request = @outgoing_message.info_request - outgoing_message_id = @outgoing_message.id - - @outgoing_message.fully_destroy - @outgoing_message.info_request.log_event("destroy_outgoing", - { :editor => admin_current_user(), :deleted_outgoing_message_id => outgoing_message_id }) - - flash[:notice] = 'Outgoing message successfully destroyed.' - redirect_to admin_request_show_url(@info_request) - end - - def update_outgoing - @outgoing_message = OutgoingMessage.find(params[:id]) - - old_body = @outgoing_message.body - - if @outgoing_message.update_attributes(params[:outgoing_message]) - @outgoing_message.info_request.log_event("edit_outgoing", - { :outgoing_message_id => @outgoing_message.id, :editor => admin_current_user(), - :old_body => old_body, :body => @outgoing_message.body }) - flash[:notice] = 'Outgoing message successfully updated.' - redirect_to admin_request_show_url(@outgoing_message.info_request) - else - render :action => 'edit_outgoing' - end - end - def edit_comment @comment = Comment.find(params[:id]) end @@ -163,58 +130,6 @@ class AdminRequestController < AdminController end end - - def destroy_incoming - @incoming_message = IncomingMessage.find(params[:incoming_message_id]) - @info_request = @incoming_message.info_request - incoming_message_id = @incoming_message.id - - @incoming_message.fully_destroy - @incoming_message.info_request.log_event("destroy_incoming", - { :editor => admin_current_user(), :deleted_incoming_message_id => incoming_message_id }) - # expire cached files - expire_for_request(@info_request) - flash[:notice] = 'Incoming message successfully destroyed.' - redirect_to admin_request_show_url(@info_request) - end - - def redeliver_incoming - incoming_message = IncomingMessage.find(params[:redeliver_incoming_message_id]) - message_ids = params[:url_title].split(",").each {|x| x.strip} - previous_request = incoming_message.info_request - destination_request = nil - ActiveRecord::Base.transaction do - for m in message_ids - if m.match(/^[0-9]+$/) - destination_request = InfoRequest.find_by_id(m.to_i) - else - destination_request = InfoRequest.find_by_url_title!(m) - end - if destination_request.nil? - flash[:error] = "Failed to find destination request '" + m + "'" - return redirect_to admin_request_show_url(previous_request) - end - - raw_email_data = incoming_message.raw_email.data - mail = MailHandler.mail_from_raw_email(raw_email_data) - destination_request.receive(mail, raw_email_data, true) - - incoming_message_id = incoming_message.id - incoming_message.info_request.log_event("redeliver_incoming", { - :editor => admin_current_user(), - :destination_request => destination_request.id, - :deleted_incoming_message_id => incoming_message_id - }) - - flash[:notice] = "Message has been moved to request(s). Showing the last one:" - end - # expire cached files - expire_for_request(previous_request) - incoming_message.fully_destroy - end - redirect_to admin_request_show_url(destination_request) - end - # change user or public body of a request magically def move_request info_request = InfoRequest.find(params[:info_request_id]) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 88b107861..cbdffc441 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -119,12 +119,9 @@ class ApplicationController < ActionController::Base end def render_exception(exception) - - # In development, or the admin interface, or for a local request, let Rails handle the exception - # with its stack trace templates. Local requests in testing are a special case so that we can - # test this method - there we use consider_all_requests_local to control behaviour. - if Rails.application.config.consider_all_requests_local || local_request? || - (request.local? && !Rails.env.test?) + # In development or the admin interface let Rails handle the exception + # with its stack trace templates + if Rails.application.config.consider_all_requests_local || show_rails_exceptions? raise exception end @@ -150,7 +147,7 @@ class ApplicationController < ActionController::Base end end - def local_request? + def show_rails_exceptions? false end @@ -214,19 +211,6 @@ class ApplicationController < ActionController::Base end end - def request_dirs(info_request) - first_three_digits = info_request.id.to_s()[0..2] - File.join(first_three_digits.to_s, info_request.id.to_s) - end - - def request_download_zip_dir(info_request) - File.join(download_zip_dir, "download", request_dirs(info_request)) - end - - def download_zip_dir() - File.join(Rails.root, '/cache/zips/') - end - # get the local locale def locale_from_params(*args) if params[:show_locale] diff --git a/app/controllers/public_body_controller.rb b/app/controllers/public_body_controller.rb index 374866eda..02f0ceb19 100644 --- a/app/controllers/public_body_controller.rb +++ b/app/controllers/public_body_controller.rb @@ -6,6 +6,7 @@ # Email: hello@mysociety.org; WWW: http://www.mysociety.org/ require 'fastercsv' +require 'confidence_intervals' class PublicBodyController < ApplicationController # XXX tidy this up with better error messages, and a more standard infrastructure for the redirect to canonical URL @@ -85,34 +86,45 @@ class PublicBodyController < ApplicationController def list long_cache # XXX move some of these tag SQL queries into has_tag_string.rb - @query = "%#{params[:public_body_query].nil? ? "" : params[:public_body_query]}%" + + like_query = params[:public_body_query] + like_query = "" if like_query.nil? + like_query = "%#{like_query}%" + @tag = params[:tag] - @locale = self.locale_from_params() - default_locale = I18n.default_locale.to_s - locale_condition = "(upper(public_body_translations.name) LIKE upper(?) - OR upper(public_body_translations.notes) LIKE upper (?)) - AND public_body_translations.locale = ? - AND public_bodies.id <> #{PublicBody.internal_admin_body.id}" + + @locale = self.locale_from_params + underscore_locale = @locale.gsub '-', '_' + underscore_default_locale = I18n.default_locale.to_s.gsub '-', '_' + + where_condition = "public_bodies.id <> #{PublicBody.internal_admin_body.id}" + where_parameters = [] + + first_letter = false + + base_tag_condition = " AND (SELECT count(*) FROM has_tag_string_tags" \ + " WHERE has_tag_string_tags.model_id = public_bodies.id" \ + " AND has_tag_string_tags.model = 'PublicBody'" + + # Restrict the public bodies shown according to the tag + # parameter supplied in the URL: if @tag.nil? or @tag == "all" @tag = "all" - conditions = [locale_condition, @query, @query, default_locale] elsif @tag == 'other' category_list = PublicBodyCategories::get().tags().map{|c| "'"+c+"'"}.join(",") - conditions = [locale_condition + ' AND (select count(*) from has_tag_string_tags where has_tag_string_tags.model_id = public_bodies.id - and has_tag_string_tags.model = \'PublicBody\' - and has_tag_string_tags.name in (' + category_list + ')) = 0', @query, @query, default_locale] + where_condition += base_tag_condition + " AND has_tag_string_tags.name in (#{category_list})) = 0" elsif @tag.size == 1 @tag.upcase! - conditions = [locale_condition + ' AND public_body_translations.first_letter = ?', @query, @query, default_locale, @tag] + # The first letter queries have to be done on + # translations, so just indicate to add that later: + first_letter = true elsif @tag.include?(":") name, value = HasTagString::HasTagStringTag.split_tag_into_name_value(@tag) - conditions = [locale_condition + ' AND (select count(*) from has_tag_string_tags where has_tag_string_tags.model_id = public_bodies.id - and has_tag_string_tags.model = \'PublicBody\' - and has_tag_string_tags.name = ? and has_tag_string_tags.value = ?) > 0', @query, @query, default_locale, name, value] + where_condition += base_tag_condition + " AND has_tag_string_tags.name = ? AND has_tag_string_tags.value = ?) > 0" + where_parameters.concat [name, value] else - conditions = [locale_condition + ' AND (select count(*) from has_tag_string_tags where has_tag_string_tags.model_id = public_bodies.id - and has_tag_string_tags.model = \'PublicBody\' - and has_tag_string_tags.name = ?) > 0', @query, @query, default_locale, @tag] + where_condition += base_tag_condition + " AND has_tag_string_tags.name = ?) > 0" + where_parameters.concat [@tag] end if @tag == "all" @@ -127,10 +139,45 @@ class PublicBodyController < ApplicationController @description = _("in the category ‘{{category_name}}’", :category_name=>category_name) end end + I18n.with_locale(@locale) do - @public_bodies = PublicBody.where(conditions).joins(:translations).order("public_body_translations.name").paginate( - :page => params[:page], :per_page => 100 - ) + + if AlaveteliConfiguration::public_body_list_fallback_to_default_locale + # Unfortunately, when we might fall back to the + # default locale, this is a rather complex query: + query = %Q{ + SELECT public_bodies.*, COALESCE(current_locale.name, default_locale.name) AS display_name + FROM public_bodies + LEFT OUTER JOIN public_body_translations as current_locale + ON (public_bodies.id = current_locale.public_body_id + AND current_locale.locale = ? AND #{get_public_body_list_translated_condition 'current_locale', first_letter}) + LEFT OUTER JOIN public_body_translations as default_locale + ON (public_bodies.id = default_locale.public_body_id + AND default_locale.locale = ? AND #{get_public_body_list_translated_condition 'default_locale', first_letter}) + WHERE #{where_condition} AND COALESCE(current_locale.name, default_locale.name) IS NOT NULL + ORDER BY display_name} + sql = [query, underscore_locale, like_query, like_query] + sql.push @tag if first_letter + sql += [underscore_default_locale, like_query, like_query] + sql.push @tag if first_letter + sql += where_parameters + @public_bodies = PublicBody.paginate_by_sql( + sql, + :page => params[:page], + :per_page => 100) + else + # The simpler case where we're just searching in the current locale: + where_condition = get_public_body_list_translated_condition('public_body_translations', first_letter, true) + + ' AND ' + where_condition + where_sql = [where_condition, like_query, like_query] + where_sql.push @tag if first_letter + where_sql += [underscore_locale] + where_parameters + @public_bodies = PublicBody.where(where_sql) \ + .joins(:translations) \ + .order("public_body_translations.name") \ + .paginate(:page => params[:page], :per_page => 100) + end + respond_to do |format| format.html { render :template => "public_body/list" } end @@ -149,6 +196,84 @@ class PublicBodyController < ApplicationController :disposition =>'attachment', :encoding => 'utf8') end + def statistics + unless AlaveteliConfiguration::public_body_statistics_page + raise ActiveRecord::RecordNotFound.new("Page not enabled") + end + + per_graph = 8 + minimum_requests = AlaveteliConfiguration::minimum_requests_for_statistics + # Make sure minimum_requests is > 0 to avoid division-by-zero + minimum_requests = [minimum_requests, 1].max + total_column = 'info_requests_count' + + @graph_list = [] + + [[total_column, + [{ + :title => _('Public bodies with the most requests'), + :y_axis => _('Number of requests'), + :highest => true}]], + ['info_requests_successful_count', + [{ + :title => _('Public bodies with the most successful requests'), + :y_axis => _('Percentage of total requests'), + :highest => true}, + { + :title => _('Public bodies with the fewest successful requests'), + :y_axis => _('Percentage of total requests'), + :highest => false}]], + ['info_requests_overdue_count', + [{ + :title => _('Public bodies with most overdue requests'), + :y_axis => _('Percentage of requests that are overdue'), + :highest => true}]], + ['info_requests_not_held_count', + [{ + :title => _('Public bodies that most frequently replied with "Not Held"'), + :y_axis => _('Percentage of total requests'), + :highest => true}]]].each do |column, graphs_properties| + + graphs_properties.each do |graph_properties| + + percentages = (column != total_column) + highest = graph_properties[:highest] + + data = nil + if percentages + data = PublicBody.get_request_percentages(column, + per_graph, + highest, + minimum_requests) + else + data = PublicBody.get_request_totals(per_graph, + highest, + minimum_requests) + end + + data_to_draw = { + 'id' => "#{column}-#{highest ? 'highest' : 'lowest'}", + 'x_axis' => _('Public Bodies'), + 'y_axis' => graph_properties[:y_axis], + 'errorbars' => percentages, + 'title' => graph_properties[:title]} + + if data + data_to_draw.update(data) + data_to_draw['x_values'] = data['public_bodies'].each_with_index.map { |pb, i| i } + data_to_draw['x_ticks'] = data['public_bodies'].each_with_index.map { |pb, i| [i, pb.name] } + end + + @graph_list.push data_to_draw + end + end + + respond_to do |format| + format.html { render :template => "public_body/statistics" } + format.json { render :json => @graph_list } + end + end + # Type ahead search def search_typeahead # Since acts_as_xapian doesn't support the Partial match flag, we work around it @@ -157,5 +282,18 @@ class PublicBodyController < ApplicationController @xapian_requests = perform_search_typeahead(query, PublicBody) render :partial => "public_body/search_ahead" end -end + private + def get_public_body_list_translated_condition(table, first_letter=false, locale=nil) + result = "(upper(#{table}.name) LIKE upper(?)" \ + " OR upper(#{table}.notes) LIKE upper (?))" + if first_letter + result += " AND #{table}.first_letter = ?" + end + if locale + result += " AND #{table}.locale = ?" + end + result + end + +end diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb index 45d8b7de6..388473b51 100644 --- a/app/controllers/request_controller.rb +++ b/app/controllers/request_controller.rb @@ -63,26 +63,24 @@ class RequestController < ApplicationController # Look up by new style text names @info_request = InfoRequest.find_by_url_title!(params[:url_title]) - set_last_request(@info_request) # Test for whole request being hidden if !@info_request.user_can_view?(authenticated_user) return render_hidden end - # Other parameters - @info_request_events = @info_request.info_request_events - @status = @info_request.calculate_status - @collapse_quotes = params[:unfold] ? false : true + set_last_request(@info_request) + # assign variables from request parameters + @collapse_quotes = params[:unfold] ? false : true # Don't allow status update on external requests, otherwise accept param if @info_request.is_external? @update_status = false else @update_status = params[:update_status] ? true : false end - @old_unclassified = @info_request.is_old_unclassified? && !authenticated_user.nil? - @is_owning_user = @info_request.is_owning_user?(authenticated_user) + + assign_variables_for_show_template(@info_request) if @update_status return if !@is_owning_user && !authenticated_as_user?(@info_request.user, @@ -92,11 +90,8 @@ class RequestController < ApplicationController ) end - - @last_info_request_event_id = @info_request.last_event_id_needing_description - @new_responses_count = @info_request.events_needing_description.select {|i| i.event_type == 'response'}.size - # Sidebar stuff + @sidebar = true # ... requests that have similar imporant terms begin limit = 10 @@ -106,13 +101,11 @@ class RequestController < ApplicationController rescue @xapian_similar = nil end - # Track corresponding to this page @track_thing = TrackThing.create_track_for_request(@info_request) @feed_autodetect = [ { :url => do_track_url(@track_thing, 'feed'), :title => @track_thing.params[:title_in_rss], :has_json => true } ] - # For send followup link at bottom - @last_response = @info_request.get_last_response + respond_to do |format| format.html { @has_json = true; render :template => 'request/show'} format.json { render :json => @info_request.json_for_api(true) } @@ -304,7 +297,7 @@ class RequestController < ApplicationController # We don't want the error "Outgoing messages is invalid", as in this # case the list of errors will also contain a more specific error # describing the reason it is invalid. - @info_request.errors.delete("outgoing_messages") + @info_request.errors.delete(:outgoing_messages) render :action => 'new' return @@ -683,9 +676,13 @@ class RequestController < ApplicationController @info_request = incoming_message.info_request # used by view return render_hidden end + if !incoming_message.user_can_view?(authenticated_user) + @incoming_message = incoming_message # used by view + return render_hidden_message + end # Is this a completely public request that we can cache attachments for # to be served up without authentication? - if incoming_message.info_request.all_can_view? + if incoming_message.info_request.all_can_view? && incoming_message.all_can_view? @files_can_be_cached = true end end @@ -871,10 +868,6 @@ class RequestController < ApplicationController @locale = self.locale_from_params() I18n.with_locale(@locale) do @info_request = InfoRequest.find_by_url_title!(params[:url_title]) - # Test for whole request being hidden or requester-only - if !@info_request.all_can_view? - return render_hidden - end if authenticated?( :web => _("To download the zip file"), :email => _("Then you can download a zip file of {{info_request_title}}.", @@ -882,54 +875,17 @@ class RequestController < ApplicationController :email_subject => _("Log in to download a zip file of {{info_request_title}}", :info_request_title=>@info_request.title) ) - updated = Digest::SHA1.hexdigest(@info_request.info_request_events.last.created_at.to_i.to_s + @info_request.updated_at.to_i.to_s) - @url_path = File.join("/download", - request_dirs(@info_request), - updated, - "#{params[:url_title]}.zip") - file_path = File.expand_path(File.join(download_zip_dir(), @url_path)) - if !File.exists?(file_path) - FileUtils.mkdir_p(File.dirname(file_path)) - Zip::ZipFile.open(file_path, Zip::ZipFile::CREATE) { |zipfile| - convert_command = AlaveteliConfiguration::html_to_pdf_command - done = false - if !convert_command.blank? && File.exists?(convert_command) - url = "http://#{AlaveteliConfiguration::domain}#{request_path(@info_request)}?print_stylesheet=1" - tempfile = Tempfile.new('foihtml2pdf') - output = AlaveteliExternalCommand.run(convert_command, url, tempfile.path) - if !output.nil? - zipfile.get_output_stream("correspondence.pdf") { |f| - f.puts(File.open(tempfile.path).read) - } - done = true - else - logger.error("Could not convert info request #{@info_request.id} to PDF with command '#{convert_command} #{url} #{tempfile.path}'") - end - tempfile.close - else - logger.warn("No HTML -> PDF converter found at #{convert_command}") - end - if !done - @info_request_events = @info_request.info_request_events - template = File.read(File.join(File.dirname(__FILE__), "..", "views", "request", "simple_correspondence.html.erb")) - output = ERB.new(template).result(binding) - zipfile.get_output_stream("correspondence.txt") { |f| - f.puts(output) - } - end - for message in @info_request.incoming_messages - attachments = message.get_attachments_for_display - for attachment in attachments - filename = "#{attachment.url_part_number}_#{attachment.display_filename}" - zipfile.get_output_stream(filename) { |f| - f.puts(attachment.body) - } - end - end - } - File.chmod(0644, file_path) + # Test for whole request being hidden or requester-only + if !@info_request.user_can_view?(@user) + return render_hidden + end + cache_file_path = @info_request.make_zip_cache_path(@user) + if !File.exists?(cache_file_path) + FileUtils.mkdir_p(File.dirname(cache_file_path)) + make_request_zip(@info_request, cache_file_path) + File.chmod(0644, cache_file_path) end - redirect_to @url_path + send_file(cache_file_path, :filename => "#{@info_request.url_title}.zip") end end end @@ -938,12 +894,82 @@ class RequestController < ApplicationController def render_hidden respond_to do |format| - response_code = 410 # gone + response_code = 403 # forbidden format.html{ render :template => 'request/hidden', :status => response_code } format.any{ render :nothing => true, :status => response_code } end false end + def render_hidden_message + respond_to do |format| + response_code = 403 # forbidden + format.html{ render :template => 'request/hidden_correspondence', :status => response_code } + format.any{ render :nothing => true, :status => response_code } + end + false + end + + def assign_variables_for_show_template(info_request) + @info_request = info_request + @info_request_events = info_request.info_request_events + @status = info_request.calculate_status + @old_unclassified = info_request.is_old_unclassified? && !authenticated_user.nil? + @is_owning_user = info_request.is_owning_user?(authenticated_user) + @last_info_request_event_id = info_request.last_event_id_needing_description + @new_responses_count = info_request.events_needing_description.select {|i| i.event_type == 'response'}.size + # For send followup link at bottom + @last_response = info_request.get_last_public_response + end + + def make_request_zip(info_request, file_path) + Zip::ZipFile.open(file_path, Zip::ZipFile::CREATE) do |zipfile| + file_info = make_request_summary_file(info_request) + zipfile.get_output_stream(file_info[:filename]) { |f| f.puts(file_info[:data]) } + message_index = 0 + info_request.incoming_messages.each do |message| + next unless message.user_can_view?(authenticated_user) + message_index += 1 + message.get_attachments_for_display.each do |attachment| + filename = "#{message_index}_#{attachment.url_part_number}_#{attachment.display_filename}" + zipfile.get_output_stream(filename) { |f| f.puts(attachment.body) } + end + end + end + end + + def make_request_summary_file(info_request) + done = false + convert_command = AlaveteliConfiguration::html_to_pdf_command + assign_variables_for_show_template(info_request) + if !convert_command.blank? && File.exists?(convert_command) + @render_to_file = true + html_output = render_to_string(:template => 'request/show') + tmp_input = Tempfile.new(['foihtml2pdf-input', '.html']) + tmp_input.write(html_output) + tmp_input.close + tmp_output = Tempfile.new('foihtml2pdf-output') + output = AlaveteliExternalCommand.run(convert_command, tmp_input.path, tmp_output.path) + if !output.nil? + file_info = { :filename => 'correspondence.pdf', + :data => File.open(tmp_output.path).read } + done = true + else + logger.error("Could not convert info request #{info_request.id} to PDF with command '#{convert_command} #{tmp_input.path} #{tmp_output.path}'") + end + tmp_output.close + tmp_input.delete + tmp_output.delete + else + logger.warn("No HTML -> PDF converter found at #{convert_command}") + end + if !done + file_info = { :filename => 'correspondence.txt', + :data => render_to_string(:template => 'request/show.text', + :layout => false) } + end + file_info + end + end diff --git a/app/helpers/link_to_helper.rb b/app/helpers/link_to_helper.rb index 5533402c5..8df28f350 100755 --- a/app/helpers/link_to_helper.rb +++ b/app/helpers/link_to_helper.rb @@ -53,7 +53,7 @@ module LinkToHelper # Respond to request def respond_to_last_url(info_request, options = {}) - last_response = info_request.get_last_response + last_response = info_request.get_last_public_response if last_response.nil? show_response_no_followup_url(options.merge(:id => info_request.id)) else diff --git a/app/mailers/request_mailer.rb b/app/mailers/request_mailer.rb index 4dbce6738..13b3bc4a1 100644 --- a/app/mailers/request_mailer.rb +++ b/app/mailers/request_mailer.rb @@ -347,8 +347,8 @@ class RequestMailer < ApplicationMailer :age_in_days => days_since) for info_request in info_requests - alert_event_id = info_request.get_last_response_event_id - last_response_message = info_request.get_last_response + alert_event_id = info_request.get_last_public_response_event_id + last_response_message = info_request.get_last_public_response if alert_event_id.nil? raise "internal error, no last response while making alert new response reminder, request id " + info_request.id.to_s end @@ -373,8 +373,8 @@ class RequestMailer < ApplicationMailer def self.alert_not_clarified_request() info_requests = InfoRequest.find(:all, :conditions => [ "awaiting_description = ? and described_state = 'waiting_clarification' and info_requests.updated_at < ?", false, Time.now() - 3.days ], :include => [ :user ], :order => "info_requests.id" ) for info_request in info_requests - alert_event_id = info_request.get_last_response_event_id - last_response_message = info_request.get_last_response + alert_event_id = info_request.get_last_public_response_event_id + last_response_message = info_request.get_last_public_response if alert_event_id.nil? raise "internal error, no last response while making alert not clarified reminder, request id " + info_request.id.to_s end diff --git a/app/models/censor_rule.rb b/app/models/censor_rule.rb index f0d06e088..3c5c77563 100644 --- a/app/models/censor_rule.rb +++ b/app/models/censor_rule.rb @@ -1,18 +1,17 @@ # == Schema Information -# Schema version: 20120919140404 # # Table name: censor_rules # -# id :integer not null, primary key +# id :integer not null, primary key # info_request_id :integer # user_id :integer # public_body_id :integer -# text :text not null -# replacement :text not null -# last_edit_editor :string(255) not null -# last_edit_comment :text not null -# created_at :datetime not null -# updated_at :datetime not null +# text :text not null +# replacement :text not null +# last_edit_editor :string(255) not null +# last_edit_comment :text not null +# created_at :datetime not null +# updated_at :datetime not null # regexp :boolean # diff --git a/app/models/comment.rb b/app/models/comment.rb index 9527030a9..75d37e04f 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,17 +1,16 @@ # == Schema Information -# Schema version: 114 # # Table name: comments # -# id :integer not null, primary key -# user_id :integer not null -# comment_type :string(255) default("internal_error"), not null +# id :integer not null, primary key +# user_id :integer not null +# comment_type :string(255) default("internal_error"), not null # info_request_id :integer -# body :text not null -# visible :boolean default(TRUE), not null -# created_at :datetime not null -# updated_at :datetime not null -# locale :text default(""), not null +# body :text not null +# visible :boolean default(TRUE), not null +# created_at :datetime not null +# updated_at :datetime not null +# locale :text default(""), not null # # models/comments.rb: diff --git a/app/models/foi_attachment.rb b/app/models/foi_attachment.rb index 0340f2b83..914420a2b 100644 --- a/app/models/foi_attachment.rb +++ b/app/models/foi_attachment.rb @@ -1,11 +1,9 @@ # encoding: UTF-8 - # == Schema Information -# Schema version: 114 # # Table name: foi_attachments # -# id :integer not null, primary key +# id :integer not null, primary key # content_type :text # filename :text # charset :text diff --git a/app/models/holiday.rb b/app/models/holiday.rb index 98f73e963..3076cc0fd 100644 --- a/app/models/holiday.rb +++ b/app/models/holiday.rb @@ -1,9 +1,8 @@ # == Schema Information -# Schema version: 114 # # Table name: holidays # -# id :integer not null, primary key +# id :integer not null, primary key # day :date # description :text # diff --git a/app/models/incoming_message.rb b/app/models/incoming_message.rb index ae3c3b407..8b2aa87e7 100644 --- a/app/models/incoming_message.rb +++ b/app/models/incoming_message.rb @@ -1,15 +1,13 @@ # coding: utf-8 - # == Schema Information -# Schema version: 114 # # Table name: incoming_messages # -# id :integer not null, primary key -# info_request_id :integer not null -# created_at :datetime not null -# updated_at :datetime not null -# raw_email_id :integer not null +# id :integer not null, primary key +# info_request_id :integer not null +# created_at :datetime not null +# updated_at :datetime not null +# raw_email_id :integer not null # cached_attachment_text_clipped :text # cached_main_body_text_folded :text # cached_main_body_text_unfolded :text @@ -19,6 +17,9 @@ # last_parsed :datetime # mail_from :text # sent_at :datetime +# prominence :string(255) default("normal"), not null +# prominence_reason :text +# # models/incoming_message.rb: # An (email) message from really anybody to be logged with a request. e.g. A @@ -37,6 +38,7 @@ require 'zip/zip' require 'iconv' unless RUBY_VERSION >= '1.9' class IncomingMessage < ActiveRecord::Base + extend MessageProminence belongs_to :info_request validates_presence_of :info_request @@ -48,6 +50,8 @@ class IncomingMessage < ActiveRecord::Base belongs_to :raw_email + has_prominence + # See binary_mask_stuff function below. It just test for inclusion # in this hash, not the value of the right hand side. DoNotBinaryMask = { @@ -59,6 +63,12 @@ class IncomingMessage < ActiveRecord::Base 'application/zip' => 1, } + # Given that there are in theory many info request events, a convenience method for + # getting the response event + def response_event + self.info_request_events.detect{ |e| e.event_type == 'response' } + end + # Return a cached structured mail object def mail(force = nil) if (!force.nil? || @mail.nil?) && !self.raw_email.nil? @@ -151,14 +161,17 @@ class IncomingMessage < ActiveRecord::Base parse_raw_email! super end + def subject parse_raw_email! super end + def mail_from parse_raw_email! super end + def safe_mail_from if !self.mail_from.nil? mail_from = self.mail_from.dup @@ -166,6 +179,15 @@ class IncomingMessage < ActiveRecord::Base return mail_from end end + + def specific_from_name? + !safe_mail_from.nil? && safe_mail_from.strip != info_request.public_body.name.strip + end + + def from_public_body? + safe_mail_from.nil? || (mail_from_domain == info_request.public_body.request_email_domain) + end + def mail_from_domain parse_raw_email! super diff --git a/app/models/info_request.rb b/app/models/info_request.rb index 14eead6ad..aaced91a2 100644 --- a/app/models/info_request.rb +++ b/app/models/info_request.rb @@ -1,26 +1,26 @@ +# encoding: utf-8 # == Schema Information -# Schema version: 20120919140404 # # Table name: info_requests # -# id :integer not null, primary key -# title :text not null +# id :integer not null, primary key +# title :text not null # user_id :integer -# public_body_id :integer not null -# created_at :datetime not null -# updated_at :datetime not null -# described_state :string(255) not null -# awaiting_description :boolean default(FALSE), not null -# prominence :string(255) default("normal"), not null -# url_title :text not null -# law_used :string(255) default("foi"), not null -# allow_new_responses_from :string(255) default("anybody"), not null -# handle_rejected_responses :string(255) default("bounce"), not null -# idhash :string(255) not null +# public_body_id :integer not null +# created_at :datetime not null +# updated_at :datetime not null +# described_state :string(255) not null +# awaiting_description :boolean default(FALSE), not null +# prominence :string(255) default("normal"), not null +# url_title :text not null +# law_used :string(255) default("foi"), not null +# allow_new_responses_from :string(255) default("anybody"), not null +# handle_rejected_responses :string(255) default("bounce"), not null +# idhash :string(255) not null # external_user_name :string(255) # external_url :string(255) -# attention_requested :boolean default(FALSE) -# comments_allowed :boolean default(TRUE), not null +# attention_requested :boolean default(FALSE) +# comments_allowed :boolean default(TRUE), not null # require 'digest/sha1' @@ -31,7 +31,10 @@ class InfoRequest < ActiveRecord::Base strip_attributes! validates_presence_of :title, :message => N_("Please enter a summary of your request") - validates_format_of :title, :with => /[a-zA-Z]/, :message => N_("Please write a summary with some text in it"), :if => Proc.new { |info_request| !info_request.title.nil? && !info_request.title.empty? } + # TODO: When we no longer support Ruby 1.8, this can be done with /[[:alpha:]]/ + validates_format_of :title, :with => /[ёЁа-яА-Яa-zA-Zà-üÀ-Ü]/iu, + :message => N_("Please write a summary with some text in it"), + :if => Proc.new { |info_request| !info_request.title.nil? && !info_request.title.empty? } belongs_to :user validate :must_be_internal_or_external @@ -764,28 +767,30 @@ public self.info_request_events.create!(:event_type => type, :params => params) end - def response_events - self.info_request_events.select{|e| e.response?} + def public_response_events + self.info_request_events.select{|e| e.response? && e.incoming_message.all_can_view? } end - # The last response is the default one people might want to reply to - def get_last_response_event_id - get_last_response_event.id if get_last_response_event + # The last public response is the default one people might want to reply to + def get_last_public_response_event_id + get_last_public_response_event.id if get_last_public_response_event end - def get_last_response_event - response_events.last + + def get_last_public_response_event + public_response_events.last end - def get_last_response - get_last_response_event.incoming_message if get_last_response_event + + def get_last_public_response + get_last_public_response_event.incoming_message if get_last_public_response_event end - def outgoing_events - info_request_events.select{|e| e.outgoing? } + def public_outgoing_events + info_request_events.select{|e| e.outgoing? && e.outgoing_message.all_can_view? } end - # The last outgoing message - def get_last_outgoing_event - outgoing_events.last + # The last public outgoing message + def get_last_public_outgoing_event + public_outgoing_events.last end # Text from the the initial request, for use in summary display @@ -836,6 +841,10 @@ public end end + def last_update_hash + Digest::SHA1.hexdigest(info_request_events.last.created_at.to_i.to_s + updated_at.to_i.to_s) + end + # Get previous email sent to def get_previous_email_sent_to(info_request_event) last_email = nil @@ -930,19 +939,29 @@ public end # Used to find when event last changed - def InfoRequest.last_event_time_clause(event_type=nil) + def InfoRequest.last_event_time_clause(event_type=nil, join_table=nil, join_clause=nil) event_type_clause = '' event_type_clause = " AND info_request_events.event_type = '#{event_type}'" if event_type - "(SELECT created_at - FROM info_request_events + tables = ['info_request_events'] + tables << join_table if join_table + join_clause = "AND #{join_clause}" if join_clause + "(SELECT info_request_events.created_at + FROM #{tables.join(', ')} WHERE info_request_events.info_request_id = info_requests.id #{event_type_clause} + #{join_clause} ORDER BY created_at desc LIMIT 1)" end + def InfoRequest.last_public_response_clause() + join_clause = "incoming_messages.id = info_request_events.incoming_message_id + AND incoming_messages.prominence = 'normal'" + last_event_time_clause('response', 'incoming_messages', join_clause) + end + def InfoRequest.old_unclassified_params(extra_params, include_last_response_time=false) - last_response_created_at = last_event_time_clause('response') + last_response_created_at = last_public_response_clause() age = extra_params[:age_in_days] ? extra_params[:age_in_days].days : OLD_AGE_IN_DAYS params = { :conditions => ["awaiting_description = ? AND #{last_response_created_at} < ? @@ -995,9 +1014,39 @@ public find(:all, params) end + def InfoRequest.download_zip_dir() + File.join(Rails.root, "cache", "zips", "#{Rails.env}") + end + + def request_dirs + first_three_digits = id.to_s()[0..2] + File.join(first_three_digits.to_s, id.to_s) + end + + def download_zip_dir + File.join(InfoRequest.download_zip_dir, "download", request_dirs) + end + + def make_zip_cache_path(user) + cache_file_dir = File.join(InfoRequest.download_zip_dir(), + "download", + request_dirs, + last_update_hash) + cache_file_suffix = if all_can_view_all_correspondence? + "" + elsif Ability.can_view_with_prominence?('hidden', self, user) + "_hidden" + elsif Ability.can_view_with_prominence?('requester_only', self, user) + "_requester_only" + else + "" + end + File.join(cache_file_dir, "#{url_title}#{cache_file_suffix}.zip") + end + def is_old_unclassified? - !is_external? && awaiting_description && url_title != 'holding_pen' && get_last_response_event && - Time.now > get_last_response_event.created_at + OLD_AGE_IN_DAYS + !is_external? && awaiting_description && url_title != 'holding_pen' && get_last_public_response_event && + Time.now > get_last_public_response_event.created_at + OLD_AGE_IN_DAYS end # List of incoming messages to followup, by unique email @@ -1010,6 +1059,8 @@ public end incoming_message.safe_mail_from + next if ! incoming_message.all_can_view? + email = OutgoingMailer.email_for_followup(self, incoming_message) name = OutgoingMailer.name_for_followup(self, incoming_message) @@ -1059,13 +1110,7 @@ public end def user_can_view?(user) - if self.prominence == 'hidden' - return User.view_hidden_requests?(user) - end - if self.prominence == 'requester_only' - return self.is_owning_user?(user) - end - return true + Ability.can_view_with_prominence?(self.prominence, self, user) end # Is this request visible to everyone? @@ -1074,6 +1119,12 @@ public return false end + def all_can_view_all_correspondence? + all_can_view? && + incoming_messages.all?{ |message| message.all_can_view? } && + outgoing_messages.all?{ |message| message.all_can_view? } + end + def indexed_by_search? if self.prominence == 'backpage' || self.prominence == 'hidden' || self.prominence == 'requester_only' return false @@ -1135,6 +1186,23 @@ public end end + after_save :update_counter_cache + after_destroy :update_counter_cache + def update_counter_cache + PublicBody.skip_callback(:save, :after, :purge_in_cache) + self.public_body.info_requests_not_held_count = InfoRequest.where( + :public_body_id => self.public_body.id, + :described_state => 'not_held').count + self.public_body.info_requests_successful_count = InfoRequest.where( + :public_body_id => self.public_body.id, + :described_state => ['successful', 'partially_successful']).count + self.public_body.without_revision do + public_body.no_xapian_reindex = true + public_body.save + end + PublicBody.set_callback(:save, :after, :purge_in_cache) + end + def for_admin_column self.class.content_columns.map{|c| c unless %w(title url_title).include?(c.name) }.compact.each do |column| yield(column.human_name, self.send(column.name), column.type.to_s, column.name) diff --git a/app/models/info_request_event.rb b/app/models/info_request_event.rb index 0967e3940..67cdda1b4 100644 --- a/app/models/info_request_event.rb +++ b/app/models/info_request_event.rb @@ -1,20 +1,18 @@ # == Schema Information -# Schema version: 114 # # Table name: info_request_events # -# id :integer not null, primary key -# info_request_id :integer not null -# event_type :text not null -# params_yaml :text not null -# created_at :datetime not null +# id :integer not null, primary key +# info_request_id :integer not null +# event_type :text not null +# params_yaml :text not null +# created_at :datetime not null # described_state :string(255) # calculated_state :string(255) # last_described_at :datetime # incoming_message_id :integer # outgoing_message_id :integer # comment_id :integer -# prominence :string(255) default("normal"), not null # # models/info_request_event.rb: @@ -48,10 +46,10 @@ class InfoRequestEvent < ActiveRecord::Base 'destroy_incoming', # deleted an incoming message (in admin interface) 'destroy_outgoing', # deleted an outgoing message (in admin interface) 'redeliver_incoming', # redelivered an incoming message elsewhere (in admin interface) + 'edit_incoming', # incoming message edited (in admin interface) 'move_request', # changed user or public body (in admin interface) 'hide', # hid a request (in admin interface) 'manual', # you did something in the db by hand - 'response', 'comment', 'status_update' @@ -63,35 +61,12 @@ class InfoRequestEvent < ActiveRecord::Base # user described state (also update in info_request) validate :must_be_valid_state - # whether event is publicly visible - validates_inclusion_of :prominence, :in => [ - 'normal', - 'hidden', - 'requester_only' - ] - def must_be_valid_state if !described_state.nil? and !InfoRequest.enumerate_states.include?(described_state) errors.add(described_state, "is not a valid state") end end - def user_can_view?(user) - unless info_request.user_can_view?(user) - raise "internal error, called user_can_view? on event when there is not permission to view entire request" - end - - case prominence - when 'hidden' - User.view_hidden_requests?(user) - when 'requester_only' - info_request.is_owning_user?(user) - else - true - end - end - - # Full text search indexing acts_as_xapian :texts => [ :search_text_main, :title ], :values => [ @@ -260,6 +235,12 @@ class InfoRequestEvent < ActiveRecord::Base if !self.info_request.indexed_by_search? return false end + if self.event_type == 'response' && !self.incoming_message.indexed_by_search? + return false + end + if ['sent', 'followup_sent'].include?(self.event_type) && !self.outgoing_message.indexed_by_search? + return false + end if self.event_type == 'comment' && !self.comment.visible return false end @@ -268,6 +249,7 @@ class InfoRequestEvent < ActiveRecord::Base return false end end + def variety self.event_type end diff --git a/app/models/mail_server_log.rb b/app/models/mail_server_log.rb index 7f61377ce..0e5b60ff1 100644 --- a/app/models/mail_server_log.rb +++ b/app/models/mail_server_log.rb @@ -1,15 +1,14 @@ # == Schema Information -# Schema version: 20121010214348 # # Table name: mail_server_logs # -# id :integer not null, primary key +# id :integer not null, primary key # mail_server_log_done_id :integer # info_request_id :integer -# order :integer not null -# line :text not null -# created_at :datetime not null -# updated_at :datetime not null +# order :integer not null +# line :text not null +# created_at :datetime not null +# updated_at :datetime not null # # We load log file lines for requests in here, for display in the admin interface. diff --git a/app/models/mail_server_log_done.rb b/app/models/mail_server_log_done.rb index 0e7e9eec3..222b072c5 100644 --- a/app/models/mail_server_log_done.rb +++ b/app/models/mail_server_log_done.rb @@ -1,13 +1,12 @@ # == Schema Information -# Schema version: 20121010214348 # # Table name: mail_server_log_dones # -# id :integer not null, primary key -# filename :text not null -# last_stat :datetime not null -# created_at :datetime not null -# updated_at :datetime not null +# id :integer not null, primary key +# filename :text not null +# last_stat :datetime not null +# created_at :datetime not null +# updated_at :datetime not null # # Stores that a particular mail server log file has been loaded in, see mail_server_log.rb diff --git a/app/models/outgoing_message.rb b/app/models/outgoing_message.rb index aedfb9cad..e89c11141 100644 --- a/app/models/outgoing_message.rb +++ b/app/models/outgoing_message.rb @@ -1,18 +1,17 @@ # == Schema Information -# Schema version: 114 # # Table name: outgoing_messages # -# id :integer not null, primary key -# info_request_id :integer not null -# body :text not null -# status :string(255) not null -# message_type :string(255) not null -# created_at :datetime not null -# updated_at :datetime not null +# id :integer not null, primary key +# info_request_id :integer not null +# body :text not null +# status :string(255) not null +# message_type :string(255) not null +# created_at :datetime not null +# updated_at :datetime not null # last_sent_at :datetime # incoming_message_followup_id :integer -# what_doing :string(255) not null +# what_doing :string(255) not null # # models/outgoing_message.rb: @@ -23,6 +22,7 @@ # Email: hello@mysociety.org; WWW: http://www.mysociety.org/ class OutgoingMessage < ActiveRecord::Base + extend MessageProminence include Rails.application.routes.url_helpers include LinkToHelper self.default_url_options[:host] = AlaveteliConfiguration::domain @@ -33,6 +33,8 @@ class OutgoingMessage < ActiveRecord::Base strip_attributes! + has_prominence + belongs_to :info_request validates_presence_of :info_request @@ -209,11 +211,11 @@ class OutgoingMessage < ActiveRecord::Base end # Returns text for indexing / text display - def get_text_for_indexing + def get_text_for_indexing(strip_salutation=true) text = self.body.strip # Remove salutation - text.sub!(/Dear .+,/, "") + text.sub!(/Dear .+,/, "") if strip_salutation # Remove email addresses from display/index etc. self.remove_privacy_sensitive_things!(text) @@ -233,6 +235,12 @@ class OutgoingMessage < ActiveRecord::Base return text.html_safe end + # Return body for display as text + def get_body_for_text_display + get_text_for_indexing(strip_salutation=false) + end + + def fully_destroy ActiveRecord::Base.transaction do info_request_event = InfoRequestEvent.find_by_outgoing_message_id(self.id) diff --git a/app/models/post_redirect.rb b/app/models/post_redirect.rb index 409069cb6..5da3d2742 100644 --- a/app/models/post_redirect.rb +++ b/app/models/post_redirect.rb @@ -1,18 +1,17 @@ # == Schema Information -# Schema version: 114 # # Table name: post_redirects # -# id :integer not null, primary key -# token :text not null -# uri :text not null +# id :integer not null, primary key +# token :text not null +# uri :text not null # post_params_yaml :text -# created_at :datetime not null -# updated_at :datetime not null -# email_token :text not null +# created_at :datetime not null +# updated_at :datetime not null +# email_token :text not null # reason_params_yaml :text # user_id :integer -# circumstance :text default("normal"), not null +# circumstance :text default("normal"), not null # # models/post_redirect.rb: diff --git a/app/models/profile_photo.rb b/app/models/profile_photo.rb index 5d542daf1..322ebe53c 100644 --- a/app/models/profile_photo.rb +++ b/app/models/profile_photo.rb @@ -1,12 +1,11 @@ # == Schema Information -# Schema version: 114 # # Table name: profile_photos # -# id :integer not null, primary key -# data :binary not null +# id :integer not null, primary key +# data :binary not null # user_id :integer -# draft :boolean default(FALSE), not null +# draft :boolean default(FALSE), not null # # models/profile_photo.rb: diff --git a/app/models/public_body.rb b/app/models/public_body.rb index a76aeb189..828e8c94a 100644 --- a/app/models/public_body.rb +++ b/app/models/public_body.rb @@ -1,27 +1,27 @@ +# -*- coding: utf-8 -*- # == Schema Information -# Schema version: 20120919140404 # # Table name: public_bodies # -# id :integer not null, primary key -# name :text not null -# short_name :text not null -# request_email :text not null -# version :integer not null -# last_edit_editor :string(255) not null -# last_edit_comment :text not null -# created_at :datetime not null -# updated_at :datetime not null -# url_name :text not null -# home_page :text default(""), not null -# notes :text default(""), not null -# first_letter :string(255) not null -# publication_scheme :text default(""), not null -# api_key :string(255) not null -# info_requests_count :integer default(0), not null +# id :integer not null, primary key +# name :text not null +# short_name :text not null +# request_email :text not null +# version :integer not null +# last_edit_editor :string(255) not null +# last_edit_comment :text not null +# created_at :datetime not null +# updated_at :datetime not null +# url_name :text not null +# home_page :text default(""), not null +# notes :text default(""), not null +# first_letter :string(255) not null +# publication_scheme :text default(""), not null +# api_key :string(255) not null +# info_requests_count :integer default(0), not null +# disclosure_log :text default(""), not null # -# -*- coding: utf-8 -*- require 'csv' require 'securerandom' require 'set' @@ -40,6 +40,7 @@ class PublicBody < ActiveRecord::Base has_many :info_requests, :order => 'created_at desc' has_many :track_things, :order => 'created_at desc' has_many :censor_rules, :order => 'created_at desc' + attr_accessor :no_xapian_reindex has_tag_string before_save :set_api_key, :set_default_publication_scheme @@ -60,12 +61,23 @@ class PublicBody < ActiveRecord::Base # XXX - Don't like repeating this! def calculate_cached_fields(t) - t.first_letter = t.name.scan(/^./mu)[0].upcase unless t.name.nil? or t.name.empty? + PublicBody.set_first_letter(t) short_long_name = t.name short_long_name = t.short_name if t.short_name and !t.short_name.empty? t.url_name = MySociety::Format.simplify_url_part(short_long_name, 'body') end + # Set the first letter on a public body or translation + def PublicBody.set_first_letter(instance) + unless instance.name.nil? or instance.name.empty? + # we use a regex to ensure it works with utf-8/multi-byte + first_letter = instance.name.scan(/^./mu)[0].upcase + if first_letter != instance.first_letter + instance.first_letter = first_letter + end + end + end + def translated_versions translations end @@ -130,8 +142,7 @@ class PublicBody < ActiveRecord::Base # Set the first letter, which is used for faster queries before_save(:set_first_letter) def set_first_letter - # we use a regex to ensure it works with utf-8/multi-byte - self.first_letter = self.name.scan(/./mu)[0].upcase + PublicBody.set_first_letter(self) end # If tagged "not_apply", then FOI/EIR no longer applies to authority at all @@ -177,7 +188,11 @@ class PublicBody < ActiveRecord::Base end acts_as_versioned - self.non_versioned_columns << 'created_at' << 'updated_at' << 'first_letter' << 'api_key' << 'info_requests_count' + self.non_versioned_columns << 'created_at' << 'updated_at' << 'first_letter' << 'api_key' + self.non_versioned_columns << 'info_requests_count' << 'info_requests_successful_count' + self.non_versioned_columns << 'info_requests_not_held_count' << 'info_requests_overdue' + self.non_versioned_columns << 'info_requests_overdue_count' + class Version attr_accessor :created_at @@ -231,6 +246,7 @@ class PublicBody < ActiveRecord::Base def reindex_requested_from if self.changes.include?('url_name') for info_request in self.info_requests + for info_request_event in info_request.info_request_events info_request_event.xapian_mark_needs_index end @@ -632,6 +648,65 @@ class PublicBody < ActiveRecord::Base end end + # Return data for the 'n' public bodies with the highest (or + # lowest) number of requests, but only returning data for those + # with at least 'minimum_requests' requests. + def self.get_request_totals(n, highest, minimum_requests) + ordering = "info_requests_count" + ordering += " DESC" if highest + where_clause = "info_requests_count >= #{minimum_requests}" + public_bodies = PublicBody.order(ordering).where(where_clause).limit(n) + public_bodies.reverse! if highest + y_values = public_bodies.map { |pb| pb.info_requests_count } + return { + 'public_bodies' => public_bodies, + 'y_values' => y_values, + 'y_max' => y_values.max} + end + + # Return data for the 'n' public bodies with the highest (or + # lowest) score according to the metric of the value in 'column' + # divided by the total number of requests, expressed as a + # percentage. This only returns data for those public bodies with + # at least 'minimum_requests' requests. + def self.get_request_percentages(column, n, highest, minimum_requests) + total_column = "info_requests_count" + ordering = "y_value" + ordering += " DESC" if highest + y_value_column = "(cast(#{column} as float) / #{total_column})" + where_clause = "#{total_column} >= #{minimum_requests} AND #{column} IS NOT NULL" + public_bodies = PublicBody.select("*, #{y_value_column} AS y_value").order(ordering).where(where_clause).limit(n) + public_bodies.reverse! if highest + y_values = public_bodies.map { |pb| pb.y_value.to_f } + + original_values = public_bodies.map { |pb| pb.send(column) } + # If these are all nil, then probably the values have never + # been set; some have to be set by a rake task. In that case, + # just return nil: + return nil unless original_values.any? { |ov| !ov.nil? } + + original_totals = public_bodies.map { |pb| pb.send(total_column) } + # Calculate confidence intervals, as offsets from the proportion: + cis_below = [] + cis_above = [] + original_totals.each_with_index.map { |total, i| + lower_ci, higher_ci = ci_bounds original_values[i], total, 0.05 + cis_below.push(y_values[i] - lower_ci) + cis_above.push(higher_ci - y_values[i]) + } + # Turn the y values and confidence interval offsets into + # percentages: + [y_values, cis_below, cis_above].each { |l| + l.map! { |v| 100 * v } + } + return { + 'public_bodies' => public_bodies, + 'y_values' => y_values, + 'cis_below' => cis_below, + 'cis_above' => cis_above, + 'y_max' => 100} + end + private def request_email_if_requestable diff --git a/app/models/purge_request.rb b/app/models/purge_request.rb index e48f3cc6f..4e6267bd2 100644 --- a/app/models/purge_request.rb +++ b/app/models/purge_request.rb @@ -1,13 +1,12 @@ # == Schema Information -# Schema version: 114 # # Table name: purge_requests # -# id :integer not null, primary key +# id :integer not null, primary key # url :string(255) -# created_at :datetime not null -# model :string(255) not null -# model_id :integer not null +# created_at :datetime not null +# model :string(255) not null +# model_id :integer not null # # models/purge_request.rb: diff --git a/app/models/raw_email.rb b/app/models/raw_email.rb index 6bf01bc74..21a53f493 100644 --- a/app/models/raw_email.rb +++ b/app/models/raw_email.rb @@ -1,9 +1,8 @@ # == Schema Information -# Schema version: 114 # # Table name: raw_emails # -# id :integer not null, primary key +# id :integer not null, primary key # # models/raw_email.rb: diff --git a/app/models/request_classification.rb b/app/models/request_classification.rb index f5a1b4bee..6873d468b 100644 --- a/app/models/request_classification.rb +++ b/app/models/request_classification.rb @@ -1,9 +1,8 @@ # == Schema Information -# Schema version: 20120919140404 # # Table name: request_classifications # -# id :integer not null, primary key +# id :integer not null, primary key # user_id :integer # info_request_event_id :integer # created_at :datetime diff --git a/app/models/track_thing.rb b/app/models/track_thing.rb index 66b8a5c47..d5e1cdb75 100644 --- a/app/models/track_thing.rb +++ b/app/models/track_thing.rb @@ -1,16 +1,15 @@ # == Schema Information -# Schema version: 114 # # Table name: track_things # -# id :integer not null, primary key -# tracking_user_id :integer not null -# track_query :string(255) not null +# id :integer not null, primary key +# tracking_user_id :integer not null +# track_query :string(255) not null # info_request_id :integer # tracked_user_id :integer # public_body_id :integer -# track_medium :string(255) not null -# track_type :string(255) default("internal_error"), not null +# track_medium :string(255) not null +# track_type :string(255) default("internal_error"), not null # created_at :datetime # updated_at :datetime # diff --git a/app/models/track_things_sent_email.rb b/app/models/track_things_sent_email.rb index a9ea2520e..072d3bdea 100644 --- a/app/models/track_things_sent_email.rb +++ b/app/models/track_things_sent_email.rb @@ -1,10 +1,9 @@ # == Schema Information -# Schema version: 114 # # Table name: track_things_sent_emails # -# id :integer not null, primary key -# track_thing_id :integer not null +# id :integer not null, primary key +# track_thing_id :integer not null # info_request_event_id :integer # user_id :integer # public_body_id :integer diff --git a/app/models/user.rb b/app/models/user.rb index 9da4ad743..d7c1c854e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,26 +1,27 @@ # == Schema Information -# Schema version: 20120919140404 # # Table name: users # -# id :integer not null, primary key -# email :string(255) not null -# name :string(255) not null -# hashed_password :string(255) not null -# salt :string(255) not null -# created_at :datetime not null -# updated_at :datetime not null -# email_confirmed :boolean default(FALSE), not null -# url_name :text not null -# last_daily_track_email :datetime default(Sat Jan 01 00:00:00 UTC 2000) -# admin_level :string(255) default("none"), not null -# ban_text :text default(""), not null -# about_me :text default(""), not null +# id :integer not null, primary key +# email :string(255) not null +# name :string(255) not null +# hashed_password :string(255) not null +# salt :string(255) not null +# created_at :datetime not null +# updated_at :datetime not null +# email_confirmed :boolean default(FALSE), not null +# url_name :text not null +# last_daily_track_email :datetime default(2000-01-01 00:00:00 UTC) +# admin_level :string(255) default("none"), not null +# ban_text :text default(""), not null +# about_me :text default(""), not null # locale :string(255) # email_bounced_at :datetime -# email_bounce_message :text default(""), not null -# no_limit :boolean default(FALSE), not null -# receive_email_alerts :boolean default(TRUE), not null +# email_bounce_message :text default(""), not null +# no_limit :boolean default(FALSE), not null +# receive_email_alerts :boolean default(TRUE), not null +# address :string(255) +# dob :date # require 'digest/sha1' @@ -243,8 +244,8 @@ class User < ActiveRecord::Base !user.nil? && user.owns_every_request? end - # Can the user see every request, even hidden ones? - def User.view_hidden_requests?(user) + # Can the user see every request, response, and outgoing message, even hidden ones? + def User.view_hidden?(user) !user.nil? && user.super? end diff --git a/app/models/user_info_request_sent_alert.rb b/app/models/user_info_request_sent_alert.rb index 449a4c237..098b773f8 100644 --- a/app/models/user_info_request_sent_alert.rb +++ b/app/models/user_info_request_sent_alert.rb @@ -1,12 +1,11 @@ # == Schema Information -# Schema version: 114 # # Table name: user_info_request_sent_alerts # -# id :integer not null, primary key -# user_id :integer not null -# info_request_id :integer not null -# alert_type :string(255) not null +# id :integer not null, primary key +# user_id :integer not null +# info_request_id :integer not null +# alert_type :string(255) not null # info_request_event_id :integer # diff --git a/app/views/admin_general/admin_js.erb b/app/views/admin_general/admin_js.erb deleted file mode 100644 index c8788a452..000000000 --- a/app/views/admin_general/admin_js.erb +++ /dev/null @@ -1,34 +0,0 @@ -(function() { - - jQuery(function() { - $('.locales a:first').tab('show'); - $('.accordion-body').on('hidden', function() { - return $(this).prev().find('i').first().removeClass().addClass('icon-chevron-right'); - }); - $('.accordion-body').on('shown', function() { - return $(this).prev().find('i').first().removeClass().addClass('icon-chevron-down'); - }); - $('.toggle-hidden').live('click', function() { - $(this).parents('td').find('div:hidden').show(); - return false; - }); - return $('#request_hidden_user_explanation_reasons input').live('click', function() { - var info_request_id, reason; - $('#request_hidden_user_subject, #request_hidden_user_explanation, #request_hide_button').show(); - info_request_id = $('#hide_request_form').attr('data-info-request-id'); - reason = $(this).val(); - $('#request_hidden_user_explanation_field').attr("value", "[loading default text...]"); - return $.ajax("/hidden_user_explanation?reason=" + reason + "&info_request_id=" + info_request_id, { - type: "GET", - dataType: "text", - error: function(data, textStatus, jqXHR) { - return $('#request_hidden_user_explanation_field').attr("value", "Error: " + textStatus); - }, - success: function(data, textStatus, jqXHR) { - return $('#request_hidden_user_explanation_field').attr("value", data); - } - }); - }); - }); - -}).call(this); diff --git a/app/views/admin_general/index.html.erb b/app/views/admin_general/index.html.erb index b239a2b3f..976860fa7 100644 --- a/app/views/admin_general/index.html.erb +++ b/app/views/admin_general/index.html.erb @@ -164,7 +164,7 @@ <%= request_both_links(@request) %> </td> <td class="span2"> - <%=simple_date(@request.get_last_response_event.created_at)%> + <%=simple_date(@request.get_last_public_response_event.created_at)%> </td> </tr> <% end %> diff --git a/app/views/admin_general/timeline.html.erb b/app/views/admin_general/timeline.html.erb index 439ae1e68..c4ea4849b 100644 --- a/app/views/admin_general/timeline.html.erb +++ b/app/views/admin_general/timeline.html.erb @@ -34,7 +34,7 @@ <%= request_both_links(event.info_request) %> <% if event.event_type == 'edit' %> was edited by administrator <strong><%=h event.params[:editor] %></strong>. - <% for p in ['title', 'prominence', 'described_state', 'awaiting_description'] + <% for p in ['title', 'described_state', 'awaiting_description'] if event.params[p.to_sym] != event.params[('old_'+p).to_sym] %> Changed <%=p%> from '<%=h event.params[('old_'+p).to_sym]%>' to '<%=h event.params[p.to_sym] %>'. <% end diff --git a/app/views/admin_incoming_message/_intro.html.erb b/app/views/admin_incoming_message/_intro.html.erb new file mode 100644 index 000000000..1d5585f11 --- /dev/null +++ b/app/views/admin_incoming_message/_intro.html.erb @@ -0,0 +1,3 @@ +<% @title = "Incoming message #{incoming_message.id} of FOI request '#{incoming_message.info_request.title}'" %> +<h1>Incoming message <%= incoming_message.id %></h1> +<p>FOI request: <%= request_both_links(incoming_message.info_request) %></p> diff --git a/app/views/admin_incoming_message/edit.html.erb b/app/views/admin_incoming_message/edit.html.erb new file mode 100644 index 000000000..1088edcab --- /dev/null +++ b/app/views/admin_incoming_message/edit.html.erb @@ -0,0 +1,26 @@ +<%= render :partial => 'intro', :locals => {:incoming_message => @incoming_message } %> +<%= render :partial => 'admin_request/incoming_message_actions', :locals => { :incoming_message => @incoming_message } %> +<fieldset class="form-horizontal"> + <legend>Prominence</legend> + <%= form_tag admin_incoming_update_path(@incoming_message), :class => "form form-inline" do %> + + <div class="control-group"> + <label class="control-label" for="incoming_message_prominence"> Prominence</label> + <div class="controls"> + <%= select('incoming_message', "prominence", IncomingMessage.prominence_states) %> + </div> + </div> + + <div class="control-group"> + <label class="control-label" for="incoming_message_prominence_reason">Reason for prominence</label> + <div class="controls"> + <%= text_area "incoming_message", "prominence_reason", :rows => 5, :class => "span6" %> + </div> + </div> + + <div class="form-actions" > + <%= submit_tag 'Save', :class => "btn" %> + </div> + + <% end %> +</fieldset> diff --git a/app/views/admin_outgoing_message/edit.html.erb b/app/views/admin_outgoing_message/edit.html.erb new file mode 100644 index 000000000..d5f5f43bf --- /dev/null +++ b/app/views/admin_outgoing_message/edit.html.erb @@ -0,0 +1,50 @@ +<h1>Edit outgoing message</h1> + +<%= error_messages_for 'outgoing_message' %> + +<%= form_tag admin_outgoing_update_path(@outgoing_message) do %> + <div class="control-group"> + <label class="control-label" for="outgoing_message_prominence"> Prominence</label> + <div class="controls"> + <%= select('outgoing_message', "prominence", OutgoingMessage.prominence_states) %> + </div> + </div> + + <div class="control-group"> + <label class="control-label" for="outgoing_message_prominence_reason">Reason for prominence</label> + <div class="controls"> + <%= text_area "outgoing_message", "prominence_reason", :rows => 5, :class => "span6" %> + </div> + </div> + + <div class="control-group"> + <label class="control-label" for="outgoing_message_body">Body of message</label> + <div class="controls"> + <%= text_area 'outgoing_message', 'body', :rows => 10, :cols => 60 %> + </div> + + <p><strong>Note:</strong> This is mainly to be used to excise information + that users inadvertently put in their messages, not realising it would be + public. It will already have been sent to the public authority, and their + reply may also include that information and be automatically published on + this site. You could also use this to edit a message before resending it, but + only the edited version will be shown on the public page if you do that.</p> + +<div class="form-actions" > +<%= submit_tag 'Save', :accesskey => 's', :class => 'btn' %> +</div> +<% end %> + +<p> +<%= link_to 'Show', admin_request_show_path(@outgoing_message.info_request) %> | +<%= link_to 'List all', admin_request_list_path %> +</p> + +<%= form_tag admin_outgoing_destroy_path do %> + <div> + <%= hidden_field_tag 'outgoing_message_id', @outgoing_message.id %> + <%= submit_tag "Destroy outgoing message", :class => "btn btn-danger", :confirm => "This is permanent! Are you sure?" %> + </div> +<% end %> + + diff --git a/app/views/admin_request/_incoming_message_actions.html.erb b/app/views/admin_request/_incoming_message_actions.html.erb index 653e73337..4cf099b53 100644 --- a/app/views/admin_request/_incoming_message_actions.html.erb +++ b/app/views/admin_request/_incoming_message_actions.html.erb @@ -1,6 +1,6 @@ <fieldset class="form-horizontal"> <legend>Actions</legend> - <%= form_tag admin_request_redeliver_incoming_path, :class => "form form-inline" do %> + <%= form_tag admin_incoming_redeliver_path, :class => "form form-inline" do %> <div class="control-group"> <label class="control-label" for="url_title_<%= incoming_message.id %>">Redeliver message to one or more other requests</label> <div class="controls"> @@ -22,7 +22,7 @@ </div> </div> - <%= form_tag admin_request_destroy_incoming_path, :class => "form form-inline" do %> + <%= form_tag admin_incoming_destroy_path, :class => "form form-inline" do %> <div class="control-group"> <label class="control-label" for="destroy_message_<%= incoming_message.id %>">Destroy message</label> <div class="controls"> diff --git a/app/views/admin_request/edit_outgoing.html.erb b/app/views/admin_request/edit_outgoing.html.erb deleted file mode 100644 index a0c60520a..000000000 --- a/app/views/admin_request/edit_outgoing.html.erb +++ /dev/null @@ -1,33 +0,0 @@ -<h1>Edit outgoing message</h1> - -<%= error_messages_for 'outgoing_message' %> - -<%= form_tag admin_request_update_outgoing_path(@outgoing_message) do %> - - <p><label for="outgoing_message_body">Body of message</label><br/> - <%= text_area 'outgoing_message', 'body', :rows => 10, :cols => 60 %></p> - - <p><strong>Note:</strong> This is mainly to be used to excise information - that users inadvertently put in their messages, not realising it would be - public. It will already have been sent to the public authority, and their - reply may also include that information and be automatically published on - this site. You could also use this to edit a message before resending it, but - only the edited version will be shown on the public page if you do that.</p> - - <p><%= submit_tag 'Save', :accesskey => 's' %></p> -<% end %> - -<p> -<%= link_to 'Show', admin_request_show_path(@outgoing_message.info_request) %> | -<%= link_to 'List all', admin_request_list_path %> -</p> - -<%= form_tag admin_request_destroy_outgoing_path do %> - <div> - <%= hidden_field_tag 'outgoing_message_id', @outgoing_message.id %> - Warning, this is permanent! ---> - <%= submit_tag "Destroy outgoing message" %> - </div> -<% end %> - - diff --git a/app/views/admin_request/show.html.erb b/app/views/admin_request/show.html.erb index e18e319be..83d9c3764 100644 --- a/app/views/admin_request/show.html.erb +++ b/app/views/admin_request/show.html.erb @@ -233,7 +233,7 @@ <div class="accordion-group"> <div class="accordion-heading"> <a href="#outgoing_<%=outgoing_message.id%>" data-toggle="collapse" data-parent="#outgoing_messages"><%= chevron_right %></a> - <%= link_to admin_request_edit_outgoing_path(outgoing_message) do %> + <%= link_to admin_outgoing_edit_path(outgoing_message) do %> #<%= outgoing_message.id %> -- <%= outgoing_message.status.humanize %> <%= outgoing_message.message_type.humanize %> <% end %> <blockquote> @@ -275,11 +275,16 @@ <hr> <h2>Incoming messages</h2> <div class="accordion" id="incoming_messages"> - <% for incoming_message in @info_request.incoming_messages.find(:all, :order => 'created_at') %> + <% for incoming_message in @info_request.incoming_messages %> <div class="accordion-group"> <div class="accordion-heading"> <a href="#incoming_<%=incoming_message.id%>" data-toggle="collapse" data-parent="#incoming_messages"><%= chevron_right %></a> - <%=incoming_message.id%> -- <%= h(incoming_message.mail_from) %> <%=_("at")%> <%=admin_value(incoming_message.sent_at)%> + <%= link_to admin_incoming_edit_path(incoming_message) do %> + <%=incoming_message.id%> + -- + <%= h(incoming_message.mail_from) %> + <%=_("at")%> <%=admin_value(incoming_message.sent_at)%> + <% end %> <blockquote class="incoming-message"> <% if !incoming_message.cached_main_body_text_folded.nil? %> <%= truncate(incoming_message.cached_main_body_text_folded.gsub('FOLDED_QUOTED_SECTION', ''), :length => 400) %> diff --git a/app/views/admin_request/show_raw_email.html.erb b/app/views/admin_request/show_raw_email.html.erb index 72c782ad6..da22b6069 100644 --- a/app/views/admin_request/show_raw_email.html.erb +++ b/app/views/admin_request/show_raw_email.html.erb @@ -1,9 +1,5 @@ -<% @title = "Incoming message #{@raw_email.incoming_message.id} of FOI request '#{@raw_email.incoming_message.info_request.title}'" %> +<%= render :partial => 'admin_incoming_message/intro', :locals => { :incoming_message => @raw_email.incoming_message } %> -<h1>Incoming message <%=@raw_email.incoming_message.id %></h1> - -<p> - FOI request: <%= request_both_links(@raw_email.incoming_message.info_request) %> <% if @holding_pen %> <br>This is in the holding pen because: <strong><%= @rejected_reason %></strong> <% if @public_bodies.size > 0 %> diff --git a/app/views/comment/_single_comment.html.erb b/app/views/comment/_single_comment.html.erb index 421a9d4ba..af1de0649 100644 --- a/app/views/comment/_single_comment.html.erb +++ b/app/views/comment/_single_comment.html.erb @@ -1,5 +1,5 @@ <div class="comment_in_request" id="comment-<%=comment.id.to_s%>"> - <% if comment.user && comment.user.profile_photo %> + <% if comment.user && comment.user.profile_photo && !@render_to_file %> <div class="user_photo_on_comment"> <img src="<%= get_profile_photo_url(:url_name => comment.user.url_name) %>" alt=""> </div> diff --git a/app/views/comment/_single_comment.text.erb b/app/views/comment/_single_comment.text.erb new file mode 100644 index 000000000..925e8b688 --- /dev/null +++ b/app/views/comment/_single_comment.text.erb @@ -0,0 +1,2 @@ +<%= _("{{username}} left an annotation:", :username =>comment.user.name) %> (<%= simple_date(comment.created_at || Time.now) %>) +<%= comment.body.strip %> diff --git a/app/views/general/_stylesheet_includes.html.erb b/app/views/general/_stylesheet_includes.html.erb index 9dd1f357d..416ddb825 100644 --- a/app/views/general/_stylesheet_includes.html.erb +++ b/app/views/general/_stylesheet_includes.html.erb @@ -1,16 +1,23 @@ - <%= stylesheet_link_tag 'main', :title => "Main", :rel => "stylesheet", :media => "all" %> - <%= stylesheet_link_tag 'fonts', :rel => "stylesheet", :media => "all" %> - <%= stylesheet_link_tag 'print', :rel => "stylesheet", :media => "print" %> - <% if !params[:print_stylesheet].nil? %> - <%= stylesheet_link_tag 'print', :rel => "stylesheet", :media => "all" %> - <% end %> - <%= stylesheet_link_tag 'admin-theme/jquery-ui-1.8.15.custom.css', :rel => 'stylesheet'%> - <!--[if LT IE 7]> - <style type="text/css">@import url("/stylesheets/ie6.css");</style> - <![endif]--> - <!--[if LT IE 8]> - <style type="text/css">@import url("/stylesheets/ie7.css");</style> - <![endif]--> - <% if AlaveteliConfiguration::force_registration_on_new_request %> - <%= stylesheet_link_tag 'jquery.fancybox-1.3.4', :rel => "stylesheet" %> - <% end %> +<%- if @render_to_file %> + <style> + <%= raw File.read(Rails.root.join('public', 'stylesheets', 'main.css')) %> + <%= raw File.read(Rails.root.join('public', 'stylesheets', 'print.css')) %> + </style> +<%- else %> + <%= stylesheet_link_tag 'main', :title => "Main", :rel => "stylesheet", :media => "all" %> + <%= stylesheet_link_tag 'fonts', :rel => "stylesheet", :media => "all" %> + <%= stylesheet_link_tag 'print', :rel => "stylesheet", :media => "print" %> + <% if !params[:print_stylesheet].nil? %> + <%= stylesheet_link_tag 'print', :rel => "stylesheet", :media => "all" %> + <% end %> + <%= stylesheet_link_tag 'admin-theme/jquery-ui-1.8.15.custom.css', :rel => 'stylesheet'%> + <!--[if LT IE 7]> + <style type="text/css">@import url("/stylesheets/ie6.css");</style> + <![endif]--> + <!--[if LT IE 8]> + <style type="text/css">@import url("/stylesheets/ie7.css");</style> + <![endif]--> + <% if AlaveteliConfiguration::force_registration_on_new_request %> + <%= stylesheet_link_tag 'jquery.fancybox-1.3.4', :rel => "stylesheet" %> + <% end %> +<% end %> diff --git a/app/views/layouts/_favicon.html.erb b/app/views/layouts/_favicon.html.erb new file mode 100644 index 000000000..4f3859d6c --- /dev/null +++ b/app/views/layouts/_favicon.html.erb @@ -0,0 +1 @@ +<link rel="shortcut icon" href="/favicon.ico"> diff --git a/app/views/layouts/admin.html.erb b/app/views/layouts/admin.html.erb index a58913892..7722efad4 100644 --- a/app/views/layouts/admin.html.erb +++ b/app/views/layouts/admin.html.erb @@ -4,7 +4,7 @@ <meta http-equiv="content-type" content="text/html;charset=UTF-8" > <title><%= site_name %> admin<%= @title ? ":" : "" %> <%=@title%></title> - <%= javascript_include_tag '/javascripts/jquery.js', '/admin/javascripts/jquery-ui.min.js', '/admin/javascripts/bootstrap-collapse', '/admin/javascripts/bootstrap-tab', '/admin/javascripts/admin' %> + <%= javascript_include_tag '/javascripts/jquery.js', '/admin/javascripts/jquery-ui.min.js', '/admin/javascripts/bootstrap-collapse', '/admin/javascripts/bootstrap-tab', '/admin/javascripts/admin', '/javascripts/jquery_ujs' %> <%= stylesheet_link_tag 'admin-theme/jquery-ui-1.8.15.custom.css', :rel => 'stylesheet'%> <%= stylesheet_link_tag "/admin/stylesheets/admin", :title => "Main", :rel => "stylesheet" %> diff --git a/app/views/layouts/default.html.erb b/app/views/layouts/default.html.erb index 472fa8ec1..5895becf7 100644 --- a/app/views/layouts/default.html.erb +++ b/app/views/layouts/default.html.erb @@ -10,7 +10,7 @@ <% end %> </title> - <link rel="shortcut icon" href="/favicon.ico"> + <%= render :partial => 'layouts/favicon' %> <%= render :partial => 'general/stylesheet_includes' %> <% if is_admin? %> diff --git a/app/views/public_body/statistics.html.erb b/app/views/public_body/statistics.html.erb new file mode 100644 index 000000000..840af0c10 --- /dev/null +++ b/app/views/public_body/statistics.html.erb @@ -0,0 +1,75 @@ +<% @title = _("Public Body Statistics") %> +<div id="main_content"> + <h1>Public Body Statistics</h1> + + <p><%= _("This page of public body statistics is currently \ +experimental, so there are some caveats that should be borne \ +in mind:") %></p> + + <ul> + + <li><%= _("The percentages are calculated with respect to \ +the total number of requests, which includes invalid \ +requests; this is a known problem that will be fixed in a \ +later release.") %></li> + + <li><%= _("The classification of requests (e.g. to say \ +whether they were successful or not) is done manually by users \ +and administrators of the site, which means that they are \ +subject to error.") %></li> + + <li><%= _("Requests are considered successful if they were \ +classified as either 'Successful' or 'Partially Successful'.") %></li> + + <li><%= _("Requests are considered overdue if they are in \ +the 'Overdue' or 'Very Overdue' states.") %></li> + + <li><%= _("The error bars shown are 95% confidence intervals \ +for the hypothesized underlying proportion (i.e. that which \ +you would obtain by making an infinite number of requests \ +through this site to that authority). In other words, the \ +population being sampled is all the current and future \ +requests to the authority through this site, rather than, \ +say, all requests that have been made to the public body by \ +any means.") %></li> + + </ul> + + <p><%= _("These graphs were partly inspired by \ +<a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some \ +statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks \ +are due to him.") %></p> + + <% @graph_list.each do |graph_data| %> + <h3 class="public-body-ranking-title"><%= graph_data['title']%></h3> + <div class="public-body-ranking" id="<%= graph_data['id'] %>"> + <% if graph_data['x_values'] %> + <table border=0> + <thead> + <tr> + <th>Public Body</th> + <th><%= graph_data['y_axis'] %></th> + </tr> + </thead> + <tbody> + <% graph_data['x_ticks'].each_with_index do |pb_and_index, i| %> + <tr> + <td><%= pb_and_index[1] %></td> + <td class="statistic"><%= graph_data['y_values'][i].round %></td> + </tr> + <% end %> + </tbody> + </table> + <% else %> + <%= _("There was no data calculated for this graph yet.") %> + <% end %> + </div> + <% end %> + +<script type="text/javascript"> + var graphs_data = <%= @graph_list.to_json.html_safe %>; +</script> +<!--[if lte IE 8]><%= javascript_include_tag 'excanvas.min.js' %><![endif]--> +<%= javascript_include_tag 'jquery.flot.min.js', 'jquery.flot.errorbars.min.js', 'jquery.flot.axislabels.js', 'stats-graphs.js' %> + +</div> diff --git a/app/views/request/_after_actions.html.erb b/app/views/request/_after_actions.html.erb index b54a8f5fb..f780e3a37 100644 --- a/app/views/request/_after_actions.html.erb +++ b/app/views/request/_after_actions.html.erb @@ -15,11 +15,9 @@ <%= link_to _('Update the status of this request'), '#describe_state_form_1' %> </li> <% end %> - <% if @info_request.all_can_view? %> <li> <%= link_to _("Download a zip file of all correspondence"), download_entire_request_path(:url_title => @info_request.url_title) %> </li> - <% end %> </ul> </div> <% if ! @info_request.is_external? %> diff --git a/app/views/request/_correspondence.html.erb b/app/views/request/_correspondence.html.erb index 68711b259..c39625c3c 100644 --- a/app/views/request/_correspondence.html.erb +++ b/app/views/request/_correspondence.html.erb @@ -1,80 +1,12 @@ <div class="ff-print-fix"></div> -<% -if !info_request_event.nil? && info_request_event.event_type == 'response' - incoming_message = info_request_event.incoming_message -end - -if not incoming_message.nil? -%> - <div class="incoming correspondence" id="incoming-<%=incoming_message.id.to_s%>"> - <h2> - <% if !incoming_message.safe_mail_from.nil? && incoming_message.safe_mail_from.strip != @info_request.public_body.name.strip %> - <%= _("From:") %> <%=h incoming_message.safe_mail_from %><br> - <% end %> - <% if incoming_message.safe_mail_from.nil? || (incoming_message.mail_from_domain == @info_request.public_body.request_email_domain) %> - <%=h @info_request.public_body.name %><br> - <% end %> - <br><%= simple_date(incoming_message.sent_at) %> - </h2> - - <%= render :partial => 'bubble', :locals => { :incoming_message => incoming_message, :body => incoming_message.get_body_for_html_display(@collapse_quotes), :attachments => incoming_message.get_attachments_for_display } %> - - <p class="event_actions"> - <% if !@user.nil? && @user.admin_page_links? %> - <%= link_to "Admin", admin_request_show_raw_email_path(incoming_message.raw_email_id) %> | - <% end %> - <%= link_to _("Link to this"), incoming_message_path(incoming_message), :class => "link_to_this" %> - </p> - </div> -<% -elsif [ 'sent', 'followup_sent' ].include?(info_request_event.event_type) - outgoing_message = info_request_event.outgoing_message - %> - <div class="outgoing correspondence" id="outgoing-<%=outgoing_message.id.to_s%>"> - - <h2> - <%= _("From:") %> <%=h @info_request.user_name %><br> - <br><%= simple_date(info_request_event.created_at) %> - </h2> - - <%= render :partial => 'bubble', :locals => { :body => outgoing_message.get_body_for_html_display(), :attachments => nil } %> - - <p class="event_actions"> - <% if outgoing_message.status == 'ready' && !@info_request.is_external? %> - <strong>Warning:</strong> This message has <strong>not yet been sent</strong> for an unknown reason. - <% end %> - - <!-- Can use this to get name of who followup was too, if say you - play with proper from display, but not sure needed - <% if outgoing_message.message_type == 'followup' && !outgoing_message.incoming_message_followup.nil? && !outgoing_message.incoming_message_followup.safe_mail_from.nil? %> - Follow up sent to: <%=h outgoing_message.incoming_message_followup.safe_mail_from %> - <% end %> - --> - - <%= link_to _("Link to this"), outgoing_message_path(outgoing_message), :class => "link_to_this" %> - </p> - </div> -<% elsif [ 'resent', 'followup_resent' ].include?(info_request_event.event_type) %> - <div class="outgoing correspondence" id="outgoing-<%=info_request_event.outgoing_message.id.to_s%>"> - <h2> - <%= simple_date(info_request_event.created_at) %> - </h2> - <p class="event_plain"> - Sent - <% if info_request_event.outgoing_message.message_type == 'initial_request' %> - request - <% elsif info_request_event.outgoing_message.message_type == 'followup' %> - a follow up - <% else %> - <% raise "unknown message_type" %> - <% end %> - - to <%= public_body_link(@info_request.public_body) %> again<% if not info_request_event.same_email_as_previous_send? %>, using a new contact address<% end %>. - </p> - </div> -<% elsif info_request_event.event_type == 'comment' - comment = info_request_event.comment -%> - <%= render :partial => 'comment/single_comment', :locals => { :comment => comment } %> +<% case info_request_event.event_type %> +<% when 'response' %> + <%= render :partial => 'request/incoming_correspondence', :locals => { :incoming_message => info_request_event.incoming_message } %> +<% when 'sent', 'followup_sent' %> + <%= render :partial => 'request/outgoing_correspondence', :locals => { :outgoing_message => info_request_event.outgoing_message, :info_request_event => info_request_event }%> +<% when 'resent', 'followup_resent' %> + <%= render :partial => 'request/resent_outgoing_correspondence', :locals => { :outgoing_message => info_request_event.outgoing_message, :info_request_event => info_request_event }%> +<% when 'comment' %> + <%= render :partial => 'comment/single_comment', :locals => { :comment => info_request_event.comment } %> <% end %> diff --git a/app/views/request/_hidden_correspondence.html.erb b/app/views/request/_hidden_correspondence.html.erb index 4c06f1f48..153164278 100644 --- a/app/views/request/_hidden_correspondence.html.erb +++ b/app/views/request/_hidden_correspondence.html.erb @@ -1,33 +1,13 @@ -<% if info_request_event.prominence == 'requester_only' %> - <% - if !info_request_event.nil? && info_request_event.event_type == 'response' - incoming_message = info_request_event.incoming_message - end - if not incoming_message.nil? - %> - <div class="correspondence" id="incoming-<%=incoming_message.id.to_s%>"> - <p> - <%= _('This response has been hidden. See annotations to find out why. - If you are the requester, then you may <a href="{{url}}">sign in</a> to view the response.', :url => signin_url(:r => request.fullpath).html_safe) %> - </p> - </div> - <% elsif [ 'sent', 'followup_sent', 'resent', 'followup_resent' ].include?(info_request_event.event_type) %> - <div class="correspondence" id="outgoing-<%=outgoing_message.id.to_s%>"> - <p> - <%= _('This outgoing message has been hidden. See annotations to - find out why. If you are the requester, then you may <a href="{{url}}">sign in</a> to view the response.', :url => signin_url(:r => request.fullpath).html_safe) %> - </p> - </div> - <% elsif info_request_event.event_type == 'comment' %> - <div class="comment_in_request" id="comment-<%=comment.id.to_s%>"> - <p><%= _('This comment has been hidden. See annotations to - find out why. If you are the requester, then you may <a href="{{url}}">sign in</a> to view the response.', :url => signin_url(:r => request.fullpath).html_safe) %> - </p> - </div> - <% end %> - -<% elsif info_request_event.prominence == 'hidden' %> - <% # show nothing when hidden %> -<% else %> - <% raise _("unexpected prominence on request event") %> -<% end %> +<p id="hidden_message"> + <%- if !message.prominence_reason.blank? %> + <%= _('This message has been hidden.') %> + <%= message.prominence_reason %> + <%= _('Please <a href="{{url}}">contact us</a> if you have any questions.', :url => help_contact_path.html_safe) %> + <%- else %> + <%= _("This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here.") %> + <%= _('Please <a href="{{url}}">contact us</a> if you have any questions.', :url => help_contact_path.html_safe) %> + <%- end %> + <% if message.prominence == 'requester_only' %> + <%= _('If you are the requester, then you may <a href="{{url}}">sign in</a> to view the message.', :url => signin_url(:r => request.fullpath).html_safe) %> + <% end %> +</p> diff --git a/app/views/request/_hidden_correspondence.text.erb b/app/views/request/_hidden_correspondence.text.erb new file mode 100644 index 000000000..010b6b66d --- /dev/null +++ b/app/views/request/_hidden_correspondence.text.erb @@ -0,0 +1,5 @@ +<%- if !message.prominence_reason.blank? %> + <%= _('This message has been hidden.') %> <%= message.prominence_reason %> +<%- else %> + <%= _("This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here.") %> +<%- end %> diff --git a/app/views/request/_incoming_correspondence.html.erb b/app/views/request/_incoming_correspondence.html.erb new file mode 100644 index 000000000..f39d650d8 --- /dev/null +++ b/app/views/request/_incoming_correspondence.html.erb @@ -0,0 +1,26 @@ +<div class="incoming correspondence <%= incoming_message.prominence %>" id="incoming-<%=incoming_message.id.to_s%>"> + <%- if not incoming_message.user_can_view?(@user) %> + <%= render :partial => 'request/hidden_correspondence', :locals => { :message => incoming_message }%> + <%- else %> + <%= render :partial => 'request/restricted_correspondence', :locals => {:message => incoming_message } %> + <h2> + <% if incoming_message.specific_from_name? %> + <%= _("From:") %> <%= incoming_message.safe_mail_from %><br> + <% end %> + <% if incoming_message.from_public_body? %> + <%= @info_request.public_body.name %><br> + <% end %> + <br><%= simple_date(incoming_message.sent_at) %> + </h2> + + <%= render :partial => 'bubble', :locals => { :incoming_message => incoming_message, :body => incoming_message.get_body_for_html_display(@collapse_quotes), :attachments => incoming_message.get_attachments_for_display } %> + + <p class="event_actions"> + <% if !@user.nil? && @user.admin_page_links? %> + <%= link_to "Admin", admin_incoming_edit_path(incoming_message.id) %> | + <% end %> + <%= link_to _("Link to this"), incoming_message_path(incoming_message), :class => "link_to_this" %> + </p> + <%- end %> +</div> + diff --git a/app/views/request/_incoming_correspondence.text.erb b/app/views/request/_incoming_correspondence.text.erb new file mode 100644 index 000000000..33ddad926 --- /dev/null +++ b/app/views/request/_incoming_correspondence.text.erb @@ -0,0 +1,12 @@ +<%- if not incoming_message.user_can_view?(@user) %> + <%= render :partial => 'request/hidden_correspondence.text', :locals => { :message => incoming_message }%> +<%- else %> +<%= _('From:') %><% if incoming_message.specific_from_name? %> <%= incoming_message.safe_mail_from %><% end %><% if incoming_message.from_public_body? %>, <%= @info_request.public_body.name %><% end %> +<%= _('To:') %> <% if @info_request.user_name %><%= @info_request.user_name %><% else %><%= "[#{_('An anonymous user')}]"%><% end %> +<%= _('Date:') %> <%= simple_date(incoming_message.sent_at) %> + + <%= incoming_message.get_body_for_quoting %> + <% incoming_message.get_attachments_for_display.each do |a| %> +<%= _('Attachment:') %> <%= a.display_filename %> (<%= a.display_size %>) + <% end %> +<% end %> diff --git a/app/views/request/_outgoing_correspondence.html.erb b/app/views/request/_outgoing_correspondence.html.erb new file mode 100644 index 000000000..dced5c94c --- /dev/null +++ b/app/views/request/_outgoing_correspondence.html.erb @@ -0,0 +1,18 @@ +<div class="outgoing correspondence" id="outgoing-<%=outgoing_message.id.to_s%>"> + <%- if not outgoing_message.user_can_view?(@user) %> + <%= render :partial => 'request/hidden_correspondence', :locals => { :message => outgoing_message }%> + <%- else %> + <%= render :partial => 'request/restricted_correspondence', :locals => {:message => outgoing_message } %> + <h2> + <%= _("From:") %> <%= @info_request.user_name %><br> + <br><%= simple_date(info_request_event.created_at) %> + </h2> + <%= render :partial => 'bubble', :locals => { :body => outgoing_message.get_body_for_html_display(), :attachments => nil } %> + <p class="event_actions"> + <% if outgoing_message.status == 'ready' && !@info_request.is_external? %> + <strong>Warning:</strong> This message has <strong>not yet been sent</strong> for an unknown reason. + <% end %> + <%= link_to _("Link to this"), outgoing_message_path(outgoing_message), :class => "link_to_this" %> + </p> + <%- end %> +</div> diff --git a/app/views/request/_outgoing_correspondence.text.erb b/app/views/request/_outgoing_correspondence.text.erb new file mode 100644 index 000000000..80c71cc01 --- /dev/null +++ b/app/views/request/_outgoing_correspondence.text.erb @@ -0,0 +1,8 @@ +<%- if not outgoing_message.user_can_view?(@user) %> + <%= render :partial => 'request/hidden_correspondence.text', :locals => { :message => outgoing_message }%> +<%- else %> + <%= _('From:') %> <% if @info_request.user_name %><%= @info_request.user_name %><% else %><%= "[#{_('An anonymous user')}]"%><% end %> + <%= _('To:') %> <%= @info_request.public_body.name %> + <%= _('Date:') %> <%= simple_date(info_request_event.created_at) %> + <%= outgoing_message.get_body_for_text_display %> +<%- end %> diff --git a/app/views/request/_resent_outgoing_correspondence.html.erb b/app/views/request/_resent_outgoing_correspondence.html.erb new file mode 100644 index 000000000..17b6b635b --- /dev/null +++ b/app/views/request/_resent_outgoing_correspondence.html.erb @@ -0,0 +1,16 @@ +<div class="outgoing correspondence" id="outgoing-<%=outgoing_message.id.to_s%>"> + <h2> + <%= simple_date(info_request_event.created_at) %> + </h2> + <p class="event_plain"> + Sent + <% if outgoing_message.message_type == 'initial_request' %> + request + <% elsif outgoing_message.message_type == 'followup' %> + a follow up + <% else %> + <% raise "unknown message_type" %> + <% end %> + to <%= public_body_link(@info_request.public_body) %> again<% if not info_request_event.same_email_as_previous_send? %>, using a new contact address<% end %>. + </p> +</div> diff --git a/app/views/request/_resent_outgoing_correspondence.text.erb b/app/views/request/_resent_outgoing_correspondence.text.erb new file mode 100644 index 000000000..d645e9488 --- /dev/null +++ b/app/views/request/_resent_outgoing_correspondence.text.erb @@ -0,0 +1,2 @@ +<%= _('Date:') %> <%= simple_date(info_request_event.created_at) %> +Sent <% if outgoing_message.message_type == 'initial_request' %> request <% elsif outgoing_message.message_type == 'followup' %> a follow up <% else %> <% raise "unknown message_type" %><% end %> to <%= public_body_link(@info_request.public_body) %> again<% if not info_request_event.same_email_as_previous_send? %>, using a new contact address<% end %>. diff --git a/app/views/request/_restricted_correspondence.html.erb b/app/views/request/_restricted_correspondence.html.erb new file mode 100644 index 000000000..745c4ff0e --- /dev/null +++ b/app/views/request/_restricted_correspondence.html.erb @@ -0,0 +1,18 @@ +<% if message.prominence == 'hidden' %> + <p id="hidden_message"> + <%- if !message.prominence_reason.blank? %> + <%= _('This message has prominence \'hidden\'. {{reason}} You can only see it because you are logged in as a super user.', :reason => message.prominence_reason) %> + <%- else %> + <%= _('This message has prominence \'hidden\'. You can only see it because you are logged in as a super user.') %> + <%- end %> + </p> +<% end %> +<% if message.prominence == 'requester_only' %> + <p id="hidden_message"> + <%- if !message.prominence_reason.blank? %> + <%= _('This message is hidden, so that only you, the requester, can see it. {{reason}}', :reason => message.prominence_reason) %> + <%- else %> + <%= _('This message is hidden, so that only you, the requester, can see it. Please <a href="{{url}}">contact us</a> if you are not sure why.', :url => help_requesting_path.html_safe) %> + <%- end %> + </p> +<% end %> diff --git a/app/views/request/hidden_correspondence.html.erb b/app/views/request/hidden_correspondence.html.erb new file mode 100644 index 000000000..46bf3ee37 --- /dev/null +++ b/app/views/request/hidden_correspondence.html.erb @@ -0,0 +1,4 @@ +<% @title = _("Message has been removed") %> + +<h1><%=@title%></h1> +<%= render :partial => 'request/hidden_correspondence', :locals => { :message => @incoming_message } %> diff --git a/app/views/request/show.html.erb b/app/views/request/show.html.erb index 4b0663f76..c520ce40c 100644 --- a/app/views/request/show.html.erb +++ b/app/views/request/show.html.erb @@ -25,7 +25,7 @@ <div id="left_column"> <h1><%=h(@info_request.title)%></h1> - <% if !@info_request.is_external? && @info_request.user.profile_photo %> + <% if !@info_request.is_external? && @info_request.user.profile_photo && !@render_to_file %> <p class="user_photo_on_request"> <img src="<%= get_profile_photo_url(:url_name => @info_request.user.url_name) %>" alt=""> </p> @@ -48,7 +48,7 @@ <p id="request_status" class="request_icon_line icon_<%= @info_request.calculate_status %>"> <% if @info_request.awaiting_description %> - <% if @is_owning_user && !@info_request.is_external? %> + <% if @is_owning_user && !@info_request.is_external? && !@render_to_file %> <%= _('Please <strong>answer the question above</strong> so we know whether the ')%> <%= MySociety::Format.fancy_pluralize(@new_responses_count, 'recent response contains', 'recent responses contain') %> <%= _('useful information.') %> <% else %> @@ -146,4 +146,4 @@ <%= render :partial => 'after_actions' %> </div> -<%= render :partial => 'sidebar' %> +<%- if @sidebar %><%= render :partial => 'sidebar' %><% end %> diff --git a/app/views/request/show.text.erb b/app/views/request/show.text.erb new file mode 100644 index 000000000..29ac2987f --- /dev/null +++ b/app/views/request/show.text.erb @@ -0,0 +1,17 @@ +<%= _('This is a plain-text version of the Freedom of Information request "{{request_title}}". The latest, full version is available online at {{full_url}}', :request_title => @info_request.title, :full_url => "http://#{AlaveteliConfiguration::domain}#{show_request_path(:url_title=>@info_request.url_title)}") %>. + +<% @info_request_events.each do |info_request_event| %> + <% if info_request_event.visible %> + <% case info_request_event.event_type %> + <% when 'response' %> + <%= render :partial => 'request/incoming_correspondence.text', :locals => { :incoming_message => info_request_event.incoming_message } %> + <% when 'sent', 'followup_sent' %> + <%= render :partial => 'request/outgoing_correspondence.text', :locals => { :outgoing_message => info_request_event.outgoing_message, :info_request_event => info_request_event }%> + <% when 'resent', 'followup_resent' %> + <%= render :partial => 'request/resent_outgoing_correspondence.text', :locals => { outgoing_message => info_request_event.outgoing_message, :info_request_event => info_request_event }%> + <% when 'comment' %> + <%= render :partial => 'comment/single_comment.text', :locals => { :comment => info_request_event.comment } %> + <% end %> +------------------------------- + <% end %> +<% end %> diff --git a/app/views/request/show_response.html.erb b/app/views/request/show_response.html.erb index a61359679..ace86cf4c 100644 --- a/app/views/request/show_response.html.erb +++ b/app/views/request/show_response.html.erb @@ -36,7 +36,7 @@ <dd> <%= _('To do that please send a private email to ') %><%=h(@postal_email_name)%> <<%=link_to h(@postal_email), "mailto:" + @postal_email%>> - <%= _('containing your postal address, and asking them to reply to this request. + <%= _('containing your postal address, and asking them to reply to this request. Or you could phone them.') %> <%= _('When you receive the paper response, please help @@ -63,16 +63,16 @@ <% end %> <% else %> <% if @incoming_message.recently_arrived %> - <h2><%= _('New response to {{law_used_short}} request',:law_used_short => h(@info_request.law_used_short))%> '<%= request_link @info_request %>'</h2> + <h2><%= _('New response to {{law_used_short}} request',:law_used_short => h(@info_request.law_used_short))%> '<%= request_link @info_request %>'</h2> <% else %> <h2>Response to <%=h(@info_request.law_used_short)%> request '<%= request_link @info_request %>'</h2> <% end %> <% end %> <% if @incoming_message.nil? %> - <%= render :partial => 'correspondence', :locals => { :info_request_event => @info_request.get_last_outgoing_event, :incoming_message => nil } %> + <%= render :partial => 'correspondence', :locals => { :info_request_event => @info_request.get_last_outgoing_event } %> <% else %> - <%= render :partial => 'correspondence', :locals => { :info_request_event => nil, :incoming_message => @incoming_message } %> + <%= render :partial => 'correspondence', :locals => { :info_request_event => @incoming_message.response_event } %> <% end %> <% end %> diff --git a/app/views/request/simple_correspondence.html.erb b/app/views/request/simple_correspondence.html.erb deleted file mode 100644 index 461fa3912..000000000 --- a/app/views/request/simple_correspondence.html.erb +++ /dev/null @@ -1,45 +0,0 @@ -<%= _('This is a plain-text version of the Freedom of Information request "{{request_title}}". The latest, full version is available online at {{full_url}}', :request_title => @info_request.title, :full_url => "http://#{AlaveteliConfiguration::domain}#{show_request_path(:url_title=>@info_request.url_title)}") %>. - -<% for info_request_event in @info_request_events %> -<% - incoming_message = nil - if info_request_event.visible - if !info_request_event.nil? && info_request_event.event_type == 'response' - incoming_message = info_request_event.incoming_message - end - - - if not incoming_message.nil? - if !incoming_message.safe_mail_from.nil? && incoming_message.safe_mail_from.strip != @info_request.public_body.name.strip %> -<%= _('From:') %> <%= incoming_message.safe_mail_from %><% end - if incoming_message.safe_mail_from.nil? || (incoming_message.mail_from_domain == @info_request.public_body.request_email_domain) %>, <%= @info_request.public_body.name %><% end %> -<%= _('To:') %> <% if @info_request.user_name %><%= @info_request.user_name %><% else %><%= "[#{_('An anonymous user')}]"%><% end %> -<%= _('Date:') %> <%= simple_date(incoming_message.sent_at) %> - -<%= incoming_message.get_body_for_quoting %> -<% incoming_message.get_attachments_for_display.each do |a| %> - <%= _('Attachment:') %> <%= a.display_filename %> (<%= a.display_size %>) - <% end %> -<% -elsif [ 'sent', 'followup_sent' ].include?(info_request_event.event_type) - outgoing_message = info_request_event.outgoing_message - %> -<%= _('From:') %> <% if @info_request.user_name %><%= @info_request.user_name %><% else %><%= "[#{_('An anonymous user')}]"%><% end %> -<%= _('To:') %> <%= @info_request.public_body.name %> -<%= _('Date:') %> <%= simple_date(info_request_event.created_at) %> -<% - text = outgoing_message.body.strip - outgoing_message.remove_privacy_sensitive_things!(text) %> - -<%= text %> -<% elsif [ 'resent', 'followup_resent' ].include?(info_request_event.event_type) %> -<%= _('Date:') %> <%= simple_date(info_request_event.created_at) %> -Sent <% if info_request_event.outgoing_message.message_type == 'initial_request' %> request <% elsif info_request_event.outgoing_message.message_type == 'followup' %> a follow up <% else %> <% raise "unknown message_type" %><% end %> to <%= public_body_link(@info_request.public_body) %> again<% if not info_request_event.same_email_as_previous_send? %>, using a new contact address<% end %>. - -<% elsif info_request_event.event_type == 'comment' - comment = info_request_event.comment -%> -<%= _("{{username}} left an annotation:", :username =>comment.user.name) %> (<%= simple_date(comment.created_at || Time.now) %>) -<%= comment.body.strip %> -<% end %> --------------------------------<% end %><% end %> diff --git a/config/crontab-example b/config/crontab-example index 32baff170..d2c3f6bd9 100644 --- a/config/crontab-example +++ b/config/crontab-example @@ -26,6 +26,8 @@ MAILTO=cron-!!(*= $site *)!!@mysociety.org 0 8 * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/alert-not-clarified-request.lock /data/vhost/!!(*= $vhost *)!!/!!(*= $vcspath *)!!/script/alert-not-clarified-request || echo "stalled?" 2 4 * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/check-recent-requests-sent.lock /data/vhost/!!(*= $vhost *)!!/!!(*= $vcspath *)!!/script/check-recent-requests-sent || echo "stalled?" 45 3 * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/stop-new-responses-on-old-requests.lock /data/vhost/!!(*= $vhost *)!!/!!(*= $vcspath *)!!/script/stop-new-responses-on-old-requests || echo "stalled?" +55 4 * * * !!(*= $user *)!! run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/update-public-body-stats.lock /data/vhost/!!(*= $vhost *)!!/!!(*= $vcspath *)!!/script/update-public-body-stats || echo "stalled?" + # Only root can restart apache 31 1 * * * root run-with-lockfile -n /data/vhost/!!(*= $vhost *)!!/change-xapian-database.lock "/data/vhost/!!(*= $vhost *)!!/!!(*= $vcspath *)!!/script/compact-xapian-database production" || echo "stalled?" diff --git a/config/deploy.rb b/config/deploy.rb index 3ce1a1969..d26a199c8 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -58,7 +58,6 @@ namespace :deploy do "#{release_path}/files" => "#{shared_path}/files", "#{release_path}/cache" => "#{shared_path}/cache", "#{release_path}/vendor/plugins/acts_as_xapian/xapiandbs" => "#{shared_path}/xapiandbs", - "#{release_path}/public/download" => "#{release_path}/cache/zips/download" } # "ln -sf <a> <b>" creates a symbolic link but deletes <b> if it already exists diff --git a/config/general.yml-example b/config/general.yml-example index 0753af46b..8e749d9d6 100644 --- a/config/general.yml-example +++ b/config/general.yml-example @@ -147,9 +147,9 @@ GAZE_URL: http://gaze.mysociety.org # The email address to which non-bounce responses should be forwarded FORWARD_NONBOUNCE_RESPONSES_TO: user-support@localhost -# Path to a program that converts a page at a URL to HTML. It should -# take two arguments: the URL, and a path to an output file. A static -# binary of wkhtmltopdf is recommended: +# Path to a program that converts an HTML page in a file to PDF. It +#should take two arguments: the URL, and a path to an output file. +# A static binary of wkhtmltopdf is recommended: # http://code.google.com/p/wkhtmltopdf/downloads/list # If the command is not present, a text-only version will be rendered # instead. @@ -192,3 +192,16 @@ MTA_LOG_TYPE: "exim" # this will be included in the message people see when their request is # successful. DONATION_URL: "http://www.mysociety.org/donate/" + +# If you set this to 'true' then a page of statistics on the +# performance of public bodies will be available: +PUBLIC_BODY_STATISTICS_PAGE: false + +# The page of statistics for public bodies will only consider public +# bodies that have had at least this number of requests: +MINIMUM_REQUESTS_FOR_STATISTICS: 50 + +# If only some of the public bodies have been translated into every +# available locale, you can allow a fallback to the default locale for +# listing of public bodies. +PUBLIC_BODY_LIST_FALLBACK_TO_DEFAULT_LOCALE: false diff --git a/config/httpd.conf-example b/config/httpd.conf-example index 1326252f5..dc2e4966e 100644 --- a/config/httpd.conf-example +++ b/config/httpd.conf-example @@ -69,3 +69,13 @@ RewriteRule ^/request/((\d{1,3})\d*)/(response/\d+/attach/(html/)?\d+/.+) /views AddOutputFilterByType DEFLATE font/opentype font/truetype font/eot AddOutputFilterByType DEFLATE image/svg+xml </IFModule> + +# Set the Sendfile header and switch sendfile on - Apache will +# now handle send_file calls from Alaveteli +<Location /> + <IfModule mod_xsendfile.c> + RequestHeader Set X-Sendfile-Type X-Sendfile + XSendFile On + XSendFileAllowAbove On + </IfModule> +</Location> diff --git a/config/initializers/alaveteli.rb b/config/initializers/alaveteli.rb index 2c6ee2fbc..8ae78c80c 100644 --- a/config/initializers/alaveteli.rb +++ b/config/initializers/alaveteli.rb @@ -10,7 +10,7 @@ load "debug_helpers.rb" load "util.rb" # Application version -ALAVETELI_VERSION = '0.13' +ALAVETELI_VERSION = '0.14' # Add new inflection rules using the following format # (all these examples are active by default): @@ -25,7 +25,6 @@ ALAVETELI_VERSION = '0.13' # Mime::Type.register "text/richtext", :rtf # Mime::Type.register "application/x-mobile", :mobile -# The Rails cache is set up by the Interlock plugin to use memcached # Domain for URLs (so can work for scripts, not just web pages) ActionMailer::Base.default_url_options[:host] = AlaveteliConfiguration::domain @@ -50,6 +49,7 @@ require 'ability' require 'normalize_string' require 'alaveteli_file_types' require 'alaveteli_localization' +require 'message_prominence' AlaveteliLocalization.set_locales(AlaveteliConfiguration::available_locales, AlaveteliConfiguration::default_locale) diff --git a/config/packages b/config/packages index 5d6622c30..8bb00a849 100644 --- a/config/packages +++ b/config/packages @@ -3,7 +3,6 @@ # alavateli mailing list if you want to change it ruby1.8 ruby -libopenssl-ruby1.8 # needed for Ubuntu 10.04 TLS; included in libruby1.8 in Squeeze rdoc | rdoc1.8 irb | irb1.8 wv @@ -28,9 +27,11 @@ wkhtmltopdf-static libmagic-dev libmagickwand-dev libpq-dev +libxml2-dev +libxslt-dev uuid-dev ruby1.8-dev -rubygems +rubygems (>= 1.8.15) rake (>= 0.9.2.2) build-essential bundler diff --git a/config/routes.rb b/config/routes.rb index 5af94768c..cadb7ec54 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -105,6 +105,7 @@ Alaveteli::Application.routes.draw do match '/body/:url_name/view_email' => 'public_body#view_email', :as => :view_public_body_email match '/body/:url_name/:tag' => 'public_body#show', :as => :show_public_body_tag match '/body/:url_name/:tag/:view' => 'public_body#show', :as => :show_public_body_tag_view + match '/body_statistics' => 'public_body#statistics', :as => :public_bodies_statistics #### #### Comment controller @@ -176,7 +177,6 @@ Alaveteli::Application.routes.draw do match '/admin/timeline' => 'admin_general#timeline', :as => :admin_timeline match '/admin/debug' => 'admin_general#debug', :as => :admin_debug match '/admin/stats' => 'admin_general#stats', :as => :admin_stats - match '/admin/javascripts/admin.js' => 'admin_general#admin_js', :as => :admin_js #### #### AdminRequest controller @@ -187,13 +187,8 @@ Alaveteli::Application.routes.draw do match '/admin/request/edit/:id' => 'admin_request#edit', :as => :admin_request_edit match '/admin/request/update/:id' => 'admin_request#update', :as => :admin_request_update match '/admin/request/destroy/:id' => 'admin_request#fully_destroy', :as => :admin_request_destroy - match '/admin/request/edit_outgoing/:id' => 'admin_request#edit_outgoing', :as => :admin_request_edit_outgoing - match '/admin/request/destroy_outgoing/:id' => 'admin_request#destroy_outgoing', :as => :admin_request_destroy_outgoing - match '/admin/request/update_outgoing/:id' => 'admin_request#update_outgoing', :as => :admin_request_update_outgoing match '/admin/request/edit_comment/:id' => 'admin_request#edit_comment', :as => :admin_request_edit_comment match '/admin/request/update_comment/:id' => 'admin_request#update_comment', :as => :admin_request_update_comment - match '/admin/request/destroy_incoming' => 'admin_request#destroy_incoming', :as => :admin_request_destroy_incoming - match '/admin/request/redeliver_incoming' => 'admin_request#redeliver_incoming', :as => :admin_request_redeliver_incoming match '/admin/request/move_request' => 'admin_request#move_request', :as => :admin_request_move_request match '/admin/request/generate_upload_url/:id' => 'admin_request#generate_upload_url', :as => :admin_request_generate_upload_url match '/admin/request/show_raw_email/:id' => 'admin_request#show_raw_email', :as => :admin_request_show_raw_email @@ -202,6 +197,19 @@ Alaveteli::Application.routes.draw do match '/admin/request/hide/:id' => 'admin_request#hide_request', :as => :admin_request_hide #### + #### AdminIncomingMessage controller + match '/admin/incoming/destroy' => 'admin_incoming_message#destroy', :as => :admin_incoming_destroy + match '/admin/incoming/redeliver' => 'admin_incoming_message#redeliver', :as => :admin_incoming_redeliver + match '/admin/incoming/edit/:id' => 'admin_incoming_message#edit', :as => :admin_incoming_edit + match '/admin/incoming/update/:id' => 'admin_incoming_message#update', :as => :admin_incoming_update + #### + + #### AdminOutgoingMessage controller + match '/admin/outgoing/edit/:id' => 'admin_outgoing_message#edit', :as => :admin_outgoing_edit + match '/admin/outgoing/destroy/:id' => 'admin_outgoing_message#destroy', :as => :admin_outgoing_destroy + match '/admin/outgoing/update/:id' => 'admin_outgoing_message#update', :as => :admin_outgoing_update + #### + #### AdminUser controller match '/admin/user' => 'admin_user#index', :as => :admin_user_index match '/admin/user/list' => 'admin_user#list', :as => :admin_user_list diff --git a/config/test.yml b/config/test.yml index 5c08e928b..b26ca99d4 100644 --- a/config/test.yml +++ b/config/test.yml @@ -108,7 +108,7 @@ ACCELERATOR_PORT: '6081' # mySociety's gazeteer service. Shouldn't change. GAZE_URL: http://gaze.mysociety.org -# Path to a program that converts a page at a URL to HTML. It should +# Path to a program that converts a page in a file to PDF. It should # take two arguments: the URL, and a path to an output file. A static # binary of wkhtmltopdf is recommended: # http://code.google.com/p/wkhtmltopdf/downloads/list diff --git a/db/migrate/20130731142632_remove_prominence_from_info_request_event.rb b/db/migrate/20130731142632_remove_prominence_from_info_request_event.rb new file mode 100644 index 000000000..df0278c20 --- /dev/null +++ b/db/migrate/20130731142632_remove_prominence_from_info_request_event.rb @@ -0,0 +1,9 @@ +class RemoveProminenceFromInfoRequestEvent < ActiveRecord::Migration + def up + remove_column :info_request_events, :prominence + end + + def down + add_column :info_request_events, :prominence, :string, :null => false, :default => 'normal' + end +end diff --git a/db/migrate/20130731145325_add_prominence_to_incoming_message.rb b/db/migrate/20130731145325_add_prominence_to_incoming_message.rb new file mode 100644 index 000000000..01c4906a7 --- /dev/null +++ b/db/migrate/20130731145325_add_prominence_to_incoming_message.rb @@ -0,0 +1,5 @@ +class AddProminenceToIncomingMessage < ActiveRecord::Migration + def change + add_column :incoming_messages, :prominence, :string, :null => false, :default => 'normal' + end +end diff --git a/db/migrate/20130801154033_add_prominence_reason_to_incoming_message.rb b/db/migrate/20130801154033_add_prominence_reason_to_incoming_message.rb new file mode 100644 index 000000000..2d189f658 --- /dev/null +++ b/db/migrate/20130801154033_add_prominence_reason_to_incoming_message.rb @@ -0,0 +1,5 @@ +class AddProminenceReasonToIncomingMessage < ActiveRecord::Migration + def change + add_column :incoming_messages, :prominence_reason, :text + end +end diff --git a/db/migrate/20130816150110_add_statistics_to_public_body.rb b/db/migrate/20130816150110_add_statistics_to_public_body.rb new file mode 100644 index 000000000..fb3a67e83 --- /dev/null +++ b/db/migrate/20130816150110_add_statistics_to_public_body.rb @@ -0,0 +1,26 @@ +class AddStatisticsToPublicBody < ActiveRecord::Migration + def self.up + add_column :public_bodies, :info_requests_successful_count, :integer + add_column :public_bodies, :info_requests_not_held_count, :integer + add_column :public_bodies, :info_requests_overdue_count, :integer + # We need to set the :info_requests_successful_count and + # :info_requests_not_held_count columns, since they will + # subsequently will be updated in after_save / + # after_destroy. :info_requests_overdue_count, however will be set + # from a periodically run rake task. + PublicBody.connection.execute("UPDATE public_bodies + SET info_requests_not_held_count = (SELECT COUNT(*) FROM info_requests + WHERE described_state = 'not_held' AND + public_body_id = public_bodies.id);") + PublicBody.connection.execute("UPDATE public_bodies + SET info_requests_successful_count = (SELECT COUNT(*) FROM info_requests + WHERE described_state IN ('successful', 'partially_successful') AND + public_body_id = public_bodies.id);") + end + + def self.down + remove_column :public_bodies, :info_requests_successful_count + remove_column :public_bodies, :info_requests_not_held_count + remove_column :public_bodies, :info_requests_overdue_count + end +end diff --git a/db/migrate/20130822161803_add_prominence_fields_to_outgoing_message.rb b/db/migrate/20130822161803_add_prominence_fields_to_outgoing_message.rb new file mode 100644 index 000000000..a75e0d426 --- /dev/null +++ b/db/migrate/20130822161803_add_prominence_fields_to_outgoing_message.rb @@ -0,0 +1,6 @@ +class AddProminenceFieldsToOutgoingMessage < ActiveRecord::Migration + def change + add_column :outgoing_messages, :prominence, :string, :null => false, :default => 'normal' + add_column :outgoing_messages, :prominence_reason, :text + end +end diff --git a/doc/ADMIN.md b/doc/ADMIN.md index 07fe9398d..6248e6cfc 100644 --- a/doc/ADMIN.md +++ b/doc/ADMIN.md @@ -11,11 +11,9 @@ If you want to work on the CSS, you'll want to use $ gem install compass $ compass compile --config .compass/config.rb -The javascript is included in a funky way -[for reasons explained in this commit](https://github.com/sebbacon/adminbootstraptheme/commit/45a73d53fc9e8f0b728933ff58764bd8d0612dab). -To change it, edit the coffeescript at -`lib/view/general/admin.coffee`, and then do something like: +To change the JavaScript, edit `public/admin/javascripts/admin.coffee` +and then run: - $ coffee -o /tmp/ -c app/views/admin_general/admin.coffee - $ mv /tmp/admin.js app/views/admin_general/admin_js.erb + $ coffee -c public/admin/javascripts/admin.coffee +That will update `public/admin/javascripts/admin.js`.
\ No newline at end of file diff --git a/doc/CHANGES.md b/doc/CHANGES.md index 4720e5283..9ad605559 100644 --- a/doc/CHANGES.md +++ b/doc/CHANGES.md @@ -1,3 +1,27 @@ +# Version 0.14 + +## Highlighted features +* There is now an option to display a public body statistics page (currently not linked to from anywhere) showing bodies with the most requests, most successful requests, fewest successful requests, most overdue requests, and bodies that reply most frequently with "Not Held" - see Upgrade notes for how to turn this option on. (Mark Longair) +* Individual incoming and outgoing messages can be made hidden, or requester_only from the admin interface. +* Zip downloads now can be run in single-threaded instances, and use send_file rather than a redirect to serve up cached zip files. +* Starting to use factory_girl to generate model instances for use in specs - hopefully in the long term removing dependencies between specs, and allowing them to run faster once we can remove the loading of fixtures each time. +* Fix to allow public body list page to use current, not default locale, with optional fallback to default [issue #1000](https://github.com/mysociety/alaveteli/issues/1000) - see Upgrade notes for fallback option (Mark Longair) +* Fix to allow request titles composed of only unicode characters [issue #902](https://github.com/mysociety/alaveteli/issues/902) +* Fix for occasional errors caused by race conditions in xapian updates [issue #555](https://github.com/mysociety/alaveteli/issues/555) +* Diagnostic errors are now not shown for local requests, so that the user-facing error pages will be shown when running Alaveteli behind a proxy in production (Henare Degan) + +## Upgrade notes +* By default, Alaveteli will now serve up request zip files itself, which will occupy a Rails process until the file has been received. To pass these files off to Apache, and free up the Rails process, install the libapache2-mod-xsendfile package, and update your httpd.conf file with the new Sendfile clause at the end of config/httpd.conf-example). +* In your production install, from the Alaveteli directory (as the Alaveteli deploy user), run the following commands to remove the zip download directory from direct access by your webserver, and preserve any cached zip files: +`mkdir cache/zips/production/` +`mv cache/zips/download cache/zips/production/download` +`rm public/download` +* This release upgrades the assumed version of Ubuntu from lucid (10.04) to precise (12.04) +* This release upgrades rubygems in config/packages - version 1.8.15 is available from squeeze-backports on Debian or by default in Ubuntu precise. This upgrade may result in "invalid date format in specification:" errors - these should be fixable by manually deleting the gems specs that are being referenced in the error and re-running rails-post-deploy +* If you would like to have a public body statistics page (this will be publicly available), set the `PUBLIC_BODY_STATISTICS_PAGE` param in general.yml to `true`. You should also add a new cron job based on the one in config/crontab-example `https://github.com/mysociety/alaveteli/blob/rails-3-develop/config/crontab-example#L29` to update the public body stats each day. +* If you would like the public body list page to include bodies that have no translation in the current locale, but do have a translation in the default locale, add a `PUBLIC_BODY_LIST_FALLBACK_TO_DEFAULT_LOCALE` param set to `true` to your config/general.yml file. + + # Version 0.13 ## Highlighted features @@ -11,7 +35,7 @@ ## Upgrade notes * Check out this version and run `rails-post-deploy` as usual. -* This release includes an update to the commonlib submodule - you should now be warned about this on running `rails-post-deploy`. You can update to the nw version with `git submodule update`. +* This release includes an update to the commonlib submodule - you should now be warned about this on running `rails-post-deploy`. You can update to the new version with `git submodule update`. * After deploying, run `rake temp:fix_bad_request_states` to find and list requests that have an inconsistent history - run `rake temp:fix_bad_request_states DRYRUN=0` to fix them. # Version 0.12 diff --git a/doc/INSTALL.md b/doc/INSTALL.md index ea8871888..e466edd55 100644 --- a/doc/INSTALL.md +++ b/doc/INSTALL.md @@ -1,4 +1,4 @@ -These instructions assume Debian Squeeze (64-bit) or Ubuntu 10.04 LTS. +These instructions assume Debian Squeeze (64-bit) or Ubuntu 12.04 LTS (precise). [Install instructions for OS X](https://github.com/mysociety/alaveteli/wiki/OS-X-Quickstart) are under development. Debian Squeeze is the best supported deployment platform. @@ -27,12 +27,16 @@ master branch (which always contains the latest stable release): # Package pinning -You need to configure [apt-pinning](http://wiki.debian.org/AptPreferences#Pinning-1) preferences in order to prevent packages being pulled from the debian testing distribution in preference to the stable distribution once you have added the testing repository as described below. +You need to configure [apt-pinning](http://wiki.debian.org/AptPreferences#Pinning-1) preferences in order to prevent packages being pulled from the debian wheezy distribution in preference to the stable distribution once you have added the wheezy repository as described below. -In order to configure apt-pinning and to keep most packages coming from the Debian stable repository while installing the ones required from testing and the mySociety repository you need to run the following commands: +In order to configure apt-pinning and to keep most packages coming from the Debian stable repository while installing the ones required from wheezy and the mySociety repository you need to run the following commands: echo "Package: *" >> /tmp/preferences - echo "Pin: release a=testing">> /tmp/preferences + echo "Pin: release a=squeeze-backports">> /tmp/preferences + echo "Pin-Priority: 200" >> /tmp/preferences + echo "" >> /tmp/preferences + echo "Package: *" >> /tmp/preferences + echo "Pin: release a=wheezy">> /tmp/preferences echo "Pin-Priority: 50" >> /tmp/preferences sudo cp /tmp/preferences /etc/apt/ rm /tmp/preferences @@ -48,7 +52,8 @@ If you are running Debian, add the following repositories to `/etc/apt/sources.list` and run `apt-get update`: deb http://debian.mysociety.org squeeze main - deb http://ftp.debian.org/debian/ testing main non-free contrib + deb http://ftp.debian.org/debian/ wheezy main non-free contrib + deb http://backports.debian.org/debian-backports squeeze-backports main contrib non-free The repositories above allow us to install the packages `wkhtmltopdf-static` and `bundler` using `apt`; so if you're running diff --git a/doc/THEMES.md b/doc/THEMES.md index bae7d7665..d6109cdc5 100644 --- a/doc/THEMES.md +++ b/doc/THEMES.md @@ -64,7 +64,7 @@ add custom help pages, as described below. # Branding the site The core templates that comprise the layout and user interface of an -Alaveteli site live in `app/views/`. They are use Rails' ERB syntax. +Alaveteli site live in `app/views/`. They use Rails' ERB syntax. For example, the template for the home page lives at `app/views/general/frontpage.html.erb`, and the template for the "about us" page is at `app/views/help/about.html.erb`. diff --git a/lib/ability.rb b/lib/ability.rb index 2865ccb1c..f63845e84 100644 --- a/lib/ability.rb +++ b/lib/ability.rb @@ -2,4 +2,15 @@ module Ability def self.can_update_request_state?(user, request) (user && request.is_old_unclassified?) || request.is_owning_user?(user) end -end
\ No newline at end of file + + def self.can_view_with_prominence?(prominence, info_request, user) + if prominence == 'hidden' + return User.view_hidden?(user) + end + if prominence == 'requester_only' + return info_request.is_owning_user?(user) + end + return true + end + +end diff --git a/lib/confidence_intervals.rb b/lib/confidence_intervals.rb new file mode 100644 index 000000000..9fe38045a --- /dev/null +++ b/lib/confidence_intervals.rb @@ -0,0 +1,31 @@ +# Calculate the confidence interval for a samples from a binonial +# distribution using Wilson's score interval. For more theoretical +# details, please see: +# +# http://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval#Wilson%20score%20interval +# +# This is a variant of the function suggested here: +# +# http://www.evanmiller.org/how-not-to-sort-by-average-rating.html +# +# total: the total number of observations +# successes: the subset of those observations that were "successes" +# power: for a 95% confidence interval, this should be 0.05 +# +# The naive proportion is (successes / total). This returns an array +# with the proportions that represent the lower and higher confidence +# intervals around that. + +require 'statistics2' + +def ci_bounds(successes, total, power) + if total == 0 + raise RuntimeError, "Can't calculate the CI for 0 observations" + end + z = Statistics2.pnormaldist(1 - power/2) + phat = successes.to_f/total + offset = z*Math.sqrt((phat*(1 - phat) + z*z/(4*total))/total) + denominator = 1 + z*z/total + return [(phat + z*z/(2*total) - offset)/denominator, + (phat + z*z/(2*total) + offset)/denominator] +end diff --git a/lib/configuration.rb b/lib/configuration.rb index 03c4ac616..ab985c8bf 100644 --- a/lib/configuration.rb +++ b/lib/configuration.rb @@ -43,10 +43,13 @@ module AlaveteliConfiguration :INCOMING_EMAIL_PREFIX => '', :INCOMING_EMAIL_SECRET => 'dummysecret', :ISO_COUNTRY_CODE => 'GB', + :MINIMUM_REQUESTS_FOR_STATISTICS => 100, :MAX_REQUESTS_PER_USER_PER_DAY => '', :MTA_LOG_TYPE => 'exim', :NEW_RESPONSE_REMINDER_AFTER_DAYS => [3, 10, 24], :OVERRIDE_ALL_PUBLIC_BODY_REQUEST_EMAILS => '', + :PUBLIC_BODY_STATISTICS_PAGE => false, + :PUBLIC_BODY_LIST_FALLBACK_TO_DEFAULT_LOCALE => false, :RAW_EMAILS_LOCATION => 'files/raw_emails', :READ_ONLY => '', :RECAPTCHA_PRIVATE_KEY => 'x', diff --git a/lib/i18n_fixes.rb b/lib/i18n_fixes.rb index 9c1206215..9f0849e75 100644 --- a/lib/i18n_fixes.rb +++ b/lib/i18n_fixes.rb @@ -49,111 +49,6 @@ def gettext_interpolate(string, values) end -module I18n - # used by Globalize plugin. - # XXX much of this stuff should (might?) be in newer versions of Rails - @@fallbacks = nil - class << self - # Returns the current fallbacks implementation. Defaults to +I18n::Locale::Fallbacks+. - def fallbacks - @@fallbacks ||= I18n::Locale::Fallbacks.new - end - end - - module Locale - module Tag - class Simple - class << self - def tag(tag) - new(tag) - end - end - - attr_reader :tag - - def initialize(*tag) - @tag = tag.join('-').to_sym - end - - def subtags - @subtags = tag.to_s.split('-').map { |subtag| subtag.to_s } - end - - def to_sym - tag - end - - def to_s - tag.to_s - end - - def to_a - subtags - end - - def parent - @parent ||= begin - segs = to_a.compact - segs.length > 1 ? self.class.tag(*segs[0..(segs.length-2)].join('-')) : nil - end - end - - def self_and_parents - @self_and_parents ||= [self] + parents - end - - def parents - @parents ||= ([parent] + (parent ? parent.parents : [])).compact - end - - - end - end - class Fallbacks < Hash - def initialize(*mappings) - @map = {} - map(mappings.pop) if mappings.last.is_a?(Hash) - self.defaults = mappings.empty? ? [I18n.default_locale.to_sym] : mappings - end - - def defaults=(defaults) - @defaults = defaults.map { |default| compute(default, false) }.flatten - end - attr_reader :defaults - - def [](locale) - raise InvalidLocale.new(locale) if locale.nil? - locale = locale.to_sym - super || store(locale, compute(locale)) - end - - def map(mappings) - mappings.each do |from, to| - from, to = from.to_sym, Array(to) - to.each do |_to| - @map[from] ||= [] - @map[from] << _to.to_sym - end - end - end - - protected - - def compute(tags, include_defaults = true) - result = Array(tags).collect do |tag| - tags = I18n::Locale::Tag::Simple.tag(tag).self_and_parents.map! { |t| t.to_sym } - tags.each { |_tag| tags += compute(@map[_tag]) if @map[_tag] } - tags - end.flatten - result.push(*defaults) if include_defaults - result.uniq.compact - end - end - autoload :Fallbacks, 'i18n/locale/fallbacks' - end -end - - # this monkeypatch corrects inconsistency with gettext_i18n_rails # where the latter deals with strings but rails i18n deals with # symbols for locales diff --git a/lib/message_prominence.rb b/lib/message_prominence.rb new file mode 100644 index 000000000..8f54fcc95 --- /dev/null +++ b/lib/message_prominence.rb @@ -0,0 +1,26 @@ +module MessageProminence + + def has_prominence + send :include, InstanceMethods + cattr_accessor :prominence_states + self.prominence_states = ['normal', 'hidden','requester_only'] + validates_inclusion_of :prominence, :in => self.prominence_states + end + + module InstanceMethods + + def user_can_view?(user) + Ability.can_view_with_prominence?(self.prominence, self.info_request, user) + end + + def indexed_by_search? + self.prominence == 'normal' + end + + def all_can_view? + self.prominence == 'normal' + end + + end +end + diff --git a/lib/tasks/gettext.rake b/lib/tasks/gettext.rake index ace7205ae..366dfbe88 100644 --- a/lib/tasks/gettext.rake +++ b/lib/tasks/gettext.rake @@ -9,27 +9,31 @@ namespace :gettext do end end - desc "Update pot file only, without fuzzy guesses (these are done by Transifex)" - task :findpot => :environment do + desc "Update pot/po files for a theme." + task :find_theme => :environment do + theme = ENV['THEME'] + unless theme + puts "Usage: Specify an Alaveteli-theme with THEME=[theme directory name]" + exit(0) + end load_gettext - $LOAD_PATH << File.join(File.dirname(__FILE__),'..','..','lib') - require 'gettext_i18n_rails/haml_parser' - files = files_to_translate + msgmerge = Rails.application.config.gettext_i18n_rails.msgmerge + msgmerge ||= %w[--sort-output --no-location --no-wrap] + GetText.update_pofiles_org( + text_domain, + theme_files_to_translate(theme), + "version 0.0.1", + :po_root => theme_locale_path(theme), + :msgmerge => msgmerge + ) + end - #write found messages to tmp.pot - temp_pot = "tmp.pot" - GetText::rgettext(files, temp_pot) + def theme_files_to_translate(theme) + Dir.glob("{vendor/plugins/#{theme}/lib}/**/*.{rb,erb}") + end - #merge tmp.pot and existing pot - FileUtils.mkdir_p('locale') - GetText::msgmerge("locale/app.pot", temp_pot, "alaveteli", :po_root => 'locale', :msgmerge=>[ :no_wrap, :sort_output ]) - Dir.glob("locale/*/app.po") do |po_file| - GetText::msgmerge(po_file, temp_pot, "alaveteli", :po_root => 'locale', :msgmerge=>[ :no_wrap, :sort_output ]) - end - File.delete(temp_pot) - end + def theme_locale_path(theme) + File.join(Rails.root, "vendor", "plugins", theme, "locale-theme") + end - def files_to_translate - Dir.glob("{app,lib,config,locale}/**/*.{rb,erb,haml,rhtml}") - end end diff --git a/lib/tasks/stats.rake b/lib/tasks/stats.rake index 9d7d70540..4eda27289 100644 --- a/lib/tasks/stats.rake +++ b/lib/tasks/stats.rake @@ -91,4 +91,30 @@ namespace :stats do end end + desc 'Update statistics in the public_bodies table' + task :update_public_bodies_stats => :environment do + verbose = ENV['VERBOSE'] == '1' + PublicBody.all.each do |public_body| + puts "Counting overdue requests for #{public_body.name}" if verbose + + # Look for values of 'waiting_response_overdue' and + # 'waiting_response_very_overdue' which aren't directly in the + # described_state column, and instead need to be calculated: + overdue_count = 0 + very_overdue_count = 0 + InfoRequest.find_each(:conditions => {:public_body_id => public_body.id}) do |ir| + case ir.calculate_status + when 'waiting_response_very_overdue' + very_overdue_count += 1 + when 'waiting_response_overdue' + overdue_count += 1 + end + end + public_body.info_requests_overdue_count = overdue_count + very_overdue_count + public_body.no_xapian_reindex = true + public_body.without_revision do + public_body.save! + end + end + end end diff --git a/locale/aln/app.po b/locale/aln/app.po index cbd7176d2..d8c0a3020 100644 --- a/locale/aln/app.po +++ b/locale/aln/app.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Albanian Gheg (http://www.transifex.com/projects/p/alaveteli/language/aln/)\n" "Language: aln\n" @@ -1002,6 +1002,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "" +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "" @@ -1071,6 +1074,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "" @@ -1104,9 +1113,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1269,6 +1275,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "" @@ -1386,6 +1395,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "" @@ -1449,6 +1461,12 @@ msgstr "" msgid "OutgoingMessage|Message type" msgstr "" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "" @@ -1476,6 +1494,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "" @@ -1491,6 +1515,9 @@ msgstr "" msgid "Please" msgstr "" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "" @@ -1695,6 +1722,12 @@ msgstr "" msgid "ProfilePhoto|Draft" msgstr "" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "" @@ -1707,6 +1740,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1734,6 +1782,15 @@ msgstr "" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "" @@ -1845,6 +1902,12 @@ msgstr "" msgid "Requested on {{date}}" msgstr "" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2153,12 +2216,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "" +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "" @@ -2302,12 +2374,18 @@ msgstr "" msgid "There was an error with the words you entered, please try again." msgstr "" +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "" msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "" @@ -2332,9 +2410,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "" -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2356,7 +2431,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "" -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2426,9 +2519,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3269,9 +3359,6 @@ msgstr "" msgid "to {{public_body}}" msgstr "" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "" diff --git a/locale/app.pot b/locale/app.pot index ce29159cf..94fbce86e 100644 --- a/locale/app.pot +++ b/locale/app.pot @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: version 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" "PO-Revision-Date: 2011-10-09 01:10+0200\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -999,6 +999,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "" +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "" @@ -1068,6 +1071,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "" @@ -1101,9 +1110,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1266,6 +1272,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "" @@ -1383,6 +1392,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "" @@ -1446,6 +1458,12 @@ msgstr "" msgid "OutgoingMessage|Message type" msgstr "" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "" @@ -1473,6 +1491,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "" @@ -1488,6 +1512,9 @@ msgstr "" msgid "Please" msgstr "" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "" @@ -1692,6 +1719,12 @@ msgstr "" msgid "ProfilePhoto|Draft" msgstr "" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "" @@ -1704,6 +1737,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1731,6 +1779,15 @@ msgstr "" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "" @@ -1842,6 +1899,12 @@ msgstr "" msgid "Requested on {{date}}" msgstr "" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2150,12 +2213,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "" +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "" @@ -2299,12 +2371,18 @@ msgstr "" msgid "There was an error with the words you entered, please try again." msgstr "" +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "" msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "" @@ -2329,9 +2407,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "" -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2353,7 +2428,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "" -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2423,9 +2516,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3266,9 +3356,6 @@ msgstr "" msgid "to {{public_body}}" msgstr "" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "" diff --git a/locale/ar/app.po b/locale/ar/app.po index 9f2d85538..f49cfd658 100644 --- a/locale/ar/app.po +++ b/locale/ar/app.po @@ -14,8 +14,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Arabic (http://www.transifex.com/projects/p/alaveteli/language/ar/)\n" "Language: ar\n" @@ -1011,6 +1011,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "" +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "" @@ -1080,6 +1083,12 @@ msgstr "رسالة واردة|بريد الكتروني من" msgid "IncomingMessage|Mail from domain" msgstr "الرسائل الواردة|بريد الكتروني من" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "رسالة واردة|بعثت على " @@ -1113,9 +1122,6 @@ msgstr "طلب المعلومة|تم اخر وصف في" msgid "InfoRequestEvent|Params yaml" msgstr "InfoRequestEvent|Params yaml" -msgid "InfoRequestEvent|Prominence" -msgstr "طلب المعلومة|الأهمية" - msgid "InfoRequest|Allow new responses from" msgstr "طلب المعلومة|السماح للردود الجديدة من قبل" @@ -1278,6 +1284,9 @@ msgstr "مطالب كثيرة" msgid "Message" msgstr "رسالة" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "تم بعث الرسالة باستخدام {{site_name}} نموذج الاتصال, " @@ -1395,6 +1404,9 @@ msgstr "الق نظرة على متابعتك الان" msgid "Now preview your message asking for an internal review" msgstr "الق نظرة على رسالتك لطلب مراجعة داخلية" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "أو أزل الصورة الحالية" @@ -1458,6 +1470,12 @@ msgstr "الرسائل الصادرة|اخر تاريخ للارسال" msgid "OutgoingMessage|Message type" msgstr "الرسائل الصادرة|نوع الرسالة" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "الرسائل الصادرة|الحالة" @@ -1485,6 +1503,12 @@ msgstr "الناس" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "الناس {{start_count}} الى {{end_count}} من {{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "صورة لك:" @@ -1500,6 +1524,9 @@ msgstr "العب لعبة تصنيف الطلب!" msgid "Please" msgstr "من فضلكم" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "" @@ -1704,6 +1731,12 @@ msgstr "صورة الحساب|بيانات" msgid "ProfilePhoto|Draft" msgstr "صورة الحساب|مسودة" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "السلطات العامة " @@ -1716,6 +1749,21 @@ msgstr "السلطات العمومية {{start_count}} الى {{end_count}} م msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "الهيكل العامّ" @@ -1743,6 +1791,15 @@ msgstr "الهيكل العامّ|الصفحة الرئيسية" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "الهيكل العامّ|اخر تعليق محوّر" @@ -1854,6 +1911,12 @@ msgstr "تم الطلب من قيل {{public_body_name}} من خلال {{info_re msgid "Requested on {{date}}" msgstr "تم الطلب بتاريخ {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "طلبات المعلومات الشخصية و الطلبات المخلة لا تعتبر صالحة لاقتراحات طلبات النفاذ الى المعلومة (<a href=\"/help/about\">اقرأ المزيد</a>)." @@ -2166,12 +2229,21 @@ msgstr "السلطات تقول انها <strong>تحتاج عنوانا\\n msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "هذه السلطة ترغب في / قامت ب <strong>الرد عبر النشر</strong> على هذا الطلب." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "البريد الالكتروني الذي, ارسلته عوضا عن {{public_body}} الى\\n{{user}} للرد على {{ law_used_short}}\\n لم يقع ارسال الطلب." +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "هذه الصفحة غير موجودة. الاشياء التي لمكن ان تجربها:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "السلطة العامة لا تملك المعلومة المطلوبة" @@ -2319,12 +2391,18 @@ msgstr "كان هنالك <strong>خطأ في التسلبم</strong> او ما msgid "There was an error with the words you entered, please try again." msgstr "كان هتالك خطأ في الكلمات التي ادخلتها الرجاء المحاولة ثانية" +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "لا يوجد ردود تتعلق بتساؤلك," msgid "There were no results matching your query." msgstr "لا يوجد نتائج تتعلق بتساؤلك" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "سيقومون بالرد <strong>عبر البريد</strong>" @@ -2349,9 +2427,6 @@ msgstr "الاشياء التي تتابعها" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "هذه السلطة لم تعد موجودة, لم يعد بامكانك تقديم طلب لها." -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "هذا يغطي مجالا واسعا من المعلومات حول حالة \\n <strong>البيئة الطبيعية و الاصطناعية</strong>, مثل :" @@ -2373,7 +2448,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "هذا طلبك الشخصي, ستبعث لك رسالة الكترونية بصفة الية عندما يصل الرد الجديد." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2451,9 +2544,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "لم يقدم هذا الطلب عبر {{site_name}}" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "هذا الجدول يظهر التفاصيل التقنية للاحداث الداخلية التي وقعت لهذا الطلب على\\ {{site_name}}. يمكن استخدام هذا لتعميم المعلومة حول\\nسرعة رد السلطات على الطلبات , عدد الطلبات\\nالتي تسوجب ردا بريديا و اكثر ." @@ -3302,9 +3392,6 @@ msgstr "لبعث رسالة متابعة" msgid "to {{public_body}}" msgstr "الى {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "أهمية غير متوقعة لطلب الحدث" - msgid "unknown reason " msgstr "سبب مجهول" diff --git a/locale/bg/app.po b/locale/bg/app.po index b0762368f..849550a46 100644 --- a/locale/bg/app.po +++ b/locale/bg/app.po @@ -4,13 +4,14 @@ # # Translators: # antitoxic <antitoxic@gmail.com>, 2013 +# antitoxic <antitoxic@gmail.com>, 2013 # Valentin Laskov <laskov@festa.bg>, 2013 msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-09-18 16:02+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-22 20:14+0000\n" "Last-Translator: Valentin Laskov <laskov@festa.bg>\n" "Language-Team: Bulgarian (http://www.transifex.com/projects/p/alaveteli/language/bg/)\n" "Language: bg\n" @@ -422,10 +423,10 @@ msgid "Beginning with" msgstr "Започващ с" msgid "Browse <a href='{{url}}'>other requests</a> for examples of how to word your request." -msgstr "Разгледайте <a href='{{url}}'>други запитвания</a> за примери за това как да опишете заявлението си." +msgstr "Разгледайте <a href='{{url}}'>други запитвания</a> като примери за това как да опишете заявлението си." msgid "Browse <a href='{{url}}'>other requests</a> to '{{public_body_name}}' for examples of how to word your request." -msgstr "Разгледайте <a href='{{url}}'>други запитвания</a> до '{{public_body_name}}' за примери над това как да опишете заявлението си." +msgstr "Разгледайте <a href='{{url}}'>други запитвания</a> до '{{public_body_name}}' като примери за това как да опишете заявлението си." msgid "Browse all authorities..." msgstr "Списък на всички органи..." @@ -1002,6 +1003,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "" +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "" @@ -1071,6 +1075,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "" @@ -1104,9 +1114,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1159,7 +1166,7 @@ msgid "Is {{email_address}} the wrong address for {{type_of_request}} requests t msgstr "Грешен ли е адресът {{email_address}} за {{type_of_request}} заявления към {{public_body_name}}? Ако да, моля свържете се с нас, използвайки тази форма:" msgid "It may be that your browser is not set to accept a thing called \"cookies\",\\nor cannot do so. If you can, please enable cookies, or try using a different\\nbrowser. Then press refresh to have another go." -msgstr "" +msgstr "Може да е от това, че браузърът Ви е конфигуриран да не работи с \"бисквитки\",\\nили не може да го прави. Ако можете, моля, разрешете бисквитките, или опитайте с друг\\nбраузър. След това натиснете опресняване, за да опитате отново." msgid "Items matching the following conditions are currently displayed on your wall." msgstr "" @@ -1222,7 +1229,7 @@ msgid "Log into the admin interface" msgstr "" msgid "Long overdue." -msgstr "Дългоочаквано." +msgstr "Значително пресрочено." msgid "Made between" msgstr "Направено между" @@ -1269,6 +1276,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Съобщението е изпратено чрез формата за контакти на {{site_name}}, " @@ -1384,7 +1394,10 @@ msgid "Now preview your follow up" msgstr "" msgid "Now preview your message asking for an internal review" -msgstr "Сега прегледайте съобщението си и поискайте вътрешно разглеждане" +msgstr "Сега прегледайте съобщението, с което ще поискате вътрешно разглеждане" + +msgid "Number of requests" +msgstr "" msgid "OR remove the existing photo" msgstr "ИЛИ премахнете съществуващата снимка" @@ -1449,6 +1462,12 @@ msgstr "" msgid "OutgoingMessage|Message type" msgstr "" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "" @@ -1476,6 +1495,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "Хора от {{start_count}} до {{end_count}} от {{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Ваша снимка:" @@ -1491,6 +1516,9 @@ msgstr "" msgid "Please" msgstr "Молим" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "" @@ -1675,7 +1703,7 @@ msgid "Preview follow up to '" msgstr "" msgid "Preview new annotation on '{{info_request_title}}'" -msgstr "" +msgstr "Преглед на новата анотация на '{{info_request_title}}'" msgid "Preview your annotation" msgstr "Преглед на бележката Ви" @@ -1695,6 +1723,12 @@ msgstr "" msgid "ProfilePhoto|Draft" msgstr "" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Публични органи" @@ -1707,6 +1741,21 @@ msgstr "Публични органи от {{start_count}} до {{end_count}}, msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1734,6 +1783,15 @@ msgstr "" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "" @@ -1845,6 +1903,12 @@ msgstr "Поискано от {{public_body_name}} от {{info_request_user}} н msgid "Requested on {{date}}" msgstr "Поискано на {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -1867,7 +1931,7 @@ msgid "Respond to the FOI request" msgstr "Отговор на заявлението за ДдИ" msgid "Respond using the web" -msgstr "Отговаряне чрез уеб" +msgstr "Отговаряне чрез уеб сайта" msgid "Response" msgstr "Отговор" @@ -1882,7 +1946,7 @@ msgid "Response to this request is <strong>delayed</strong>." msgstr "Отговорът на това заявление е <strong>закъснял</strong>." msgid "Response to this request is <strong>long overdue</strong>." -msgstr "Отговорът на това заявление е <strong>твърде закъснял</strong>." +msgstr "Отговорът на това заявление е <strong>значително закъснял</strong>." msgid "Response to your request" msgstr "Отговор на Ваше заявление" @@ -1938,7 +2002,7 @@ msgid "See bounce message" msgstr "" msgid "Select one to see more information about the authority." -msgstr "Изберете някой за да видите повече информация за органа." +msgstr "Изберете някой, за да видите повече информация за органа." msgid "Select the authority to write to" msgstr "Изберете органа, на който ще пишете" @@ -1959,16 +2023,16 @@ msgid "Send follow up to '{{title}}'" msgstr "" msgid "Send message" -msgstr "Изпращане съобщение" +msgstr "Изпращане на съобщение" msgid "Send message to " -msgstr "Изпращане съобщение до " +msgstr "Изпращане на съобщение до " msgid "Send request" -msgstr "Изпращане заявление" +msgstr "Изпращане на заявление" msgid "Set your profile photo" -msgstr "Задаване снимка за профила Ви" +msgstr "Задайте снимка за профила Ви" msgid "Short name" msgstr "" @@ -1980,25 +2044,25 @@ msgid "Show most relevant results first" msgstr "" msgid "Show only..." -msgstr "" +msgstr "Покажи само..." msgid "Showing" -msgstr "" +msgstr "Показва" msgid "Sign in" msgstr "Влизане" msgid "Sign in or make a new account" -msgstr "Влизане или нова регистрация" +msgstr "Вход или нова регистрация" msgid "Sign in or sign up" -msgstr "Влизане или записване" +msgstr "Вход или регистрация" msgid "Sign out" -msgstr "Излизане" +msgstr "Изход" msgid "Sign up" -msgstr "Записване" +msgstr "Регистрация" msgid "Similar requests" msgstr "Подобни заявления" @@ -2031,7 +2095,7 @@ msgid "Sorry, but only {{user_name}} is allowed to do that." msgstr "Съжаляваме, но само {{user_name}} има право да направи това." msgid "Sorry, there was a problem processing this page" -msgstr "Съжаляваме, получи се проблем, обработвайки тази страница" +msgstr "Съжаляваме, имаше се проблем в обработването на тази страница" msgid "Sorry, we couldn't find that page" msgstr "Съжаляваме, не можахме да намерим тази страница" @@ -2067,13 +2131,13 @@ msgid "Submit status and send message" msgstr "" msgid "Subscribe to blog" -msgstr "" +msgstr "Абониране за блога" msgid "Successful Freedom of Information requests" -msgstr "" +msgstr "Успешни Заявления за Достъп до информация" msgid "Successful." -msgstr "" +msgstr "Успешно." msgid "Suggest how the requester can find the <strong>rest of the information</strong>." msgstr "Предложете как питащия може да намери <strong>останалата част от информацията</strong>." @@ -2085,7 +2149,7 @@ msgid "Table of statuses" msgstr "Таблица на състоянията" msgid "Table of varieties" -msgstr "Таблица на свойствата" +msgstr "Таблица на разновидностите" msgid "Tags" msgstr "" @@ -2103,7 +2167,7 @@ msgid "Thank you for helping us keep the site tidy!" msgstr "Благодарим Ви, че ни помагате да поддържаме сайта спретнат!" msgid "Thank you for making an annotation!" -msgstr "Благодарим Ви, че написахте анотация!" +msgstr "Благодарим Ви, че добавихте бележка!" msgid "Thank you for responding to this FOI request! Your response has been published below, and a link to your response has been emailed to " msgstr "Благодарим Ви, че отговорихте на това заявление за ДдИ! Вашият отговор беше публикуван по-долу, а препратка към отговора Ви беше изпратена с имейл на " @@ -2136,29 +2200,38 @@ msgid "The <strong>review has finished</strong> and overall:" msgstr "" msgid "The Freedom of Information Act <strong>does not apply</strong> to" -msgstr "" +msgstr "Законът за Достъп до обществена информация <strong>не се прилага</strong> за" msgid "The accounts have been left as they previously were." msgstr "Акаунтите бяха оставени както си бяха." msgid "The authority do <strong>not have</strong> the information <small>(maybe they say who does)" -msgstr "" +msgstr "Органът <strong>не притежава</strong> информацията <small>(вероятно посочват кой я притежава)" msgid "The authority only has a <strong>paper copy</strong> of the information." -msgstr "" +msgstr "Органът притежава информацията само на <strong>хартиен носител</strong>." msgid "The authority say that they <strong>need a postal\\n address</strong>, not just an email, for it to be a valid FOI request" msgstr "Органът съобщи, че те <strong>се нуждаят от пощенски\\n адрес</strong>, а не само имейл, за да бъде валидно заявление за ДдИ" msgid "The authority would like to / has <strong>responded by post</strong> to this request." +msgstr "Публичният орган би желал или вече е<strong>отговорил по пощата</strong> на това заявление." + +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." msgstr "" msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "Имейлът, който Вие изпратихте от името на {{public_body}}, до\\n{{user}} в отговор на заявление за {{law_used_short}}\\nне беше доставено." +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "Страницата не съществува. Това, което може да опитате сега:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "Публичният орган не разполага с исканата информация" @@ -2166,34 +2239,34 @@ msgid "The public authority would like part of the request explained" msgstr "Публичният орган желае пояснение на част от заявлението" msgid "The public authority would like to / has responded by post" -msgstr "Публичният орган би желал или вече отговори по пощата" +msgstr "Публичният орган би желал или вече е отговорил по пощата" msgid "The request has been <strong>refused</strong>" msgstr "Заявлението беше <strong>отхвърлено</strong>" msgid "The request has been updated since you originally loaded this page. Please check for any new incoming messages below, and try again." -msgstr "" +msgstr "Заявлението беше обновено от както заредихте тази страница. Моля, проверете за нови съобщения по-долу, и опитайте отново." msgid "The request is <strong>waiting for clarification</strong>." -msgstr "" +msgstr "Заявлението <strong>очаква пояснение</strong>." msgid "The request was <strong>partially successful</strong>." -msgstr "" +msgstr "Заявлението беше <strong>частично успешно</strong>." msgid "The request was <strong>refused</strong> by" -msgstr "" +msgstr "Заявлението беше <strong>отказано</strong> от" msgid "The request was <strong>successful</strong>." -msgstr "" +msgstr "Заявлението беше <strong>успешно</strong>." msgid "The request was refused by the public authority" -msgstr "" +msgstr "Заявлението беше отхвърлено от публичния орган" msgid "The request you have tried to view has been removed. There are\\nvarious reasons why we might have done this, sorry we can't be more specific here. Please <a\\n href=\"{{url}}\">contact us</a> if you have any questions." msgstr "" msgid "The requester has abandoned this request for some reason" -msgstr "" +msgstr "Това заявление беше изоставено от заявителя поради някаква причина" msgid "The response to your request has been <strong>delayed</strong>. You can say that,\\n by law, the authority should normally have responded\\n <strong>promptly</strong> and" msgstr "" @@ -2202,10 +2275,10 @@ msgid "The response to your request is <strong>long overdue</strong>. You can msgstr "" msgid "The search index is currently offline, so we can't show the Freedom of Information requests that have been made to this authority." -msgstr "" +msgstr "Търсачката ни не е достъпна в момента, поради което не можем да покажем Заявленията за Достъп до информация, отправени към този орган." msgid "The search index is currently offline, so we can't show the Freedom of Information requests this person has made." -msgstr "" +msgstr "Търсачката ни не е достъпна в момента, поради което не можем да покажем Заявленията за Достъп до информация, направени от този потребител." msgid "The {{site_name}} team." msgstr "" @@ -2217,19 +2290,19 @@ msgid "Then you can cancel the alerts." msgstr "След това ще можете да спрете известяванията." msgid "Then you can change your email address used on {{site_name}}" -msgstr "После можете да промените имейл адреса си, използван в {{site_name}}" +msgstr "След това ще можете да промените имейл адреса си, използван в {{site_name}}" msgid "Then you can change your password on {{site_name}}" -msgstr "" +msgstr "След това ще може да промените паролата си в {{site_name}}" msgid "Then you can classify the FOI response you have got from " msgstr "След това може да класифицирате отговора за ДдИ, който сте получили от " msgid "Then you can download a zip file of {{info_request_title}}." -msgstr "" +msgstr "След това ще може да свалите zip файл на {{info_request_title}}." msgid "Then you can log into the administrative interface" -msgstr "" +msgstr "След това ще можете да влезете в административния интерфейс" msgid "Then you can play the request categorisation game." msgstr "" @@ -2238,22 +2311,22 @@ msgid "Then you can report the request '{{title}}'" msgstr "" msgid "Then you can send a message to " -msgstr "" +msgstr "След това ще може да изпратите съобщение до " msgid "Then you can sign in to {{site_name}}" -msgstr "" +msgstr "След това ще можете да влезете в {{site_name}}" msgid "Then you can update the status of your request to " -msgstr "" +msgstr "След това ще можете да обновите статуса на заявлението Ви до " msgid "Then you can upload an FOI response. " -msgstr "След това може да качите отговор за ДдИ. " +msgstr "След това ще може да качите отговор за ДдИ. " msgid "Then you can write follow up message to " msgstr "" msgid "Then you can write your reply to " -msgstr "" +msgstr "След това ще можете да напишете отговора си до " msgid "Then you will be following all new FOI requests." msgstr "" @@ -2302,12 +2375,18 @@ msgstr "" msgid "There was an error with the words you entered, please try again." msgstr "" +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "" msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "" @@ -2332,9 +2411,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "" -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2356,7 +2432,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Това е Ваше собствено заявление, така че автоматично ще Ви уведомяваме с имейл при пристигане на нови отговори." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2426,9 +2520,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "Тази таблица показва техническите подробности над вътрешните събития, случили се\\nпо това заявление в {{site_name}}. Това може да се използва за генериране на информация за\\nбързината, с която органите отговарят на заявления, броят на заявленията,\\nкоито изискват отговор по пощата и много други." @@ -2757,7 +2848,7 @@ msgid "We've sent you an email, and you'll need to click the link in it before y msgstr "Изпратихме Ви имейл. Ще трябва да цъкнете връзката в него, след което\\nще можете да продължите." msgid "We've sent you an email, click the link in it, then you can change your password." -msgstr "Изпратихме Ви имейл. Цъкнете връзката в него, след което сменете паролата си." +msgstr "Изпратихме Ви имейл. Цъкнете връзката в него, след което ще можете да смените паролата си." msgid "What are you doing?" msgstr "" @@ -3269,9 +3360,6 @@ msgstr "" msgid "to {{public_body}}" msgstr "" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "" diff --git a/locale/bs/app.po b/locale/bs/app.po index ae935f74a..2782b2c79 100644 --- a/locale/bs/app.po +++ b/locale/bs/app.po @@ -13,8 +13,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Bosnian (http://www.transifex.com/projects/p/alaveteli/language/bs/)\n" "Language: bs\n" @@ -1073,6 +1073,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Ako i dalje imate problema, molimo <a href=\"{{url}}\">kontaktirajte nas</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Ako ste podnosioc zahtjeva, možete se <a href=\"{{url}}\">prijaviti</a> da biste pogledali zahtjev." @@ -1157,6 +1160,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "Nadolazeća poruka|Pošta sa domene" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "Nadolazeća poruka|Poslana u" @@ -1190,9 +1199,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1366,6 +1372,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Poruka poslana koristeći {{site_name}} formular za kontakt, " @@ -1483,6 +1492,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "Sada pregledajte Vašu poruku u kojoj tražite urgenciju " +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "ILI odstrani postojeću sliku" @@ -1546,6 +1558,12 @@ msgstr "Odlazeća poruka|Zadnja poslana u" msgid "OutgoingMessage|Message type" msgstr "Odlazeća poruka|Tip poruke" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "Odlazeća poruka|Status" @@ -1573,6 +1591,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Vaša slika:" @@ -1588,6 +1612,9 @@ msgstr "Igrajte igru kategorizacije zahtjeva!" msgid "Please" msgstr "Molimo" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Molimo <a href=\"{{url}}\">kontaktirajte</a> nas kako bi to mogli popraviti." @@ -1803,6 +1830,12 @@ msgstr "Slika na profilu|Podaci" msgid "ProfilePhoto|Draft" msgstr "Slika na profilu|Skica" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Javne ustanove" @@ -1815,6 +1848,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1842,6 +1890,15 @@ msgstr "Javno tijelo|Home page" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "Javno tijelo|Zadnji uređeni komentar" @@ -1955,6 +2012,12 @@ msgstr "Traženo od {{public_body_name}} od strane {{info_request_user}} na datu msgid "Requested on {{date}}" msgstr "Traženo na datum {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2280,12 +2343,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "Ustanova bi željela / je <strong>odgovorila poštom</strong> na ovaj zahtjev." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "Stranica ne postoji. Stvari koje možete probati sada:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "Javna ustanova ne posjeduje tražene informacije" @@ -2439,12 +2511,18 @@ msgstr "Došlo je do <strong>greške u isporuci</strong> ili nečega sličnog š msgid "There was an error with the words you entered, please try again." msgstr "Postoji greška u riječima koje ste ukucali, molimo pokušajte ponovo." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "Nema zahtjeva koji odgovaraju Vašoj pretrazi." msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "Odgovoriti će <strong>poštom</strong>" @@ -2471,9 +2549,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Ova ustanova više ne postoji, zato joj nije moguće podnijeti zahtjev. " -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2497,7 +2572,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Ovo je Vaš zahtjev, biti ćete automatski obaviješteni e-mailom kada novi odgovori budu stizali." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2575,9 +2668,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3460,9 +3550,6 @@ msgstr "poslati prateću poruku." msgid "to {{public_body}}" msgstr "za {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "nepoznat razlog " diff --git a/locale/ca/app.po b/locale/ca/app.po index 228fbce1a..c3dd04463 100644 --- a/locale/ca/app.po +++ b/locale/ca/app.po @@ -12,8 +12,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Catalan (http://www.transifex.com/projects/p/alaveteli/language/ca/)\n" "Language: ca\n" @@ -1092,6 +1092,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Si aún tiene problemas, por favor <a href=\"{{url}}\">contáctenos</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Si la solicitud es tuya, puedes <a href=\"{{url}}\">abrir una sesión</a> para verla." @@ -1176,6 +1179,12 @@ msgstr "IncomingMessage|Mail from" msgid "IncomingMessage|Mail from domain" msgstr "IncomingMessage|Mail from domain" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "IncomingMessage|Sent at" @@ -1209,9 +1218,6 @@ msgstr "InfoRequestEvent|Last described at" msgid "InfoRequestEvent|Params yaml" msgstr "InfoRequestEvent|Params yaml" -msgid "InfoRequestEvent|Prominence" -msgstr "InfoRequestEvent|Prominence" - msgid "InfoRequest|Allow new responses from" msgstr "InfoRequest|Allow new responses from" @@ -1385,6 +1391,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Mensaje enviado usando {{site_name}}, " @@ -1502,6 +1511,9 @@ msgstr "Ahora revisa tu mensaje" msgid "Now preview your message asking for an internal review" msgstr "Ahora revisa tu mensaje pidiendo una revisión interna" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "O borre la foto actual" @@ -1565,6 +1577,12 @@ msgstr "OutgoingMessage|Last sent at" msgid "OutgoingMessage|Message type" msgstr "OutgoingMessage|Message type" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "OutgoingMessage|Status" @@ -1592,6 +1610,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "Personas {{start_count}} a {{end_count}} de {{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Foto:" @@ -1607,6 +1631,9 @@ msgstr "Juega al juego de clasificación de solicitudes!" msgid "Please" msgstr "Por favor" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Por favor <a href=\"{{url}}\">contacta</a> con nosotros para que podamos arreglarlo." @@ -1822,6 +1849,12 @@ msgstr "ProfilePhoto|Data" msgid "ProfilePhoto|Draft" msgstr "ProfilePhoto|Draft" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Organismos públicos" @@ -1834,6 +1867,21 @@ msgstr "Organismos públicos {{start_count}} a {{end_count}} de {{total_count}}" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1861,6 +1909,15 @@ msgstr "Sitio web" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "PublicBody|Last edit comment" @@ -1974,6 +2031,12 @@ msgstr "Solicitud a {{public_body_name}} de {{info_request_user}} el {{date}}" msgid "Requested on {{date}}" msgstr "Pedida el {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2301,15 +2364,24 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "El organismo querría / ha respondido <strong>por correo ordinario</strong> a esta solicitud." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" "El correo envíado por usted, en nombre de {{public_body}}, enviado a\n" "{{user}} como respuesta a la solicitud {{law_used_short}}\n" "no ha sido entregado." +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "La página no existe. Puede intentar:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "El organismo no tiene la información solicitada" @@ -2462,12 +2534,18 @@ msgstr "Se ha producido un <strong>error en la entrega</strong> o similar, y nec msgid "There was an error with the words you entered, please try again." msgstr "Ha habido un error con las palabras introducidas, por favor pruebe otra vez." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "No se encontraron solicitudes para tu búsqueda." msgid "There were no results matching your query." msgstr "No se han encontrado resultados para tu búsqueda." +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "Van a responder <strong>por correo ordinario</strong>" @@ -2494,11 +2572,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Este organismo ya no existe, no pueden realizarse solicitudes de información." -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" -"Este respuesta está oculta. Revisa los comentarios\n" -" para descubrir por qué. Si es tu solicitud, <a href=\"{{url}}\">abre una sesión</a> para ver la respuesta." - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" "Esto incluye un amplio espectro de información sobre el estado de\n" @@ -2524,10 +2597,26 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Esta es tu solicitud, por lo que recibirás correos automáticamente cuando lleguen nuevas respuestas." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" -"Este mensaje está oculto. Lee los comentarios\n" -"\t\t\t\t\t\tpara descubrir por qué. Si es tu solicitud, <a href=\"{{url}}\">abra una sesión</a> para ver la respuesta." msgid "This particular request is finished:" msgstr "Esta solicitud está cerrada:" @@ -2602,11 +2691,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" -"Este respuesta está oculta. Revisa los comentarios\n" -" para descubrir por qué. Si es tu solicitud, <a href=\"{{url}}\">abre una sesión</a> para ver la respuesta." - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" "La siguiente tabla muestra datos técnicos sobre los eventos internos relacionados \n" @@ -3513,9 +3597,6 @@ msgstr "mandar un mensaje de seguimiento." msgid "to {{public_body}}" msgstr "a {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "visibilidad inesperada en el evento de la solicitud" - msgid "unknown reason " msgstr "motivo desconocido " diff --git a/locale/cs/app.po b/locale/cs/app.po index be89e29ba..0a6ea3e99 100644 --- a/locale/cs/app.po +++ b/locale/cs/app.po @@ -19,8 +19,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Czech (http://www.transifex.com/projects/p/alaveteli/language/cs/)\n" "Language: cs\n" @@ -1086,6 +1086,9 @@ msgstr "Pokud nejste spokojeni s odpovědí, kterou jste obdrželi od instituce, msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Pokud máte stále problémy <a href=\"{{url}}\">kontaktujte nás</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Pokud jste tazatel, můžete se <a href=\"{{url}}\">přihlásit</a> a podívat se na svůj dotaz." @@ -1163,6 +1166,12 @@ msgstr "IncomingMessage | Zpráva od" msgid "IncomingMessage|Mail from domain" msgstr "IncomingMessage| Mail z domény" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "IncomingMessage | Odeslána v" @@ -1196,9 +1205,6 @@ msgstr "InfoRequestEvent | Naposledy popsán v" msgid "InfoRequestEvent|Params yaml" msgstr "InfoRequestEvent | Params yaml ??" -msgid "InfoRequestEvent|Prominence" -msgstr "InfoRequestEvent | Prominence ??" - msgid "InfoRequest|Allow new responses from" msgstr "InfoRequestEvent | Povolit nové odpovědi od " @@ -1370,6 +1376,9 @@ msgstr "Mnoho dotazů" msgid "Message" msgstr "Zpráva" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Zpráva zaslána pomocí kontaktního formuláře stránek {{site_name}}, " @@ -1487,6 +1496,9 @@ msgstr "Nyní přejděte na náhled své odpovědi." msgid "Now preview your message asking for an internal review" msgstr "Nyní přejděte na náhled své zprávy žádající prozkoumání. " +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "NEBO odstraňte existující foto" @@ -1550,6 +1562,12 @@ msgstr "Odchozí zpráva | Naposledy viděn v" msgid "OutgoingMessage|Message type" msgstr "Odchozí zpráva | Typ zprávy" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "Odchozí zpráva | Status" @@ -1577,6 +1595,12 @@ msgstr "Lidé" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "Lidé od {{start_count}} do {{end_count}} z {{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Vaše foto:" @@ -1592,6 +1616,9 @@ msgstr "Hrajte hru na kategorizaci dotazů!" msgid "Please" msgstr "Prosíme" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Prosíme <a href=\"{{url}}\">kontaktujte nás</a> abychom to mohli upravit." @@ -1803,6 +1830,12 @@ msgstr "Profilové foto | Data" msgid "ProfilePhoto|Draft" msgstr "Profilové foto | Koncept" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Instituce" @@ -1815,6 +1848,21 @@ msgstr "Instituce od {{start_count}} do {{end_count}} z {{total_count}}" msgid "Public authority – {{name}}" msgstr "Veřejná instituce – {{name}}" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "Instituce" @@ -1842,6 +1890,15 @@ msgstr "PublicBody | Domovská stránka" msgid "PublicBody|Info requests count" msgstr "Veřejný orgán | Info o počtu dotazů" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "PublicBody | Naposled aktualizovaný komentář" @@ -1955,6 +2012,12 @@ msgstr "Vyžádáno institucí {{public_body_name}} od {{info_request_user}} dne msgid "Requested on {{date}}" msgstr "Dotaz byl vznesen dne {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "Požadavky na informace osobního charakteru a obsah odporující dobrým mravům odporují zákonu 106/1999 Sb., o svobodném přístupu k informacím (<a href=\"/help/about\">Více si přečtěte v nápovědě</a>)." @@ -2282,14 +2345,23 @@ msgstr "Instituce tvrdí, že pro úspěšné vyřízení dotazu<strong>potřebu msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "Instituce by na tento dotaz ráda /nebo již odpověděla<strong>posláním odpovědi poštou</strong>." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" "E-mail, který jste poslali v zastoupení instituce {{public_body}}, uživateli\n" "{{user}} jako odpověď na dotaz o poskytnutí informací podle zákona 106/1999 Sb. {{law_used_short}} nebyl doručen." +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "Stránka neexistuje. Zkuste toto:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "Instituce nemá požadované informace k dispozici" @@ -2441,12 +2513,18 @@ msgstr "Vyskytla se <strong>chyba při doručení</strong> nebo něco podobného msgid "There was an error with the words you entered, please try again." msgstr "Nastala chyba, prosíme zkuste to znovu." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "Nejsou tu žádné dotazy shodné s vaším vyhledáváním." msgid "There were no results matching your query." msgstr "Nemáme žádné výsledky pro vaše kritéria vyhledávání." +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "Odpověď bude doručena <strong>poštou</strong>" @@ -2473,11 +2551,6 @@ msgstr "Sledujete:" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Tato instituce již neexistuje, nelze na ni proto vznést dotaz. " -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" -"Tento komentář byl skryt. Podívejte se na vysvětlení.\n" -"Pokud jste tazatel, můžete se <a href=\"{{url}}\">přihlásit</a> k prohlížení odpovědi." - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" "Toto zahrnuje široké spektrum informací o stavu \n" @@ -2501,10 +2574,26 @@ msgstr "Toto je první verze." msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Toto je váš vlastní dotaz, proto budete odpovědi dostávat e-mailem automaticky." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" -"Tato odchozí zpráva byla skryta. Podívejte se na vysvětlení.\n" -"Pokud jste tazatel, můžete se <a href=\"{{url}}\">přihlásit</a> k prohlížení odpovědi." msgid "This particular request is finished:" msgstr "Tento dotaz je ukončen:" @@ -2579,11 +2668,6 @@ msgstr "Tento dotaz vyžaduje pozornost administrátora" msgid "This request was not made via {{site_name}}" msgstr "Tento dotaz nebyl vznesen pomocí stránek {{site_name}}" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" -"Tato odpověď byla skryta. Podívejte se na vysvětlení. \n" -"Pokud jste tazatel, můžete se <a href=\"{{url}}\">přihlásit</a> k prohlížení odpovědi." - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "Tato tabulka ukazuje technické detaily související s tímto dotazem vzneseným na stránkách {{site_name}}. Tento přehled lze použít k analýze rychlosti, s jakou instituce odpovídají na dotazy, počtu dotazů, které byly zodpovězeny poštou atd. " @@ -3480,9 +3564,6 @@ msgstr "poslat odpověď" msgid "to {{public_body}}" msgstr "pro instituci {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "neočekávaná operace s dotazem" - msgid "unknown reason " msgstr "neznámé důvody" diff --git a/locale/cy/app.po b/locale/cy/app.po index ef4050f84..3b2267d93 100644 --- a/locale/cy/app.po +++ b/locale/cy/app.po @@ -13,8 +13,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Welsh (http://www.transifex.com/projects/p/alaveteli/language/cy/)\n" "Language: cy\n" @@ -1008,6 +1008,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "" +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Os chi yw'r ceisydd, rydych chi'n gallu <a href=\"{{url}}\">mewngofnodi</a> i weld y cais;." @@ -1077,6 +1080,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "" @@ -1110,9 +1119,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1275,6 +1281,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "" @@ -1392,6 +1401,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "" @@ -1455,6 +1467,12 @@ msgstr "" msgid "OutgoingMessage|Message type" msgstr "" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "" @@ -1482,6 +1500,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "" @@ -1497,6 +1521,9 @@ msgstr "" msgid "Please" msgstr "" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "" @@ -1701,6 +1728,12 @@ msgstr "" msgid "ProfilePhoto|Draft" msgstr "" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "" @@ -1713,6 +1746,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1740,6 +1788,15 @@ msgstr "" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "" @@ -1851,6 +1908,12 @@ msgstr "" msgid "Requested on {{date}}" msgstr "" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2161,12 +2224,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "" +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "" @@ -2312,12 +2384,18 @@ msgstr "" msgid "There was an error with the words you entered, please try again." msgstr "" +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "" msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "" @@ -2342,9 +2420,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "" -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2366,7 +2441,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "" -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2440,9 +2533,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3291,9 +3381,6 @@ msgstr "" msgid "to {{public_body}}" msgstr "" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "" diff --git a/locale/de/app.po b/locale/de/app.po index 944401221..e311585e9 100644 --- a/locale/de/app.po +++ b/locale/de/app.po @@ -12,8 +12,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: German (http://www.transifex.com/projects/p/alaveteli/language/de/)\n" "Language: de\n" @@ -1047,6 +1047,9 @@ msgstr "Sollten Sie mit den erhaltenen Informationen nicht zufrieden sein, haben msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Sollten weiterhin Probleme bestehen, bitte <a href=\"{{url}}\">kontaktieren Sie uns</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Falls Sie der Antragsteller sind, <a href=\"{{url}}\">loggen Sie sich ein</a>, um die Anfrage anzusehen." @@ -1120,6 +1123,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "IncomingMessage|Mail from domain" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "IncomingMessage|Sent at" @@ -1153,9 +1162,6 @@ msgstr "InfoRequestEvent|Last described at" msgid "InfoRequestEvent|Params yaml" msgstr "InfoRequestEvent|Params yaml" -msgid "InfoRequestEvent|Prominence" -msgstr "InfoRequestEvent|Prominence" - msgid "InfoRequest|Allow new responses from" msgstr "InfoAnfrage | Neue Antworten zulassen von" @@ -1322,6 +1328,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Nachricht gesendet über {{site_name}} Kontaktformular, " @@ -1439,6 +1448,9 @@ msgstr "Überprüfen Sie nun Ihr Follow-up" msgid "Now preview your message asking for an internal review" msgstr "Überprüfen Sie nun Ihre Anfrage zur internen Prüfung" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "OR entfernen Sie das bestehende Photo" @@ -1502,6 +1514,12 @@ msgstr "OutgoingMessage|Last sent at" msgid "OutgoingMessage|Message type" msgstr "OutgoingMessage|Message type" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "OutgoingMessage|Status" @@ -1529,6 +1547,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "Leute {{start_count}} bis {{end_count}} von {{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Ihr Profilbild:" @@ -1544,6 +1568,9 @@ msgstr "Helfen Sie uns ausstehende Anfragen zu kategorisieren!" msgid "Please" msgstr "Bitte" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Bitte<a href=\"{{url}}\">nehmen Sie Kontakt mit uns auf</a>, damit wir das Problem beheben können. " @@ -1751,6 +1778,12 @@ msgstr "ProfilePhoto|Data" msgid "ProfilePhoto|Draft" msgstr "ProfilePhoto|Draft" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Behörden" @@ -1763,6 +1796,21 @@ msgstr "Behörde {{start_count}} bis {{end_count}} von {{total_count}}" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1790,6 +1838,15 @@ msgstr "PublicBody|Home page" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "PublicBody|Last edit comment" @@ -1901,6 +1958,12 @@ msgstr "Angefragt von {{public_body_name}} durch {{info_request_user}} am {{date msgid "Requested on {{date}}" msgstr "Angefragt am {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2214,15 +2277,24 @@ msgstr "Die Behörde gibt an, dass sie für eine gültige IFG-Anfrage eine <stro msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "Dhe Behörde würde gerne / hat <strong>postalisch</strong> auf diese Anfrage reagiert." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" "Ihre im Namen von {{public_body}} an\n" "{{user}} gesendete Anfrage, um auf {{law_used_short}}\n" "zu reagieren, wurde nicht übermittelt." +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "Die Seite existiert nicht. Was Sie nun versuchen können:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "Der Behörde liegen die angefragten Informationen nicht vor. " @@ -2368,12 +2440,18 @@ msgstr "Es ist ein <strong>Übermittlungsfehler</strong>oder ähnliches aufgetre msgid "There was an error with the words you entered, please try again." msgstr "Mit den von Ihren eingegebenen Worten ist etwas schiefgegangen. Versuchen Sie es erneut. " +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "Es gab keine zu Ihrer Suche passenden Anfragen." msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "Ich erhalte meine Antwort <strong>auf dem Postweg</strong>" @@ -2398,9 +2476,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Diese Behörde existiert nichtmehr. Es ist folglich nicht möglich eine Anfrage zu stellen. " -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Dieser Kommentar wurde verborgen. Sehen Sie die Anmerkungen, um den Grund zu erfahren. Falls Sie diese Anfrage gestellt haben können Sie sich <a href=\"{{url}}\">einloggen</a> um die Antwort zu lesen." - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2424,8 +2499,26 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Dies ist Ihre eigene Anfrage. Sie erhalten eine automatische Emailbenachrichtigung, sobald Ihre Anfrage beantwortet wird. " -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Dieser Kommentar wurde verborgen. Sehen Sie die Anmerkungen, um den Grund zu erfahren. Falls Sie diese Anfrage gestellt haben können Sie sich <a href=\"{{url}}\">einloggen</a> um die Antwort zu lesen." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" +msgstr "" msgid "This particular request is finished:" msgstr "Diese Anfrage wurde abgeschlossen:" @@ -2498,9 +2591,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Dieser Kommentar wurde verborgen. Sehen Sie die Anmerkungen, um den Grund zu erfahren. Falls Sie diese Anfrage gestellt haben können Sie sich <a href=\"{{url}}\">anmelden</a> um die Antwort zu lesen." - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3360,9 +3450,6 @@ msgstr "um eine Nachfrage zu senden. " msgid "to {{public_body}}" msgstr "an {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "unbekannte Ursache" diff --git a/locale/en/app.po b/locale/en/app.po index 17cea227b..8527db557 100644 --- a/locale/en/app.po +++ b/locale/en/app.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" "PO-Revision-Date: 2011-02-24 07:11-0000\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -1000,6 +1000,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "" +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "" @@ -1069,6 +1072,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "" @@ -1102,9 +1111,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1267,6 +1273,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "" @@ -1384,6 +1393,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "" @@ -1447,6 +1459,12 @@ msgstr "" msgid "OutgoingMessage|Message type" msgstr "" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "" @@ -1474,6 +1492,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "" @@ -1489,6 +1513,9 @@ msgstr "" msgid "Please" msgstr "" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "" @@ -1693,6 +1720,12 @@ msgstr "" msgid "ProfilePhoto|Draft" msgstr "" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "" @@ -1705,6 +1738,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1732,6 +1780,15 @@ msgstr "" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "" @@ -1843,6 +1900,12 @@ msgstr "" msgid "Requested on {{date}}" msgstr "" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2151,12 +2214,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "" +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "" @@ -2300,12 +2372,18 @@ msgstr "" msgid "There was an error with the words you entered, please try again." msgstr "" +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "" msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "" @@ -2330,9 +2408,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "" -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2354,7 +2429,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "" -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2424,9 +2517,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3267,9 +3357,6 @@ msgstr "" msgid "to {{public_body}}" msgstr "" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "" diff --git a/locale/en_IE/app.po b/locale/en_IE/app.po index a9f46885a..8309c3be3 100644 --- a/locale/en_IE/app.po +++ b/locale/en_IE/app.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: English (Ireland) (http://www.transifex.com/projects/p/alaveteli/language/en_IE/)\n" "Language: en_IE\n" @@ -1004,6 +1004,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "" +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "" @@ -1073,6 +1076,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "" @@ -1106,9 +1115,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1271,6 +1277,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "" @@ -1388,6 +1397,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "" @@ -1451,6 +1463,12 @@ msgstr "" msgid "OutgoingMessage|Message type" msgstr "" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "" @@ -1478,6 +1496,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "" @@ -1493,6 +1517,9 @@ msgstr "" msgid "Please" msgstr "" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "" @@ -1697,6 +1724,12 @@ msgstr "" msgid "ProfilePhoto|Draft" msgstr "" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "" @@ -1709,6 +1742,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1736,6 +1784,15 @@ msgstr "" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "" @@ -1847,6 +1904,12 @@ msgstr "" msgid "Requested on {{date}}" msgstr "" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2155,12 +2218,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "" +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "" @@ -2304,12 +2376,18 @@ msgstr "" msgid "There was an error with the words you entered, please try again." msgstr "" +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "" msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "" @@ -2334,9 +2412,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "" -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2358,7 +2433,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "" -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2428,9 +2521,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3271,9 +3361,6 @@ msgstr "" msgid "to {{public_body}}" msgstr "" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "" diff --git a/locale/es/app.po b/locale/es/app.po index bd0112c58..37ac7e389 100644 --- a/locale/es/app.po +++ b/locale/es/app.po @@ -15,8 +15,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Spanish (http://www.transifex.com/projects/p/alaveteli/language/es/)\n" "Language: es\n" @@ -1114,6 +1114,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Si aún tienes problemas, por favor <a href=\"{{url}}\">contáctanos</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Si la solicitud es tuya, puedes <a href=\"{{url}}\">abrir una sesión</a> para verla." @@ -1198,6 +1201,12 @@ msgstr "IncomingMessage|Mail from" msgid "IncomingMessage|Mail from domain" msgstr "IncomingMessage|Mail from domain" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "IncomingMessage|Sent at" @@ -1231,9 +1240,6 @@ msgstr "InfoRequestEvent|Last described at" msgid "InfoRequestEvent|Params yaml" msgstr "InfoRequestEvent|Params yaml" -msgid "InfoRequestEvent|Prominence" -msgstr "InfoRequestEvent|Prominence" - msgid "InfoRequest|Allow new responses from" msgstr "InfoRequest|Allow new responses from" @@ -1407,6 +1413,9 @@ msgstr "Solicitudes diversas" msgid "Message" msgstr "Mensaje" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Mensaje enviado usando {{site_name}}, " @@ -1524,6 +1533,9 @@ msgstr "Ahora revisa tu mensaje" msgid "Now preview your message asking for an internal review" msgstr "Ahora revisa tu mensaje pidiendo una revisión interna" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "O borre la foto actual" @@ -1587,6 +1599,12 @@ msgstr "OutgoingMessage|Last sent at" msgid "OutgoingMessage|Message type" msgstr "OutgoingMessage|Message type" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "OutgoingMessage|Status" @@ -1614,6 +1632,12 @@ msgstr "Personas" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "Personas {{start_count}} a {{end_count}} de {{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Foto:" @@ -1629,6 +1653,9 @@ msgstr "Juega al juego de clasificación de solicitudes!" msgid "Please" msgstr "Por favor" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Por favor <a href=\"{{url}}\">contacta</a> con nosotros para que podamos arreglarlo." @@ -1844,6 +1871,12 @@ msgstr "ProfilePhoto|Data" msgid "ProfilePhoto|Draft" msgstr "ProfilePhoto|Draft" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Organismos públicos" @@ -1856,6 +1889,21 @@ msgstr "Organismos públicos {{start_count}} a {{end_count}} de {{total_count}}" msgid "Public authority – {{name}}" msgstr "Organismo público - {{name}}" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "Autoridad/Organismo Publico" @@ -1883,6 +1931,15 @@ msgstr "Sitio web" msgid "PublicBody|Info requests count" msgstr "PublicBody|Info requests count" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "PublicBody|Last edit comment" @@ -1996,6 +2053,12 @@ msgstr "Solicitud a {{public_body_name}} de {{info_request_user}} el {{date}}" msgid "Requested on {{date}}" msgstr "Pedida el {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "Solicitudes de informacion personal y solicitudes inapropiadas o espureas no son consideradas solicitudes validas de acceso (<a href=\"/help/about\">read more</a>)." @@ -2323,15 +2386,24 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "El organismo querría / ha respondido <strong>por correo ordinario</strong> a esta solicitud." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" "El correo envíado por usted, en nombre de {{public_body}}, enviado a\n" "{{user}} como respuesta a la solicitud {{law_used_short}}\n" "no ha sido entregado." +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "La página no existe. Puede intentar:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "El organismo no tiene la información solicitada" @@ -2484,12 +2556,18 @@ msgstr "Se ha producido un <strong>error en la entrega</strong> o similar, y nec msgid "There was an error with the words you entered, please try again." msgstr "Ha habido un error con las palabras introducidas, por favor pruebe otra vez." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "No se encontraron solicitudes para tu búsqueda." msgid "There were no results matching your query." msgstr "No se han encontrado resultados para tu búsqueda." +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "Van a responder <strong>por correo ordinario</strong>" @@ -2516,11 +2594,6 @@ msgstr "Pedidos que estas siguiendo" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Este organismo ya no existe, no pueden realizarse solicitudes de información." -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" -"Este respuesta está oculta. Revisa los comentarios\n" -" para descubrir por qué. Si es tu solicitud, <a href=\"{{url}}\">abre una sesión</a> para ver la respuesta." - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" "Esto incluye un amplio espectro de información sobre el estado de\n" @@ -2546,10 +2619,26 @@ msgstr "Esta es la primera versión." msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Esta es tu solicitud, por lo que recibirás correos automáticamente cuando lleguen nuevas respuestas." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" -"Este mensaje está oculto. Lee los comentarios\n" -"\t\t\t\t\t\tpara descubrir por qué. Si es tu solicitud, <a href=\"{{url}}\">abra una sesión</a> para ver la respuesta." msgid "This particular request is finished:" msgstr "Esta solicitud está cerrada:" @@ -2624,11 +2713,6 @@ msgstr "Esta solicitud necesita que un moderador la revise." msgid "This request was not made via {{site_name}}" msgstr "Esta solicitud no fue hecha vía {{site_name}}" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" -"Este respuesta está oculta. Revisa los comentarios\n" -" para descubrir por qué. Si es tu solicitud, <a href=\"{{url}}\">abre una sesión</a> para ver la respuesta." - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" "La siguiente tabla muestra datos técnicos sobre los eventos internos relacionados \n" @@ -3537,9 +3621,6 @@ msgstr "mandar un mensaje de seguimiento." msgid "to {{public_body}}" msgstr "a {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "visibilidad inesperada en el evento de la solicitud" - msgid "unknown reason " msgstr "motivo desconocido " diff --git a/locale/eu/app.po b/locale/eu/app.po index f3548e5af..f546085cd 100644 --- a/locale/eu/app.po +++ b/locale/eu/app.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Basque (http://www.transifex.com/projects/p/alaveteli/language/eu/)\n" "Language: eu\n" @@ -1042,6 +1042,9 @@ msgstr "Erakunde publikotik jaso duzun erantzunarekin pozik ez bazaude, apelatze msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Oraindik arazoak baldin badituzu, mesedez, jar zaitez gurekin <a href=\"{{url}}\">harremanetan</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Eskabidea zurea baldin bada, <a href=\"{{url}}\">saio bat zabaldu</a> ahal duzu ikusteko." @@ -1111,6 +1114,12 @@ msgstr "IncomingMessage|Mail from" msgid "IncomingMessage|Mail from domain" msgstr "IncomingMessage|Mail from domain" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "IncomingMessage|Sent at" @@ -1144,9 +1153,6 @@ msgstr "InfoRequestEvent|Last described at" msgid "InfoRequestEvent|Params yaml" msgstr "InfoRequestEvent|Params yaml" -msgid "InfoRequestEvent|Prominence" -msgstr "InfoRequestEvent|Prominence" - msgid "InfoRequest|Allow new responses from" msgstr "InfoRequest|Allow new responses from" @@ -1312,6 +1318,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Mezua bidali da {{site_name}} erabiliz, " @@ -1429,6 +1438,9 @@ msgstr "Orain, berrikusi zure mezua" msgid "Now preview your message asking for an internal review" msgstr "Orain berrikusi zure mezua, barneko berrikusketa eskatuz" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "EDO ezaba ezazu oraingo argazkia" @@ -1492,6 +1504,12 @@ msgstr "OutgoingMessage|Last sent at" msgid "OutgoingMessage|Message type" msgstr "OutgoingMessage|Message type" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "OutgoingMessage|Status" @@ -1519,6 +1537,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "Pertsonak, {{start_count}}-tik {{end_count}}-ra, guztira {{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Zure argazkia:" @@ -1534,6 +1558,9 @@ msgstr "Eskabideak sailkatzeko jolasean aritu nahi?" msgid "Please" msgstr "Mesedez" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Mesedez, jar zaitez gurekin <a href=\"{{url}}\">harremanetan</a>, hau konpon dezagun." @@ -1740,6 +1767,12 @@ msgstr "ProfilePhoto|Data" msgid "ProfilePhoto|Draft" msgstr "ProfilePhoto|Draft" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Erakunde publikoak" @@ -1752,6 +1785,21 @@ msgstr "Erakunde publikoak {{start_count}}-etik {{end_count}}-era, guztira {{tot msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1779,6 +1827,15 @@ msgstr "Sitio web" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "PublicBody|Last edit comment" @@ -1892,6 +1949,12 @@ msgstr "{{info_request_user}}-k eskabidea egin dio {{public_body_name}}-ri {{dat msgid "Requested on {{date}}" msgstr " {{date}} egunean egindako eskabidea." +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2209,14 +2272,23 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "Erakundeak eskabide honi erantzun dio / nahi izango luke <strong>posta arruntaren bidez</strong>." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" "Zuk bidalitako emaila, {{public_body}}-ren izenean, enviado a\n" "{{user}}-ri {{law_used_short}} eskabidearen erantzuna bezala, ez da eman." +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "Orrialdea ez da existitzen. Orain saiatu ahal duzu:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "Erakundeak ez dauka eskatutako informazioa" @@ -2364,12 +2436,18 @@ msgstr "<strong>Ematean errorea gertatu da</strong> edo antzeko zerbait, eta {{s msgid "There was an error with the words you entered, please try again." msgstr "Sartu dituzun hitzetan errorea gertatu da, mesedez saia zaitez berriro." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "Ez da zure bilaketarako eskabiderik aurkitu." msgid "There were no results matching your query." msgstr "Ez da zure bilaketarako emaitzarik aurkitu." +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "<strong>Posta arruntaren bidez</strong> erantzungo dute." @@ -2396,9 +2474,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Erakunde hau jadanik ez da existitzen, ezin da informazio eskabiderik egin." -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Erantzun hau ezkutatuta dago. Ikus itzazu iruzkinak jakiteko zergatik. Zure eskabidea baldin bada, <a href=\"{{url}}\">ireki saioa</a> erantzuna ikusteko." - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "Honek <strong>ingurune naturala eta hiritartuaren</strong> egoerari buruzko informazio zabala dakar, esaterako:" @@ -2420,8 +2495,26 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Hauxe da zure eskabidea, horregatik erantzun berriak heltzen direnean automatikoki emailak jasoko dituzu." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Mezu hau ezkutatuta dago. Irakur itzazu iruzkinak jakiteko zergatik. Zure eskabidea baldin bada, <a href=\"{{url}}\">ireki ezazu saioa</a> erantzuna ikusteko." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" +msgstr "" msgid "This particular request is finished:" msgstr "Eskabide hau itxita dago:" @@ -2492,9 +2585,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Erantzun hau ezkututa dago. Ikus itzazu iruzkinak jakiteko zergatik. Zeure eskabidea baldin bada, <a href=\"{{url}}\">ireki saioa</a> erantzuna ikusteko." - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "Ondoko taulak {{site_name}} eskabidearekin zerikusia duten barne gertaeren datu teknikoak erakusten ditu. Datu hauek erabil daitezke estatistikak sortzeko, esaterako erakundeen erantzun abiadura edo posta arrunta erabiltzeko eskatzen duten eskabide kopurua." @@ -3353,9 +3443,6 @@ msgstr "jarraipen mezua bidali." msgid "to {{public_body}}" msgstr "{{public_body}}-ri" -msgid "unexpected prominence on request event" -msgstr "eskabidearen gertaeran ustegabeko ikusgarritasuna" - msgid "unknown reason " msgstr "arrazoi ezezaguna" diff --git a/locale/fi/app.po b/locale/fi/app.po index 12a58281d..e57e424ff 100644 --- a/locale/fi/app.po +++ b/locale/fi/app.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Finnish (http://www.transifex.com/projects/p/alaveteli/language/fi/)\n" "Language: fi\n" @@ -1004,6 +1004,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "" +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "" @@ -1073,6 +1076,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "" @@ -1106,9 +1115,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1271,6 +1277,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "" @@ -1388,6 +1397,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "" @@ -1451,6 +1463,12 @@ msgstr "" msgid "OutgoingMessage|Message type" msgstr "" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "" @@ -1478,6 +1496,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "" @@ -1493,6 +1517,9 @@ msgstr "" msgid "Please" msgstr "" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "" @@ -1697,6 +1724,12 @@ msgstr "" msgid "ProfilePhoto|Draft" msgstr "" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "" @@ -1709,6 +1742,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1736,6 +1784,15 @@ msgstr "" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "" @@ -1847,6 +1904,12 @@ msgstr "" msgid "Requested on {{date}}" msgstr "" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2155,12 +2218,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "" +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "" @@ -2304,12 +2376,18 @@ msgstr "" msgid "There was an error with the words you entered, please try again." msgstr "" +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "" msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "" @@ -2334,9 +2412,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "" -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2358,7 +2433,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "" -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2428,9 +2521,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3271,9 +3361,6 @@ msgstr "" msgid "to {{public_body}}" msgstr "" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "" diff --git a/locale/fr/app.po b/locale/fr/app.po index 4b3acd06b..2c6207e36 100644 --- a/locale/fr/app.po +++ b/locale/fr/app.po @@ -30,9 +30,9 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-06 20:04+0000\n" -"Last-Translator: cegall\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" +"Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: French (http://www.transifex.com/projects/p/alaveteli/language/fr/)\n" "Language: fr\n" "MIME-Version: 1.0\n" @@ -1027,6 +1027,9 @@ msgstr "Si vous n'etes pad satisfait de la réponse faite par l'organisme public msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Si vous rencontrez toujours des problèmes, s'il vous plaît <a href=\"{{url}}\">contact us</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Si vous êtes le demandeur, alors vous pouvez <a href=\"{{url}}\">sign in</a> voir à la demande." @@ -1096,6 +1099,12 @@ msgstr "IncomingMessage|Mail from" msgid "IncomingMessage|Mail from domain" msgstr "IncomingMessage|Mail from domain" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "IncomingMessage|Envoyé à" @@ -1129,9 +1138,6 @@ msgstr "InfoRequestEvent|Last described at" msgid "InfoRequestEvent|Params yaml" msgstr "InfoRequestEvent|Params yaml" -msgid "InfoRequestEvent|Prominence" -msgstr "InfoRequestEvent|Prominence" - msgid "InfoRequest|Allow new responses from" msgstr "InfoRequest|Allow new responses from" @@ -1294,6 +1300,9 @@ msgstr "Beaucoup de demandes" msgid "Message" msgstr "Message" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Message envoyé en utilisant le formulaire {{site_name}}" @@ -1411,6 +1420,9 @@ msgstr "Maintenant prévisualisez votre suivi" msgid "Now preview your message asking for an internal review" msgstr "Maintenant prévisualisez votre message demandant un examen interne" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "Ou effacer la photo existante" @@ -1474,6 +1486,12 @@ msgstr "OutgoingMessage|Last sent at" msgid "OutgoingMessage|Message type" msgstr "OutgoingMessage|Message type" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "OutgoingMessage|Status" @@ -1501,6 +1519,12 @@ msgstr "Citoyens" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "Personnes {{start_count}} à {{end_count}} de {{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Votre photo :" @@ -1516,6 +1540,9 @@ msgstr "Jouez au jeu de catégorisation des demandes !" msgid "Please" msgstr "S'il vous plait" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Veuillez <a href=\"{{url}}\">nous contacter </a> afin que nous puissions le corriger." @@ -1720,6 +1747,12 @@ msgstr "ProfilePhoto|Data" msgid "ProfilePhoto|Draft" msgstr "ProfilePhoto|Draft" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Organismes publics" @@ -1732,6 +1765,21 @@ msgstr "Organismes publics {{start_count}} à {{end_count}} de {{total_count}}" msgid "Public authority – {{name}}" msgstr "Organisme public – {{name}}" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "Organisme public" @@ -1759,6 +1807,15 @@ msgstr "PublicBody|Home page" msgid "PublicBody|Info requests count" msgstr "PublicBody|Info requests count" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "PublicBody|Last edit comment" @@ -1870,6 +1927,12 @@ msgstr "Demande de {{public_body_name}} par {{info_request_user}} le {{date}}" msgid "Requested on {{date}}" msgstr "Demandé le {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "Les demandes de renseignements personnels et les demandes abusives ne sont pas considérées comme demandes valides (<a href=\"/help/about\">Lire plus</a>)." @@ -2178,12 +2241,21 @@ msgstr "l'etablissement public dit qu'ils ont besoin d'une <strong> adresse pos msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "L'autorité aimerait répondre, ou a répondu, <strong> par la Poste </strong> à cette demande." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "Le message que vous , au nom de {{public_body}}, avez envoyé à \\n{{user}} en réponse à la demande {{law_used_short}}\\n n'a pas été delivré" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "La page n'existe pas . Vous pouvez essayer de :" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "L'autorité administrative n'a pas les informations demandées" @@ -2327,12 +2399,18 @@ msgstr "Il y a eu <strong>une erreur de transmission</strong> ou autre , qui doi msgid "There was an error with the words you entered, please try again." msgstr "Il y a une erreur liée aux mots que vous avez saisis, veuillez réessayer." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "Aucune demande d'information ne correspond à votre recherche." msgid "There were no results matching your query." msgstr "Aucun résultat correspondant à votre recherche." +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "Ils vont répondre <strong>par courrier</strong>" @@ -2357,9 +2435,6 @@ msgstr "Choses que vous suivez" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Cette institution n'existe plus, vous ne pouvez donc pas lui envoyer une demande." -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Ce commentaire a été caché . Voir les annotations ci dessous pour \\n savoir pourquoi. Si vous êtes le demandeur, alors vous pouvez<a href=\"{{url}}\">vous connecter </a> pour voir la réponse." - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "Cela couvre un très large spectre d'informations sur l'état de <strong>l'environnement naturel et construit par l'homme,</strong> comme par exemple :" @@ -2381,8 +2456,26 @@ msgstr "Ceci est la première version." msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Ceci est votre propre demande, afin que vous receviez automatiquement un e-mail dès que de nouvelles réponses arrivent." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Ce message sortant a été caché. Voir les commentaires pour \\n\t\t\t\t\t\tsavoir pourquoi. Si vous êtes le demandeur, alors vous pouvez <a href=\"{{url}}\">vous connecter </a>pour voir la réponse." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" +msgstr "" msgid "This particular request is finished:" msgstr "Cette demande particulière est terminée:" @@ -2451,9 +2544,6 @@ msgstr "Cette demande nécessite une attention de l'administrateur " msgid "This request was not made via {{site_name}}" msgstr "cette demande n'a pas été faite à travers {{site_name}}" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Cette réponse a été cachée. Voir les commentaires pour savoir pourquoi. \\n Si vous êtes le demandeur, alors vous pouvez <a href=\"{{url}}\">vous connecter</a> pour voir la réponse." - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "Ce tableau présente les détails techniques des événements internes qui ont eu lieu \\n à cette demande sur {{site_name}}. Cela pourrait être utilisé pour générer des informations sur \\n la vitesse avec laquelle les autorités répondent aux demandes, le nombre de demandes \\n qui nécessitent une réponse postale et bien plus encore." @@ -3294,9 +3384,6 @@ msgstr "Pour envoyer un message de suivi ." msgid "to {{public_body}}" msgstr "à {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "Importance inattendue de la demande " - msgid "unknown reason " msgstr "raison inconnue" diff --git a/locale/fr_CA/app.po b/locale/fr_CA/app.po index e7d2a36e9..573323f23 100644 --- a/locale/fr_CA/app.po +++ b/locale/fr_CA/app.po @@ -18,9 +18,9 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-09-18 18:35+0000\n" -"Last-Translator: marichelleleclair <marichelle.leclair@gmail.com>\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" +"Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: French (Canada) (http://www.transifex.com/projects/p/alaveteli/language/fr_CA/)\n" "Language: fr_CA\n" "MIME-Version: 1.0\n" @@ -1013,6 +1013,9 @@ msgstr "Si vous n'êtes pas satisfait de la réponse fournie par l'autorité, vo msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Si vous rencontrez toujours des problèmes, veuillez <a href=\"{{url}}\">nous contacter</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Si vous êtes le demandeur, vous pouvez <a href=\"{{url}}\">vous connecter</a> pour voir la demande." @@ -1082,6 +1085,12 @@ msgstr "IncomingMessage|Mail from" msgid "IncomingMessage|Mail from domain" msgstr "IncomingMessage|Mail from domain" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "IncomingMessage|Sent at" @@ -1115,9 +1124,6 @@ msgstr "InfoRequestEvent|Last described at" msgid "InfoRequestEvent|Params yaml" msgstr "InfoRequestEvent|Params yaml" -msgid "InfoRequestEvent|Prominence" -msgstr "InfoRequestEvent|Prominence" - msgid "InfoRequest|Allow new responses from" msgstr "InfoRequest|Allow new responses from" @@ -1280,6 +1286,9 @@ msgstr "Beaucoup de demandes" msgid "Message" msgstr "Message" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Message envoyé en utilisant le formulaire {{site_name}}" @@ -1397,6 +1406,9 @@ msgstr "Maintenant, prévisualisez votre suivi" msgid "Now preview your message asking for an internal review" msgstr "Maintenant, prévisualisez votre message demandant un examen interne" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "OU effacer la photo existante" @@ -1460,6 +1472,12 @@ msgstr "OutgoingMessage|Last sent at" msgid "OutgoingMessage|Message type" msgstr "OutgoingMessage|Message type" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "OutgoingMessage|Status" @@ -1487,6 +1505,12 @@ msgstr "Citoyens" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "Les gens {{start_count}} à {{end_count}} de {{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Votre photo :" @@ -1502,6 +1526,9 @@ msgstr "Jouez au jeu de catégorisation des demandes!" msgid "Please" msgstr "Veuillez" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Veuillez <a href=\"{{url}}\">nous contacter </a> afin que nous puissions le corriger." @@ -1706,6 +1733,12 @@ msgstr "ProfilePhoto|Data" msgid "ProfilePhoto|Draft" msgstr "ProfilePhoto|Draft" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Public authorities" @@ -1718,6 +1751,21 @@ msgstr "Organismes gouvernementaux {{start_count}} à {{end_count}} de {{total_c msgid "Public authority – {{name}}" msgstr "Public authority – {{name}}" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "Public body" @@ -1745,6 +1793,15 @@ msgstr "PublicBody|Home page" msgid "PublicBody|Info requests count" msgstr "PublicBody|Info requests count" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "PublicBody|Last edit comment" @@ -1856,6 +1913,12 @@ msgstr "Demandé à {{public_body_name}} par {{info_request_user}} le {{date}}" msgid "Requested on {{date}}" msgstr "Demandé le {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "Les demandes de renseignements personnels et les demandes abusives ne sont pas considérées comme des demandes valides (<a href=\"/help/about\">Davantage de détails</a>)." @@ -2164,12 +2227,21 @@ msgstr "L'organisme affirme qu'une <strong> adresse postale </ strong> est néce msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "L'organisme aimerait répondre ou a répondu <strong> par la poste </strong> à cette demande." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "Le message que vous avez envoyé au nom de {{public_body}} à \\n{{user}} en réponse à la demande {{law_used_short}}\\n n'a pas été livré." +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "La page n'existe pas. Vous pouvez essayer de :" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "L'organisme n'a pas les informations demandées" @@ -2313,12 +2385,18 @@ msgstr "Il y a eu <strong> une erreur de transmission </strong> ou autre, qui do msgid "There was an error with the words you entered, please try again." msgstr "Il y a une erreur liée aux mots saisis. Veuillez réessayer. " +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "Aucune demande d'information ne correspond à votre recherche." msgid "There were no results matching your query." msgstr "Aucun résultat ne correspond à votre recherche." +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "Ils vont répondre <strong>par la poste</strong>" @@ -2343,9 +2421,6 @@ msgstr "Ce que vous suivez" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Cet organisme n'existe plus, donc vous ne pouvez lui adresser une demande." -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Ce commentaire a été masqué. Voir les annotations ci-dessous pour \\n savoir pourquoi. Si vous êtes le demandeur, vous pouvez<a href=\"{{url}}\">vous connecter </a> pour lire la réponse." - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "Cela couvre un très large spectre d'informations sur l'état de\\n <strong>l'environnement naturel et construit par l'homme</strong>, comme " @@ -2367,8 +2442,26 @@ msgstr "Ceci est la première version." msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Ceci est votre demande, alors vous recevrez un courriel lorsque de nouvelles réponses seront soumises." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Ce message sortant a été masqué. Voir les commentaires pour \\n\t\t\t\t\t\tsavoir pourquoi. Si vous êtes le demandeur, vous pouvez <a href=\"{{url}}\">vous connecter </a>pour lire la réponse." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" +msgstr "" msgid "This particular request is finished:" msgstr "Cette demande particulière est achevée:" @@ -2437,9 +2530,6 @@ msgstr "Cette demande nécessite l'attention d'un administrateur " msgid "This request was not made via {{site_name}}" msgstr "Cette demande n'a pas été faite à travers {{site_name}}" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Cette réponse à été masquée. Voir les annotations afin de comprendre pourquoi. \\n Si vous êtes le demandeur, vous pouvez vous <a href=\"{{url}}\">identifier</a> pour lire la réponse." - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "Ce tableau montre les détails techniques de cet événement interne survenu \\n dans le cadre de cette requête sur {{site_name}}. Cela pourrait être utilisé dans le but de générer de l'information au sujet \\n de la rapidité à laquelle les autorités répondent aux demandes, du nombre de demandes \\n exigeant une réponse par la poste, et bien plus encore." @@ -3280,9 +3370,6 @@ msgstr "pour envoyer un message de suivi." msgid "to {{public_body}}" msgstr "à {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "Notoriété inattendue de la demande" - msgid "unknown reason " msgstr "raison inconnue" diff --git a/locale/gl/app.po b/locale/gl/app.po index c6469bb26..f3e110f8d 100644 --- a/locale/gl/app.po +++ b/locale/gl/app.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Galician (http://www.transifex.com/projects/p/alaveteli/language/gl/)\n" "Language: gl\n" @@ -1092,6 +1092,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Si aún tiene problemas, por favor <a href=\"{{url}}\">contáctenos</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Si la solicitud es tuya, puedes <a href=\"{{url}}\">abrir una sesión</a> para verla." @@ -1176,6 +1179,12 @@ msgstr "IncomingMessage|Mail from" msgid "IncomingMessage|Mail from domain" msgstr "IncomingMessage|Mail from domain" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "IncomingMessage|Sent at" @@ -1209,9 +1218,6 @@ msgstr "InfoRequestEvent|Last described at" msgid "InfoRequestEvent|Params yaml" msgstr "InfoRequestEvent|Params yaml" -msgid "InfoRequestEvent|Prominence" -msgstr "InfoRequestEvent|Prominence" - msgid "InfoRequest|Allow new responses from" msgstr "InfoRequest|Allow new responses from" @@ -1385,6 +1391,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Mensaje enviado usando {{site_name}}, " @@ -1502,6 +1511,9 @@ msgstr "Ahora revisa tu mensaje" msgid "Now preview your message asking for an internal review" msgstr "Ahora revisa tu mensaje pidiendo una revisión interna" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "O borre la foto actual" @@ -1565,6 +1577,12 @@ msgstr "OutgoingMessage|Last sent at" msgid "OutgoingMessage|Message type" msgstr "OutgoingMessage|Message type" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "OutgoingMessage|Status" @@ -1592,6 +1610,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "Personas {{start_count}} a {{end_count}} de {{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Foto:" @@ -1607,6 +1631,9 @@ msgstr "Juega al juego de clasificación de solicitudes!" msgid "Please" msgstr "Por favor" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Por favor <a href=\"{{url}}\">contacta</a> con nosotros para que podamos arreglarlo." @@ -1822,6 +1849,12 @@ msgstr "ProfilePhoto|Data" msgid "ProfilePhoto|Draft" msgstr "ProfilePhoto|Draft" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Organismos públicos" @@ -1834,6 +1867,21 @@ msgstr "Organismos públicos {{start_count}} a {{end_count}} de {{total_count}}" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1861,6 +1909,15 @@ msgstr "Sitio web" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "PublicBody|Last edit comment" @@ -1974,6 +2031,12 @@ msgstr "Solicitud a {{public_body_name}} de {{info_request_user}} el {{date}}" msgid "Requested on {{date}}" msgstr "Pedida el {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2301,15 +2364,24 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "El organismo querría / ha respondido <strong>por correo ordinario</strong> a esta solicitud." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" "El correo envíado por usted, en nombre de {{public_body}}, enviado a\n" "{{user}} como respuesta a la solicitud {{law_used_short}}\n" "no ha sido entregado." +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "La página no existe. Puede intentar:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "El organismo no tiene la información solicitada" @@ -2462,12 +2534,18 @@ msgstr "Se ha producido un <strong>error en la entrega</strong> o similar, y nec msgid "There was an error with the words you entered, please try again." msgstr "Ha habido un error con las palabras introducidas, por favor pruebe otra vez." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "No se encontraron solicitudes para tu búsqueda." msgid "There were no results matching your query." msgstr "No se han encontrado resultados para tu búsqueda." +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "Van a responder <strong>por correo ordinario</strong>" @@ -2494,11 +2572,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Este organismo ya no existe, no pueden realizarse solicitudes de información." -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" -"Este respuesta está oculta. Revisa los comentarios\n" -" para descubrir por qué. Si es tu solicitud, <a href=\"{{url}}\">abre una sesión</a> para ver la respuesta." - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" "Esto incluye un amplio espectro de información sobre el estado de\n" @@ -2524,10 +2597,26 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Esta es tu solicitud, por lo que recibirás correos automáticamente cuando lleguen nuevas respuestas." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" -"Este mensaje está oculto. Lee los comentarios\n" -"\t\t\t\t\t\tpara descubrir por qué. Si es tu solicitud, <a href=\"{{url}}\">abra una sesión</a> para ver la respuesta." msgid "This particular request is finished:" msgstr "Esta solicitud está cerrada:" @@ -2602,11 +2691,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" -"Este respuesta está oculta. Revisa los comentarios\n" -" para descubrir por qué. Si es tu solicitud, <a href=\"{{url}}\">abre una sesión</a> para ver la respuesta." - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" "La siguiente tabla muestra datos técnicos sobre los eventos internos relacionados \n" @@ -3513,9 +3597,6 @@ msgstr "mandar un mensaje de seguimiento." msgid "to {{public_body}}" msgstr "a {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "visibilidad inesperada en el evento de la solicitud" - msgid "unknown reason " msgstr "motivo desconocido " diff --git a/locale/he_IL/app.po b/locale/he_IL/app.po index 8083abf62..1c810ccca 100644 --- a/locale/he_IL/app.po +++ b/locale/he_IL/app.po @@ -20,9 +20,9 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-09-16 17:55+0000\n" -"Last-Translator: yehuda <yehudab@gmail.com>\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" +"Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Hebrew (Israel) (http://www.transifex.com/projects/p/alaveteli/language/he_IL/)\n" "Language: he_IL\n" "MIME-Version: 1.0\n" @@ -1015,6 +1015,9 @@ msgstr "אם אתם לא מרוצים מהתגובה שקיבלתם מהגוף msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "אם עדיין נתקלתם בבעיה אנא <a href=\"{{url}}\">צרו איתנו קשר</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "אם אתם מגישי הבקשה, תרצו אולי <a href=\"{{url}}\">להתחבר</a> כדי לצפות בבקשה." @@ -1084,6 +1087,12 @@ msgstr "IncomingMessage|Mail מאת" msgid "IncomingMessage|Mail from domain" msgstr "IncomingMessage|Mail מהדומיין" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "IncomingMessage|Sent בשעה" @@ -1117,9 +1126,6 @@ msgstr "InfoRequestEvent|Last תואר ב- " msgid "InfoRequestEvent|Params yaml" msgstr "InfoRequestEvent|Params yaml" -msgid "InfoRequestEvent|Prominence" -msgstr "InfoRequestEvent|Prominence" - msgid "InfoRequest|Allow new responses from" msgstr "InfoRequest|Allow תגובות חדשות מ- " @@ -1282,6 +1288,9 @@ msgstr "דרישות שונות" msgid "Message" msgstr "הודעה" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "הבקשה נשלחה באמצעות טופס יצירת קשר של {{site_name}}," @@ -1399,6 +1408,9 @@ msgstr "ראו את פניית ההמשך שלכם כעת" msgid "Now preview your message asking for an internal review" msgstr "ראו את בקשתכם לקבלת בדיקה פנימית" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "-או- הסירו את התמונה הקיימת" @@ -1462,6 +1474,12 @@ msgstr "OutgoingMessage|Last נשלחה ב- " msgid "OutgoingMessage|Message type" msgstr "OutgoingMessage|Message סוג" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "OutgoingMessage|Status" @@ -1489,6 +1507,12 @@ msgstr "אנשים" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "מס' אנשים: {{start_count}} עד {{end_count}} מתוך {{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "תמונה שלך:" @@ -1504,6 +1528,9 @@ msgstr "שחקו במשחק סיווג בקשות המידע!" msgid "Please" msgstr "בבקשה" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "נא <a href=\"{{url}}\">צרו איתנו קשר</a> שנוכל לטפל בכך." @@ -1708,6 +1735,12 @@ msgstr "ProfilePhoto|Data" msgid "ProfilePhoto|Draft" msgstr "ProfilePhoto|Draft" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "רשויות ציבוריות" @@ -1720,6 +1753,21 @@ msgstr "רשויות ציבוריות {{start_count}} עד {{end_count}} מתו msgid "Public authority – {{name}}" msgstr "רשות ציבורית – {{name}}" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "גוף ציבורי" @@ -1747,6 +1795,15 @@ msgstr "PublicBody|Home עמ'" msgid "PublicBody|Info requests count" msgstr "גוף ציבורי|מספר הבקשות שהוגשו" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "PublicBody|Last ערכו הערה" @@ -1858,6 +1915,12 @@ msgstr "בקשה מ{{public_body_name}} ע\"י {{info_request_user}} בתארי msgid "Requested on {{date}}" msgstr "הוגשה בתאריך {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "בקשות למידע אישי ובקשות מטרידות אינן קבילות לפי החלטת הממשלה (<a href=\"/help/about\">למידע נוסף</a>)." @@ -2166,12 +2229,21 @@ msgstr "הרשות מבקשת <strong>כתובת\\n דואר</strong> msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "הרשות רוצה להגיב / כבר הגיבה <strong>בדואר רגיל</strong> לבקשה הזאת." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "הדוא\"ל ששלחתם בשם {{public_body}}, ל- \\n{{user}} כדי להגיב על בקשת {{law_used_short}}\\nלא נמסר." +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "הדף לא קיים. דברים שתוכלו לנסות כעת:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "לרשות הציבורית אין את המידע המבוקש" @@ -2315,12 +2387,18 @@ msgstr "היתה <strong>תקלה במסירה</strong> שדורשת טיפול msgid "There was an error with the words you entered, please try again." msgstr "יש שגיאה בטקסט שהכנסתם. נסו שנית." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "אין בקשות התואמות את שאילתת החיפוש שלכם" msgid "There were no results matching your query." msgstr "אין תוצאות שמתאימות לחיפוש שלך." +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "הם עומדים להשיב <strong>בפוסט</strong>" @@ -2345,9 +2423,6 @@ msgstr "דברים אחריהם אתם עוקבים" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "רשות זו לא קיימת כבר, לכן לא ניתן להגיש לה בקשה." -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "תגובה זו הוסתרה. תוכלו לבדוק בהערות כדי לגלות\\n מדוע. אם אתם המבקשים, תוכלו <a href=\"{{url}}\">להיכנס למערכת</a> כדי לראות את התגובה." - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "דבר זה מכסה מנעד רחב של מידע על מצב\\n <strong>הסביבה הטבעית והבנויה</strong>, כגון:" @@ -2369,8 +2444,26 @@ msgstr "זוהי הגרסה הראשונה" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "זו בקשה שלכם, כך שתקבלו דוא\"ל מייד כשיגיעו תגובות חדשות." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "ההודעה היוצאת הזו הוסתרה. ראה הערות ל\\n»»»»»» כדי לגלות מדוע. אם אתם המבקשים, תוכלו <a href=\"{{url}}\">להיכנס למערכת</a> כדי לראות את התגובה." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" +msgstr "" msgid "This particular request is finished:" msgstr "הטיפול בבקשה זו הסתיים" @@ -2439,9 +2532,6 @@ msgstr "בקשה זו נדרשת לבדיקת סמכות ניהולית" msgid "This request was not made via {{site_name}}" msgstr "בקשה זו לא בוצעה דרך {{site_name}}" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "תגובה זו הוסתרה. תוכלו לבדוק בהערות כדי לגלות\\n מדוע. אם אתם המבקשים, תוכלו <a href=\"{{url}}\">להיכנס למערכת</a> כדי לראות את התגובה." - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "הטבלה מציגה את הפרטים הטכניים של אירועים פנימיים שקרו\\n לבקשה הזאת ב {{site_name}}. ניתן להשתמש במידע כדי לדעת מהי\\n המהירות בה רשויות מגיבות לבקשות, מספר הבקשות\\n שדרשו שליחת דואר ודברים רבים נוספים." @@ -3284,9 +3374,6 @@ msgstr "לשלוח הודעת מעקב." msgid "to {{public_body}}" msgstr "אל {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "תקלה בלתי צפויה בבקשה" - msgid "unknown reason " msgstr "סיבה לא ידוע" diff --git a/locale/hr/app.po b/locale/hr/app.po index e7a541cd8..b5a0a98fe 100644 --- a/locale/hr/app.po +++ b/locale/hr/app.po @@ -11,9 +11,9 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-21 15:45+0000\n" -"Last-Translator: BojanOpacak <bojan@rationalinternational.net>\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" +"Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Croatian (http://www.transifex.com/projects/p/alaveteli/language/hr/)\n" "Language: hr\n" "MIME-Version: 1.0\n" @@ -1071,6 +1071,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Ako i dalje imate problema, molimo <a href=\"{{url}}\">kontaktirajte nas</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Ako ste podnosioc zahtjeva, možete se <a href=\"{{url}}\">prijaviti</a> da biste pogledali zahtjev." @@ -1155,6 +1158,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "Nadolazeća poruka|Pošta sa domene" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "Nadolazeća poruka|Poslana u" @@ -1188,9 +1197,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1364,6 +1370,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Poruka poslana koristeći {{site_name}} formular za kontakt, " @@ -1481,6 +1490,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "Sada pregledajte Vašu poruku u kojoj tražite urgenciju " +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "ILI odstrani postojeću sliku" @@ -1544,6 +1556,12 @@ msgstr "Odlazeća poruka|Zadnja poslana u" msgid "OutgoingMessage|Message type" msgstr "Odlazeća poruka|Tip poruke" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "Odlazeća poruka|Status" @@ -1571,6 +1589,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Vaša slika:" @@ -1586,6 +1610,9 @@ msgstr "Igrajte igru kategorizacije zahtjeva!" msgid "Please" msgstr "Molimo" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Molimo <a href=\"{{url}}\">kontaktirajte</a> nas kako bi to mogli popraviti." @@ -1801,6 +1828,12 @@ msgstr "Slika na profilu|Podaci" msgid "ProfilePhoto|Draft" msgstr "Slika na profilu|Skica" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Javne ustanove" @@ -1813,6 +1846,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1840,6 +1888,15 @@ msgstr "Javno tijelo|Home page" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "Javno tijelo|Zadnji uređeni komentar" @@ -1953,6 +2010,12 @@ msgstr "Traženo od {{public_body_name}} od strane {{info_request_user}} na datu msgid "Requested on {{date}}" msgstr "Traženo na datum {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2278,12 +2341,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "Ustanova bi željela / je <strong>odgovorila poštom</strong> na ovaj zahtjev." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "Stranica ne postoji. Stvari koje možete probati sada:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "Javna ustanova ne posjeduje tražene informacije" @@ -2437,12 +2509,18 @@ msgstr "Došlo je do <strong>greške u isporuci</strong> ili nečega sličnog š msgid "There was an error with the words you entered, please try again." msgstr "Postoji greška u riječima koje ste ukucali, molimo pokušajte ponovo." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "Nema zahtjeva koji odgovaraju Vašoj pretrazi." msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "Odgovoriti će <strong>poštom</strong>" @@ -2469,9 +2547,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Ova ustanova više ne postoji, zato joj nije moguće podnijeti zahtjev. " -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2495,7 +2570,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Ovo je Vaš zahtjev, biti ćete automatski obaviješteni e-mailom kada novi odgovori budu stizali." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2573,9 +2666,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3458,9 +3548,6 @@ msgstr "poslati prateću poruku." msgid "to {{public_body}}" msgstr "za {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "nepoznat razlog " diff --git a/locale/hr_HR/app.po b/locale/hr_HR/app.po index 1e3b6386c..397db45fb 100644 --- a/locale/hr_HR/app.po +++ b/locale/hr_HR/app.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Croatian (Croatia) (http://www.transifex.com/projects/p/alaveteli/language/hr_HR/)\n" "Language: hr_HR\n" @@ -1005,6 +1005,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "" +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "" @@ -1074,6 +1077,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "" @@ -1107,9 +1116,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1272,6 +1278,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "" @@ -1389,6 +1398,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "" @@ -1452,6 +1464,12 @@ msgstr "" msgid "OutgoingMessage|Message type" msgstr "" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "" @@ -1479,6 +1497,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "" @@ -1494,6 +1518,9 @@ msgstr "" msgid "Please" msgstr "" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "" @@ -1698,6 +1725,12 @@ msgstr "" msgid "ProfilePhoto|Draft" msgstr "" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "" @@ -1710,6 +1743,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1737,6 +1785,15 @@ msgstr "" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "" @@ -1848,6 +1905,12 @@ msgstr "" msgid "Requested on {{date}}" msgstr "" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2157,12 +2220,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "" +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "" @@ -2307,12 +2379,18 @@ msgstr "" msgid "There was an error with the words you entered, please try again." msgstr "" +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "" msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "" @@ -2337,9 +2415,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "" -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2361,7 +2436,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "" -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2433,9 +2526,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3278,9 +3368,6 @@ msgstr "" msgid "to {{public_body}}" msgstr "" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "" diff --git a/locale/hu_HU/app.po b/locale/hu_HU/app.po index 6f1c025a5..3d67f6e4e 100644 --- a/locale/hu_HU/app.po +++ b/locale/hu_HU/app.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Hungarian (Hungary) (http://www.transifex.com/projects/p/alaveteli/language/hu_HU/)\n" "Language: hu_HU\n" @@ -1090,6 +1090,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Ha továbbra is fennáll a probléma, <a href=\"{{url}}\">lépjen velünk kapcsolatba</a>. " +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Ha ön az igénylő, az igénylés megtekintéséhez <a href=\"{{url}}\">bejelentkezhet</a>. " @@ -1174,6 +1177,12 @@ msgstr "IncomingMessage|Mail from" msgid "IncomingMessage|Mail from domain" msgstr "IncomingMessage|Mail from domain" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "IncomingMessage|Sent at" @@ -1207,9 +1216,6 @@ msgstr "InfoRequestEvent|Last described at" msgid "InfoRequestEvent|Params yaml" msgstr "InfoRequestEvent|Params yaml" -msgid "InfoRequestEvent|Prominence" -msgstr "InfoRequestEvent|Prominence" - msgid "InfoRequest|Allow new responses from" msgstr "InfoRequest|Allow new responses from" @@ -1384,6 +1390,9 @@ msgstr "Sok igénylés" msgid "Message" msgstr "Üzenet" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Üzenet elküldve a {{site_name}} kapcsolatfelvételi űrlapján, " @@ -1501,6 +1510,9 @@ msgstr "Előnézet megtekintése" msgid "Now preview your message asking for an internal review" msgstr "Előnézet megtekintése " +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "VAGY meglevő fénykép eltávolítása " @@ -1564,6 +1576,12 @@ msgstr "OutgoingMessage|Last sent at" msgid "OutgoingMessage|Message type" msgstr "OutgoingMessage|Message type" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "OutgoingMessage|Status" @@ -1591,6 +1609,12 @@ msgstr "Személyek" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "Személyek: {{start_count}} - {{end_count}}, összesen: {{total_count}} " +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Fényképem: " @@ -1606,6 +1630,9 @@ msgstr "Kérjük, hajtsa végre az igénylések besorolását. " msgid "Please" msgstr "Kérjük, " +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Kérjük, <a href=\"{{url}}\">lépjen velünk kapcsolatba</a>, hogy kijavítsuk a hibát. " @@ -1823,6 +1850,12 @@ msgstr "ProfilePhoto|Data" msgid "ProfilePhoto|Draft" msgstr "ProfilePhoto|Draft" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Adatgazdák" @@ -1835,6 +1868,21 @@ msgstr "Adatgazdák: {{start_count}} - {{end_count}}, összesen: {{total_count}} msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "Adatgazda" @@ -1862,6 +1910,15 @@ msgstr "PublicBody|Home page" msgid "PublicBody|Info requests count" msgstr "PublicBody|Info requests count" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "PublicBody|Last edit comment" @@ -1975,6 +2032,12 @@ msgstr "{{info_request_user}} igénylése a(z) {{public_body_name}} adatgazda r msgid "Requested on {{date}}" msgstr "Igénylés benyújtva {{date}} napon " +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "Személyes információk kérése vagy zaklatásnak minősülő igénylés nem tekinthetők érvényes közérdekűadat-igénylésnek (<a href=\"/help/about\">További részletek</a>)." @@ -2302,15 +2365,24 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "Az adatgazda <strong>postai úton</strong> szeretne válaszolni / válaszolt az igénylésre. " +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" "Az az e-mail, amelyet ön a(z) {{public_body}} adatgazda nevében\n" "{{user}} felhasználónak küldött a {{law_used_short}}\n" "igénylésre vonatkozóan, nem lehetett kézbesíteni. " +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "Az oldal nem létezik. Amit megpróbálhat: " +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "Az adatgazda nem rendelkezik a kért információval " @@ -2463,12 +2535,18 @@ msgstr "<strong>Kézbesítési hiba</strong> vagy valami hasonló történt, ame msgid "There was an error with the words you entered, please try again." msgstr "A CAPTCHA ellenőrzés sikertelen. Próbálja újra beírni a képen látható szavakat, vagy kérjen új képet, ha a megjelenített betűk végképp olvashatatlanok az ön számára." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "Nincsen a lekérdezésének megfelelő igénylés. " msgid "There were no results matching your query." msgstr "Nincsen a lekérdezésének megfelelő eredmény. " +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "<strong>Postai úton</strong> fognak válaszolni " @@ -2495,11 +2573,6 @@ msgstr "Követett elemek:" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Ez az adatgazda már nem létezik, ezért nem tud adatigényléseket fogadni. " -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" -"Ez a hozzászolás el lett rejtve. A megjegyzésekből\n" -" megtudhatja ennek okát. Ha ön az igénylő, a válasz megtekintéséhez <a href=\"{{url}}\">bejelentkezhet</a>. " - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" "Az információk széles köre tartozik ide\n" @@ -2525,10 +2598,26 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Ez az ön saját igénylése, így automatikusan e-mail üzenetet kap, ha válasz érkezik. " -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" -"Ez a kimenő üzenet el lett rejtve. A megjegyzésekből\n" -"\t\t\t\t\t\tmegtudhatja ennek okát. Ha ön az igénylő, a válasz megtekintéséhez <a href=\"{{url}}\">bejelentkezhet</a>. " msgid "This particular request is finished:" msgstr "Ez az igénylés lezárult: " @@ -2603,11 +2692,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "Az igénylést nem a(z) {{site_name}} weboldalon keresztül nyújtották be" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" -"Ez a válasz el lett rejtve. A megjegyzésekből megtudhatja ennek okát.\n" -" Ha ön az igénylő, a válasz megtekintéséhez <a href=\"{{url}}\">bejelentkezhet</a>. " - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" "Ez a táblázat tartalmazza azoknak a belső eseményeknek a technikai részleteit,\n" @@ -3510,9 +3594,6 @@ msgstr "nyomon követési üzenet küldése céljából. " msgid "to {{public_body}}" msgstr "{{public_body}} részére " -msgid "unexpected prominence on request event" -msgstr "váratlan népszerűség az igénylési eseménnyel kapcsolatosan " - msgid "unknown reason " msgstr "ismeretlen ok " diff --git a/locale/id/app.po b/locale/id/app.po index 626c7d0a3..758a7c9a4 100644 --- a/locale/id/app.po +++ b/locale/id/app.po @@ -14,8 +14,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Indonesian (http://www.transifex.com/projects/p/alaveteli/language/id/)\n" "Language: id\n" @@ -1116,6 +1116,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Jika Anda masih mengalami kesulitan, silakan <a href=\"{{url}}\">hubungi kami</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Jika Anda adalah sang pemohon, maka Anda dapat <a href=\"{{url}}\">mendaftar</a> untuk menampilkan permintaan tersebut." @@ -1200,6 +1203,12 @@ msgstr "IncomingMessage|Mail from" msgid "IncomingMessage|Mail from domain" msgstr "IncomingMessage|Mail from domain" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "IncomingMessage|Sent at" @@ -1233,9 +1242,6 @@ msgstr "InfoRequestEvent|Last described at" msgid "InfoRequestEvent|Params yaml" msgstr "InfoRequestEvent|Params yaml" -msgid "InfoRequestEvent|Prominence" -msgstr "InfoRequestEvent|Prominence" - msgid "InfoRequest|Allow new responses from" msgstr "InfoRequest|Allow new responses from" @@ -1409,6 +1415,9 @@ msgstr "Banyak permintaan" msgid "Message" msgstr "Pesan" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Pesan dikirim menggunakan {{site_name}} kontak dari, " @@ -1526,6 +1535,9 @@ msgstr "Sekarang tinjau tindak lanjut Anda" msgid "Now preview your message asking for an internal review" msgstr "Sekarang tinjau pesan Anda yang meminta akan sebuah kajian internal" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "ATAU menghapus foto yang sudah ada" @@ -1589,6 +1601,12 @@ msgstr "OutgoingMessage|Last sent at" msgid "OutgoingMessage|Message type" msgstr "OutgoingMessage|Message type" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "OutgoingMessage|Status" @@ -1616,6 +1634,12 @@ msgstr "Masyarakat" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "Orang{{start_count}} ke{{end_count}} dari{{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Foto Anda:" @@ -1631,6 +1655,9 @@ msgstr "Mainkan permainan kategorisasi permintaan!" msgid "Please" msgstr "Silakan" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Silakan<a href=\"{{url}}\">berhubungan</a> dengan kami sehingga kami dapat memperbaikinya." @@ -1846,6 +1873,12 @@ msgstr "ProfilePhoto|Data" msgid "ProfilePhoto|Draft" msgstr "ProfilePhoto|Draft" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Otoritas publik" @@ -1858,6 +1891,21 @@ msgstr "Ptoritas publik {{start_count}} ke{{end_count}} dari {{total_count}}" msgid "Public authority – {{name}}" msgstr "Otoritas publik - {{name}}" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "Badan publik" @@ -1885,6 +1933,15 @@ msgstr "PublicBody|Home page" msgid "PublicBody|Info requests count" msgstr "PublicBody | Info requests count" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "PublicBody|Last edit comment" @@ -1998,6 +2055,12 @@ msgstr "Diminta dari {{public_body_name}} oleh {{info_request_user}} pada {{date msgid "Requested on {{date}}" msgstr "Diminta pada {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "Permintaan informasi pribadi dan permintaan tidak sopan dianggap tidak sah untuk tujuan KIP (<a href=\"/help/about\">selengkapnya</a>)." @@ -2324,15 +2387,24 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "Otoritas hendak /sudah <strong>merespon lewat pos</strong> terhadap permintaan ini." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" "Email yang Anda, atas nama {{public_body}}, dikirimkan kepada\n" "{{user}} untuk membalas kepada{{law_used_short}}\n" "permintaan belum terkirim." +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "Halaman ini tidak ada. Hal-hal yang sekarang bisa Anda coba:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "Otoritas publik tidak memiliki informasi yang diminta" @@ -2484,12 +2556,18 @@ msgstr "Ada <strong>kesalahan pengiriman</strong> atau yang serupa, yang perlu d msgid "There was an error with the words you entered, please try again." msgstr "Ada kesalahan pada kata-kata yang Anda masukkan, silakan coba lagi." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "Tidak ada permintaan yang cocok dengan pertanyaan Anda." msgid "There were no results matching your query." msgstr "Tidak ada hasil yang cocok dengan pertanyaan Anda." +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "Mereka akan membalas <strong>lewat pos</strong>" @@ -2516,11 +2594,6 @@ msgstr "Hal yang Anda ikuti" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Otoritas ini tidak lagi ada, sehingga Anda tidak dapat membuat permintaan kepadanya." -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" -"Komentar ini sudah disembunyikan. Lihat anotasi untuk\n" -" mengetahui kenapa. Jika Anda adalah sang pemohon, maka Anda dapat <a href=\"{{url}}\">masuk</a> untuk menampilkan respon tersebut." - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" "Hal ini mencakup spektrum informasi yang sangat luas tentang keadaan dari\n" @@ -2546,10 +2619,26 @@ msgstr "Ini merupakan versi pertama" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Ini adalah permintaan Anda sendiri, sehingga Anda akan secara otomatis dikirimi email ketika respon baru diterima." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" -"Pesan keluar ini telah disembunyikan. Lihat anotasi untuk\n" -"\t\t\t\t\t\tmengetahui kenapa. Jika Anda adalah sang pemohon, maka Anda dapat <a href=\"{{url}}\">masuk</a> untuk menampilkan respon tersebut." msgid "This particular request is finished:" msgstr "Peemintaan khusus ini telah selesai:" @@ -2622,11 +2711,6 @@ msgstr "Permintaan ini membutuhkan perhatian administrator" msgid "This request was not made via {{site_name}}" msgstr "Permintaan ini tidak dibuat melalui {{site_name}}" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" -"Respon ini telah disembunyikan. Lihat anotasi untuk mengetahui kenapa.\n" -" Jika Anda adalah sang pemohon, maka Anda dapat <a href=\"{{url}}\">masuk</a> untuk melihat respon tersebut." - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" "Tabel ini menunjukkan rincian teknis peristiwa internal yang terjadi\n" @@ -3533,9 +3617,6 @@ msgstr "untuk mengirimkan pesan tindak lanjut." msgid "to {{public_body}}" msgstr "kepada {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "menonjol tidak terduga pada peristiwa permintaan" - msgid "unknown reason " msgstr "alasan tidak diketahui " diff --git a/locale/it/app.po b/locale/it/app.po index fcde9a791..c65e7c819 100644 --- a/locale/it/app.po +++ b/locale/it/app.po @@ -9,9 +9,9 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-09-19 04:45+0000\n" -"Last-Translator: marcogiustini <info@marcogiustini.info>\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" +"Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Italian (http://www.transifex.com/projects/p/alaveteli/language/it/)\n" "Language: it\n" "MIME-Version: 1.0\n" @@ -1004,6 +1004,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "" +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "" @@ -1073,6 +1076,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "" @@ -1106,9 +1115,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1271,6 +1277,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "" @@ -1388,6 +1397,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "" @@ -1451,6 +1463,12 @@ msgstr "" msgid "OutgoingMessage|Message type" msgstr "" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "" @@ -1478,6 +1496,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "La tua foto:" @@ -1493,6 +1517,9 @@ msgstr "" msgid "Please" msgstr "" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "" @@ -1697,6 +1724,12 @@ msgstr "" msgid "ProfilePhoto|Draft" msgstr "" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Guarda e cerca autorità pubbliche" @@ -1709,6 +1742,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1736,6 +1784,15 @@ msgstr "" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "" @@ -1847,6 +1904,12 @@ msgstr "" msgid "Requested on {{date}}" msgstr "" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2155,12 +2218,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "" +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "" @@ -2304,12 +2376,18 @@ msgstr "" msgid "There was an error with the words you entered, please try again." msgstr "" +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "" msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "" @@ -2334,9 +2412,6 @@ msgstr "Cose che stai seguendo" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "" -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2358,7 +2433,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "" -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2428,9 +2521,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3271,9 +3361,6 @@ msgstr "" msgid "to {{public_body}}" msgstr "" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "" diff --git a/locale/model_attributes.rb b/locale/model_attributes.rb index ba3a60c90..9f7da5e62 100644 --- a/locale/model_attributes.rb +++ b/locale/model_attributes.rb @@ -35,6 +35,8 @@ _('IncomingMessage|Cached main body text unfolded') _('IncomingMessage|Last parsed') _('IncomingMessage|Mail from') _('IncomingMessage|Mail from domain') +_('IncomingMessage|Prominence') +_('IncomingMessage|Prominence reason') _('IncomingMessage|Sent at') _('IncomingMessage|Subject') _('IncomingMessage|Valid to reply to') @@ -58,7 +60,6 @@ _('InfoRequestEvent|Described state') _('InfoRequestEvent|Event type') _('InfoRequestEvent|Last described at') _('InfoRequestEvent|Params yaml') -_('InfoRequestEvent|Prominence') _('Mail server log') _('MailServerLog|Line') _('MailServerLog|Order') @@ -69,6 +70,8 @@ _('Outgoing message') _('OutgoingMessage|Body') _('OutgoingMessage|Last sent at') _('OutgoingMessage|Message type') +_('OutgoingMessage|Prominence') +_('OutgoingMessage|Prominence reason') _('OutgoingMessage|Status') _('OutgoingMessage|What doing') _('Post redirect') @@ -87,6 +90,9 @@ _('PublicBody|Disclosure log') _('PublicBody|First letter') _('PublicBody|Home page') _('PublicBody|Info requests count') +_('PublicBody|Info requests not held count') +_('PublicBody|Info requests overdue count') +_('PublicBody|Info requests successful count') _('PublicBody|Last edit comment') _('PublicBody|Last edit editor') _('PublicBody|Name') diff --git a/locale/nb_NO/app.po b/locale/nb_NO/app.po index 9e75a34d1..570290c95 100644 --- a/locale/nb_NO/app.po +++ b/locale/nb_NO/app.po @@ -4,13 +4,14 @@ # # Translators: # pere <pere-transifex@hungry.com>, 2013 +# pere <pere-transifex@hungry.com>, 2013 msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-09-04 11:52+0000\n" -"Last-Translator: pere <pere-transifex@hungry.com>\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" +"Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.com/projects/p/alaveteli/language/nb_NO/)\n" "Language: nb_NO\n" "MIME-Version: 1.0\n" @@ -1006,6 +1007,9 @@ msgstr "Du har rett til å klage, om du ikke er fornøyd med svaret du fikk fra\ msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Hvis du fortsatt ar problemer, vær så snill å <a href=\"{{url}}\">kontakt oss</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "" @@ -1075,6 +1079,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "" @@ -1108,9 +1118,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1273,6 +1280,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Melding sendt ved hjelp av kontaktskjema for {{site_name}}," @@ -1390,6 +1400,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "" @@ -1453,6 +1466,12 @@ msgstr "" msgid "OutgoingMessage|Message type" msgstr "" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "" @@ -1480,6 +1499,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Foto av deg:" @@ -1495,6 +1520,9 @@ msgstr "" msgid "Please" msgstr "" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "" @@ -1699,6 +1727,12 @@ msgstr "" msgid "ProfilePhoto|Draft" msgstr "" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Offentlige myndigheter" @@ -1711,6 +1745,21 @@ msgstr "Offentlige myndigheter {{start_count}} til {{end_count}} av totalt {{tot msgid "Public authority – {{name}}" msgstr "Offentlig myndighet – {{name}}" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1738,6 +1787,15 @@ msgstr "" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "" @@ -1849,6 +1907,12 @@ msgstr "" msgid "Requested on {{date}}" msgstr "" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "Henvendelser om personlig informasjon og sjikanøse henvendelser er ikke tillatt (<a href=\"/help/about\">les mer</a>)." @@ -2157,12 +2221,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "" +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "Siden finnes ikke. Det du kan forsøke nå:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "" @@ -2306,12 +2379,18 @@ msgstr "" msgid "There was an error with the words you entered, please try again." msgstr "" +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "" msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "De kommer til å svare <stron>per brev</strong>" @@ -2336,9 +2415,6 @@ msgstr "Ting du følger" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Denne myndigheten er slettet, og kan ikke kontaktes." -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2360,7 +2436,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Dette er din egen forespørsel, så du vil automatisk få epost når nye svar ankommer." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2430,9 +2524,6 @@ msgstr "En administrator må se på denne henvendelsen" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3276,9 +3367,6 @@ msgstr "for å sende en oppfølgningsmelding." msgid "to {{public_body}}" msgstr "til {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "uventet primærfaktor på forespørselhendelse" - msgid "unknown reason " msgstr "ukjent grunn " diff --git a/locale/nl/app.po b/locale/nl/app.po index 2c211512e..3b8f8d10a 100644 --- a/locale/nl/app.po +++ b/locale/nl/app.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Dutch (http://www.transifex.com/projects/p/alaveteli/language/nl/)\n" "Language: nl\n" @@ -1001,6 +1001,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "" +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "" @@ -1070,6 +1073,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "" @@ -1103,9 +1112,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1268,6 +1274,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "" @@ -1385,6 +1394,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "" @@ -1448,6 +1460,12 @@ msgstr "" msgid "OutgoingMessage|Message type" msgstr "" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "" @@ -1475,6 +1493,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "" @@ -1490,6 +1514,9 @@ msgstr "" msgid "Please" msgstr "" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "" @@ -1694,6 +1721,12 @@ msgstr "" msgid "ProfilePhoto|Draft" msgstr "" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "" @@ -1706,6 +1739,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1733,6 +1781,15 @@ msgstr "" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "" @@ -1844,6 +1901,12 @@ msgstr "" msgid "Requested on {{date}}" msgstr "" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2152,12 +2215,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "" +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "" @@ -2301,12 +2373,18 @@ msgstr "" msgid "There was an error with the words you entered, please try again." msgstr "" +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "" msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "" @@ -2331,9 +2409,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "" -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2355,7 +2430,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "" -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2425,9 +2518,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3268,9 +3358,6 @@ msgstr "" msgid "to {{public_body}}" msgstr "" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "" diff --git a/locale/pl/app.po b/locale/pl/app.po index 5fd1de0ea..9efa0e398 100644 --- a/locale/pl/app.po +++ b/locale/pl/app.po @@ -4,13 +4,14 @@ # # Translators: # EwaModrzejewska <ewa.modrzejewska@art61.pl>, 2013 +# EwaModrzejewska <ewa.modrzejewska@art61.pl>, 2013 msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-21 12:25+0000\n" -"Last-Translator: EwaModrzejewska <ewa.modrzejewska@art61.pl>\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" +"Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Polish (http://www.transifex.com/projects/p/alaveteli/language/pl/)\n" "Language: pl\n" "MIME-Version: 1.0\n" @@ -1002,6 +1003,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "" +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "" @@ -1071,6 +1075,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "" @@ -1104,9 +1114,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1269,6 +1276,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "" @@ -1386,6 +1396,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "" @@ -1449,6 +1462,12 @@ msgstr "" msgid "OutgoingMessage|Message type" msgstr "" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "" @@ -1476,6 +1495,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "" @@ -1491,6 +1516,9 @@ msgstr "" msgid "Please" msgstr "" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "" @@ -1695,6 +1723,12 @@ msgstr "" msgid "ProfilePhoto|Draft" msgstr "" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "" @@ -1707,6 +1741,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1734,6 +1783,15 @@ msgstr "" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "" @@ -1845,6 +1903,12 @@ msgstr "" msgid "Requested on {{date}}" msgstr "" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2154,12 +2218,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "" +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "" @@ -2304,12 +2377,18 @@ msgstr "" msgid "There was an error with the words you entered, please try again." msgstr "" +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "" msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "" @@ -2334,9 +2413,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "" -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2358,7 +2434,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "" -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2430,9 +2524,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3275,9 +3366,6 @@ msgstr "" msgid "to {{public_body}}" msgstr "" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "" diff --git a/locale/pt_BR/app.po b/locale/pt_BR/app.po index 6b040cef5..6545b7edb 100644 --- a/locale/pt_BR/app.po +++ b/locale/pt_BR/app.po @@ -42,8 +42,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/alaveteli/language/pt_BR/)\n" "Language: pt_BR\n" @@ -1061,6 +1061,9 @@ msgstr "Se você estiver insatisfeito com a resposta que recebeu do órgão púb msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Se você continua com problemas, <a href=\"{{url}}\">entre em contato conosco</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Se você for o solicitante, então pode <a href=\"{{url}}\">entrar</a> para visualizar o pedido." @@ -1130,6 +1133,12 @@ msgstr "MensagemRecebida|Remetente" msgid "IncomingMessage|Mail from domain" msgstr "IncomingMessage | Mensagem do site" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "IncomingMessage | Enviado em" @@ -1163,9 +1172,6 @@ msgstr "InfoRequestEvent | Última descrição em" msgid "InfoRequestEvent|Params yaml" msgstr "InfoRequestEvent | Params yaml" -msgid "InfoRequestEvent|Prominence" -msgstr "InfoRequestEvent | Destaque" - msgid "InfoRequest|Allow new responses from" msgstr "InfoRequest | Permitir novas respostas de" @@ -1331,6 +1337,9 @@ msgstr "Vários pedidos" msgid "Message" msgstr "Mensagem" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Mensagem enviada por meio do formulário de contato do {{site_name}}," @@ -1448,6 +1457,9 @@ msgstr "Agora, visualize seu acompanhamento" msgid "Now preview your message asking for an internal review" msgstr "Agora, visualize sua mensagem pedindo por uma revisão interna" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "OU remova a foto atual" @@ -1511,6 +1523,12 @@ msgstr "OutgoingMessage | Última enviada em" msgid "OutgoingMessage|Message type" msgstr "OutgoingMessage | Tipo de mensagem" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "OutgoingMessage | Situação" @@ -1538,6 +1556,12 @@ msgstr "Pessoas" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "Pessoas {{start_count}} para {{end_count}} de {{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Sua foto:" @@ -1553,6 +1577,9 @@ msgstr "Adicione categorias ao seu pedido!" msgid "Please" msgstr "Por favor" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Por favor <a href=\"{{url}}\">entre em contato</a> conosco para consertarmos isso." @@ -1757,6 +1784,12 @@ msgstr "ProfilePhoto | Dados" msgid "ProfilePhoto|Draft" msgstr "ProfilePhoto | Rascunho" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Órgãos públicos" @@ -1769,6 +1802,21 @@ msgstr "Órgão público {{start_count}} para {{end_count}} de {{total_count}}" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "Órgão público" @@ -1796,6 +1844,15 @@ msgstr "PublicBody | Home page" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "PublicBody | Última edição" @@ -1907,6 +1964,12 @@ msgstr "Solicitadas {{public_body_name}} por {{info_request_user}} em {{data}}" msgid "Requested on {{date}}" msgstr "Solicitado em {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "Pedidos de informação pessoal ou constrangedora não são considerados válidos para os propósitos da Lei de Acesso à Informação (<a href=\"/help/about\">saiba mais</a>)." @@ -2217,12 +2280,21 @@ msgstr "A autoridade diz que eles <strong>precisam de um endereço postal</stron msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "A autoridade gostaria de responder/respondeu </strong>por correio</strong> esta requisição." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "O email que você, em nome de {{public_body}}, enviou para {{user}} para responder a um Pedido de Informação não foi entregue." +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "Esta página não existe. O que você pode tentar agora:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "A autoridade pública não tem a informação solicitada" @@ -2368,12 +2440,18 @@ msgstr "Ocorreu um <strong>erro no envio</strong> ou algo parecido, que precisa msgid "There was an error with the words you entered, please try again." msgstr "Houve um erro nas palavras que você inseriu, por favor tente novamente." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "Não há pedidos correspondentes à sua consulta." msgid "There were no results matching your query." msgstr "Não houve resultados para sua busca." +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "Eles vão responder através de um <strong>post</strong>" @@ -2400,9 +2478,6 @@ msgstr "O que você está seguindo" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Este órgão de governo não existe, portanto você não pode criar um pedido de informação para ele." -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Este comentário foi ocultado. Veja as anotações para descobrir o motivo. Se você é o solicitante, então pode <a href=\"{{url}}\">entrar</a> para visualizar a resposta." - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "Este pedido abrange um espectro muito amplo de informações sobre o estado do <strong>meio-ambiente, </strong> tais como:" @@ -2424,8 +2499,26 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Esse é o seu próprio pedido, então você vai receber um email automaticamente quando uma nova resposta chegar." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Esta mensagem foi ocultada. Veja as anotações para \\n\t\t\t\t\t\tdescobrir o porquê. Se você é o requerente, deve <a href=\"{{url}}\">logar</a> para visualizar a resposta." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" +msgstr "" msgid "This particular request is finished:" msgstr "Esse pedido foi finalizado:" @@ -2494,11 +2587,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "Este pedido não foi feito através de {{site_name}}" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" -"Essa resposta foi ocultada. Veja as anotações para descobrir por quê.\n" -" Se você for o solicitante, então pode <a href=\"{{url}}\">entrar</a> para visualizar a resposta." - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" "Esta tabela mostra detalhes técnicos dos eventos internos que\n" @@ -3353,9 +3441,6 @@ msgstr "enviar uma mensagem de acompanhamento." msgid "to {{public_body}}" msgstr "para {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "unexpected prominence on request event" - msgid "unknown reason " msgstr "razão desconhecida" diff --git a/locale/ro_RO/app.po b/locale/ro_RO/app.po index d553d3d36..a75e1c8ca 100644 --- a/locale/ro_RO/app.po +++ b/locale/ro_RO/app.po @@ -21,8 +21,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Romanian (Romania) (http://www.transifex.com/projects/p/alaveteli/language/ro_RO/)\n" "Language: ro_RO\n" @@ -1017,6 +1017,9 @@ msgstr "Dacă ești nemulțumit de răspunsul primit de la\\n instituția public msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Dacă aveţi în continuare probleme, vă rugăm <a href=\"{{url}}\"> să ne contactaţi</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Dacă sunteţi solicitantul, atunci trebuie să <a href=\"{{url}}\">vă logaţi</a> pentru a vedea cererea." @@ -1086,6 +1089,12 @@ msgstr "Mesaj primit |Mail de la " msgid "IncomingMessage|Mail from domain" msgstr "Mesaj primit |Mail de la domeniul " +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "Mesaj primit | Trimis la" @@ -1119,9 +1128,6 @@ msgstr "EvenimentCerereInfo | Ultima descriere la" msgid "InfoRequestEvent|Params yaml" msgstr "EvenimentCerereInfo | Parametri yaml" -msgid "InfoRequestEvent|Prominence" -msgstr "EvenimentCerereInfo | Proeminenţă" - msgid "InfoRequest|Allow new responses from" msgstr "CerereInfo | Permite noi răspunsuri de la" @@ -1284,6 +1290,9 @@ msgstr "Multe cereri" msgid "Message" msgstr "Mesaj" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Mesaj trimis utilizând formularul de contact al {{site_name}} " @@ -1401,6 +1410,9 @@ msgstr "Acum previzualizează follow up-ul tău" msgid "Now preview your message asking for an internal review" msgstr "Acum previzualizează mesajul tău cerând o revizuire internă." +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "SAU înlocuiţi poza existentă" @@ -1464,6 +1476,12 @@ msgstr "MesajTrimis|Ultimul trimis la" msgid "OutgoingMessage|Message type" msgstr "MesajTrimis|Tip mesaj" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "MesajTrimis|Status" @@ -1491,6 +1509,12 @@ msgstr "Persoane" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "Oameni de la {{start_count}} la {{end_count}} din {{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Poza ta:" @@ -1506,6 +1530,9 @@ msgstr "Jucaţi categorisirea cerută!" msgid "Please" msgstr "Vă rugăm" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Vă rugăm <a href=\"{{url}}\"> staţi în legătură</a> cu noi, ca să o rezolvăm." @@ -1710,6 +1737,12 @@ msgstr "Poza de profil|Data" msgid "ProfilePhoto|Draft" msgstr "Poza de profil|Ciornă" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Instituții publice" @@ -1722,6 +1755,21 @@ msgstr "Instituții publice de la {{start_count}} la {{end_count}} din {{total_c msgid "Public authority – {{name}}" msgstr "Autoritatea publică – {{name}}" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "Autoritate publică" @@ -1749,6 +1797,15 @@ msgstr "Instituţie publică|Pagina principală" msgid "PublicBody|Info requests count" msgstr "InstituţiePublică|Info număr de cereri " +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "Instituţie publică| Ultimul comentariu editat" @@ -1860,6 +1917,12 @@ msgstr "Cerere de la {{public_body_name}} de către {{info_request_user}} la {{d msgid "Requested on {{date}}" msgstr "Cerere la data {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "Solicitările de informații personale și solicitările ofensatoare nu sunt considerate valide pentru scopurile solicitărilor de acces la informații (<a href=\"/help/about\">citește mai multe</a>)." @@ -2169,12 +2232,21 @@ msgstr "Instituția <strong>solicită o adresă\\n poștală</strong>, pe lâng msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "Autoritatea ar <strong>vrea să răspundă / a răspuns prin postarea</strong> la această cerere." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "Email-ul trimis din partea {{public_body}}, către\\n{{user}} ca răspuns la {{law_used_short}}\\nsolicitare nu a fost transmis." +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "Pagina nu există. Ceea ce puteţi încerca acum:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "Autritatea publică nu deţine informaţiile solicitate" @@ -2319,12 +2391,18 @@ msgstr "A apărut o <strong>eroare de transmitere</strong> sau similară ce va msgid "There was an error with the words you entered, please try again." msgstr "Există o eroare printre cuvintele pe care le-aţi introdus, vă rugăm încercaţi din nou." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "Nu sunt cereri care se potrivesc cu interogarea ta." msgid "There were no results matching your query." msgstr "Nu sunt rezultate care satisfac interogarea ta." +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "Ei vor răspunde <strong>prin postarea </strong>" @@ -2349,9 +2427,6 @@ msgstr "Lucruri pe care le urmăriţi" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Această autoritate nu mai există, deci nu puteţi face o cerere către aceasta." -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Acest comentariu a fost ascuns. Vezi adnotaţiile pentru\\n a afla de ce. Dacă eşti solicitantul, atunci te poţi <a href=\"{{url}}\">autentifica</a> pentru a vedea răspunsul." - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "Aceasta acoperă un spectru foarte larg de informaţii despre stadiul\\n <strong>mediului natural şi construit</strong>, precum:" @@ -2373,8 +2448,26 @@ msgstr "Aceasta este prima versiune." msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Aceasta este solicitarea proprie, aşa că ți se va comunica automat prin email când va sosi un răspuns." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Acest mesaj în curs de expediere a fost ascuns. Vezi adnotaţiile pentru\\n»»»»»»a afla de ce. Dacă eşti solicitantul, atunci te poţi <a href=\"{{url}}\">autentifica</a> pentru a vedea răspunsul." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" +msgstr "" msgid "This particular request is finished:" msgstr "Acesată cerere anume este finalizată:" @@ -2445,9 +2538,6 @@ msgstr "Această solicitare are nevoie de intervenția administratorului" msgid "This request was not made via {{site_name}}" msgstr "Cererea nu a fost făcută prin {{site_name}}" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Acest răspuns a fost ascuns. Vezi adnotările pentru a afla de ce.\\n Dacă eşti solicitantul, atunci te poţi <a href=\"{{url}}\">autentifica</a> pentru a vedea răspunsul." - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "Acest tabel arată detaliile tehnice ale evenimentelor interne care au avut loc\\n cu această solicitare pe {{site_name}}. Acesta poate fi utilizat pentru a genera informaţii cu privire la\\nviteza cu care autorităţile răspund la solicitări, la numărul de solicitări\\ncare au nevoie de un răspuns scris şi multe altele." @@ -3290,9 +3380,6 @@ msgstr "a transmite un mesaj de urmărire" msgid "to {{public_body}}" msgstr "către {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "proeminenţă neaşteptată la un eveniment cerere" - msgid "unknown reason " msgstr "motiv necunoscut" diff --git a/locale/sl/app.po b/locale/sl/app.po index 4b16e7f88..5401d9e55 100644 --- a/locale/sl/app.po +++ b/locale/sl/app.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:09+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Slovenian (http://www.transifex.com/projects/p/alaveteli/language/sl/)\n" "Language: sl\n" @@ -1004,6 +1004,9 @@ msgstr "Če niste zadovoljni z odgovorom, ki ste ga prejeli od organa, se imate msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Če imate še vedno težave, nas prosimo <a href=\"{{url}}\">kontaktirajte</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Če ste vi prosilec, potem se lahko <a href=\"{{url}}\">prijavite</a>, da si ogledate zahtevek." @@ -1073,6 +1076,12 @@ msgstr "PrihajajoceSporocilo|Pošiljatelj" msgid "IncomingMessage|Mail from domain" msgstr "PrihajajoceSporocilo|Domena pošiljatelja" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "PrihajajoceSporocilo|Poslano ob" @@ -1106,9 +1115,6 @@ msgstr "InfoZahtevekDogodek|Zadnje opisano ob" msgid "InfoRequestEvent|Params yaml" msgstr "InfoZahtevekDogodek|Parametri" -msgid "InfoRequestEvent|Prominence" -msgstr "InfoZahtevekDogodek|Prominenca" - msgid "InfoRequest|Allow new responses from" msgstr "InfoZahtevek|Dovoli nove odzive od" @@ -1271,6 +1277,9 @@ msgstr "Veliko zahtevkov" msgid "Message" msgstr "Sporočilo" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Sporočilo je bilo poslano z uporabo obrazca na {{site_name}}," @@ -1388,6 +1397,9 @@ msgstr "Preglejte vaš odziv" msgid "Now preview your message asking for an internal review" msgstr "Preglejte vaš zahtevek za interno revizijo" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "ALI odstranite trenutno fotografijo" @@ -1451,6 +1463,12 @@ msgstr "IzhodnoSporočilo|Zadnje poslano ob" msgid "OutgoingMessage|Message type" msgstr "IzhodnoSporočilo|Tip sporočila" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "IzhodnoSporočilo|Status" @@ -1478,6 +1496,12 @@ msgstr "Ljudje" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "Ljudje od {{start_count}} do {{end_count}} od skupno {{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Vaša slika:" @@ -1493,6 +1517,9 @@ msgstr "Igrajte igro kategorizacije zahtevkov!" msgid "Please" msgstr "Prosimo" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Prosimo, <a href=\"{{url}}\">stopite v kontakt z nami</a>, da lahko zadevo popravimo." @@ -1697,6 +1724,12 @@ msgstr "ProfilnaSlika|Podatki" msgid "ProfilePhoto|Draft" msgstr "ProfilnaSlika|Osnutek" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Javni organi" @@ -1709,6 +1742,21 @@ msgstr "Javni organi od {{start_count}} do {{end_count}} od skupno {{total_count msgid "Public authority – {{name}}" msgstr "Javni organ - {{name}}" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "Javni organ" @@ -1736,6 +1784,15 @@ msgstr "JavniOrgan|Domača stran" msgid "PublicBody|Info requests count" msgstr "PublicBody|Število zahtevkov IJZ" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "JavniOrgan|Zadnji urejani komentar" @@ -1847,6 +1904,12 @@ msgstr "Zahtevano od {{public_body_name}} s strani uporabnika {{info_request_use msgid "Requested on {{date}}" msgstr "Zahtevano dne {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "Zahtevki za osebne podatke in provokativni zahtevki se ne smatrajo za veljavne zahtevke za IJZ (<a href=\"/help/about\">preberite več</a>)." @@ -2157,12 +2220,21 @@ msgstr "Organ pravi, da potrebuje poštni naslov, ne zgolj e-pošte, da gre za v msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "Organ bi želel oziroma je na ta zahtevek <strong>odgovoril preko pošte</strong>." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "E-pošta, ki ste jo v imenu {{public_body}} poslali {{user}} \\nkot odgovor na zahtevek za {{law_used_short}} ni bila dostavljena." +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "Stran ne obstaja. Kaj lahko storite:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "Organ nima zahtevanih informacij" @@ -2308,12 +2380,18 @@ msgstr "Prišlo je do <strong>napake pri pošiljanju</strong> ali druge napake, msgid "There was an error with the words you entered, please try again." msgstr "Pri vnešenem besedilu je prišlo do napake, prosimo poskusite ponovno." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "Poizvedbi ne ustreza noben zahtevek." msgid "There were no results matching your query." msgstr "Vaša poizvedba ni vrnila rezultatov." +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "Odgovorili bodo <strong>po pošti</strong>" @@ -2338,9 +2416,6 @@ msgstr "Stvari, ki jim sledite" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Ta organ ne obstaja več, zato mu ne morete več posredovati zahtevkov" -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Ta komentar je bil skrit. Poglejte zaznamke, da bi videli čemu. Če ste prosilec vi, se lahko <a href=\"{{url}}\">prijavite</a>, da vidite odgovor." - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "To pokriva zelo širok spekter informacij o stanju <strong>narave in okolja</strong>, na primer:" @@ -2362,8 +2437,26 @@ msgstr "To je prva različica." msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "To je vaš zahtevek, zato boste ob spremembah obveščeni po e-pošti" -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "To odhodno sporočilo je bilo skrito. Poglejte zaznamke, da bi videli čemu. Če ste prosilec vi, se lahko <a href=\"{{url}}\">prijavite</a> in vidite odgovor." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" +msgstr "" msgid "This particular request is finished:" msgstr "Ta zahtevek je končan:" @@ -2436,9 +2529,6 @@ msgstr "Ta zahtevek zahteva pozornost administratorja" msgid "This request was not made via {{site_name}}" msgstr "Ta zahtevek ni bil narejen z uporabo {{site_name}}" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Ta odgovor je bil skrit. Poglejte zaznamke, da bi videli čemu. Če ste prosilec vi, potem se lahko <a href=\"{{url}}\">prijavite</a> in vidite odgovor." - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "Ta tabela prikazuje tehnične podrobnosti internih dogodkov, ki so se dogajali na tem zahtevku na {{site_name}}. To lahko uporabite, da zgenerirate informacije o odzivnosti oz. hitrosti, s katero organi odgovarjajo na zahteve, število zahtev ki zahtevajo poštno pošiljanje in še mnogo več." @@ -3283,9 +3373,6 @@ msgstr "da pošljete odziv" msgid "to {{public_body}}" msgstr "za {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "nepričakovana pozornost za zahtevek" - msgid "unknown reason " msgstr "neznan razlog" diff --git a/locale/sq/app.po b/locale/sq/app.po index 9f54c3208..71cad4874 100644 --- a/locale/sq/app.po +++ b/locale/sq/app.po @@ -17,8 +17,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Albanian (http://www.transifex.com/projects/p/alaveteli/language/sq/)\n" "Language: sq\n" @@ -1088,6 +1088,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Nëse ende po ka probleme, të lutem <a href=\"{{url}}\">na kontakto</a> ." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Nëse ti je kërkuesi, atëherë ti mund të <a href=\"{{url}}\">kyçesh</a> për të parë kërkesën." @@ -1161,6 +1164,12 @@ msgstr "IncomingMessage|Email prej" msgid "IncomingMessage|Mail from domain" msgstr "IncomingMessage | Email prej domain-it" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "IncomingMessage | Dërguar më" @@ -1194,9 +1203,6 @@ msgstr "InfoRequestEvent|Last described at" msgid "InfoRequestEvent|Params yaml" msgstr "InfoRequestEvent|Params yaml" -msgid "InfoRequestEvent|Prominence" -msgstr "InfoRequestEvent|Prominence" - msgid "InfoRequest|Allow new responses from" msgstr "InfoRequest|Lejo përgjigje të reja prej" @@ -1363,6 +1369,9 @@ msgstr "Shumë kërkesa" msgid "Message" msgstr "Porosia" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Mesazhi i dërguar duke përdorur kontakt formën e {{site_name}}, " @@ -1480,6 +1489,9 @@ msgstr "Shiko vazhdimësinë e komunikimit" msgid "Now preview your message asking for an internal review" msgstr "Shiko mesazhin tënd ku ke kërkuar rishqyrtim intern" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "Ose hiqni fotografinë ekzistuese" @@ -1543,6 +1555,12 @@ msgstr "OutgoingMessage | Së fundi është dërguar në" msgid "OutgoingMessage|Message type" msgstr "OutgoingMessage|Message type" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "OutgoingMessage|Status" @@ -1570,6 +1588,12 @@ msgstr "Njerëzit" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "Personat {{start_count}} deri {{end_count}} prej {{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Fotografia yte:" @@ -1585,6 +1609,9 @@ msgstr "Luaj lojën e kategorizimit të kërkesave!" msgid "Please" msgstr "Të lutem" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Të lutem <a href=\"{{url}}\">na kontakto</a> që neve ta rregullojme ate." @@ -1798,6 +1825,12 @@ msgstr "ProfilePhoto|Data" msgid "ProfilePhoto|Draft" msgstr "ProfilePhoto|Draft" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Autoritetet publike" @@ -1810,6 +1843,21 @@ msgstr "Autoritetet publike {{start_count}} deri {{end_count}} prej {{total_coun msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "Institucion publik" @@ -1837,6 +1885,15 @@ msgstr "PublicBody |Ballina" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "PublicBody | Editimi i fundit i komentit" @@ -1950,6 +2007,12 @@ msgstr "Kërkuar nga {{public_body_name}} nga {{info_request_user}} me {{date}}" msgid "Requested on {{date}}" msgstr "Kërkuar me {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2267,12 +2330,21 @@ msgstr "Autoriteti thotë se ata kanë <strong>nevojë për një adresë postare msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "Autoriteti do të / është <strong>përgjigjur me postë</strong> në këtë kërkesë." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "Emaili që ju, në emër të {{public_body}}, keni dërguar te {{user}} për t'iu përgjigjur një kërkese nuk është dorëzuar." +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "Faqja nuk ekziston. Gjërat që ti mund ti provosh:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "Autoriteti publik nuk i ka informatat e kërkuara" @@ -2422,12 +2494,18 @@ msgstr "Kishte një <strong>dështim gjatë dorëzimit.</strong> apo diç e ngja msgid "There was an error with the words you entered, please try again." msgstr "Kishte një gabim me fjalët që keni shtypur, të lutem provo përsëri." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "Nuk ka kërkesa që përputhen me kërkimin tënd." msgid "There were no results matching your query." msgstr "Nuk ka kërkesa që përputhen me kërkimin tënd." +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "Ata do të përgjigjen <strong>me postë</strong>" @@ -2452,9 +2530,6 @@ msgstr "Gjërat që po i ndiqni" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Ky autoritet nuk ekziston më, kështu që ju nuk mund të bëni një kërkesë për të." -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Ky koment është fshehur. Shih shënimet për të gjetur pse. Nëse ti je kërkuesi, atëherë ti mund të <a href=\"{{url}}\">kyçesh </a> për të parë përgjigjen." - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2476,10 +2551,26 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Kjo është kërkesa yte, kështu që ti do të merr email automatikisht kur përgjigjet e reja arrijnë." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" -"Mesazhi në largim është fshehur. Shih shënimet në \n" -" »» »» »» për të kuptuar arsyen. Nëse ti je kërkuesi, atëherë ti mund të <a href=\"{{url}}\">kyçesh</a> për të parë përgjigjen." msgid "This particular request is finished:" msgstr "Kjo kërkesë është përmbyllur:" @@ -2550,9 +2641,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "Kjo kërkesë nuk është bërë nëpërmjet {{site_name}}" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Kjo përgjigje është fshehur. Shih shënimet për të kuptuar pse. Nëse ti je kërkuesi, atëherë ti mund të <a href=\"{{url}}\">kyçesh</a> për të parë përgjigjen." - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" "Kjo tabelë paraqet detajet teknike rreth ndodhive të\n" @@ -3440,9 +3528,6 @@ msgstr "për të dërguar një mesazh përcjellës." msgid "to {{public_body}}" msgstr "për {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "rëndësi (prominence) e papritur për kërkesën" - msgid "unknown reason " msgstr "arsye e panjohur " diff --git a/locale/sr@latin/app.po b/locale/sr@latin/app.po index ce5e2a979..4560bc482 100644 --- a/locale/sr@latin/app.po +++ b/locale/sr@latin/app.po @@ -12,8 +12,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Serbian (Latin) (http://www.transifex.com/projects/p/alaveteli/language/sr@latin/)\n" "Language: sr@latin\n" @@ -1070,6 +1070,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Ako i dalje imate problema, molimo <a href=\"{{url}}\">kontaktirajte nas</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Ako ste podnosioc zahteva, možete se <a href=\"{{url}}\">prijaviti</a> da biste pogledali zahtev." @@ -1154,6 +1157,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "Nadolazeća poruka|Pošta sa domene" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "Nadolazeća poruka|Poslana u" @@ -1187,9 +1196,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1363,6 +1369,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Poruka poslana koristeći {{site_name}} formular za kontakt, " @@ -1480,6 +1489,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "Sada pregledajte Vašu poruku u kojoj tražite urgenciju " +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "ILI odstrani postojeću sliku" @@ -1543,6 +1555,12 @@ msgstr "Odlazeća poruka|Zadnja poslana u" msgid "OutgoingMessage|Message type" msgstr "Odlazeća poruka|Tip poruke" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "Odlazeća poruka|Status" @@ -1570,6 +1588,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Vaša slika:" @@ -1585,6 +1609,9 @@ msgstr "Igrajte igru kategorizacije zahteva!" msgid "Please" msgstr "Molimo" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Molimo <a href=\"{{url}}\">kontaktirajte</a> nas kako bi to mogli popraviti." @@ -1800,6 +1827,12 @@ msgstr "Slika na profilu|Podaci" msgid "ProfilePhoto|Draft" msgstr "Slika na profilu|Skica" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Javne ustanove" @@ -1812,6 +1845,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1839,6 +1887,15 @@ msgstr "Javno tijelo|Home page" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "Javno tijelo|Zadnji uređeni komentar" @@ -1952,6 +2009,12 @@ msgstr "Traženo od {{public_body_name}} od strane {{info_request_user}} na datu msgid "Requested on {{date}}" msgstr "Traženo na datum {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2280,12 +2343,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "Ustanova bi željela / je <strong>odgovorila poštom</strong> na ovaj zahtev." +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "Stranica ne postoji. Stvari koje možete probati sada:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "Javna ustanova ne posjeduje tražene informacije" @@ -2439,12 +2511,18 @@ msgstr "Došlo je do <strong>greške u isporuci</strong> ili nečega sličnog š msgid "There was an error with the words you entered, please try again." msgstr "Postoji greška u rečima koje ste ukucali, molimo pokušajte ponovo." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "Nema zahteva koji odgovaraju Vašoj pretrazi." msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "Odgovoriti će <strong>poštom</strong>" @@ -2471,9 +2549,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Ova ustanova više ne postoji, zato joj nije moguće podnijeti zahtev. " -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2497,7 +2572,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Ovo je Vaš zahtev, biti ćete automatski obavešteni e-mailom kada novi odgovori budu stizali." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2575,9 +2668,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3460,9 +3550,6 @@ msgstr "poslati prateću poruku." msgid "to {{public_body}}" msgstr "za {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "nepoznat razlog " diff --git a/locale/sv/app.po b/locale/sv/app.po index ef8b82b38..15eb35a7e 100644 --- a/locale/sv/app.po +++ b/locale/sv/app.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-07 18:41+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Swedish (http://www.transifex.com/projects/p/alaveteli/language/sv/)\n" "Language: sv\n" @@ -1000,6 +1000,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "" +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "" @@ -1069,6 +1072,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "" @@ -1102,9 +1111,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1267,6 +1273,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "" @@ -1384,6 +1393,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "" @@ -1447,6 +1459,12 @@ msgstr "" msgid "OutgoingMessage|Message type" msgstr "" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "" @@ -1474,6 +1492,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "" @@ -1489,6 +1513,9 @@ msgstr "" msgid "Please" msgstr "" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "" @@ -1693,6 +1720,12 @@ msgstr "" msgid "ProfilePhoto|Draft" msgstr "" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "" @@ -1705,6 +1738,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1732,6 +1780,15 @@ msgstr "" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "" @@ -1843,6 +1900,12 @@ msgstr "" msgid "Requested on {{date}}" msgstr "" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2151,12 +2214,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "" +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "" @@ -2300,12 +2372,18 @@ msgstr "" msgid "There was an error with the words you entered, please try again." msgstr "" +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "" msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "" @@ -2330,9 +2408,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "" -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2354,7 +2429,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "" -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2424,9 +2517,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3267,9 +3357,6 @@ msgstr "" msgid "to {{public_body}}" msgstr "" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "" diff --git a/locale/tr/app.po b/locale/tr/app.po index 173a51745..1d6cb9d33 100644 --- a/locale/tr/app.po +++ b/locale/tr/app.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Turkish (http://www.transifex.com/projects/p/alaveteli/language/tr/)\n" "Language: tr\n" @@ -1002,6 +1002,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "" +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "" @@ -1071,6 +1074,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "" @@ -1104,9 +1113,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1269,6 +1275,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "" @@ -1386,6 +1395,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "" @@ -1449,6 +1461,12 @@ msgstr "" msgid "OutgoingMessage|Message type" msgstr "" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "" @@ -1476,6 +1494,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "" @@ -1491,6 +1515,9 @@ msgstr "" msgid "Please" msgstr "" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "" @@ -1695,6 +1722,12 @@ msgstr "" msgid "ProfilePhoto|Draft" msgstr "" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "" @@ -1707,6 +1740,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1734,6 +1782,15 @@ msgstr "" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "" @@ -1845,6 +1902,12 @@ msgstr "" msgid "Requested on {{date}}" msgstr "" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2153,12 +2216,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "" +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "" @@ -2302,12 +2374,18 @@ msgstr "" msgid "There was an error with the words you entered, please try again." msgstr "" +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "" msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "" @@ -2332,9 +2410,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "" -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2356,7 +2431,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "" -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2426,9 +2519,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3269,9 +3359,6 @@ msgstr "" msgid "to {{public_body}}" msgstr "" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "" diff --git a/locale/uk/app.po b/locale/uk/app.po index cff61afbf..52c85a9c0 100644 --- a/locale/uk/app.po +++ b/locale/uk/app.po @@ -14,8 +14,8 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-08-05 16:04+0000\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" "Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Ukrainian (http://www.transifex.com/projects/p/alaveteli/language/uk/)\n" "Language: uk\n" @@ -1091,6 +1091,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "Якщо у вас все ще виникають проблеми, <a href=\"{{url}}\">зверніться до нас</a>." +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "Якщо ви автор запиту, ви можете <a href=\"{{url}}\">увійти</a>, щоб його переглянути." @@ -1172,6 +1175,12 @@ msgstr "IncomingMessage|Mail from" msgid "IncomingMessage|Mail from domain" msgstr "IncomingMessage|Mail from domain" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "IncomingMessage|Sent at" @@ -1205,9 +1214,6 @@ msgstr "InfoRequestEvent|Last described at" msgid "InfoRequestEvent|Params yaml" msgstr "InfoRequestEvent|Params yaml" -msgid "InfoRequestEvent|Prominence" -msgstr "InfoRequestEvent|Prominence" - msgid "InfoRequest|Allow new responses from" msgstr "InfoRequest|Allow new responses from" @@ -1379,6 +1385,9 @@ msgstr "" msgid "Message" msgstr "Повідомлення" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "Повідомлення надіслане з використанням форми на сайті {{site_name}}, " @@ -1496,6 +1505,9 @@ msgstr "Попередній перегляд" msgid "Now preview your message asking for an internal review" msgstr "Попередній перегляд" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "АБО видалити існуюче фото" @@ -1559,6 +1571,12 @@ msgstr "" msgid "OutgoingMessage|Message type" msgstr "" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "" @@ -1586,6 +1604,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "Люди починаючи з {{start_count}} до {{end_count}} з {{total_count}}" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "Оберіть фото:" @@ -1601,6 +1625,9 @@ msgstr "" msgid "Please" msgstr "Будь ласка" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "Будь ласа, <a href=\"{{url}}\">дайте нам знати</a>, щоб ми могли це виправити." @@ -1808,6 +1835,12 @@ msgstr "" msgid "ProfilePhoto|Draft" msgstr "" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "Розпорядники інформації" @@ -1820,6 +1853,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "Розпорядник інформації – {{name}}" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1847,6 +1895,15 @@ msgstr "" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "" @@ -1960,6 +2017,12 @@ msgstr "" msgid "Requested on {{date}}" msgstr "Дата запиту: {{date}}" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "Запити про особисту інформацію або беззмістовні запити відповідають принципам цього сайту (<a href=\"/help/about\">читати більше</a>)" @@ -2269,12 +2332,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "" +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "Такої сторінки не існує. Ось що ви можете зробити зараз:" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "Розпорядник інформації не володіє запитаною інформацією" @@ -2421,12 +2493,18 @@ msgstr "Зафіксовано <strong>помилку доставки</strong> msgid "There was an error with the words you entered, please try again." msgstr "Ви ввели слова неправильно, спробуйте ще раз." +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "Нічого не знайдено." msgid "There were no results matching your query." msgstr "Нічого не знайдено." +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "Вони збираються відповісти поштою." @@ -2451,9 +2529,6 @@ msgstr "Відслідковуване вами" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "Цього органу більше не існує, тож ви не можете зробити запит." -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "Цей коментар було приховано. Якщо ви автор запиту, ви можете <a href=\"{{url}}\">sign in</a>,щоб переглянути відповідь." - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" "This covers a very wide spectrum of information about the state of\n" @@ -2477,7 +2552,25 @@ msgstr "Це перша версія." msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "Це ваш власний запит, тому вас буде автоматично повідомлено, коли прибуде відповідь." -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2551,11 +2644,6 @@ msgstr "Цей запит вимагає уваги адміністратора msgid "This request was not made via {{site_name}}" msgstr "Цей запит не було зроблено через сайт {{site_name}}" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" -"Цю відповідь було приховано. Ознайомтесь з коментарями, щоб з’ясувати, чому це сталось.\n" -" Якщо ви автор запиту, <a href=\"{{url}}\">увійдіть в систему</a>, щоб переглянути відповідь." - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3432,9 +3520,6 @@ msgstr "відправити уточнення." msgid "to {{public_body}}" msgstr "до {{public_body}}" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "невідома причина" diff --git a/locale/vi/app.po b/locale/vi/app.po index 0ef0e6c1c..28bc581bd 100644 --- a/locale/vi/app.po +++ b/locale/vi/app.po @@ -10,9 +10,9 @@ msgid "" msgstr "" "Project-Id-Version: alaveteli\n" "Report-Msgid-Bugs-To: http://github.com/sebbacon/alaveteli/issues\n" -"POT-Creation-Date: 2013-08-05 17:01+0100\n" -"PO-Revision-Date: 2013-09-18 05:43+0000\n" -"Last-Translator: ppanhh <ppanhh@gmail.com>\n" +"POT-Creation-Date: 2013-09-19 10:47+0100\n" +"PO-Revision-Date: 2013-09-19 09:50+0000\n" +"Last-Translator: louisecrow <louise@mysociety.org>\n" "Language-Team: Vietnamese (http://www.transifex.com/projects/p/alaveteli/language/vi/)\n" "Language: vi\n" "MIME-Version: 1.0\n" @@ -1002,6 +1002,9 @@ msgstr "" msgid "If you are still having trouble, please <a href=\"{{url}}\">contact us</a>." msgstr "" +msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the message." +msgstr "" + msgid "If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the request." msgstr "" @@ -1071,6 +1074,12 @@ msgstr "" msgid "IncomingMessage|Mail from domain" msgstr "" +msgid "IncomingMessage|Prominence" +msgstr "" + +msgid "IncomingMessage|Prominence reason" +msgstr "" + msgid "IncomingMessage|Sent at" msgstr "" @@ -1104,9 +1113,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -msgid "InfoRequestEvent|Prominence" -msgstr "" - msgid "InfoRequest|Allow new responses from" msgstr "" @@ -1269,6 +1275,9 @@ msgstr "" msgid "Message" msgstr "" +msgid "Message has been removed" +msgstr "" + msgid "Message sent using {{site_name}} contact form, " msgstr "" @@ -1386,6 +1395,9 @@ msgstr "" msgid "Now preview your message asking for an internal review" msgstr "" +msgid "Number of requests" +msgstr "" + msgid "OR remove the existing photo" msgstr "" @@ -1449,6 +1461,12 @@ msgstr "" msgid "OutgoingMessage|Message type" msgstr "" +msgid "OutgoingMessage|Prominence" +msgstr "" + +msgid "OutgoingMessage|Prominence reason" +msgstr "" + msgid "OutgoingMessage|Status" msgstr "" @@ -1476,6 +1494,12 @@ msgstr "" msgid "People {{start_count}} to {{end_count}} of {{total_count}}" msgstr "" +msgid "Percentage of requests that are overdue" +msgstr "" + +msgid "Percentage of total requests" +msgstr "" + msgid "Photo of you:" msgstr "" @@ -1491,6 +1515,9 @@ msgstr "" msgid "Please" msgstr "" +msgid "Please <a href=\"{{url}}\">contact us</a> if you have any questions." +msgstr "" + msgid "Please <a href=\"{{url}}\">get in touch</a> with us so we can fix it." msgstr "" @@ -1695,6 +1722,12 @@ msgstr "" msgid "ProfilePhoto|Draft" msgstr "" +msgid "Public Bodies" +msgstr "" + +msgid "Public Body Statistics" +msgstr "" + msgid "Public authorities" msgstr "" @@ -1707,6 +1740,21 @@ msgstr "" msgid "Public authority – {{name}}" msgstr "" +msgid "Public bodies that most frequently replied with \"Not Held\"" +msgstr "" + +msgid "Public bodies with most overdue requests" +msgstr "" + +msgid "Public bodies with the fewest successful requests" +msgstr "" + +msgid "Public bodies with the most requests" +msgstr "" + +msgid "Public bodies with the most successful requests" +msgstr "" + msgid "Public body" msgstr "" @@ -1734,6 +1782,15 @@ msgstr "" msgid "PublicBody|Info requests count" msgstr "" +msgid "PublicBody|Info requests not held count" +msgstr "" + +msgid "PublicBody|Info requests overdue count" +msgstr "" + +msgid "PublicBody|Info requests successful count" +msgstr "" + msgid "PublicBody|Last edit comment" msgstr "" @@ -1845,6 +1902,12 @@ msgstr "" msgid "Requested on {{date}}" msgstr "" +msgid "Requests are considered overdue if they are in the 'Overdue' or 'Very Overdue' states." +msgstr "" + +msgid "Requests are considered successful if they were classified as either 'Successful' or 'Partially Successful'." +msgstr "" + msgid "Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href=\"/help/about\">read more</a>)." msgstr "" @@ -2152,12 +2215,21 @@ msgstr "" msgid "The authority would like to / has <strong>responded by post</strong> to this request." msgstr "" +msgid "The classification of requests (e.g. to say whether they were successful or not) is done manually by users and administrators of the site, which means that they are subject to error." +msgstr "" + msgid "The email that you, on behalf of {{public_body}}, sent to\\n{{user}} to reply to an {{law_used_short}}\\nrequest has not been delivered." msgstr "" +msgid "The error bars shown are 95% confidence intervals for the hypothesized underlying proportion (i.e. that which you would obtain by making an infinite number of requests through this site to that authority). In other words, the population being sampled is all the current and future requests to the authority through this site, rather than, say, all requests that have been made to the public body by any means." +msgstr "" + msgid "The page doesn't exist. Things you can try now:" msgstr "" +msgid "The percentages are calculated with respect to the total number of requests, which includes invalid requests; this is a known problem that will be fixed in a later release." +msgstr "" + msgid "The public authority does not have the information requested" msgstr "" @@ -2300,12 +2372,18 @@ msgstr "" msgid "There was an error with the words you entered, please try again." msgstr "" +msgid "There was no data calculated for this graph yet." +msgstr "" + msgid "There were no requests matching your query." msgstr "" msgid "There were no results matching your query." msgstr "" +msgid "These graphs were partly inspired by <a href=\"http://mark.goodge.co.uk/2011/08/number-crunching-whatdotheyknow/\">some statistics that Mark Goodge produced for WhatDoTheyKnow</a>, so thanks are due to him." +msgstr "" + msgid "They are going to reply <strong>by post</strong>" msgstr "" @@ -2330,9 +2408,6 @@ msgstr "" msgid "This authority no longer exists, so you cannot make a request to it." msgstr "" -msgid "This comment has been hidden. See annotations to\\n find out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This covers a very wide spectrum of information about the state of\\n the <strong>natural and built environment</strong>, such as:" msgstr "" @@ -2354,7 +2429,25 @@ msgstr "" msgid "This is your own request, so you will be automatically emailed when new responses arrive." msgstr "" -msgid "This outgoing message has been hidden. See annotations to\\n\t\t\t\t\t\tfind out why. If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." +msgid "This message has been hidden." +msgstr "" + +msgid "This message has been hidden. There are various reasons why we might have done this, sorry we can't be more specific here." +msgstr "" + +msgid "This message has prominence 'hidden'. You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message has prominence 'hidden'. {{reason}} You can only see it because you are logged in as a super user." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. Please <a href=\"{{url}}\">contact us</a> if you are not sure why." +msgstr "" + +msgid "This message is hidden, so that only you, the requester, can see it. {{reason}}" +msgstr "" + +msgid "This page of public body statistics is currently experimental, so there are some caveats that should be borne in mind:" msgstr "" msgid "This particular request is finished:" @@ -2422,9 +2515,6 @@ msgstr "" msgid "This request was not made via {{site_name}}" msgstr "" -msgid "This response has been hidden. See annotations to find out why.\\n If you are the requester, then you may <a href=\"{{url}}\">sign in</a> to view the response." -msgstr "" - msgid "This table shows the technical details of the internal events that happened\\nto this request on {{site_name}}. This could be used to generate information about\\nthe speed with which authorities respond to requests, the number of requests\\nwhich require a postal response and much more." msgstr "" @@ -3263,9 +3353,6 @@ msgstr "" msgid "to {{public_body}}" msgstr "" -msgid "unexpected prominence on request event" -msgstr "" - msgid "unknown reason " msgstr "" diff --git a/app/views/admin_general/admin.coffee b/public/admin/javascripts/admin.coffee index 3d39369a4..3d39369a4 100644 --- a/app/views/admin_general/admin.coffee +++ b/public/admin/javascripts/admin.coffee diff --git a/app/views/admin_general/admin.js b/public/admin/javascripts/admin.js index 9daa51459..9daa51459 100644 --- a/app/views/admin_general/admin.js +++ b/public/admin/javascripts/admin.js diff --git a/public/javascripts/admin.coffee b/public/javascripts/admin.coffee deleted file mode 100644 index 59c5c0a6f..000000000 --- a/public/javascripts/admin.coffee +++ /dev/null @@ -1,10 +0,0 @@ -(($) -> - $(document).ready(-> - $('.locales a:first').tab('show') - ) - $('.toggle-hidden').live('click', -> - $(@).parents('td').find('div:hidden').show() - false - ) -)(jQuery) - diff --git a/public/javascripts/admin.js b/public/javascripts/admin.js deleted file mode 100644 index 21725ded4..000000000 --- a/public/javascripts/admin.js +++ /dev/null @@ -1,14 +0,0 @@ -// Generated by CoffeeScript 1.3.1 -(function() { - - (function($) { - $(document).ready(function() { - return $('.locales a:first').tab('show'); - }); - return $('.toggle-hidden').live('click', function() { - $(this).parents('td').find('div:hidden').show(); - return false; - }); - })(jQuery); - -}).call(this); diff --git a/public/javascripts/controls.js b/public/javascripts/controls.js deleted file mode 100644 index 7392fb664..000000000 --- a/public/javascripts/controls.js +++ /dev/null @@ -1,965 +0,0 @@ -// script.aculo.us controls.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 - -// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005-2009 Ivan Krstic (http://blogs.law.harvard.edu/ivan) -// (c) 2005-2009 Jon Tirsen (http://www.tirsen.com) -// Contributors: -// Richard Livsey -// Rahul Bhargava -// Rob Wills -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -// Autocompleter.Base handles all the autocompletion functionality -// that's independent of the data source for autocompletion. This -// includes drawing the autocompletion menu, observing keyboard -// and mouse events, and similar. -// -// Specific autocompleters need to provide, at the very least, -// a getUpdatedChoices function that will be invoked every time -// the text inside the monitored textbox changes. This method -// should get the text for which to provide autocompletion by -// invoking this.getToken(), NOT by directly accessing -// this.element.value. This is to allow incremental tokenized -// autocompletion. Specific auto-completion logic (AJAX, etc) -// belongs in getUpdatedChoices. -// -// Tokenized incremental autocompletion is enabled automatically -// when an autocompleter is instantiated with the 'tokens' option -// in the options parameter, e.g.: -// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); -// will incrementally autocomplete with a comma as the token. -// Additionally, ',' in the above example can be replaced with -// a token array, e.g. { tokens: [',', '\n'] } which -// enables autocompletion on multiple tokens. This is most -// useful when one of the tokens is \n (a newline), as it -// allows smart autocompletion after linebreaks. - -if(typeof Effect == 'undefined') - throw("controls.js requires including script.aculo.us' effects.js library"); - -var Autocompleter = { }; -Autocompleter.Base = Class.create({ - baseInitialize: function(element, update, options) { - element = $(element); - this.element = element; - this.update = $(update); - this.hasFocus = false; - this.changed = false; - this.active = false; - this.index = 0; - this.entryCount = 0; - this.oldElementValue = this.element.value; - - if(this.setOptions) - this.setOptions(options); - else - this.options = options || { }; - - this.options.paramName = this.options.paramName || this.element.name; - this.options.tokens = this.options.tokens || []; - this.options.frequency = this.options.frequency || 0.4; - this.options.minChars = this.options.minChars || 1; - this.options.onShow = this.options.onShow || - function(element, update){ - if(!update.style.position || update.style.position=='absolute') { - update.style.position = 'absolute'; - Position.clone(element, update, { - setHeight: false, - offsetTop: element.offsetHeight - }); - } - Effect.Appear(update,{duration:0.15}); - }; - this.options.onHide = this.options.onHide || - function(element, update){ new Effect.Fade(update,{duration:0.15}) }; - - if(typeof(this.options.tokens) == 'string') - this.options.tokens = new Array(this.options.tokens); - // Force carriage returns as token delimiters anyway - if (!this.options.tokens.include('\n')) - this.options.tokens.push('\n'); - - this.observer = null; - - this.element.setAttribute('autocomplete','off'); - - Element.hide(this.update); - - Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); - Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); - }, - - show: function() { - if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); - if(!this.iefix && - (Prototype.Browser.IE) && - (Element.getStyle(this.update, 'position')=='absolute')) { - new Insertion.After(this.update, - '<iframe id="' + this.update.id + '_iefix" '+ - 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + - 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>'); - this.iefix = $(this.update.id+'_iefix'); - } - if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); - }, - - fixIEOverlapping: function() { - Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); - this.iefix.style.zIndex = 1; - this.update.style.zIndex = 2; - Element.show(this.iefix); - }, - - hide: function() { - this.stopIndicator(); - if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); - if(this.iefix) Element.hide(this.iefix); - }, - - startIndicator: function() { - if(this.options.indicator) Element.show(this.options.indicator); - }, - - stopIndicator: function() { - if(this.options.indicator) Element.hide(this.options.indicator); - }, - - onKeyPress: function(event) { - if(this.active) - switch(event.keyCode) { - case Event.KEY_TAB: - case Event.KEY_RETURN: - this.selectEntry(); - Event.stop(event); - case Event.KEY_ESC: - this.hide(); - this.active = false; - Event.stop(event); - return; - case Event.KEY_LEFT: - case Event.KEY_RIGHT: - return; - case Event.KEY_UP: - this.markPrevious(); - this.render(); - Event.stop(event); - return; - case Event.KEY_DOWN: - this.markNext(); - this.render(); - Event.stop(event); - return; - } - else - if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || - (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; - - this.changed = true; - this.hasFocus = true; - - if(this.observer) clearTimeout(this.observer); - this.observer = - setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); - }, - - activate: function() { - this.changed = false; - this.hasFocus = true; - this.getUpdatedChoices(); - }, - - onHover: function(event) { - var element = Event.findElement(event, 'LI'); - if(this.index != element.autocompleteIndex) - { - this.index = element.autocompleteIndex; - this.render(); - } - Event.stop(event); - }, - - onClick: function(event) { - var element = Event.findElement(event, 'LI'); - this.index = element.autocompleteIndex; - this.selectEntry(); - this.hide(); - }, - - onBlur: function(event) { - // needed to make click events working - setTimeout(this.hide.bind(this), 250); - this.hasFocus = false; - this.active = false; - }, - - render: function() { - if(this.entryCount > 0) { - for (var i = 0; i < this.entryCount; i++) - this.index==i ? - Element.addClassName(this.getEntry(i),"selected") : - Element.removeClassName(this.getEntry(i),"selected"); - if(this.hasFocus) { - this.show(); - this.active = true; - } - } else { - this.active = false; - this.hide(); - } - }, - - markPrevious: function() { - if(this.index > 0) this.index--; - else this.index = this.entryCount-1; - this.getEntry(this.index).scrollIntoView(true); - }, - - markNext: function() { - if(this.index < this.entryCount-1) this.index++; - else this.index = 0; - this.getEntry(this.index).scrollIntoView(false); - }, - - getEntry: function(index) { - return this.update.firstChild.childNodes[index]; - }, - - getCurrentEntry: function() { - return this.getEntry(this.index); - }, - - selectEntry: function() { - this.active = false; - this.updateElement(this.getCurrentEntry()); - }, - - updateElement: function(selectedElement) { - if (this.options.updateElement) { - this.options.updateElement(selectedElement); - return; - } - var value = ''; - if (this.options.select) { - var nodes = $(selectedElement).select('.' + this.options.select) || []; - if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); - } else - value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); - - var bounds = this.getTokenBounds(); - if (bounds[0] != -1) { - var newValue = this.element.value.substr(0, bounds[0]); - var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); - if (whitespace) - newValue += whitespace[0]; - this.element.value = newValue + value + this.element.value.substr(bounds[1]); - } else { - this.element.value = value; - } - this.oldElementValue = this.element.value; - this.element.focus(); - - if (this.options.afterUpdateElement) - this.options.afterUpdateElement(this.element, selectedElement); - }, - - updateChoices: function(choices) { - if(!this.changed && this.hasFocus) { - this.update.innerHTML = choices; - Element.cleanWhitespace(this.update); - Element.cleanWhitespace(this.update.down()); - - if(this.update.firstChild && this.update.down().childNodes) { - this.entryCount = - this.update.down().childNodes.length; - for (var i = 0; i < this.entryCount; i++) { - var entry = this.getEntry(i); - entry.autocompleteIndex = i; - this.addObservers(entry); - } - } else { - this.entryCount = 0; - } - - this.stopIndicator(); - this.index = 0; - - if(this.entryCount==1 && this.options.autoSelect) { - this.selectEntry(); - this.hide(); - } else { - this.render(); - } - } - }, - - addObservers: function(element) { - Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); - Event.observe(element, "click", this.onClick.bindAsEventListener(this)); - }, - - onObserverEvent: function() { - this.changed = false; - this.tokenBounds = null; - if(this.getToken().length>=this.options.minChars) { - this.getUpdatedChoices(); - } else { - this.active = false; - this.hide(); - } - this.oldElementValue = this.element.value; - }, - - getToken: function() { - var bounds = this.getTokenBounds(); - return this.element.value.substring(bounds[0], bounds[1]).strip(); - }, - - getTokenBounds: function() { - if (null != this.tokenBounds) return this.tokenBounds; - var value = this.element.value; - if (value.strip().empty()) return [-1, 0]; - var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); - var offset = (diff == this.oldElementValue.length ? 1 : 0); - var prevTokenPos = -1, nextTokenPos = value.length; - var tp; - for (var index = 0, l = this.options.tokens.length; index < l; ++index) { - tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); - if (tp > prevTokenPos) prevTokenPos = tp; - tp = value.indexOf(this.options.tokens[index], diff + offset); - if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; - } - return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); - } -}); - -Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { - var boundary = Math.min(newS.length, oldS.length); - for (var index = 0; index < boundary; ++index) - if (newS[index] != oldS[index]) - return index; - return boundary; -}; - -Ajax.Autocompleter = Class.create(Autocompleter.Base, { - initialize: function(element, update, url, options) { - this.baseInitialize(element, update, options); - this.options.asynchronous = true; - this.options.onComplete = this.onComplete.bind(this); - this.options.defaultParams = this.options.parameters || null; - this.url = url; - }, - - getUpdatedChoices: function() { - this.startIndicator(); - - var entry = encodeURIComponent(this.options.paramName) + '=' + - encodeURIComponent(this.getToken()); - - this.options.parameters = this.options.callback ? - this.options.callback(this.element, entry) : entry; - - if(this.options.defaultParams) - this.options.parameters += '&' + this.options.defaultParams; - - new Ajax.Request(this.url, this.options); - }, - - onComplete: function(request) { - this.updateChoices(request.responseText); - } -}); - -// The local array autocompleter. Used when you'd prefer to -// inject an array of autocompletion options into the page, rather -// than sending out Ajax queries, which can be quite slow sometimes. -// -// The constructor takes four parameters. The first two are, as usual, -// the id of the monitored textbox, and id of the autocompletion menu. -// The third is the array you want to autocomplete from, and the fourth -// is the options block. -// -// Extra local autocompletion options: -// - choices - How many autocompletion choices to offer -// -// - partialSearch - If false, the autocompleter will match entered -// text only at the beginning of strings in the -// autocomplete array. Defaults to true, which will -// match text at the beginning of any *word* in the -// strings in the autocomplete array. If you want to -// search anywhere in the string, additionally set -// the option fullSearch to true (default: off). -// -// - fullSsearch - Search anywhere in autocomplete array strings. -// -// - partialChars - How many characters to enter before triggering -// a partial match (unlike minChars, which defines -// how many characters are required to do any match -// at all). Defaults to 2. -// -// - ignoreCase - Whether to ignore case when autocompleting. -// Defaults to true. -// -// It's possible to pass in a custom function as the 'selector' -// option, if you prefer to write your own autocompletion logic. -// In that case, the other options above will not apply unless -// you support them. - -Autocompleter.Local = Class.create(Autocompleter.Base, { - initialize: function(element, update, array, options) { - this.baseInitialize(element, update, options); - this.options.array = array; - }, - - getUpdatedChoices: function() { - this.updateChoices(this.options.selector(this)); - }, - - setOptions: function(options) { - this.options = Object.extend({ - choices: 10, - partialSearch: true, - partialChars: 2, - ignoreCase: true, - fullSearch: false, - selector: function(instance) { - var ret = []; // Beginning matches - var partial = []; // Inside matches - var entry = instance.getToken(); - var count = 0; - - for (var i = 0; i < instance.options.array.length && - ret.length < instance.options.choices ; i++) { - - var elem = instance.options.array[i]; - var foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase()) : - elem.indexOf(entry); - - while (foundPos != -1) { - if (foundPos == 0 && elem.length != entry.length) { - ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + - elem.substr(entry.length) + "</li>"); - break; - } else if (entry.length >= instance.options.partialChars && - instance.options.partialSearch && foundPos != -1) { - if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { - partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" + - elem.substr(foundPos, entry.length) + "</strong>" + elem.substr( - foundPos + entry.length) + "</li>"); - break; - } - } - - foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : - elem.indexOf(entry, foundPos + 1); - - } - } - if (partial.length) - ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)); - return "<ul>" + ret.join('') + "</ul>"; - } - }, options || { }); - } -}); - -// AJAX in-place editor and collection editor -// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007). - -// Use this if you notice weird scrolling problems on some browsers, -// the DOM might be a bit confused when this gets called so do this -// waits 1 ms (with setTimeout) until it does the activation -Field.scrollFreeActivate = function(field) { - setTimeout(function() { - Field.activate(field); - }, 1); -}; - -Ajax.InPlaceEditor = Class.create({ - initialize: function(element, url, options) { - this.url = url; - this.element = element = $(element); - this.prepareOptions(); - this._controls = { }; - arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! - Object.extend(this.options, options || { }); - if (!this.options.formId && this.element.id) { - this.options.formId = this.element.id + '-inplaceeditor'; - if ($(this.options.formId)) - this.options.formId = ''; - } - if (this.options.externalControl) - this.options.externalControl = $(this.options.externalControl); - if (!this.options.externalControl) - this.options.externalControlOnly = false; - this._originalBackground = this.element.getStyle('background-color') || 'transparent'; - this.element.title = this.options.clickToEditText; - this._boundCancelHandler = this.handleFormCancellation.bind(this); - this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); - this._boundFailureHandler = this.handleAJAXFailure.bind(this); - this._boundSubmitHandler = this.handleFormSubmission.bind(this); - this._boundWrapperHandler = this.wrapUp.bind(this); - this.registerListeners(); - }, - checkForEscapeOrReturn: function(e) { - if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; - if (Event.KEY_ESC == e.keyCode) - this.handleFormCancellation(e); - else if (Event.KEY_RETURN == e.keyCode) - this.handleFormSubmission(e); - }, - createControl: function(mode, handler, extraClasses) { - var control = this.options[mode + 'Control']; - var text = this.options[mode + 'Text']; - if ('button' == control) { - var btn = document.createElement('input'); - btn.type = 'submit'; - btn.value = text; - btn.className = 'editor_' + mode + '_button'; - if ('cancel' == mode) - btn.onclick = this._boundCancelHandler; - this._form.appendChild(btn); - this._controls[mode] = btn; - } else if ('link' == control) { - var link = document.createElement('a'); - link.href = '#'; - link.appendChild(document.createTextNode(text)); - link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; - link.className = 'editor_' + mode + '_link'; - if (extraClasses) - link.className += ' ' + extraClasses; - this._form.appendChild(link); - this._controls[mode] = link; - } - }, - createEditField: function() { - var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); - var fld; - if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { - fld = document.createElement('input'); - fld.type = 'text'; - var size = this.options.size || this.options.cols || 0; - if (0 < size) fld.size = size; - } else { - fld = document.createElement('textarea'); - fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); - fld.cols = this.options.cols || 40; - } - fld.name = this.options.paramName; - fld.value = text; // No HTML breaks conversion anymore - fld.className = 'editor_field'; - if (this.options.submitOnBlur) - fld.onblur = this._boundSubmitHandler; - this._controls.editor = fld; - if (this.options.loadTextURL) - this.loadExternalText(); - this._form.appendChild(this._controls.editor); - }, - createForm: function() { - var ipe = this; - function addText(mode, condition) { - var text = ipe.options['text' + mode + 'Controls']; - if (!text || condition === false) return; - ipe._form.appendChild(document.createTextNode(text)); - }; - this._form = $(document.createElement('form')); - this._form.id = this.options.formId; - this._form.addClassName(this.options.formClassName); - this._form.onsubmit = this._boundSubmitHandler; - this.createEditField(); - if ('textarea' == this._controls.editor.tagName.toLowerCase()) - this._form.appendChild(document.createElement('br')); - if (this.options.onFormCustomization) - this.options.onFormCustomization(this, this._form); - addText('Before', this.options.okControl || this.options.cancelControl); - this.createControl('ok', this._boundSubmitHandler); - addText('Between', this.options.okControl && this.options.cancelControl); - this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); - addText('After', this.options.okControl || this.options.cancelControl); - }, - destroy: function() { - if (this._oldInnerHTML) - this.element.innerHTML = this._oldInnerHTML; - this.leaveEditMode(); - this.unregisterListeners(); - }, - enterEditMode: function(e) { - if (this._saving || this._editing) return; - this._editing = true; - this.triggerCallback('onEnterEditMode'); - if (this.options.externalControl) - this.options.externalControl.hide(); - this.element.hide(); - this.createForm(); - this.element.parentNode.insertBefore(this._form, this.element); - if (!this.options.loadTextURL) - this.postProcessEditField(); - if (e) Event.stop(e); - }, - enterHover: function(e) { - if (this.options.hoverClassName) - this.element.addClassName(this.options.hoverClassName); - if (this._saving) return; - this.triggerCallback('onEnterHover'); - }, - getText: function() { - return this.element.innerHTML.unescapeHTML(); - }, - handleAJAXFailure: function(transport) { - this.triggerCallback('onFailure', transport); - if (this._oldInnerHTML) { - this.element.innerHTML = this._oldInnerHTML; - this._oldInnerHTML = null; - } - }, - handleFormCancellation: function(e) { - this.wrapUp(); - if (e) Event.stop(e); - }, - handleFormSubmission: function(e) { - var form = this._form; - var value = $F(this._controls.editor); - this.prepareSubmission(); - var params = this.options.callback(form, value) || ''; - if (Object.isString(params)) - params = params.toQueryParams(); - params.editorId = this.element.id; - if (this.options.htmlResponse) { - var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); - Object.extend(options, { - parameters: params, - onComplete: this._boundWrapperHandler, - onFailure: this._boundFailureHandler - }); - new Ajax.Updater({ success: this.element }, this.url, options); - } else { - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: params, - onComplete: this._boundWrapperHandler, - onFailure: this._boundFailureHandler - }); - new Ajax.Request(this.url, options); - } - if (e) Event.stop(e); - }, - leaveEditMode: function() { - this.element.removeClassName(this.options.savingClassName); - this.removeForm(); - this.leaveHover(); - this.element.style.backgroundColor = this._originalBackground; - this.element.show(); - if (this.options.externalControl) - this.options.externalControl.show(); - this._saving = false; - this._editing = false; - this._oldInnerHTML = null; - this.triggerCallback('onLeaveEditMode'); - }, - leaveHover: function(e) { - if (this.options.hoverClassName) - this.element.removeClassName(this.options.hoverClassName); - if (this._saving) return; - this.triggerCallback('onLeaveHover'); - }, - loadExternalText: function() { - this._form.addClassName(this.options.loadingClassName); - this._controls.editor.disabled = true; - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - this._form.removeClassName(this.options.loadingClassName); - var text = transport.responseText; - if (this.options.stripLoadedTextTags) - text = text.stripTags(); - this._controls.editor.value = text; - this._controls.editor.disabled = false; - this.postProcessEditField(); - }.bind(this), - onFailure: this._boundFailureHandler - }); - new Ajax.Request(this.options.loadTextURL, options); - }, - postProcessEditField: function() { - var fpc = this.options.fieldPostCreation; - if (fpc) - $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); - }, - prepareOptions: function() { - this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); - Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); - [this._extraDefaultOptions].flatten().compact().each(function(defs) { - Object.extend(this.options, defs); - }.bind(this)); - }, - prepareSubmission: function() { - this._saving = true; - this.removeForm(); - this.leaveHover(); - this.showSaving(); - }, - registerListeners: function() { - this._listeners = { }; - var listener; - $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { - listener = this[pair.value].bind(this); - this._listeners[pair.key] = listener; - if (!this.options.externalControlOnly) - this.element.observe(pair.key, listener); - if (this.options.externalControl) - this.options.externalControl.observe(pair.key, listener); - }.bind(this)); - }, - removeForm: function() { - if (!this._form) return; - this._form.remove(); - this._form = null; - this._controls = { }; - }, - showSaving: function() { - this._oldInnerHTML = this.element.innerHTML; - this.element.innerHTML = this.options.savingText; - this.element.addClassName(this.options.savingClassName); - this.element.style.backgroundColor = this._originalBackground; - this.element.show(); - }, - triggerCallback: function(cbName, arg) { - if ('function' == typeof this.options[cbName]) { - this.options[cbName](this, arg); - } - }, - unregisterListeners: function() { - $H(this._listeners).each(function(pair) { - if (!this.options.externalControlOnly) - this.element.stopObserving(pair.key, pair.value); - if (this.options.externalControl) - this.options.externalControl.stopObserving(pair.key, pair.value); - }.bind(this)); - }, - wrapUp: function(transport) { - this.leaveEditMode(); - // Can't use triggerCallback due to backward compatibility: requires - // binding + direct element - this._boundComplete(transport, this.element); - } -}); - -Object.extend(Ajax.InPlaceEditor.prototype, { - dispose: Ajax.InPlaceEditor.prototype.destroy -}); - -Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { - initialize: function($super, element, url, options) { - this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; - $super(element, url, options); - }, - - createEditField: function() { - var list = document.createElement('select'); - list.name = this.options.paramName; - list.size = 1; - this._controls.editor = list; - this._collection = this.options.collection || []; - if (this.options.loadCollectionURL) - this.loadCollection(); - else - this.checkForExternalText(); - this._form.appendChild(this._controls.editor); - }, - - loadCollection: function() { - this._form.addClassName(this.options.loadingClassName); - this.showLoadingText(this.options.loadingCollectionText); - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - var js = transport.responseText.strip(); - if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check - throw('Server returned an invalid collection representation.'); - this._collection = eval(js); - this.checkForExternalText(); - }.bind(this), - onFailure: this.onFailure - }); - new Ajax.Request(this.options.loadCollectionURL, options); - }, - - showLoadingText: function(text) { - this._controls.editor.disabled = true; - var tempOption = this._controls.editor.firstChild; - if (!tempOption) { - tempOption = document.createElement('option'); - tempOption.value = ''; - this._controls.editor.appendChild(tempOption); - tempOption.selected = true; - } - tempOption.update((text || '').stripScripts().stripTags()); - }, - - checkForExternalText: function() { - this._text = this.getText(); - if (this.options.loadTextURL) - this.loadExternalText(); - else - this.buildOptionList(); - }, - - loadExternalText: function() { - this.showLoadingText(this.options.loadingText); - var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); - Object.extend(options, { - parameters: 'editorId=' + encodeURIComponent(this.element.id), - onComplete: Prototype.emptyFunction, - onSuccess: function(transport) { - this._text = transport.responseText.strip(); - this.buildOptionList(); - }.bind(this), - onFailure: this.onFailure - }); - new Ajax.Request(this.options.loadTextURL, options); - }, - - buildOptionList: function() { - this._form.removeClassName(this.options.loadingClassName); - this._collection = this._collection.map(function(entry) { - return 2 === entry.length ? entry : [entry, entry].flatten(); - }); - var marker = ('value' in this.options) ? this.options.value : this._text; - var textFound = this._collection.any(function(entry) { - return entry[0] == marker; - }.bind(this)); - this._controls.editor.update(''); - var option; - this._collection.each(function(entry, index) { - option = document.createElement('option'); - option.value = entry[0]; - option.selected = textFound ? entry[0] == marker : 0 == index; - option.appendChild(document.createTextNode(entry[1])); - this._controls.editor.appendChild(option); - }.bind(this)); - this._controls.editor.disabled = false; - Field.scrollFreeActivate(this._controls.editor); - } -}); - -//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** -//**** This only exists for a while, in order to let **** -//**** users adapt to the new API. Read up on the new **** -//**** API and convert your code to it ASAP! **** - -Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { - if (!options) return; - function fallback(name, expr) { - if (name in options || expr === undefined) return; - options[name] = expr; - }; - fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : - options.cancelLink == options.cancelButton == false ? false : undefined))); - fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : - options.okLink == options.okButton == false ? false : undefined))); - fallback('highlightColor', options.highlightcolor); - fallback('highlightEndColor', options.highlightendcolor); -}; - -Object.extend(Ajax.InPlaceEditor, { - DefaultOptions: { - ajaxOptions: { }, - autoRows: 3, // Use when multi-line w/ rows == 1 - cancelControl: 'link', // 'link'|'button'|false - cancelText: 'cancel', - clickToEditText: 'Click to edit', - externalControl: null, // id|elt - externalControlOnly: false, - fieldPostCreation: 'activate', // 'activate'|'focus'|false - formClassName: 'inplaceeditor-form', - formId: null, // id|elt - highlightColor: '#ffff99', - highlightEndColor: '#ffffff', - hoverClassName: '', - htmlResponse: true, - loadingClassName: 'inplaceeditor-loading', - loadingText: 'Loading...', - okControl: 'button', // 'link'|'button'|false - okText: 'ok', - paramName: 'value', - rows: 1, // If 1 and multi-line, uses autoRows - savingClassName: 'inplaceeditor-saving', - savingText: 'Saving...', - size: 0, - stripLoadedTextTags: false, - submitOnBlur: false, - textAfterControls: '', - textBeforeControls: '', - textBetweenControls: '' - }, - DefaultCallbacks: { - callback: function(form) { - return Form.serialize(form); - }, - onComplete: function(transport, element) { - // For backward compatibility, this one is bound to the IPE, and passes - // the element directly. It was too often customized, so we don't break it. - new Effect.Highlight(element, { - startcolor: this.options.highlightColor, keepBackgroundImage: true }); - }, - onEnterEditMode: null, - onEnterHover: function(ipe) { - ipe.element.style.backgroundColor = ipe.options.highlightColor; - if (ipe._effect) - ipe._effect.cancel(); - }, - onFailure: function(transport, ipe) { - alert('Error communication with the server: ' + transport.responseText.stripTags()); - }, - onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. - onLeaveEditMode: null, - onLeaveHover: function(ipe) { - ipe._effect = new Effect.Highlight(ipe.element, { - startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, - restorecolor: ipe._originalBackground, keepBackgroundImage: true - }); - } - }, - Listeners: { - click: 'enterEditMode', - keydown: 'checkForEscapeOrReturn', - mouseover: 'enterHover', - mouseout: 'leaveHover' - } -}); - -Ajax.InPlaceCollectionEditor.DefaultOptions = { - loadingCollectionText: 'Loading options...' -}; - -// Delayed observer, like Form.Element.Observer, -// but waits for delay after last key input -// Ideal for live-search fields - -Form.Element.DelayedObserver = Class.create({ - initialize: function(element, delay, callback) { - this.delay = delay || 0.5; - this.element = $(element); - this.callback = callback; - this.timer = null; - this.lastValue = $F(this.element); - Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); - }, - delayedListener: function(event) { - if(this.lastValue == $F(this.element)) return; - if(this.timer) clearTimeout(this.timer); - this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); - this.lastValue = $F(this.element); - }, - onTimerEvent: function() { - this.timer = null; - this.callback(this.element, $F(this.element)); - } -});
\ No newline at end of file diff --git a/public/javascripts/dragdrop.js b/public/javascripts/dragdrop.js deleted file mode 100644 index 15c6dbca6..000000000 --- a/public/javascripts/dragdrop.js +++ /dev/null @@ -1,974 +0,0 @@ -// script.aculo.us dragdrop.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 - -// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -if(Object.isUndefined(Effect)) - throw("dragdrop.js requires including script.aculo.us' effects.js library"); - -var Droppables = { - drops: [], - - remove: function(element) { - this.drops = this.drops.reject(function(d) { return d.element==$(element) }); - }, - - add: function(element) { - element = $(element); - var options = Object.extend({ - greedy: true, - hoverclass: null, - tree: false - }, arguments[1] || { }); - - // cache containers - if(options.containment) { - options._containers = []; - var containment = options.containment; - if(Object.isArray(containment)) { - containment.each( function(c) { options._containers.push($(c)) }); - } else { - options._containers.push($(containment)); - } - } - - if(options.accept) options.accept = [options.accept].flatten(); - - Element.makePositioned(element); // fix IE - options.element = element; - - this.drops.push(options); - }, - - findDeepestChild: function(drops) { - deepest = drops[0]; - - for (i = 1; i < drops.length; ++i) - if (Element.isParent(drops[i].element, deepest.element)) - deepest = drops[i]; - - return deepest; - }, - - isContained: function(element, drop) { - var containmentNode; - if(drop.tree) { - containmentNode = element.treeNode; - } else { - containmentNode = element.parentNode; - } - return drop._containers.detect(function(c) { return containmentNode == c }); - }, - - isAffected: function(point, element, drop) { - return ( - (drop.element!=element) && - ((!drop._containers) || - this.isContained(element, drop)) && - ((!drop.accept) || - (Element.classNames(element).detect( - function(v) { return drop.accept.include(v) } ) )) && - Position.within(drop.element, point[0], point[1]) ); - }, - - deactivate: function(drop) { - if(drop.hoverclass) - Element.removeClassName(drop.element, drop.hoverclass); - this.last_active = null; - }, - - activate: function(drop) { - if(drop.hoverclass) - Element.addClassName(drop.element, drop.hoverclass); - this.last_active = drop; - }, - - show: function(point, element) { - if(!this.drops.length) return; - var drop, affected = []; - - this.drops.each( function(drop) { - if(Droppables.isAffected(point, element, drop)) - affected.push(drop); - }); - - if(affected.length>0) - drop = Droppables.findDeepestChild(affected); - - if(this.last_active && this.last_active != drop) this.deactivate(this.last_active); - if (drop) { - Position.within(drop.element, point[0], point[1]); - if(drop.onHover) - drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); - - if (drop != this.last_active) Droppables.activate(drop); - } - }, - - fire: function(event, element) { - if(!this.last_active) return; - Position.prepare(); - - if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) - if (this.last_active.onDrop) { - this.last_active.onDrop(element, this.last_active.element, event); - return true; - } - }, - - reset: function() { - if(this.last_active) - this.deactivate(this.last_active); - } -}; - -var Draggables = { - drags: [], - observers: [], - - register: function(draggable) { - if(this.drags.length == 0) { - this.eventMouseUp = this.endDrag.bindAsEventListener(this); - this.eventMouseMove = this.updateDrag.bindAsEventListener(this); - this.eventKeypress = this.keyPress.bindAsEventListener(this); - - Event.observe(document, "mouseup", this.eventMouseUp); - Event.observe(document, "mousemove", this.eventMouseMove); - Event.observe(document, "keypress", this.eventKeypress); - } - this.drags.push(draggable); - }, - - unregister: function(draggable) { - this.drags = this.drags.reject(function(d) { return d==draggable }); - if(this.drags.length == 0) { - Event.stopObserving(document, "mouseup", this.eventMouseUp); - Event.stopObserving(document, "mousemove", this.eventMouseMove); - Event.stopObserving(document, "keypress", this.eventKeypress); - } - }, - - activate: function(draggable) { - if(draggable.options.delay) { - this._timeout = setTimeout(function() { - Draggables._timeout = null; - window.focus(); - Draggables.activeDraggable = draggable; - }.bind(this), draggable.options.delay); - } else { - window.focus(); // allows keypress events if window isn't currently focused, fails for Safari - this.activeDraggable = draggable; - } - }, - - deactivate: function() { - this.activeDraggable = null; - }, - - updateDrag: function(event) { - if(!this.activeDraggable) return; - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - // Mozilla-based browsers fire successive mousemove events with - // the same coordinates, prevent needless redrawing (moz bug?) - if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; - this._lastPointer = pointer; - - this.activeDraggable.updateDrag(event, pointer); - }, - - endDrag: function(event) { - if(this._timeout) { - clearTimeout(this._timeout); - this._timeout = null; - } - if(!this.activeDraggable) return; - this._lastPointer = null; - this.activeDraggable.endDrag(event); - this.activeDraggable = null; - }, - - keyPress: function(event) { - if(this.activeDraggable) - this.activeDraggable.keyPress(event); - }, - - addObserver: function(observer) { - this.observers.push(observer); - this._cacheObserverCallbacks(); - }, - - removeObserver: function(element) { // element instead of observer fixes mem leaks - this.observers = this.observers.reject( function(o) { return o.element==element }); - this._cacheObserverCallbacks(); - }, - - notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' - if(this[eventName+'Count'] > 0) - this.observers.each( function(o) { - if(o[eventName]) o[eventName](eventName, draggable, event); - }); - if(draggable.options[eventName]) draggable.options[eventName](draggable, event); - }, - - _cacheObserverCallbacks: function() { - ['onStart','onEnd','onDrag'].each( function(eventName) { - Draggables[eventName+'Count'] = Draggables.observers.select( - function(o) { return o[eventName]; } - ).length; - }); - } -}; - -/*--------------------------------------------------------------------------*/ - -var Draggable = Class.create({ - initialize: function(element) { - var defaults = { - handle: false, - reverteffect: function(element, top_offset, left_offset) { - var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; - new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, - queue: {scope:'_draggable', position:'end'} - }); - }, - endeffect: function(element) { - var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; - new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, - queue: {scope:'_draggable', position:'end'}, - afterFinish: function(){ - Draggable._dragging[element] = false - } - }); - }, - zindex: 1000, - revert: false, - quiet: false, - scroll: false, - scrollSensitivity: 20, - scrollSpeed: 15, - snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] } - delay: 0 - }; - - if(!arguments[1] || Object.isUndefined(arguments[1].endeffect)) - Object.extend(defaults, { - starteffect: function(element) { - element._opacity = Element.getOpacity(element); - Draggable._dragging[element] = true; - new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); - } - }); - - var options = Object.extend(defaults, arguments[1] || { }); - - this.element = $(element); - - if(options.handle && Object.isString(options.handle)) - this.handle = this.element.down('.'+options.handle, 0); - - if(!this.handle) this.handle = $(options.handle); - if(!this.handle) this.handle = this.element; - - if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { - options.scroll = $(options.scroll); - this._isScrollChild = Element.childOf(this.element, options.scroll); - } - - Element.makePositioned(this.element); // fix IE - - this.options = options; - this.dragging = false; - - this.eventMouseDown = this.initDrag.bindAsEventListener(this); - Event.observe(this.handle, "mousedown", this.eventMouseDown); - - Draggables.register(this); - }, - - destroy: function() { - Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); - Draggables.unregister(this); - }, - - currentDelta: function() { - return([ - parseInt(Element.getStyle(this.element,'left') || '0'), - parseInt(Element.getStyle(this.element,'top') || '0')]); - }, - - initDrag: function(event) { - if(!Object.isUndefined(Draggable._dragging[this.element]) && - Draggable._dragging[this.element]) return; - if(Event.isLeftClick(event)) { - // abort on form elements, fixes a Firefox issue - var src = Event.element(event); - if((tag_name = src.tagName.toUpperCase()) && ( - tag_name=='INPUT' || - tag_name=='SELECT' || - tag_name=='OPTION' || - tag_name=='BUTTON' || - tag_name=='TEXTAREA')) return; - - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - var pos = this.element.cumulativeOffset(); - this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); - - Draggables.activate(this); - Event.stop(event); - } - }, - - startDrag: function(event) { - this.dragging = true; - if(!this.delta) - this.delta = this.currentDelta(); - - if(this.options.zindex) { - this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); - this.element.style.zIndex = this.options.zindex; - } - - if(this.options.ghosting) { - this._clone = this.element.cloneNode(true); - this._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); - if (!this._originallyAbsolute) - Position.absolutize(this.element); - this.element.parentNode.insertBefore(this._clone, this.element); - } - - if(this.options.scroll) { - if (this.options.scroll == window) { - var where = this._getWindowScroll(this.options.scroll); - this.originalScrollLeft = where.left; - this.originalScrollTop = where.top; - } else { - this.originalScrollLeft = this.options.scroll.scrollLeft; - this.originalScrollTop = this.options.scroll.scrollTop; - } - } - - Draggables.notify('onStart', this, event); - - if(this.options.starteffect) this.options.starteffect(this.element); - }, - - updateDrag: function(event, pointer) { - if(!this.dragging) this.startDrag(event); - - if(!this.options.quiet){ - Position.prepare(); - Droppables.show(pointer, this.element); - } - - Draggables.notify('onDrag', this, event); - - this.draw(pointer); - if(this.options.change) this.options.change(this); - - if(this.options.scroll) { - this.stopScrolling(); - - var p; - if (this.options.scroll == window) { - with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } - } else { - p = Position.page(this.options.scroll); - p[0] += this.options.scroll.scrollLeft + Position.deltaX; - p[1] += this.options.scroll.scrollTop + Position.deltaY; - p.push(p[0]+this.options.scroll.offsetWidth); - p.push(p[1]+this.options.scroll.offsetHeight); - } - var speed = [0,0]; - if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); - if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); - if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); - if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); - this.startScrolling(speed); - } - - // fix AppleWebKit rendering - if(Prototype.Browser.WebKit) window.scrollBy(0,0); - - Event.stop(event); - }, - - finishDrag: function(event, success) { - this.dragging = false; - - if(this.options.quiet){ - Position.prepare(); - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - Droppables.show(pointer, this.element); - } - - if(this.options.ghosting) { - if (!this._originallyAbsolute) - Position.relativize(this.element); - delete this._originallyAbsolute; - Element.remove(this._clone); - this._clone = null; - } - - var dropped = false; - if(success) { - dropped = Droppables.fire(event, this.element); - if (!dropped) dropped = false; - } - if(dropped && this.options.onDropped) this.options.onDropped(this.element); - Draggables.notify('onEnd', this, event); - - var revert = this.options.revert; - if(revert && Object.isFunction(revert)) revert = revert(this.element); - - var d = this.currentDelta(); - if(revert && this.options.reverteffect) { - if (dropped == 0 || revert != 'failure') - this.options.reverteffect(this.element, - d[1]-this.delta[1], d[0]-this.delta[0]); - } else { - this.delta = d; - } - - if(this.options.zindex) - this.element.style.zIndex = this.originalZ; - - if(this.options.endeffect) - this.options.endeffect(this.element); - - Draggables.deactivate(this); - Droppables.reset(); - }, - - keyPress: function(event) { - if(event.keyCode!=Event.KEY_ESC) return; - this.finishDrag(event, false); - Event.stop(event); - }, - - endDrag: function(event) { - if(!this.dragging) return; - this.stopScrolling(); - this.finishDrag(event, true); - Event.stop(event); - }, - - draw: function(point) { - var pos = this.element.cumulativeOffset(); - if(this.options.ghosting) { - var r = Position.realOffset(this.element); - pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY; - } - - var d = this.currentDelta(); - pos[0] -= d[0]; pos[1] -= d[1]; - - if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { - pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; - pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; - } - - var p = [0,1].map(function(i){ - return (point[i]-pos[i]-this.offset[i]) - }.bind(this)); - - if(this.options.snap) { - if(Object.isFunction(this.options.snap)) { - p = this.options.snap(p[0],p[1],this); - } else { - if(Object.isArray(this.options.snap)) { - p = p.map( function(v, i) { - return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this)); - } else { - p = p.map( function(v) { - return (v/this.options.snap).round()*this.options.snap }.bind(this)); - } - }} - - var style = this.element.style; - if((!this.options.constraint) || (this.options.constraint=='horizontal')) - style.left = p[0] + "px"; - if((!this.options.constraint) || (this.options.constraint=='vertical')) - style.top = p[1] + "px"; - - if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering - }, - - stopScrolling: function() { - if(this.scrollInterval) { - clearInterval(this.scrollInterval); - this.scrollInterval = null; - Draggables._lastScrollPointer = null; - } - }, - - startScrolling: function(speed) { - if(!(speed[0] || speed[1])) return; - this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; - this.lastScrolled = new Date(); - this.scrollInterval = setInterval(this.scroll.bind(this), 10); - }, - - scroll: function() { - var current = new Date(); - var delta = current - this.lastScrolled; - this.lastScrolled = current; - if(this.options.scroll == window) { - with (this._getWindowScroll(this.options.scroll)) { - if (this.scrollSpeed[0] || this.scrollSpeed[1]) { - var d = delta / 1000; - this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); - } - } - } else { - this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; - this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; - } - - Position.prepare(); - Droppables.show(Draggables._lastPointer, this.element); - Draggables.notify('onDrag', this); - if (this._isScrollChild) { - Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); - Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; - Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; - if (Draggables._lastScrollPointer[0] < 0) - Draggables._lastScrollPointer[0] = 0; - if (Draggables._lastScrollPointer[1] < 0) - Draggables._lastScrollPointer[1] = 0; - this.draw(Draggables._lastScrollPointer); - } - - if(this.options.change) this.options.change(this); - }, - - _getWindowScroll: function(w) { - var T, L, W, H; - with (w.document) { - if (w.document.documentElement && documentElement.scrollTop) { - T = documentElement.scrollTop; - L = documentElement.scrollLeft; - } else if (w.document.body) { - T = body.scrollTop; - L = body.scrollLeft; - } - if (w.innerWidth) { - W = w.innerWidth; - H = w.innerHeight; - } else if (w.document.documentElement && documentElement.clientWidth) { - W = documentElement.clientWidth; - H = documentElement.clientHeight; - } else { - W = body.offsetWidth; - H = body.offsetHeight; - } - } - return { top: T, left: L, width: W, height: H }; - } -}); - -Draggable._dragging = { }; - -/*--------------------------------------------------------------------------*/ - -var SortableObserver = Class.create({ - initialize: function(element, observer) { - this.element = $(element); - this.observer = observer; - this.lastValue = Sortable.serialize(this.element); - }, - - onStart: function() { - this.lastValue = Sortable.serialize(this.element); - }, - - onEnd: function() { - Sortable.unmark(); - if(this.lastValue != Sortable.serialize(this.element)) - this.observer(this.element) - } -}); - -var Sortable = { - SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, - - sortables: { }, - - _findRootElement: function(element) { - while (element.tagName.toUpperCase() != "BODY") { - if(element.id && Sortable.sortables[element.id]) return element; - element = element.parentNode; - } - }, - - options: function(element) { - element = Sortable._findRootElement($(element)); - if(!element) return; - return Sortable.sortables[element.id]; - }, - - destroy: function(element){ - element = $(element); - var s = Sortable.sortables[element.id]; - - if(s) { - Draggables.removeObserver(s.element); - s.droppables.each(function(d){ Droppables.remove(d) }); - s.draggables.invoke('destroy'); - - delete Sortable.sortables[s.element.id]; - } - }, - - create: function(element) { - element = $(element); - var options = Object.extend({ - element: element, - tag: 'li', // assumes li children, override with tag: 'tagname' - dropOnEmpty: false, - tree: false, - treeTag: 'ul', - overlap: 'vertical', // one of 'vertical', 'horizontal' - constraint: 'vertical', // one of 'vertical', 'horizontal', false - containment: element, // also takes array of elements (or id's); or false - handle: false, // or a CSS class - only: false, - delay: 0, - hoverclass: null, - ghosting: false, - quiet: false, - scroll: false, - scrollSensitivity: 20, - scrollSpeed: 15, - format: this.SERIALIZE_RULE, - - // these take arrays of elements or ids and can be - // used for better initialization performance - elements: false, - handles: false, - - onChange: Prototype.emptyFunction, - onUpdate: Prototype.emptyFunction - }, arguments[1] || { }); - - // clear any old sortable with same element - this.destroy(element); - - // build options for the draggables - var options_for_draggable = { - revert: true, - quiet: options.quiet, - scroll: options.scroll, - scrollSpeed: options.scrollSpeed, - scrollSensitivity: options.scrollSensitivity, - delay: options.delay, - ghosting: options.ghosting, - constraint: options.constraint, - handle: options.handle }; - - if(options.starteffect) - options_for_draggable.starteffect = options.starteffect; - - if(options.reverteffect) - options_for_draggable.reverteffect = options.reverteffect; - else - if(options.ghosting) options_for_draggable.reverteffect = function(element) { - element.style.top = 0; - element.style.left = 0; - }; - - if(options.endeffect) - options_for_draggable.endeffect = options.endeffect; - - if(options.zindex) - options_for_draggable.zindex = options.zindex; - - // build options for the droppables - var options_for_droppable = { - overlap: options.overlap, - containment: options.containment, - tree: options.tree, - hoverclass: options.hoverclass, - onHover: Sortable.onHover - }; - - var options_for_tree = { - onHover: Sortable.onEmptyHover, - overlap: options.overlap, - containment: options.containment, - hoverclass: options.hoverclass - }; - - // fix for gecko engine - Element.cleanWhitespace(element); - - options.draggables = []; - options.droppables = []; - - // drop on empty handling - if(options.dropOnEmpty || options.tree) { - Droppables.add(element, options_for_tree); - options.droppables.push(element); - } - - (options.elements || this.findElements(element, options) || []).each( function(e,i) { - var handle = options.handles ? $(options.handles[i]) : - (options.handle ? $(e).select('.' + options.handle)[0] : e); - options.draggables.push( - new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); - Droppables.add(e, options_for_droppable); - if(options.tree) e.treeNode = element; - options.droppables.push(e); - }); - - if(options.tree) { - (Sortable.findTreeElements(element, options) || []).each( function(e) { - Droppables.add(e, options_for_tree); - e.treeNode = element; - options.droppables.push(e); - }); - } - - // keep reference - this.sortables[element.identify()] = options; - - // for onupdate - Draggables.addObserver(new SortableObserver(element, options.onUpdate)); - - }, - - // return all suitable-for-sortable elements in a guaranteed order - findElements: function(element, options) { - return Element.findChildren( - element, options.only, options.tree ? true : false, options.tag); - }, - - findTreeElements: function(element, options) { - return Element.findChildren( - element, options.only, options.tree ? true : false, options.treeTag); - }, - - onHover: function(element, dropon, overlap) { - if(Element.isParent(dropon, element)) return; - - if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { - return; - } else if(overlap>0.5) { - Sortable.mark(dropon, 'before'); - if(dropon.previousSibling != element) { - var oldParentNode = element.parentNode; - element.style.visibility = "hidden"; // fix gecko rendering - dropon.parentNode.insertBefore(element, dropon); - if(dropon.parentNode!=oldParentNode) - Sortable.options(oldParentNode).onChange(element); - Sortable.options(dropon.parentNode).onChange(element); - } - } else { - Sortable.mark(dropon, 'after'); - var nextElement = dropon.nextSibling || null; - if(nextElement != element) { - var oldParentNode = element.parentNode; - element.style.visibility = "hidden"; // fix gecko rendering - dropon.parentNode.insertBefore(element, nextElement); - if(dropon.parentNode!=oldParentNode) - Sortable.options(oldParentNode).onChange(element); - Sortable.options(dropon.parentNode).onChange(element); - } - } - }, - - onEmptyHover: function(element, dropon, overlap) { - var oldParentNode = element.parentNode; - var droponOptions = Sortable.options(dropon); - - if(!Element.isParent(dropon, element)) { - var index; - - var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); - var child = null; - - if(children) { - var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); - - for (index = 0; index < children.length; index += 1) { - if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { - offset -= Element.offsetSize (children[index], droponOptions.overlap); - } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { - child = index + 1 < children.length ? children[index + 1] : null; - break; - } else { - child = children[index]; - break; - } - } - } - - dropon.insertBefore(element, child); - - Sortable.options(oldParentNode).onChange(element); - droponOptions.onChange(element); - } - }, - - unmark: function() { - if(Sortable._marker) Sortable._marker.hide(); - }, - - mark: function(dropon, position) { - // mark on ghosting only - var sortable = Sortable.options(dropon.parentNode); - if(sortable && !sortable.ghosting) return; - - if(!Sortable._marker) { - Sortable._marker = - ($('dropmarker') || Element.extend(document.createElement('DIV'))). - hide().addClassName('dropmarker').setStyle({position:'absolute'}); - document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); - } - var offsets = dropon.cumulativeOffset(); - Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'}); - - if(position=='after') - if(sortable.overlap == 'horizontal') - Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'}); - else - Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'}); - - Sortable._marker.show(); - }, - - _tree: function(element, options, parent) { - var children = Sortable.findElements(element, options) || []; - - for (var i = 0; i < children.length; ++i) { - var match = children[i].id.match(options.format); - - if (!match) continue; - - var child = { - id: encodeURIComponent(match ? match[1] : null), - element: element, - parent: parent, - children: [], - position: parent.children.length, - container: $(children[i]).down(options.treeTag) - }; - - /* Get the element containing the children and recurse over it */ - if (child.container) - this._tree(child.container, options, child); - - parent.children.push (child); - } - - return parent; - }, - - tree: function(element) { - element = $(element); - var sortableOptions = this.options(element); - var options = Object.extend({ - tag: sortableOptions.tag, - treeTag: sortableOptions.treeTag, - only: sortableOptions.only, - name: element.id, - format: sortableOptions.format - }, arguments[1] || { }); - - var root = { - id: null, - parent: null, - children: [], - container: element, - position: 0 - }; - - return Sortable._tree(element, options, root); - }, - - /* Construct a [i] index for a particular node */ - _constructIndex: function(node) { - var index = ''; - do { - if (node.id) index = '[' + node.position + ']' + index; - } while ((node = node.parent) != null); - return index; - }, - - sequence: function(element) { - element = $(element); - var options = Object.extend(this.options(element), arguments[1] || { }); - - return $(this.findElements(element, options) || []).map( function(item) { - return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; - }); - }, - - setSequence: function(element, new_sequence) { - element = $(element); - var options = Object.extend(this.options(element), arguments[2] || { }); - - var nodeMap = { }; - this.findElements(element, options).each( function(n) { - if (n.id.match(options.format)) - nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; - n.parentNode.removeChild(n); - }); - - new_sequence.each(function(ident) { - var n = nodeMap[ident]; - if (n) { - n[1].appendChild(n[0]); - delete nodeMap[ident]; - } - }); - }, - - serialize: function(element) { - element = $(element); - var options = Object.extend(Sortable.options(element), arguments[1] || { }); - var name = encodeURIComponent( - (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); - - if (options.tree) { - return Sortable.tree(element, arguments[1]).children.map( function (item) { - return [name + Sortable._constructIndex(item) + "[id]=" + - encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); - }).flatten().join('&'); - } else { - return Sortable.sequence(element, arguments[1]).map( function(item) { - return name + "[]=" + encodeURIComponent(item); - }).join('&'); - } - } -}; - -// Returns true if child is contained within element -Element.isParent = function(child, element) { - if (!child.parentNode || child == element) return false; - if (child.parentNode == element) return true; - return Element.isParent(child.parentNode, element); -}; - -Element.findChildren = function(element, only, recursive, tagName) { - if(!element.hasChildNodes()) return null; - tagName = tagName.toUpperCase(); - if(only) only = [only].flatten(); - var elements = []; - $A(element.childNodes).each( function(e) { - if(e.tagName && e.tagName.toUpperCase()==tagName && - (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) - elements.push(e); - if(recursive) { - var grandchildren = Element.findChildren(e, only, recursive, tagName); - if(grandchildren) elements.push(grandchildren); - } - }); - - return (elements.length>0 ? elements.flatten() : []); -}; - -Element.offsetSize = function (element, type) { - return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')]; -};
\ No newline at end of file diff --git a/public/javascripts/effects.js b/public/javascripts/effects.js deleted file mode 100644 index c81e6c7d5..000000000 --- a/public/javascripts/effects.js +++ /dev/null @@ -1,1123 +0,0 @@ -// script.aculo.us effects.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009 - -// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// Contributors: -// Justin Palmer (http://encytemedia.com/) -// Mark Pilgrim (http://diveintomark.org/) -// Martin Bialasinki -// -// script.aculo.us is freely distributable under the terms of an MIT-style license. -// For details, see the script.aculo.us web site: http://script.aculo.us/ - -// converts rgb() and #xxx to #xxxxxx format, -// returns self (or first argument) if not convertable -String.prototype.parseColor = function() { - var color = '#'; - if (this.slice(0,4) == 'rgb(') { - var cols = this.slice(4,this.length-1).split(','); - var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); - } else { - if (this.slice(0,1) == '#') { - if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); - if (this.length==7) color = this.toLowerCase(); - } - } - return (color.length==7 ? color : (arguments[0] || this)); -}; - -/*--------------------------------------------------------------------------*/ - -Element.collectTextNodes = function(element) { - return $A($(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); - }).flatten().join(''); -}; - -Element.collectTextNodesIgnoreClass = function(element, className) { - return $A($(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? - Element.collectTextNodesIgnoreClass(node, className) : '')); - }).flatten().join(''); -}; - -Element.setContentZoom = function(element, percent) { - element = $(element); - element.setStyle({fontSize: (percent/100) + 'em'}); - if (Prototype.Browser.WebKit) window.scrollBy(0,0); - return element; -}; - -Element.getInlineOpacity = function(element){ - return $(element).style.opacity || ''; -}; - -Element.forceRerendering = function(element) { - try { - element = $(element); - var n = document.createTextNode(' '); - element.appendChild(n); - element.removeChild(n); - } catch(e) { } -}; - -/*--------------------------------------------------------------------------*/ - -var Effect = { - _elementDoesNotExistError: { - name: 'ElementDoesNotExistError', - message: 'The specified DOM element does not exist, but is required for this effect to operate' - }, - Transitions: { - linear: Prototype.K, - sinoidal: function(pos) { - return (-Math.cos(pos*Math.PI)/2) + .5; - }, - reverse: function(pos) { - return 1-pos; - }, - flicker: function(pos) { - var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4; - return pos > 1 ? 1 : pos; - }, - wobble: function(pos) { - return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5; - }, - pulse: function(pos, pulses) { - return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5; - }, - spring: function(pos) { - return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); - }, - none: function(pos) { - return 0; - }, - full: function(pos) { - return 1; - } - }, - DefaultOptions: { - duration: 1.0, // seconds - fps: 100, // 100= assume 66fps max. - sync: false, // true for combining - from: 0.0, - to: 1.0, - delay: 0.0, - queue: 'parallel' - }, - tagifyText: function(element) { - var tagifyStyle = 'position:relative'; - if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; - - element = $(element); - $A(element.childNodes).each( function(child) { - if (child.nodeType==3) { - child.nodeValue.toArray().each( function(character) { - element.insertBefore( - new Element('span', {style: tagifyStyle}).update( - character == ' ' ? String.fromCharCode(160) : character), - child); - }); - Element.remove(child); - } - }); - }, - multiple: function(element, effect) { - var elements; - if (((typeof element == 'object') || - Object.isFunction(element)) && - (element.length)) - elements = element; - else - elements = $(element).childNodes; - - var options = Object.extend({ - speed: 0.1, - delay: 0.0 - }, arguments[2] || { }); - var masterDelay = options.delay; - - $A(elements).each( function(element, index) { - new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); - }); - }, - PAIRS: { - 'slide': ['SlideDown','SlideUp'], - 'blind': ['BlindDown','BlindUp'], - 'appear': ['Appear','Fade'] - }, - toggle: function(element, effect, options) { - element = $(element); - effect = (effect || 'appear').toLowerCase(); - - return Effect[ Effect.PAIRS[ effect ][ element.visible() ? 1 : 0 ] ](element, Object.extend({ - queue: { position:'end', scope:(element.id || 'global'), limit: 1 } - }, options || {})); - } -}; - -Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; - -/* ------------- core effects ------------- */ - -Effect.ScopedQueue = Class.create(Enumerable, { - initialize: function() { - this.effects = []; - this.interval = null; - }, - _each: function(iterator) { - this.effects._each(iterator); - }, - add: function(effect) { - var timestamp = new Date().getTime(); - - var position = Object.isString(effect.options.queue) ? - effect.options.queue : effect.options.queue.position; - - switch(position) { - case 'front': - // move unstarted effects after this effect - this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { - e.startOn += effect.finishOn; - e.finishOn += effect.finishOn; - }); - break; - case 'with-last': - timestamp = this.effects.pluck('startOn').max() || timestamp; - break; - case 'end': - // start effect after last queued effect has finished - timestamp = this.effects.pluck('finishOn').max() || timestamp; - break; - } - - effect.startOn += timestamp; - effect.finishOn += timestamp; - - if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) - this.effects.push(effect); - - if (!this.interval) - this.interval = setInterval(this.loop.bind(this), 15); - }, - remove: function(effect) { - this.effects = this.effects.reject(function(e) { return e==effect }); - if (this.effects.length == 0) { - clearInterval(this.interval); - this.interval = null; - } - }, - loop: function() { - var timePos = new Date().getTime(); - for(var i=0, len=this.effects.length;i<len;i++) - this.effects[i] && this.effects[i].loop(timePos); - } -}); - -Effect.Queues = { - instances: $H(), - get: function(queueName) { - if (!Object.isString(queueName)) return queueName; - - return this.instances.get(queueName) || - this.instances.set(queueName, new Effect.ScopedQueue()); - } -}; -Effect.Queue = Effect.Queues.get('global'); - -Effect.Base = Class.create({ - position: null, - start: function(options) { - if (options && options.transition === false) options.transition = Effect.Transitions.linear; - this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { }); - this.currentFrame = 0; - this.state = 'idle'; - this.startOn = this.options.delay*1000; - this.finishOn = this.startOn+(this.options.duration*1000); - this.fromToDelta = this.options.to-this.options.from; - this.totalTime = this.finishOn-this.startOn; - this.totalFrames = this.options.fps*this.options.duration; - - this.render = (function() { - function dispatch(effect, eventName) { - if (effect.options[eventName + 'Internal']) - effect.options[eventName + 'Internal'](effect); - if (effect.options[eventName]) - effect.options[eventName](effect); - } - - return function(pos) { - if (this.state === "idle") { - this.state = "running"; - dispatch(this, 'beforeSetup'); - if (this.setup) this.setup(); - dispatch(this, 'afterSetup'); - } - if (this.state === "running") { - pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from; - this.position = pos; - dispatch(this, 'beforeUpdate'); - if (this.update) this.update(pos); - dispatch(this, 'afterUpdate'); - } - }; - })(); - - this.event('beforeStart'); - if (!this.options.sync) - Effect.Queues.get(Object.isString(this.options.queue) ? - 'global' : this.options.queue.scope).add(this); - }, - loop: function(timePos) { - if (timePos >= this.startOn) { - if (timePos >= this.finishOn) { - this.render(1.0); - this.cancel(); - this.event('beforeFinish'); - if (this.finish) this.finish(); - this.event('afterFinish'); - return; - } - var pos = (timePos - this.startOn) / this.totalTime, - frame = (pos * this.totalFrames).round(); - if (frame > this.currentFrame) { - this.render(pos); - this.currentFrame = frame; - } - } - }, - cancel: function() { - if (!this.options.sync) - Effect.Queues.get(Object.isString(this.options.queue) ? - 'global' : this.options.queue.scope).remove(this); - this.state = 'finished'; - }, - event: function(eventName) { - if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); - if (this.options[eventName]) this.options[eventName](this); - }, - inspect: function() { - var data = $H(); - for(property in this) - if (!Object.isFunction(this[property])) data.set(property, this[property]); - return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>'; - } -}); - -Effect.Parallel = Class.create(Effect.Base, { - initialize: function(effects) { - this.effects = effects || []; - this.start(arguments[1]); - }, - update: function(position) { - this.effects.invoke('render', position); - }, - finish: function(position) { - this.effects.each( function(effect) { - effect.render(1.0); - effect.cancel(); - effect.event('beforeFinish'); - if (effect.finish) effect.finish(position); - effect.event('afterFinish'); - }); - } -}); - -Effect.Tween = Class.create(Effect.Base, { - initialize: function(object, from, to) { - object = Object.isString(object) ? $(object) : object; - var args = $A(arguments), method = args.last(), - options = args.length == 5 ? args[3] : null; - this.method = Object.isFunction(method) ? method.bind(object) : - Object.isFunction(object[method]) ? object[method].bind(object) : - function(value) { object[method] = value }; - this.start(Object.extend({ from: from, to: to }, options || { })); - }, - update: function(position) { - this.method(position); - } -}); - -Effect.Event = Class.create(Effect.Base, { - initialize: function() { - this.start(Object.extend({ duration: 0 }, arguments[0] || { })); - }, - update: Prototype.emptyFunction -}); - -Effect.Opacity = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - // make this work on IE on elements without 'layout' - if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) - this.element.setStyle({zoom: 1}); - var options = Object.extend({ - from: this.element.getOpacity() || 0.0, - to: 1.0 - }, arguments[1] || { }); - this.start(options); - }, - update: function(position) { - this.element.setOpacity(position); - } -}); - -Effect.Move = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - x: 0, - y: 0, - mode: 'relative' - }, arguments[1] || { }); - this.start(options); - }, - setup: function() { - this.element.makePositioned(); - this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); - this.originalTop = parseFloat(this.element.getStyle('top') || '0'); - if (this.options.mode == 'absolute') { - this.options.x = this.options.x - this.originalLeft; - this.options.y = this.options.y - this.originalTop; - } - }, - update: function(position) { - this.element.setStyle({ - left: (this.options.x * position + this.originalLeft).round() + 'px', - top: (this.options.y * position + this.originalTop).round() + 'px' - }); - } -}); - -// for backwards compatibility -Effect.MoveBy = function(element, toTop, toLeft) { - return new Effect.Move(element, - Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); -}; - -Effect.Scale = Class.create(Effect.Base, { - initialize: function(element, percent) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - scaleX: true, - scaleY: true, - scaleContent: true, - scaleFromCenter: false, - scaleMode: 'box', // 'box' or 'contents' or { } with provided values - scaleFrom: 100.0, - scaleTo: percent - }, arguments[2] || { }); - this.start(options); - }, - setup: function() { - this.restoreAfterFinish = this.options.restoreAfterFinish || false; - this.elementPositioning = this.element.getStyle('position'); - - this.originalStyle = { }; - ['top','left','width','height','fontSize'].each( function(k) { - this.originalStyle[k] = this.element.style[k]; - }.bind(this)); - - this.originalTop = this.element.offsetTop; - this.originalLeft = this.element.offsetLeft; - - var fontSize = this.element.getStyle('font-size') || '100%'; - ['em','px','%','pt'].each( function(fontSizeType) { - if (fontSize.indexOf(fontSizeType)>0) { - this.fontSize = parseFloat(fontSize); - this.fontSizeType = fontSizeType; - } - }.bind(this)); - - this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; - - this.dims = null; - if (this.options.scaleMode=='box') - this.dims = [this.element.offsetHeight, this.element.offsetWidth]; - if (/^content/.test(this.options.scaleMode)) - this.dims = [this.element.scrollHeight, this.element.scrollWidth]; - if (!this.dims) - this.dims = [this.options.scaleMode.originalHeight, - this.options.scaleMode.originalWidth]; - }, - update: function(position) { - var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); - if (this.options.scaleContent && this.fontSize) - this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); - this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); - }, - finish: function(position) { - if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); - }, - setDimensions: function(height, width) { - var d = { }; - if (this.options.scaleX) d.width = width.round() + 'px'; - if (this.options.scaleY) d.height = height.round() + 'px'; - if (this.options.scaleFromCenter) { - var topd = (height - this.dims[0])/2; - var leftd = (width - this.dims[1])/2; - if (this.elementPositioning == 'absolute') { - if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; - if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; - } else { - if (this.options.scaleY) d.top = -topd + 'px'; - if (this.options.scaleX) d.left = -leftd + 'px'; - } - } - this.element.setStyle(d); - } -}); - -Effect.Highlight = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); - this.start(options); - }, - setup: function() { - // Prevent executing on elements not in the layout flow - if (this.element.getStyle('display')=='none') { this.cancel(); return; } - // Disable background image during the effect - this.oldStyle = { }; - if (!this.options.keepBackgroundImage) { - this.oldStyle.backgroundImage = this.element.getStyle('background-image'); - this.element.setStyle({backgroundImage: 'none'}); - } - if (!this.options.endcolor) - this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); - if (!this.options.restorecolor) - this.options.restorecolor = this.element.getStyle('background-color'); - // init color calculations - this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); - this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); - }, - update: function(position) { - this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ - return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); - }, - finish: function() { - this.element.setStyle(Object.extend(this.oldStyle, { - backgroundColor: this.options.restorecolor - })); - } -}); - -Effect.ScrollTo = function(element) { - var options = arguments[1] || { }, - scrollOffsets = document.viewport.getScrollOffsets(), - elementOffsets = $(element).cumulativeOffset(); - - if (options.offset) elementOffsets[1] += options.offset; - - return new Effect.Tween(null, - scrollOffsets.top, - elementOffsets[1], - options, - function(p){ scrollTo(scrollOffsets.left, p.round()); } - ); -}; - -/* ------------- combination effects ------------- */ - -Effect.Fade = function(element) { - element = $(element); - var oldOpacity = element.getInlineOpacity(); - var options = Object.extend({ - from: element.getOpacity() || 1.0, - to: 0.0, - afterFinishInternal: function(effect) { - if (effect.options.to!=0) return; - effect.element.hide().setStyle({opacity: oldOpacity}); - } - }, arguments[1] || { }); - return new Effect.Opacity(element,options); -}; - -Effect.Appear = function(element) { - element = $(element); - var options = Object.extend({ - from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), - to: 1.0, - // force Safari to render floated elements properly - afterFinishInternal: function(effect) { - effect.element.forceRerendering(); - }, - beforeSetup: function(effect) { - effect.element.setOpacity(effect.options.from).show(); - }}, arguments[1] || { }); - return new Effect.Opacity(element,options); -}; - -Effect.Puff = function(element) { - element = $(element); - var oldStyle = { - opacity: element.getInlineOpacity(), - position: element.getStyle('position'), - top: element.style.top, - left: element.style.left, - width: element.style.width, - height: element.style.height - }; - return new Effect.Parallel( - [ new Effect.Scale(element, 200, - { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], - Object.extend({ duration: 1.0, - beforeSetupInternal: function(effect) { - Position.absolutize(effect.effects[0].element); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().setStyle(oldStyle); } - }, arguments[1] || { }) - ); -}; - -Effect.BlindUp = function(element) { - element = $(element); - element.makeClipping(); - return new Effect.Scale(element, 0, - Object.extend({ scaleContent: false, - scaleX: false, - restoreAfterFinish: true, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping(); - } - }, arguments[1] || { }) - ); -}; - -Effect.BlindDown = function(element) { - element = $(element); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, Object.extend({ - scaleContent: false, - scaleX: false, - scaleFrom: 0, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makeClipping().setStyle({height: '0px'}).show(); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping(); - } - }, arguments[1] || { })); -}; - -Effect.SwitchOff = function(element) { - element = $(element); - var oldOpacity = element.getInlineOpacity(); - return new Effect.Appear(element, Object.extend({ - duration: 0.4, - from: 0, - transition: Effect.Transitions.flicker, - afterFinishInternal: function(effect) { - new Effect.Scale(effect.element, 1, { - duration: 0.3, scaleFromCenter: true, - scaleX: false, scaleContent: false, restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makePositioned().makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); - } - }); - } - }, arguments[1] || { })); -}; - -Effect.DropOut = function(element) { - element = $(element); - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left'), - opacity: element.getInlineOpacity() }; - return new Effect.Parallel( - [ new Effect.Move(element, {x: 0, y: 100, sync: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 }) ], - Object.extend( - { duration: 0.5, - beforeSetup: function(effect) { - effect.effects[0].element.makePositioned(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); - } - }, arguments[1] || { })); -}; - -Effect.Shake = function(element) { - element = $(element); - var options = Object.extend({ - distance: 20, - duration: 0.5 - }, arguments[1] || {}); - var distance = parseFloat(options.distance); - var split = parseFloat(options.duration) / 10.0; - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left') }; - return new Effect.Move(element, - { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { - effect.element.undoPositioned().setStyle(oldStyle); - }}); }}); }}); }}); }}); }}); -}; - -Effect.SlideDown = function(element) { - element = $(element).cleanWhitespace(); - // SlideDown need to have the content of the element wrapped in a container element with fixed height! - var oldInnerBottom = element.down().getStyle('bottom'); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, Object.extend({ - scaleContent: false, - scaleX: false, - scaleFrom: window.opera ? 0 : 1, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makePositioned(); - effect.element.down().makePositioned(); - if (window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping().setStyle({height: '0px'}).show(); - }, - afterUpdateInternal: function(effect) { - effect.element.down().setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping().undoPositioned(); - effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } - }, arguments[1] || { }) - ); -}; - -Effect.SlideUp = function(element) { - element = $(element).cleanWhitespace(); - var oldInnerBottom = element.down().getStyle('bottom'); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, window.opera ? 0 : 1, - Object.extend({ scaleContent: false, - scaleX: false, - scaleMode: 'box', - scaleFrom: 100, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makePositioned(); - effect.element.down().makePositioned(); - if (window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping().show(); - }, - afterUpdateInternal: function(effect) { - effect.element.down().setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().undoPositioned(); - effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); - } - }, arguments[1] || { }) - ); -}; - -// Bug in opera makes the TD containing this element expand for a instance after finish -Effect.Squish = function(element) { - return new Effect.Scale(element, window.opera ? 1 : 0, { - restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping(); - } - }); -}; - -Effect.Grow = function(element) { - element = $(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.full - }, arguments[1] || { }); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var initialMoveX, initialMoveY; - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - initialMoveX = initialMoveY = moveX = moveY = 0; - break; - case 'top-right': - initialMoveX = dims.width; - initialMoveY = moveY = 0; - moveX = -dims.width; - break; - case 'bottom-left': - initialMoveX = moveX = 0; - initialMoveY = dims.height; - moveY = -dims.height; - break; - case 'bottom-right': - initialMoveX = dims.width; - initialMoveY = dims.height; - moveX = -dims.width; - moveY = -dims.height; - break; - case 'center': - initialMoveX = dims.width / 2; - initialMoveY = dims.height / 2; - moveX = -dims.width / 2; - moveY = -dims.height / 2; - break; - } - - return new Effect.Move(element, { - x: initialMoveX, - y: initialMoveY, - duration: 0.01, - beforeSetup: function(effect) { - effect.element.hide().makeClipping().makePositioned(); - }, - afterFinishInternal: function(effect) { - new Effect.Parallel( - [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), - new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), - new Effect.Scale(effect.element, 100, { - scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, - sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) - ], Object.extend({ - beforeSetup: function(effect) { - effect.effects[0].element.setStyle({height: '0px'}).show(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); - } - }, options) - ); - } - }); -}; - -Effect.Shrink = function(element) { - element = $(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.none - }, arguments[1] || { }); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - moveX = moveY = 0; - break; - case 'top-right': - moveX = dims.width; - moveY = 0; - break; - case 'bottom-left': - moveX = 0; - moveY = dims.height; - break; - case 'bottom-right': - moveX = dims.width; - moveY = dims.height; - break; - case 'center': - moveX = dims.width / 2; - moveY = dims.height / 2; - break; - } - - return new Effect.Parallel( - [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), - new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), - new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) - ], Object.extend({ - beforeStartInternal: function(effect) { - effect.effects[0].element.makePositioned().makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } - }, options) - ); -}; - -Effect.Pulsate = function(element) { - element = $(element); - var options = arguments[1] || { }, - oldOpacity = element.getInlineOpacity(), - transition = options.transition || Effect.Transitions.linear, - reverser = function(pos){ - return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5); - }; - - return new Effect.Opacity(element, - Object.extend(Object.extend({ duration: 2.0, from: 0, - afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } - }, options), {transition: reverser})); -}; - -Effect.Fold = function(element) { - element = $(element); - var oldStyle = { - top: element.style.top, - left: element.style.left, - width: element.style.width, - height: element.style.height }; - element.makeClipping(); - return new Effect.Scale(element, 5, Object.extend({ - scaleContent: false, - scaleX: false, - afterFinishInternal: function(effect) { - new Effect.Scale(element, 1, { - scaleContent: false, - scaleY: false, - afterFinishInternal: function(effect) { - effect.element.hide().undoClipping().setStyle(oldStyle); - } }); - }}, arguments[1] || { })); -}; - -Effect.Morph = Class.create(Effect.Base, { - initialize: function(element) { - this.element = $(element); - if (!this.element) throw(Effect._elementDoesNotExistError); - var options = Object.extend({ - style: { } - }, arguments[1] || { }); - - if (!Object.isString(options.style)) this.style = $H(options.style); - else { - if (options.style.include(':')) - this.style = options.style.parseStyle(); - else { - this.element.addClassName(options.style); - this.style = $H(this.element.getStyles()); - this.element.removeClassName(options.style); - var css = this.element.getStyles(); - this.style = this.style.reject(function(style) { - return style.value == css[style.key]; - }); - options.afterFinishInternal = function(effect) { - effect.element.addClassName(effect.options.style); - effect.transforms.each(function(transform) { - effect.element.style[transform.style] = ''; - }); - }; - } - } - this.start(options); - }, - - setup: function(){ - function parseColor(color){ - if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; - color = color.parseColor(); - return $R(0,2).map(function(i){ - return parseInt( color.slice(i*2+1,i*2+3), 16 ); - }); - } - this.transforms = this.style.map(function(pair){ - var property = pair[0], value = pair[1], unit = null; - - if (value.parseColor('#zzzzzz') != '#zzzzzz') { - value = value.parseColor(); - unit = 'color'; - } else if (property == 'opacity') { - value = parseFloat(value); - if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) - this.element.setStyle({zoom: 1}); - } else if (Element.CSS_LENGTH.test(value)) { - var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); - value = parseFloat(components[1]); - unit = (components.length == 3) ? components[2] : null; - } - - var originalValue = this.element.getStyle(property); - return { - style: property.camelize(), - originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), - targetValue: unit=='color' ? parseColor(value) : value, - unit: unit - }; - }.bind(this)).reject(function(transform){ - return ( - (transform.originalValue == transform.targetValue) || - ( - transform.unit != 'color' && - (isNaN(transform.originalValue) || isNaN(transform.targetValue)) - ) - ); - }); - }, - update: function(position) { - var style = { }, transform, i = this.transforms.length; - while(i--) - style[(transform = this.transforms[i]).style] = - transform.unit=='color' ? '#'+ - (Math.round(transform.originalValue[0]+ - (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + - (Math.round(transform.originalValue[1]+ - (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + - (Math.round(transform.originalValue[2]+ - (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : - (transform.originalValue + - (transform.targetValue - transform.originalValue) * position).toFixed(3) + - (transform.unit === null ? '' : transform.unit); - this.element.setStyle(style, true); - } -}); - -Effect.Transform = Class.create({ - initialize: function(tracks){ - this.tracks = []; - this.options = arguments[1] || { }; - this.addTracks(tracks); - }, - addTracks: function(tracks){ - tracks.each(function(track){ - track = $H(track); - var data = track.values().first(); - this.tracks.push($H({ - ids: track.keys().first(), - effect: Effect.Morph, - options: { style: data } - })); - }.bind(this)); - return this; - }, - play: function(){ - return new Effect.Parallel( - this.tracks.map(function(track){ - var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); - var elements = [$(ids) || $$(ids)].flatten(); - return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); - }).flatten(), - this.options - ); - } -}); - -Element.CSS_PROPERTIES = $w( - 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + - 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + - 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + - 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + - 'fontSize fontWeight height left letterSpacing lineHeight ' + - 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ - 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + - 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + - 'right textIndent top width wordSpacing zIndex'); - -Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; - -String.__parseStyleElement = document.createElement('div'); -String.prototype.parseStyle = function(){ - var style, styleRules = $H(); - if (Prototype.Browser.WebKit) - style = new Element('div',{style:this}).style; - else { - String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>'; - style = String.__parseStyleElement.childNodes[0].style; - } - - Element.CSS_PROPERTIES.each(function(property){ - if (style[property]) styleRules.set(property, style[property]); - }); - - if (Prototype.Browser.IE && this.include('opacity')) - styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); - - return styleRules; -}; - -if (document.defaultView && document.defaultView.getComputedStyle) { - Element.getStyles = function(element) { - var css = document.defaultView.getComputedStyle($(element), null); - return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { - styles[property] = css[property]; - return styles; - }); - }; -} else { - Element.getStyles = function(element) { - element = $(element); - var css = element.currentStyle, styles; - styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { - results[property] = css[property]; - return results; - }); - if (!styles.opacity) styles.opacity = element.getOpacity(); - return styles; - }; -} - -Effect.Methods = { - morph: function(element, style) { - element = $(element); - new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); - return element; - }, - visualEffect: function(element, effect, options) { - element = $(element); - var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); - new Effect[klass](element, options); - return element; - }, - highlight: function(element, options) { - element = $(element); - new Effect.Highlight(element, options); - return element; - } -}; - -$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ - 'pulsate shake puff squish switchOff dropOut').each( - function(effect) { - Effect.Methods[effect] = function(element, options){ - element = $(element); - Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); - return element; - }; - } -); - -$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( - function(f) { Effect.Methods[f] = Element[f]; } -); - -Element.addMethods(Effect.Methods);
\ No newline at end of file diff --git a/public/javascripts/excanvas.min.js b/public/javascripts/excanvas.min.js new file mode 100644 index 000000000..fcf876c74 --- /dev/null +++ b/public/javascripts/excanvas.min.js @@ -0,0 +1 @@ +if(!document.createElement("canvas").getContext){(function(){var ab=Math;var n=ab.round;var l=ab.sin;var A=ab.cos;var H=ab.abs;var N=ab.sqrt;var d=10;var f=d/2;var z=+navigator.userAgent.match(/MSIE ([\d.]+)?/)[1];function y(){return this.context_||(this.context_=new D(this))}var t=Array.prototype.slice;function g(j,m,p){var i=t.call(arguments,2);return function(){return j.apply(m,i.concat(t.call(arguments)))}}function af(i){return String(i).replace(/&/g,"&").replace(/"/g,""")}function Y(m,j,i){if(!m.namespaces[j]){m.namespaces.add(j,i,"#default#VML")}}function R(j){Y(j,"g_vml_","urn:schemas-microsoft-com:vml");Y(j,"g_o_","urn:schemas-microsoft-com:office:office");if(!j.styleSheets.ex_canvas_){var i=j.createStyleSheet();i.owningElement.id="ex_canvas_";i.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"}}R(document);var e={init:function(i){var j=i||document;j.createElement("canvas");j.attachEvent("onreadystatechange",g(this.init_,this,j))},init_:function(p){var m=p.getElementsByTagName("canvas");for(var j=0;j<m.length;j++){this.initElement(m[j])}},initElement:function(j){if(!j.getContext){j.getContext=y;R(j.ownerDocument);j.innerHTML="";j.attachEvent("onpropertychange",x);j.attachEvent("onresize",W);var i=j.attributes;if(i.width&&i.width.specified){j.style.width=i.width.nodeValue+"px"}else{j.width=j.clientWidth}if(i.height&&i.height.specified){j.style.height=i.height.nodeValue+"px"}else{j.height=j.clientHeight}}return j}};function x(j){var i=j.srcElement;switch(j.propertyName){case"width":i.getContext().clearRect();i.style.width=i.attributes.width.nodeValue+"px";i.firstChild.style.width=i.clientWidth+"px";break;case"height":i.getContext().clearRect();i.style.height=i.attributes.height.nodeValue+"px";i.firstChild.style.height=i.clientHeight+"px";break}}function W(j){var i=j.srcElement;if(i.firstChild){i.firstChild.style.width=i.clientWidth+"px";i.firstChild.style.height=i.clientHeight+"px"}}e.init();var k=[];for(var ae=0;ae<16;ae++){for(var ad=0;ad<16;ad++){k[ae*16+ad]=ae.toString(16)+ad.toString(16)}}function B(){return[[1,0,0],[0,1,0],[0,0,1]]}function J(p,m){var j=B();for(var i=0;i<3;i++){for(var ah=0;ah<3;ah++){var Z=0;for(var ag=0;ag<3;ag++){Z+=p[i][ag]*m[ag][ah]}j[i][ah]=Z}}return j}function v(j,i){i.fillStyle=j.fillStyle;i.lineCap=j.lineCap;i.lineJoin=j.lineJoin;i.lineWidth=j.lineWidth;i.miterLimit=j.miterLimit;i.shadowBlur=j.shadowBlur;i.shadowColor=j.shadowColor;i.shadowOffsetX=j.shadowOffsetX;i.shadowOffsetY=j.shadowOffsetY;i.strokeStyle=j.strokeStyle;i.globalAlpha=j.globalAlpha;i.font=j.font;i.textAlign=j.textAlign;i.textBaseline=j.textBaseline;i.arcScaleX_=j.arcScaleX_;i.arcScaleY_=j.arcScaleY_;i.lineScale_=j.lineScale_}var b={aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC",bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",darkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgreen:"#006400",darkgrey:"#A9A9A9",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000",darksalmon:"#E9967A",darkseagreen:"#8FBC8F",darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",grey:"#808080",greenyellow:"#ADFF2F",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082",ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",lightgreen:"#90EE90",lightgrey:"#D3D3D3",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",limegreen:"#32CD32",linen:"#FAF0E6",magenta:"#FF00FF",mediumaquamarine:"#66CDAA",mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",oldlace:"#FDF5E6",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA",palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5",peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F",steelblue:"#4682B4",tan:"#D2B48C",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",wheat:"#F5DEB3",whitesmoke:"#F5F5F5",yellowgreen:"#9ACD32"};function M(j){var p=j.indexOf("(",3);var i=j.indexOf(")",p+1);var m=j.substring(p+1,i).split(",");if(m.length!=4||j.charAt(3)!="a"){m[3]=1}return m}function c(i){return parseFloat(i)/100}function r(j,m,i){return Math.min(i,Math.max(m,j))}function I(ag){var i,ai,aj,ah,ak,Z;ah=parseFloat(ag[0])/360%360;if(ah<0){ah++}ak=r(c(ag[1]),0,1);Z=r(c(ag[2]),0,1);if(ak==0){i=ai=aj=Z}else{var j=Z<0.5?Z*(1+ak):Z+ak-Z*ak;var m=2*Z-j;i=a(m,j,ah+1/3);ai=a(m,j,ah);aj=a(m,j,ah-1/3)}return"#"+k[Math.floor(i*255)]+k[Math.floor(ai*255)]+k[Math.floor(aj*255)]}function a(j,i,m){if(m<0){m++}if(m>1){m--}if(6*m<1){return j+(i-j)*6*m}else{if(2*m<1){return i}else{if(3*m<2){return j+(i-j)*(2/3-m)*6}else{return j}}}}var C={};function F(j){if(j in C){return C[j]}var ag,Z=1;j=String(j);if(j.charAt(0)=="#"){ag=j}else{if(/^rgb/.test(j)){var p=M(j);var ag="#",ah;for(var m=0;m<3;m++){if(p[m].indexOf("%")!=-1){ah=Math.floor(c(p[m])*255)}else{ah=+p[m]}ag+=k[r(ah,0,255)]}Z=+p[3]}else{if(/^hsl/.test(j)){var p=M(j);ag=I(p);Z=p[3]}else{ag=b[j]||j}}}return C[j]={color:ag,alpha:Z}}var o={style:"normal",variant:"normal",weight:"normal",size:10,family:"sans-serif"};var L={};function E(i){if(L[i]){return L[i]}var p=document.createElement("div");var m=p.style;try{m.font=i}catch(j){}return L[i]={style:m.fontStyle||o.style,variant:m.fontVariant||o.variant,weight:m.fontWeight||o.weight,size:m.fontSize||o.size,family:m.fontFamily||o.family}}function u(m,j){var i={};for(var ah in m){i[ah]=m[ah]}var ag=parseFloat(j.currentStyle.fontSize),Z=parseFloat(m.size);if(typeof m.size=="number"){i.size=m.size}else{if(m.size.indexOf("px")!=-1){i.size=Z}else{if(m.size.indexOf("em")!=-1){i.size=ag*Z}else{if(m.size.indexOf("%")!=-1){i.size=(ag/100)*Z}else{if(m.size.indexOf("pt")!=-1){i.size=Z/0.75}else{i.size=ag}}}}}i.size*=0.981;return i}function ac(i){return i.style+" "+i.variant+" "+i.weight+" "+i.size+"px "+i.family}var s={butt:"flat",round:"round"};function S(i){return s[i]||"square"}function D(i){this.m_=B();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.strokeStyle="#000";this.fillStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=d*1;this.globalAlpha=1;this.font="10px sans-serif";this.textAlign="left";this.textBaseline="alphabetic";this.canvas=i;var m="width:"+i.clientWidth+"px;height:"+i.clientHeight+"px;overflow:hidden;position:absolute";var j=i.ownerDocument.createElement("div");j.style.cssText=m;i.appendChild(j);var p=j.cloneNode(false);p.style.backgroundColor="red";p.style.filter="alpha(opacity=0)";i.appendChild(p);this.element_=j;this.arcScaleX_=1;this.arcScaleY_=1;this.lineScale_=1}var q=D.prototype;q.clearRect=function(){if(this.textMeasureEl_){this.textMeasureEl_.removeNode(true);this.textMeasureEl_=null}this.element_.innerHTML=""};q.beginPath=function(){this.currentPath_=[]};q.moveTo=function(j,i){var m=V(this,j,i);this.currentPath_.push({type:"moveTo",x:m.x,y:m.y});this.currentX_=m.x;this.currentY_=m.y};q.lineTo=function(j,i){var m=V(this,j,i);this.currentPath_.push({type:"lineTo",x:m.x,y:m.y});this.currentX_=m.x;this.currentY_=m.y};q.bezierCurveTo=function(m,j,ak,aj,ai,ag){var i=V(this,ai,ag);var ah=V(this,m,j);var Z=V(this,ak,aj);K(this,ah,Z,i)};function K(i,Z,m,j){i.currentPath_.push({type:"bezierCurveTo",cp1x:Z.x,cp1y:Z.y,cp2x:m.x,cp2y:m.y,x:j.x,y:j.y});i.currentX_=j.x;i.currentY_=j.y}q.quadraticCurveTo=function(ai,m,j,i){var ah=V(this,ai,m);var ag=V(this,j,i);var aj={x:this.currentX_+2/3*(ah.x-this.currentX_),y:this.currentY_+2/3*(ah.y-this.currentY_)};var Z={x:aj.x+(ag.x-this.currentX_)/3,y:aj.y+(ag.y-this.currentY_)/3};K(this,aj,Z,ag)};q.arc=function(al,aj,ak,ag,j,m){ak*=d;var ap=m?"at":"wa";var am=al+A(ag)*ak-f;var ao=aj+l(ag)*ak-f;var i=al+A(j)*ak-f;var an=aj+l(j)*ak-f;if(am==i&&!m){am+=0.125}var Z=V(this,al,aj);var ai=V(this,am,ao);var ah=V(this,i,an);this.currentPath_.push({type:ap,x:Z.x,y:Z.y,radius:ak,xStart:ai.x,yStart:ai.y,xEnd:ah.x,yEnd:ah.y})};q.rect=function(m,j,i,p){this.moveTo(m,j);this.lineTo(m+i,j);this.lineTo(m+i,j+p);this.lineTo(m,j+p);this.closePath()};q.strokeRect=function(m,j,i,p){var Z=this.currentPath_;this.beginPath();this.moveTo(m,j);this.lineTo(m+i,j);this.lineTo(m+i,j+p);this.lineTo(m,j+p);this.closePath();this.stroke();this.currentPath_=Z};q.fillRect=function(m,j,i,p){var Z=this.currentPath_;this.beginPath();this.moveTo(m,j);this.lineTo(m+i,j);this.lineTo(m+i,j+p);this.lineTo(m,j+p);this.closePath();this.fill();this.currentPath_=Z};q.createLinearGradient=function(j,p,i,m){var Z=new U("gradient");Z.x0_=j;Z.y0_=p;Z.x1_=i;Z.y1_=m;return Z};q.createRadialGradient=function(p,ag,m,j,Z,i){var ah=new U("gradientradial");ah.x0_=p;ah.y0_=ag;ah.r0_=m;ah.x1_=j;ah.y1_=Z;ah.r1_=i;return ah};q.drawImage=function(aq,m){var aj,ah,al,ay,ao,am,at,aA;var ak=aq.runtimeStyle.width;var ap=aq.runtimeStyle.height;aq.runtimeStyle.width="auto";aq.runtimeStyle.height="auto";var ai=aq.width;var aw=aq.height;aq.runtimeStyle.width=ak;aq.runtimeStyle.height=ap;if(arguments.length==3){aj=arguments[1];ah=arguments[2];ao=am=0;at=al=ai;aA=ay=aw}else{if(arguments.length==5){aj=arguments[1];ah=arguments[2];al=arguments[3];ay=arguments[4];ao=am=0;at=ai;aA=aw}else{if(arguments.length==9){ao=arguments[1];am=arguments[2];at=arguments[3];aA=arguments[4];aj=arguments[5];ah=arguments[6];al=arguments[7];ay=arguments[8]}else{throw Error("Invalid number of arguments")}}}var az=V(this,aj,ah);var p=at/2;var j=aA/2;var ax=[];var i=10;var ag=10;ax.push(" <g_vml_:group",' coordsize="',d*i,",",d*ag,'"',' coordorigin="0,0"',' style="width:',i,"px;height:",ag,"px;position:absolute;");if(this.m_[0][0]!=1||this.m_[0][1]||this.m_[1][1]!=1||this.m_[1][0]){var Z=[];Z.push("M11=",this.m_[0][0],",","M12=",this.m_[1][0],",","M21=",this.m_[0][1],",","M22=",this.m_[1][1],",","Dx=",n(az.x/d),",","Dy=",n(az.y/d),"");var av=az;var au=V(this,aj+al,ah);var ar=V(this,aj,ah+ay);var an=V(this,aj+al,ah+ay);av.x=ab.max(av.x,au.x,ar.x,an.x);av.y=ab.max(av.y,au.y,ar.y,an.y);ax.push("padding:0 ",n(av.x/d),"px ",n(av.y/d),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",Z.join(""),", sizingmethod='clip');")}else{ax.push("top:",n(az.y/d),"px;left:",n(az.x/d),"px;")}ax.push(' ">','<g_vml_:image src="',aq.src,'"',' style="width:',d*al,"px;"," height:",d*ay,'px"',' cropleft="',ao/ai,'"',' croptop="',am/aw,'"',' cropright="',(ai-ao-at)/ai,'"',' cropbottom="',(aw-am-aA)/aw,'"'," />","</g_vml_:group>");this.element_.insertAdjacentHTML("BeforeEnd",ax.join(""))};q.stroke=function(ao){var Z=10;var ap=10;var ag=5000;var ai={x:null,y:null};var an={x:null,y:null};for(var aj=0;aj<this.currentPath_.length;aj+=ag){var am=[];var ah=false;am.push("<g_vml_:shape",' filled="',!!ao,'"',' style="position:absolute;width:',Z,"px;height:",ap,'px;"',' coordorigin="0,0"',' coordsize="',d*Z,",",d*ap,'"',' stroked="',!ao,'"',' path="');var aq=false;for(var ak=aj;ak<Math.min(aj+ag,this.currentPath_.length);ak++){if(ak%ag==0&&ak>0){am.push(" m ",n(this.currentPath_[ak-1].x),",",n(this.currentPath_[ak-1].y))}var m=this.currentPath_[ak];var al;switch(m.type){case"moveTo":al=m;am.push(" m ",n(m.x),",",n(m.y));break;case"lineTo":am.push(" l ",n(m.x),",",n(m.y));break;case"close":am.push(" x ");m=null;break;case"bezierCurveTo":am.push(" c ",n(m.cp1x),",",n(m.cp1y),",",n(m.cp2x),",",n(m.cp2y),",",n(m.x),",",n(m.y));break;case"at":case"wa":am.push(" ",m.type," ",n(m.x-this.arcScaleX_*m.radius),",",n(m.y-this.arcScaleY_*m.radius)," ",n(m.x+this.arcScaleX_*m.radius),",",n(m.y+this.arcScaleY_*m.radius)," ",n(m.xStart),",",n(m.yStart)," ",n(m.xEnd),",",n(m.yEnd));break}if(m){if(ai.x==null||m.x<ai.x){ai.x=m.x}if(an.x==null||m.x>an.x){an.x=m.x}if(ai.y==null||m.y<ai.y){ai.y=m.y}if(an.y==null||m.y>an.y){an.y=m.y}}}am.push(' ">');if(!ao){w(this,am)}else{G(this,am,ai,an)}am.push("</g_vml_:shape>");this.element_.insertAdjacentHTML("beforeEnd",am.join(""))}};function w(m,ag){var j=F(m.strokeStyle);var p=j.color;var Z=j.alpha*m.globalAlpha;var i=m.lineScale_*m.lineWidth;if(i<1){Z*=i}ag.push("<g_vml_:stroke",' opacity="',Z,'"',' joinstyle="',m.lineJoin,'"',' miterlimit="',m.miterLimit,'"',' endcap="',S(m.lineCap),'"',' weight="',i,'px"',' color="',p,'" />')}function G(aq,ai,aK,ar){var aj=aq.fillStyle;var aB=aq.arcScaleX_;var aA=aq.arcScaleY_;var j=ar.x-aK.x;var p=ar.y-aK.y;if(aj instanceof U){var an=0;var aF={x:0,y:0};var ax=0;var am=1;if(aj.type_=="gradient"){var al=aj.x0_/aB;var m=aj.y0_/aA;var ak=aj.x1_/aB;var aM=aj.y1_/aA;var aJ=V(aq,al,m);var aI=V(aq,ak,aM);var ag=aI.x-aJ.x;var Z=aI.y-aJ.y;an=Math.atan2(ag,Z)*180/Math.PI;if(an<0){an+=360}if(an<0.000001){an=0}}else{var aJ=V(aq,aj.x0_,aj.y0_);aF={x:(aJ.x-aK.x)/j,y:(aJ.y-aK.y)/p};j/=aB*d;p/=aA*d;var aD=ab.max(j,p);ax=2*aj.r0_/aD;am=2*aj.r1_/aD-ax}var av=aj.colors_;av.sort(function(aN,i){return aN.offset-i.offset});var ap=av.length;var au=av[0].color;var at=av[ap-1].color;var az=av[0].alpha*aq.globalAlpha;var ay=av[ap-1].alpha*aq.globalAlpha;var aE=[];for(var aH=0;aH<ap;aH++){var ao=av[aH];aE.push(ao.offset*am+ax+" "+ao.color)}ai.push('<g_vml_:fill type="',aj.type_,'"',' method="none" focus="100%"',' color="',au,'"',' color2="',at,'"',' colors="',aE.join(","),'"',' opacity="',ay,'"',' g_o_:opacity2="',az,'"',' angle="',an,'"',' focusposition="',aF.x,",",aF.y,'" />')}else{if(aj instanceof T){if(j&&p){var ah=-aK.x;var aC=-aK.y;ai.push("<g_vml_:fill",' position="',ah/j*aB*aB,",",aC/p*aA*aA,'"',' type="tile"',' src="',aj.src_,'" />')}}else{var aL=F(aq.fillStyle);var aw=aL.color;var aG=aL.alpha*aq.globalAlpha;ai.push('<g_vml_:fill color="',aw,'" opacity="',aG,'" />')}}}q.fill=function(){this.stroke(true)};q.closePath=function(){this.currentPath_.push({type:"close"})};function V(j,Z,p){var i=j.m_;return{x:d*(Z*i[0][0]+p*i[1][0]+i[2][0])-f,y:d*(Z*i[0][1]+p*i[1][1]+i[2][1])-f}}q.save=function(){var i={};v(this,i);this.aStack_.push(i);this.mStack_.push(this.m_);this.m_=J(B(),this.m_)};q.restore=function(){if(this.aStack_.length){v(this.aStack_.pop(),this);this.m_=this.mStack_.pop()}};function h(i){return isFinite(i[0][0])&&isFinite(i[0][1])&&isFinite(i[1][0])&&isFinite(i[1][1])&&isFinite(i[2][0])&&isFinite(i[2][1])}function aa(j,i,p){if(!h(i)){return}j.m_=i;if(p){var Z=i[0][0]*i[1][1]-i[0][1]*i[1][0];j.lineScale_=N(H(Z))}}q.translate=function(m,j){var i=[[1,0,0],[0,1,0],[m,j,1]];aa(this,J(i,this.m_),false)};q.rotate=function(j){var p=A(j);var m=l(j);var i=[[p,m,0],[-m,p,0],[0,0,1]];aa(this,J(i,this.m_),false)};q.scale=function(m,j){this.arcScaleX_*=m;this.arcScaleY_*=j;var i=[[m,0,0],[0,j,0],[0,0,1]];aa(this,J(i,this.m_),true)};q.transform=function(Z,p,ah,ag,j,i){var m=[[Z,p,0],[ah,ag,0],[j,i,1]];aa(this,J(m,this.m_),true)};q.setTransform=function(ag,Z,ai,ah,p,j){var i=[[ag,Z,0],[ai,ah,0],[p,j,1]];aa(this,i,true)};q.drawText_=function(am,ak,aj,ap,ai){var ao=this.m_,at=1000,j=0,ar=at,ah={x:0,y:0},ag=[];var i=u(E(this.font),this.element_);var p=ac(i);var au=this.element_.currentStyle;var Z=this.textAlign.toLowerCase();switch(Z){case"left":case"center":case"right":break;case"end":Z=au.direction=="ltr"?"right":"left";break;case"start":Z=au.direction=="rtl"?"right":"left";break;default:Z="left"}switch(this.textBaseline){case"hanging":case"top":ah.y=i.size/1.75;break;case"middle":break;default:case null:case"alphabetic":case"ideographic":case"bottom":ah.y=-i.size/2.25;break}switch(Z){case"right":j=at;ar=0.05;break;case"center":j=ar=at/2;break}var aq=V(this,ak+ah.x,aj+ah.y);ag.push('<g_vml_:line from="',-j,' 0" to="',ar,' 0.05" ',' coordsize="100 100" coordorigin="0 0"',' filled="',!ai,'" stroked="',!!ai,'" style="position:absolute;width:1px;height:1px;">');if(ai){w(this,ag)}else{G(this,ag,{x:-j,y:0},{x:ar,y:i.size})}var an=ao[0][0].toFixed(3)+","+ao[1][0].toFixed(3)+","+ao[0][1].toFixed(3)+","+ao[1][1].toFixed(3)+",0,0";var al=n(aq.x/d)+","+n(aq.y/d);ag.push('<g_vml_:skew on="t" matrix="',an,'" ',' offset="',al,'" origin="',j,' 0" />','<g_vml_:path textpathok="true" />','<g_vml_:textpath on="true" string="',af(am),'" style="v-text-align:',Z,";font:",af(p),'" /></g_vml_:line>');this.element_.insertAdjacentHTML("beforeEnd",ag.join(""))};q.fillText=function(m,i,p,j){this.drawText_(m,i,p,j,false)};q.strokeText=function(m,i,p,j){this.drawText_(m,i,p,j,true)};q.measureText=function(m){if(!this.textMeasureEl_){var i='<span style="position:absolute;top:-20000px;left:0;padding:0;margin:0;border:none;white-space:pre;"></span>';this.element_.insertAdjacentHTML("beforeEnd",i);this.textMeasureEl_=this.element_.lastChild}var j=this.element_.ownerDocument;this.textMeasureEl_.innerHTML="";this.textMeasureEl_.style.font=this.font;this.textMeasureEl_.appendChild(j.createTextNode(m));return{width:this.textMeasureEl_.offsetWidth}};q.clip=function(){};q.arcTo=function(){};q.createPattern=function(j,i){return new T(j,i)};function U(i){this.type_=i;this.x0_=0;this.y0_=0;this.r0_=0;this.x1_=0;this.y1_=0;this.r1_=0;this.colors_=[]}U.prototype.addColorStop=function(j,i){i=F(i);this.colors_.push({offset:j,color:i.color,alpha:i.alpha})};function T(j,i){Q(j);switch(i){case"repeat":case null:case"":this.repetition_="repeat";break;case"repeat-x":case"repeat-y":case"no-repeat":this.repetition_=i;break;default:O("SYNTAX_ERR")}this.src_=j.src;this.width_=j.width;this.height_=j.height}function O(i){throw new P(i)}function Q(i){if(!i||i.nodeType!=1||i.tagName!="IMG"){O("TYPE_MISMATCH_ERR")}if(i.readyState!="complete"){O("INVALID_STATE_ERR")}}function P(i){this.code=this[i];this.message=i+": DOM Exception "+this.code}var X=P.prototype=new Error;X.INDEX_SIZE_ERR=1;X.DOMSTRING_SIZE_ERR=2;X.HIERARCHY_REQUEST_ERR=3;X.WRONG_DOCUMENT_ERR=4;X.INVALID_CHARACTER_ERR=5;X.NO_DATA_ALLOWED_ERR=6;X.NO_MODIFICATION_ALLOWED_ERR=7;X.NOT_FOUND_ERR=8;X.NOT_SUPPORTED_ERR=9;X.INUSE_ATTRIBUTE_ERR=10;X.INVALID_STATE_ERR=11;X.SYNTAX_ERR=12;X.INVALID_MODIFICATION_ERR=13;X.NAMESPACE_ERR=14;X.INVALID_ACCESS_ERR=15;X.VALIDATION_ERR=16;X.TYPE_MISMATCH_ERR=17;G_vmlCanvasManager=e;CanvasRenderingContext2D=D;CanvasGradient=U;CanvasPattern=T;DOMException=P})()};
\ No newline at end of file diff --git a/public/javascripts/jquery.flot.axislabels.js b/public/javascripts/jquery.flot.axislabels.js new file mode 100644 index 000000000..d75b03ba9 --- /dev/null +++ b/public/javascripts/jquery.flot.axislabels.js @@ -0,0 +1,451 @@ +/* +Axis Labels Plugin for flot. +http://github.com/markrcote/flot-axislabels + +Original code is Copyright (c) 2010 Xuan Luo. +Original code was released under the GPLv3 license by Xuan Luo, September 2010. +Original code was rereleased under the MIT license by Xuan Luo, April 2012. + +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. + */ + +(function ($) { + var options = { }; + + function canvasSupported() { + return !!document.createElement('canvas').getContext; + } + + function canvasTextSupported() { + if (!canvasSupported()) { + return false; + } + var dummy_canvas = document.createElement('canvas'); + var context = dummy_canvas.getContext('2d'); + return typeof context.fillText == 'function'; + } + + function css3TransitionSupported() { + var div = document.createElement('div'); + return typeof div.style.MozTransition != 'undefined' // Gecko + || typeof div.style.OTransition != 'undefined' // Opera + || typeof div.style.webkitTransition != 'undefined' // WebKit + || typeof div.style.transition != 'undefined'; + } + + + function AxisLabel(axisName, position, padding, plot, opts) { + this.axisName = axisName; + this.position = position; + this.padding = padding; + this.plot = plot; + this.opts = opts; + this.width = 0; + this.height = 0; + } + + AxisLabel.prototype.delete = function() { + }; + + + CanvasAxisLabel.prototype = new AxisLabel(); + CanvasAxisLabel.prototype.constructor = CanvasAxisLabel; + function CanvasAxisLabel(axisName, position, padding, plot, opts) { + AxisLabel.prototype.constructor.call(this, axisName, position, padding, + plot, opts); + } + + CanvasAxisLabel.prototype.calculateSize = function() { + if (!this.opts.axisLabelFontSizePixels) + this.opts.axisLabelFontSizePixels = 14; + if (!this.opts.axisLabelFontFamily) + this.opts.axisLabelFontFamily = 'sans-serif'; + + var textWidth = this.opts.axisLabelFontSizePixels + this.padding; + var textHeight = this.opts.axisLabelFontSizePixels + this.padding; + if (this.position == 'left' || this.position == 'right') { + this.width = this.opts.axisLabelFontSizePixels + this.padding; + this.height = 0; + } else { + this.width = 0; + this.height = this.opts.axisLabelFontSizePixels + this.padding; + } + }; + + CanvasAxisLabel.prototype.draw = function(box) { + var ctx = this.plot.getCanvas().getContext('2d'); + ctx.save(); + ctx.font = this.opts.axisLabelFontSizePixels + 'px ' + + this.opts.axisLabelFontFamily; + var width = ctx.measureText(this.opts.axisLabel).width; + var height = this.opts.axisLabelFontSizePixels; + var x, y, angle = 0; + if (this.position == 'top') { + x = box.left + box.width/2 - width/2; + y = box.top + height*0.72; + } else if (this.position == 'bottom') { + x = box.left + box.width/2 - width/2; + y = box.top + box.height - height*0.72; + } else if (this.position == 'left') { + x = box.left + height*0.72; + y = box.height/2 + box.top + width/2; + angle = -Math.PI/2; + } else if (this.position == 'right') { + x = box.left + box.width - height*0.72; + y = box.height/2 + box.top - width/2; + angle = Math.PI/2; + } + ctx.translate(x, y); + ctx.rotate(angle); + ctx.fillText(this.opts.axisLabel, 0, 0); + ctx.restore(); + }; + + + HtmlAxisLabel.prototype = new AxisLabel(); + HtmlAxisLabel.prototype.constructor = HtmlAxisLabel; + function HtmlAxisLabel(axisName, position, padding, plot, opts) { + AxisLabel.prototype.constructor.call(this, axisName, position, + padding, plot, opts); + this.elem = null; + } + + HtmlAxisLabel.prototype.calculateSize = function() { + var elem = $('<div class="axisLabels" style="position:absolute;">' + + this.opts.axisLabel + '</div>'); + this.plot.getPlaceholder().append(elem); + // store height and width of label itself, for use in draw() + this.labelWidth = elem.outerWidth(true); + this.labelHeight = elem.outerHeight(true); + elem.remove(); + + this.width = this.height = 0; + if (this.position == 'left' || this.position == 'right') { + this.width = this.labelWidth + this.padding; + } else { + this.height = this.labelHeight + this.padding; + } + }; + + HtmlAxisLabel.prototype.delete = function() { + if (this.elem) { + this.elem.remove(); + } + }; + + HtmlAxisLabel.prototype.draw = function(box) { + this.plot.getPlaceholder().find('#' + this.axisName + 'Label').remove(); + this.elem = $('<div id="' + this.axisName + + 'Label" " class="axisLabels" style="position:absolute;">' + + this.opts.axisLabel + '</div>'); + this.plot.getPlaceholder().append(this.elem); + if (this.position == 'top') { + this.elem.css('left', box.left + box.width/2 - this.labelWidth/2 + + 'px'); + this.elem.css('top', box.top + 'px'); + } else if (this.position == 'bottom') { + this.elem.css('left', box.left + box.width/2 - this.labelWidth/2 + + 'px'); + this.elem.css('top', box.top + box.height - this.labelHeight + + 'px'); + } else if (this.position == 'left') { + this.elem.css('top', box.top + box.height/2 - this.labelHeight/2 + + 'px'); + this.elem.css('left', box.left + 'px'); + } else if (this.position == 'right') { + this.elem.css('top', box.top + box.height/2 - this.labelHeight/2 + + 'px'); + this.elem.css('left', box.left + box.width - this.labelWidth + + 'px'); + } + }; + + + CssTransformAxisLabel.prototype = new HtmlAxisLabel(); + CssTransformAxisLabel.prototype.constructor = CssTransformAxisLabel; + function CssTransformAxisLabel(axisName, position, padding, plot, opts) { + HtmlAxisLabel.prototype.constructor.call(this, axisName, position, + padding, plot, opts); + } + + CssTransformAxisLabel.prototype.calculateSize = function() { + HtmlAxisLabel.prototype.calculateSize.call(this); + this.width = this.height = 0; + if (this.position == 'left' || this.position == 'right') { + this.width = this.labelHeight + this.padding; + } else { + this.height = this.labelHeight + this.padding; + } + }; + + CssTransformAxisLabel.prototype.transforms = function(degrees, x, y) { + var stransforms = { + '-moz-transform': '', + '-webkit-transform': '', + '-o-transform': '', + '-ms-transform': '' + }; + if (x != 0 || y != 0) { + var stdTranslate = ' translate(' + x + 'px, ' + y + 'px)'; + stransforms['-moz-transform'] += stdTranslate; + stransforms['-webkit-transform'] += stdTranslate; + stransforms['-o-transform'] += stdTranslate; + stransforms['-ms-transform'] += stdTranslate; + } + if (degrees != 0) { + var rotation = degrees / 90; + var stdRotate = ' rotate(' + degrees + 'deg)'; + stransforms['-moz-transform'] += stdRotate; + stransforms['-webkit-transform'] += stdRotate; + stransforms['-o-transform'] += stdRotate; + stransforms['-ms-transform'] += stdRotate; + } + var s = 'top: 0; left: 0; '; + for (var prop in stransforms) { + if (stransforms[prop]) { + s += prop + ':' + stransforms[prop] + ';'; + } + } + s += ';'; + return s; + }; + + CssTransformAxisLabel.prototype.calculateOffsets = function(box) { + var offsets = { x: 0, y: 0, degrees: 0 }; + if (this.position == 'bottom') { + offsets.x = box.left + box.width/2 - this.labelWidth/2; + offsets.y = box.top + box.height - this.labelHeight; + } else if (this.position == 'top') { + offsets.x = box.left + box.width/2 - this.labelWidth/2; + offsets.y = box.top; + } else if (this.position == 'left') { + offsets.degrees = -90; + offsets.x = box.left - this.labelWidth/2 + this.labelHeight/2; + offsets.y = box.height/2 + box.top; + } else if (this.position == 'right') { + offsets.degrees = 90; + offsets.x = box.left + box.width - this.labelWidth/2 + - this.labelHeight/2; + offsets.y = box.height/2 + box.top; + } + return offsets; + }; + + CssTransformAxisLabel.prototype.draw = function(box) { + this.plot.getPlaceholder().find("." + this.axisName + "Label").remove(); + var offsets = this.calculateOffsets(box); + this.elem = $('<div class="axisLabels ' + this.axisName + + 'Label" style="position:absolute; ' + + 'color: ' + this.opts.color + '; ' + + this.transforms(offsets.degrees, offsets.x, offsets.y) + + '">' + this.opts.axisLabel + '</div>'); + this.plot.getPlaceholder().append(this.elem); + }; + + + IeTransformAxisLabel.prototype = new CssTransformAxisLabel(); + IeTransformAxisLabel.prototype.constructor = IeTransformAxisLabel; + function IeTransformAxisLabel(axisName, position, padding, plot, opts) { + CssTransformAxisLabel.prototype.constructor.call(this, axisName, + position, padding, + plot, opts); + this.requiresResize = false; + } + + IeTransformAxisLabel.prototype.transforms = function(degrees, x, y) { + // I didn't feel like learning the crazy Matrix stuff, so this uses + // a combination of the rotation transform and CSS positioning. + var s = ''; + if (degrees != 0) { + var rotation = degrees/90; + while (rotation < 0) { + rotation += 4; + } + s += ' filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=' + rotation + '); '; + // see below + this.requiresResize = (this.position == 'right'); + } + if (x != 0) { + s += 'left: ' + x + 'px; '; + } + if (y != 0) { + s += 'top: ' + y + 'px; '; + } + return s; + }; + + IeTransformAxisLabel.prototype.calculateOffsets = function(box) { + var offsets = CssTransformAxisLabel.prototype.calculateOffsets.call( + this, box); + // adjust some values to take into account differences between + // CSS and IE rotations. + if (this.position == 'top') { + // FIXME: not sure why, but placing this exactly at the top causes + // the top axis label to flip to the bottom... + offsets.y = box.top + 1; + } else if (this.position == 'left') { + offsets.x = box.left; + offsets.y = box.height/2 + box.top - this.labelWidth/2; + } else if (this.position == 'right') { + offsets.x = box.left + box.width - this.labelHeight; + offsets.y = box.height/2 + box.top - this.labelWidth/2; + } + return offsets; + }; + + IeTransformAxisLabel.prototype.draw = function(box) { + CssTransformAxisLabel.prototype.draw.call(this, box); + if (this.requiresResize) { + this.elem = this.plot.getPlaceholder().find("." + this.axisName + + "Label"); + // Since we used CSS positioning instead of transforms for + // translating the element, and since the positioning is done + // before any rotations, we have to reset the width and height + // in case the browser wrapped the text (specifically for the + // y2axis). + this.elem.css('width', this.labelWidth); + this.elem.css('height', this.labelHeight); + } + }; + + + function init(plot) { + // This is kind of a hack. There are no hooks in Flot between + // the creation and measuring of the ticks (setTicks, measureTickLabels + // in setupGrid() ) and the drawing of the ticks and plot box + // (insertAxisLabels in setupGrid() ). + // + // Therefore, we use a trick where we run the draw routine twice: + // the first time to get the tick measurements, so that we can change + // them, and then have it draw it again. + var secondPass = false; + + var axisLabels = {}; + var axisOffsetCounts = { left: 0, right: 0, top: 0, bottom: 0 }; + + var defaultPadding = 2; // padding between axis and tick labels + plot.hooks.draw.push(function (plot, ctx) { + var hasAxisLabels = false; + if (!secondPass) { + // MEASURE AND SET OPTIONS + $.each(plot.getAxes(), function(axisName, axis) { + var opts = axis.options // Flot 0.7 + || plot.getOptions()[axisName]; // Flot 0.6 + + // Handle redraws initiated outside of this plug-in. + if (axisName in axisLabels) { + axis.labelHeight = axis.labelHeight - + axisLabels[axisName].height; + axis.labelWidth = axis.labelWidth - + axisLabels[axisName].width; + opts.labelHeight = axis.labelHeight; + opts.labelWidth = axis.labelWidth; + axisLabels[axisName].delete(); + delete axisLabels[axisName]; + } + + if (!opts || !opts.axisLabel || !axis.show) + return; + + hasAxisLabels = true; + var renderer = null; + + if (!opts.axisLabelUseHtml && + navigator.appName == 'Microsoft Internet Explorer') { + var ua = navigator.userAgent; + var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); + if (re.exec(ua) != null) { + rv = parseFloat(RegExp.$1); + } + if (rv >= 9 && !opts.axisLabelUseCanvas && !opts.axisLabelUseHtml) { + renderer = CssTransformAxisLabel; + } else if (!opts.axisLabelUseCanvas && !opts.axisLabelUseHtml) { + renderer = IeTransformAxisLabel; + } else if (opts.axisLabelUseCanvas) { + renderer = CanvasAxisLabel; + } else { + renderer = HtmlAxisLabel; + } + } else { + if (opts.axisLabelUseHtml || (!css3TransitionSupported() && !canvasTextSupported()) && !opts.axisLabelUseCanvas) { + renderer = HtmlAxisLabel; + } else if (opts.axisLabelUseCanvas || !css3TransitionSupported()) { + renderer = CanvasAxisLabel; + } else { + renderer = CssTransformAxisLabel; + } + } + + var padding = opts.axisLabelPadding === undefined ? + defaultPadding : opts.axisLabelPadding; + + axisLabels[axisName] = new renderer(axisName, + axis.position, padding, + plot, opts); + + // flot interprets axis.labelHeight and .labelWidth as + // the height and width of the tick labels. We increase + // these values to make room for the axis label and + // padding. + + axisLabels[axisName].calculateSize(); + + // AxisLabel.height and .width are the size of the + // axis label and padding. + // Just set opts here because axis will be sorted out on + // the redraw. + + opts.labelHeight = axis.labelHeight + + axisLabels[axisName].height; + opts.labelWidth = axis.labelWidth + + axisLabels[axisName].width; + }); + + // If there are axis labels, re-draw with new label widths and + // heights. + + if (hasAxisLabels) { + secondPass = true; + plot.setupGrid(); + plot.draw(); + } + } else { + secondPass = false; + // DRAW + $.each(plot.getAxes(), function(axisName, axis) { + var opts = axis.options // Flot 0.7 + || plot.getOptions()[axisName]; // Flot 0.6 + if (!opts || !opts.axisLabel || !axis.show) + return; + + axisLabels[axisName].draw(axis.box); + }); + } + }); + } + + + $.plot.plugins.push({ + init: init, + options: options, + name: 'axisLabels', + version: '2.0b0' + }); +})(jQuery); diff --git a/public/javascripts/jquery.flot.errorbars.min.js b/public/javascripts/jquery.flot.errorbars.min.js new file mode 100644 index 000000000..72d7e3dc7 --- /dev/null +++ b/public/javascripts/jquery.flot.errorbars.min.js @@ -0,0 +1,63 @@ +/* Flot plugin for plotting error bars. + +Copyright (c) 2007-2013 IOLA and Ole Laursen. +Licensed under the MIT license. + +Error bars are used to show standard deviation and other statistical +properties in a plot. + +* Created by Rui Pereira - rui (dot) pereira (at) gmail (dot) com + +This plugin allows you to plot error-bars over points. Set "errorbars" inside +the points series to the axis name over which there will be error values in +your data array (*even* if you do not intend to plot them later, by setting +"show: null" on xerr/yerr). + +The plugin supports these options: + + series: { + points: { + errorbars: "x" or "y" or "xy", + xerr: { + show: null/false or true, + asymmetric: null/false or true, + upperCap: null or "-" or function, + lowerCap: null or "-" or function, + color: null or color, + radius: null or number + }, + yerr: { same options as xerr } + } + } + +Each data point array is expected to be of the type: + + "x" [ x, y, xerr ] + "y" [ x, y, yerr ] + "xy" [ x, y, xerr, yerr ] + +Where xerr becomes xerr_lower,xerr_upper for the asymmetric error case, and +equivalently for yerr. Eg., a datapoint for the "xy" case with symmetric +error-bars on X and asymmetric on Y would be: + + [ x, y, xerr, yerr_lower, yerr_upper ] + +By default no end caps are drawn. Setting upperCap and/or lowerCap to "-" will +draw a small cap perpendicular to the error bar. They can also be set to a +user-defined drawing function, with (ctx, x, y, radius) as parameters, as eg. + + function drawSemiCircle( ctx, x, y, radius ) { + ctx.beginPath(); + ctx.arc( x, y, radius, 0, Math.PI, false ); + ctx.moveTo( x - radius, y ); + ctx.lineTo( x + radius, y ); + ctx.stroke(); + } + +Color and radius both default to the same ones of the points series if not +set. The independent radius parameter on xerr/yerr is useful for the case when +we may want to add error-bars to a line, without showing the interconnecting +points (with radius: 0), and still showing end caps on the error-bars. +shadowSize and lineWidth are derived as well from the points series. + +*/(function(e){function n(e,t,n,r){if(!t.points.errorbars)return;var i=[{x:!0,number:!0,required:!0},{y:!0,number:!0,required:!0}],s=t.points.errorbars;if(s=="x"||s=="xy")t.points.xerr.asymmetric?(i.push({x:!0,number:!0,required:!0}),i.push({x:!0,number:!0,required:!0})):i.push({x:!0,number:!0,required:!0});if(s=="y"||s=="xy")t.points.yerr.asymmetric?(i.push({y:!0,number:!0,required:!0}),i.push({y:!0,number:!0,required:!0})):i.push({y:!0,number:!0,required:!0});r.format=i}function r(e,t){var n=e.datapoints.points,r=null,i=null,s=null,o=null,u=e.points.xerr,a=e.points.yerr,f=e.points.errorbars;f=="x"||f=="xy"?u.asymmetric?(r=n[t+2],i=n[t+3],f=="xy"&&(a.asymmetric?(s=n[t+4],o=n[t+5]):s=n[t+4])):(r=n[t+2],f=="xy"&&(a.asymmetric?(s=n[t+3],o=n[t+4]):s=n[t+3])):f=="y"&&(a.asymmetric?(s=n[t+2],o=n[t+3]):s=n[t+2]),i==null&&(i=r),o==null&&(o=s);var l=[r,i,s,o];return u.show||(l[0]=null,l[1]=null),a.show||(l[2]=null,l[3]=null),l}function i(e,t,n){var i=n.datapoints.points,o=n.datapoints.pointsize,u=[n.xaxis,n.yaxis],a=n.points.radius,f=[n.points.xerr,n.points.yerr],l=!1;if(u[0].p2c(u[0].max)<u[0].p2c(u[0].min)){l=!0;var c=f[0].lowerCap;f[0].lowerCap=f[0].upperCap,f[0].upperCap=c}var h=!1;if(u[1].p2c(u[1].min)<u[1].p2c(u[1].max)){h=!0;var c=f[1].lowerCap;f[1].lowerCap=f[1].upperCap,f[1].upperCap=c}for(var p=0;p<n.datapoints.points.length;p+=o){var d=r(n,p);for(var v=0;v<f.length;v++){var m=[u[v].min,u[v].max];if(d[v*f.length]){var g=i[p],y=i[p+1],b=[g,y][v]+d[v*f.length+1],w=[g,y][v]-d[v*f.length];if(f[v].err=="x")if(y>u[1].max||y<u[1].min||b<u[0].min||w>u[0].max)continue;if(f[v].err=="y")if(g>u[0].max||g<u[0].min||b<u[1].min||w>u[1].max)continue;var E=!0,S=!0;b>m[1]&&(E=!1,b=m[1]),w<m[0]&&(S=!1,w=m[0]);if(f[v].err=="x"&&l||f[v].err=="y"&&h){var c=w;w=b,b=c,c=S,S=E,E=c,c=m[0],m[0]=m[1],m[1]=c}g=u[0].p2c(g),y=u[1].p2c(y),b=u[v].p2c(b),w=u[v].p2c(w),m[0]=u[v].p2c(m[0]),m[1]=u[v].p2c(m[1]);var x=f[v].lineWidth?f[v].lineWidth:n.points.lineWidth,T=n.points.shadowSize!=null?n.points.shadowSize:n.shadowSize;if(x>0&&T>0){var N=T/2;t.lineWidth=N,t.strokeStyle="rgba(0,0,0,0.1)",s(t,f[v],g,y,b,w,E,S,a,N+N/2,m),t.strokeStyle="rgba(0,0,0,0.2)",s(t,f[v],g,y,b,w,E,S,a,N/2,m)}t.strokeStyle=f[v].color?f[v].color:n.color,t.lineWidth=x,s(t,f[v],g,y,b,w,E,S,a,0,m)}}}}function s(t,n,r,i,s,u,a,f,l,c,h){i+=c,s+=c,u+=c,n.err=="x"?(s>r+l?o(t,[[s,i],[Math.max(r+l,h[0]),i]]):a=!1,u<r-l?o(t,[[Math.min(r-l,h[1]),i],[u,i]]):f=!1):(s<i-l?o(t,[[r,s],[r,Math.min(i-l,h[0])]]):a=!1,u>i+l?o(t,[[r,Math.max(i+l,h[1])],[r,u]]):f=!1),l=n.radius!=null?n.radius:l,a&&(n.upperCap=="-"?n.err=="x"?o(t,[[s,i-l],[s,i+l]]):o(t,[[r-l,s],[r+l,s]]):e.isFunction(n.upperCap)&&(n.err=="x"?n.upperCap(t,s,i,l):n.upperCap(t,r,s,l))),f&&(n.lowerCap=="-"?n.err=="x"?o(t,[[u,i-l],[u,i+l]]):o(t,[[r-l,u],[r+l,u]]):e.isFunction(n.lowerCap)&&(n.err=="x"?n.lowerCap(t,u,i,l):n.lowerCap(t,r,u,l)))}function o(e,t){e.beginPath(),e.moveTo(t[0][0],t[0][1]);for(var n=1;n<t.length;n++)e.lineTo(t[n][0],t[n][1]);e.stroke()}function u(t,n){var r=t.getPlotOffset();n.save(),n.translate(r.left,r.top),e.each(t.getData(),function(e,r){r.points.errorbars&&(r.points.xerr.show||r.points.yerr.show)&&i(t,n,r)}),n.restore()}function a(e){e.hooks.processRawData.push(n),e.hooks.draw.push(u)}var t={series:{points:{errorbars:null,xerr:{err:"x",show:null,asymmetric:null,upperCap:null,lowerCap:null,color:null,radius:null},yerr:{err:"y",show:null,asymmetric:null,upperCap:null,lowerCap:null,color:null,radius:null}}}};e.plot.plugins.push({init:a,options:t,name:"errorbars",version:"1.0"})})(jQuery);
\ No newline at end of file diff --git a/public/javascripts/jquery.flot.min.js b/public/javascripts/jquery.flot.min.js new file mode 100644 index 000000000..3706512c4 --- /dev/null +++ b/public/javascripts/jquery.flot.min.js @@ -0,0 +1,29 @@ +/* Javascript plotting library for jQuery, version 0.8.1. + +Copyright (c) 2007-2013 IOLA and Ole Laursen. +Licensed under the MIT license. + +*/// first an inline dependency, jquery.colorhelpers.js, we inline it here +// for convenience +/* Plugin for jQuery for working with colors. + * + * Version 1.1. + * + * Inspiration from jQuery color animation plugin by John Resig. + * + * Released under the MIT license by Ole Laursen, October 2009. + * + * Examples: + * + * $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString() + * var c = $.color.extract($("#mydiv"), 'background-color'); + * console.log(c.r, c.g, c.b, c.a); + * $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)" + * + * Note that .scale() and .add() return the same modified object + * instead of making a new one. + * + * V. 1.1: Fix error handling so e.g. parsing an empty string does + * produce a color rather than just crashing. + */(function(e){e.color={},e.color.make=function(t,n,r,i){var s={};return s.r=t||0,s.g=n||0,s.b=r||0,s.a=i!=null?i:1,s.add=function(e,t){for(var n=0;n<e.length;++n)s[e.charAt(n)]+=t;return s.normalize()},s.scale=function(e,t){for(var n=0;n<e.length;++n)s[e.charAt(n)]*=t;return s.normalize()},s.toString=function(){return s.a>=1?"rgb("+[s.r,s.g,s.b].join(",")+")":"rgba("+[s.r,s.g,s.b,s.a].join(",")+")"},s.normalize=function(){function e(e,t,n){return t<e?e:t>n?n:t}return s.r=e(0,parseInt(s.r),255),s.g=e(0,parseInt(s.g),255),s.b=e(0,parseInt(s.b),255),s.a=e(0,s.a,1),s},s.clone=function(){return e.color.make(s.r,s.b,s.g,s.a)},s.normalize()},e.color.extract=function(t,n){var r;do{r=t.css(n).toLowerCase();if(r!=""&&r!="transparent")break;t=t.parent()}while(!e.nodeName(t.get(0),"body"));return r=="rgba(0, 0, 0, 0)"&&(r="transparent"),e.color.parse(r)},e.color.parse=function(n){var r,i=e.color.make;if(r=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(n))return i(parseInt(r[1],10),parseInt(r[2],10),parseInt(r[3],10));if(r=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(n))return i(parseInt(r[1],10),parseInt(r[2],10),parseInt(r[3],10),parseFloat(r[4]));if(r=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(n))return i(parseFloat(r[1])*2.55,parseFloat(r[2])*2.55,parseFloat(r[3])*2.55);if(r=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(n))return i(parseFloat(r[1])*2.55,parseFloat(r[2])*2.55,parseFloat(r[3])*2.55,parseFloat(r[4]));if(r=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(n))return i(parseInt(r[1],16),parseInt(r[2],16),parseInt(r[3],16));if(r=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(n))return i(parseInt(r[1]+r[1],16),parseInt(r[2]+r[2],16),parseInt(r[3]+r[3],16));var s=e.trim(n).toLowerCase();return s=="transparent"?i(255,255,255,0):(r=t[s]||[0,0,0],i(r[0],r[1],r[2]))};var t={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery),function(e){function n(t,n){var r=n.children("."+t)[0];if(r==null){r=document.createElement("canvas"),r.className=t,e(r).css({direction:"ltr",position:"absolute",left:0,top:0}).appendTo(n);if(!r.getContext){if(!window.G_vmlCanvasManager)throw new Error("Canvas is not available. If you're using IE with a fall-back such as Excanvas, then there's either a mistake in your conditional include, or the page has no DOCTYPE and is rendering in Quirks Mode.");r=window.G_vmlCanvasManager.initElement(r)}}this.element=r;var i=this.context=r.getContext("2d"),s=window.devicePixelRatio||1,o=i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1;this.pixelRatio=s/o,this.resize(n.width(),n.height()),this.textContainer=null,this.text={},this._textCache={}}function r(t,r,s,o){function E(e,t){t=[w].concat(t);for(var n=0;n<e.length;++n)e[n].apply(this,t)}function S(){var t={Canvas:n};for(var r=0;r<o.length;++r){var i=o[r];i.init(w,t),i.options&&e.extend(!0,a,i.options)}}function x(n){e.extend(!0,a,n),n&&n.colors&&(a.colors=n.colors),a.xaxis.color==null&&(a.xaxis.color=e.color.parse(a.grid.color).scale("a",.22).toString()),a.yaxis.color==null&&(a.yaxis.color=e.color.parse(a.grid.color).scale("a",.22).toString()),a.xaxis.tickColor==null&&(a.xaxis.tickColor=a.grid.tickColor||a.xaxis.color),a.yaxis.tickColor==null&&(a.yaxis.tickColor=a.grid.tickColor||a.yaxis.color),a.grid.borderColor==null&&(a.grid.borderColor=a.grid.color),a.grid.tickColor==null&&(a.grid.tickColor=e.color.parse(a.grid.color).scale("a",.22).toString());var r,i,s,o={style:t.css("font-style"),size:Math.round(.8*(+t.css("font-size").replace("px","")||13)),variant:t.css("font-variant"),weight:t.css("font-weight"),family:t.css("font-family")};o.lineHeight=o.size*1.15,s=a.xaxes.length||1;for(r=0;r<s;++r)i=a.xaxes[r],i&&!i.tickColor&&(i.tickColor=i.color),i=e.extend(!0,{},a.xaxis,i),a.xaxes[r]=i,i.font&&(i.font=e.extend({},o,i.font),i.font.color||(i.font.color=i.color));s=a.yaxes.length||1;for(r=0;r<s;++r)i=a.yaxes[r],i&&!i.tickColor&&(i.tickColor=i.color),i=e.extend(!0,{},a.yaxis,i),a.yaxes[r]=i,i.font&&(i.font=e.extend({},o,i.font),i.font.color||(i.font.color=i.color));a.xaxis.noTicks&&a.xaxis.ticks==null&&(a.xaxis.ticks=a.xaxis.noTicks),a.yaxis.noTicks&&a.yaxis.ticks==null&&(a.yaxis.ticks=a.yaxis.noTicks),a.x2axis&&(a.xaxes[1]=e.extend(!0,{},a.xaxis,a.x2axis),a.xaxes[1].position="top"),a.y2axis&&(a.yaxes[1]=e.extend(!0,{},a.yaxis,a.y2axis),a.yaxes[1].position="right"),a.grid.coloredAreas&&(a.grid.markings=a.grid.coloredAreas),a.grid.coloredAreasColor&&(a.grid.markingsColor=a.grid.coloredAreasColor),a.lines&&e.extend(!0,a.series.lines,a.lines),a.points&&e.extend(!0,a.series.points,a.points),a.bars&&e.extend(!0,a.series.bars,a.bars),a.shadowSize!=null&&(a.series.shadowSize=a.shadowSize),a.highlightColor!=null&&(a.series.highlightColor=a.highlightColor);for(r=0;r<a.xaxes.length;++r)O(d,r+1).options=a.xaxes[r];for(r=0;r<a.yaxes.length;++r)O(v,r+1).options=a.yaxes[r];for(var u in b)a.hooks[u]&&a.hooks[u].length&&(b[u]=b[u].concat(a.hooks[u]));E(b.processOptions,[a])}function T(e){u=N(e),M(),_()}function N(t){var n=[];for(var r=0;r<t.length;++r){var i=e.extend(!0,{},a.series);t[r].data!=null?(i.data=t[r].data,delete t[r].data,e.extend(!0,i,t[r]),t[r].data=i.data):i.data=t[r],n.push(i)}return n}function C(e,t){var n=e[t+"axis"];return typeof n=="object"&&(n=n.n),typeof n!="number"&&(n=1),n}function k(){return e.grep(d.concat(v),function(e){return e})}function L(e){var t={},n,r;for(n=0;n<d.length;++n)r=d[n],r&&r.used&&(t["x"+r.n]=r.c2p(e.left));for(n=0;n<v.length;++n)r=v[n],r&&r.used&&(t["y"+r.n]=r.c2p(e.top));return t.x1!==undefined&&(t.x=t.x1),t.y1!==undefined&&(t.y=t.y1),t}function A(e){var t={},n,r,i;for(n=0;n<d.length;++n){r=d[n];if(r&&r.used){i="x"+r.n,e[i]==null&&r.n==1&&(i="x");if(e[i]!=null){t.left=r.p2c(e[i]);break}}}for(n=0;n<v.length;++n){r=v[n];if(r&&r.used){i="y"+r.n,e[i]==null&&r.n==1&&(i="y");if(e[i]!=null){t.top=r.p2c(e[i]);break}}}return t}function O(t,n){return t[n-1]||(t[n-1]={n:n,direction:t==d?"x":"y",options:e.extend(!0,{},t==d?a.xaxis:a.yaxis)}),t[n-1]}function M(){var t=u.length,n=-1,r;for(r=0;r<u.length;++r){var i=u[r].color;i!=null&&(t--,typeof i=="number"&&i>n&&(n=i))}t<=n&&(t=n+1);var s,o=[],f=a.colors,l=f.length,c=0;for(r=0;r<t;r++)s=e.color.parse(f[r%l]||"#666"),r%l==0&&r&&(c>=0?c<.5?c=-c-.2:c=0:c=-c),o[r]=s.scale("rgb",1+c);var h=0,p;for(r=0;r<u.length;++r){p=u[r],p.color==null?(p.color=o[h].toString(),++h):typeof p.color=="number"&&(p.color=o[p.color].toString());if(p.lines.show==null){var m,g=!0;for(m in p)if(p[m]&&p[m].show){g=!1;break}g&&(p.lines.show=!0)}p.lines.zero==null&&(p.lines.zero=!!p.lines.fill),p.xaxis=O(d,C(p,"x")),p.yaxis=O(v,C(p,"y"))}}function _(){function x(e,t,n){t<e.datamin&&t!=-r&&(e.datamin=t),n>e.datamax&&n!=r&&(e.datamax=n)}var t=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY,r=Number.MAX_VALUE,i,s,o,a,f,l,c,h,p,d,v,m,g,y,w,S;e.each(k(),function(e,r){r.datamin=t,r.datamax=n,r.used=!1});for(i=0;i<u.length;++i)l=u[i],l.datapoints={points:[]},E(b.processRawData,[l,l.data,l.datapoints]);for(i=0;i<u.length;++i){l=u[i],w=l.data,S=l.datapoints.format;if(!S){S=[],S.push({x:!0,number:!0,required:!0}),S.push({y:!0,number:!0,required:!0});if(l.bars.show||l.lines.show&&l.lines.fill){var T=!!(l.bars.show&&l.bars.zero||l.lines.show&&l.lines.zero);S.push({y:!0,number:!0,required:!1,defaultValue:0,autoscale:T}),l.bars.horizontal&&(delete S[S.length-1].y,S[S.length-1].x=!0)}l.datapoints.format=S}if(l.datapoints.pointsize!=null)continue;l.datapoints.pointsize=S.length,h=l.datapoints.pointsize,c=l.datapoints.points;var N=l.lines.show&&l.lines.steps;l.xaxis.used=l.yaxis.used=!0;for(s=o=0;s<w.length;++s,o+=h){y=w[s];var C=y==null;if(!C)for(a=0;a<h;++a)m=y[a],g=S[a],g&&(g.number&&m!=null&&(m=+m,isNaN(m)?m=null:m==Infinity?m=r:m==-Infinity&&(m=-r)),m==null&&(g.required&&(C=!0),g.defaultValue!=null&&(m=g.defaultValue))),c[o+a]=m;if(C)for(a=0;a<h;++a)m=c[o+a],m!=null&&(g=S[a],g.autoscale&&(g.x&&x(l.xaxis,m,m),g.y&&x(l.yaxis,m,m))),c[o+a]=null;else if(N&&o>0&&c[o-h]!=null&&c[o-h]!=c[o]&&c[o-h+1]!=c[o+1]){for(a=0;a<h;++a)c[o+h+a]=c[o+a];c[o+1]=c[o-h+1],o+=h}}}for(i=0;i<u.length;++i)l=u[i],E(b.processDatapoints,[l,l.datapoints]);for(i=0;i<u.length;++i){l=u[i],c=l.datapoints.points,h=l.datapoints.pointsize,S=l.datapoints.format;var L=t,A=t,O=n,M=n;for(s=0;s<c.length;s+=h){if(c[s]==null)continue;for(a=0;a<h;++a){m=c[s+a],g=S[a];if(!g||g.autoscale===!1||m==r||m==-r)continue;g.x&&(m<L&&(L=m),m>O&&(O=m)),g.y&&(m<A&&(A=m),m>M&&(M=m))}}if(l.bars.show){var _;switch(l.bars.align){case"left":_=0;break;case"right":_=-l.bars.barWidth;break;case"center":_=-l.bars.barWidth/2;break;default:throw new Error("Invalid bar alignment: "+l.bars.align)}l.bars.horizontal?(A+=_,M+=_+l.bars.barWidth):(L+=_,O+=_+l.bars.barWidth)}x(l.xaxis,L,O),x(l.yaxis,A,M)}e.each(k(),function(e,r){r.datamin==t&&(r.datamin=null),r.datamax==n&&(r.datamax=null)})}function D(){t.css("padding",0).children(":not(.flot-base,.flot-overlay)").remove(),t.css("position")=="static"&&t.css("position","relative"),f=new n("flot-base",t),l=new n("flot-overlay",t),h=f.context,p=l.context,c=e(l.element).unbind();var r=t.data("plot");r&&(r.shutdown(),l.clear()),t.data("plot",w)}function P(){a.grid.hoverable&&(c.mousemove(at),c.bind("mouseleave",ft)),a.grid.clickable&&c.click(lt),E(b.bindEvents,[c])}function H(){ot&&clearTimeout(ot),c.unbind("mousemove",at),c.unbind("mouseleave",ft),c.unbind("click",lt),E(b.shutdown,[c])}function B(e){function t(e){return e}var n,r,i=e.options.transform||t,s=e.options.inverseTransform;e.direction=="x"?(n=e.scale=g/Math.abs(i(e.max)-i(e.min)),r=Math.min(i(e.max),i(e.min))):(n=e.scale=y/Math.abs(i(e.max)-i(e.min)),n=-n,r=Math.max(i(e.max),i(e.min))),i==t?e.p2c=function(e){return(e-r)*n}:e.p2c=function(e){return(i(e)-r)*n},s?e.c2p=function(e){return s(r+e/n)}:e.c2p=function(e){return r+e/n}}function j(e){var t=e.options,n=e.ticks||[],r=t.labelWidth||0,i=t.labelHeight||0,s=r||e.direction=="x"?Math.floor(f.width/(n.length||1)):null;legacyStyles=e.direction+"Axis "+e.direction+e.n+"Axis",layer="flot-"+e.direction+"-axis flot-"+e.direction+e.n+"-axis "+legacyStyles,font=t.font||"flot-tick-label tickLabel";for(var o=0;o<n.length;++o){var u=n[o];if(!u.label)continue;var a=f.getTextInfo(layer,u.label,font,null,s);r=Math.max(r,a.width),i=Math.max(i,a.height)}e.labelWidth=t.labelWidth||r,e.labelHeight=t.labelHeight||i}function F(t){var n=t.labelWidth,r=t.labelHeight,i=t.options.position,s=t.options.tickLength,o=a.grid.axisMargin,u=a.grid.labelMargin,l=t.direction=="x"?d:v,c,h,p=e.grep(l,function(e){return e&&e.options.position==i&&e.reserveSpace});e.inArray(t,p)==p.length-1&&(o=0);if(s==null){var g=e.grep(l,function(e){return e&&e.reserveSpace});h=e.inArray(t,g)==0,h?s="full":s=5}isNaN(+s)||(u+=+s),t.direction=="x"?(r+=u,i=="bottom"?(m.bottom+=r+o,t.box={top:f.height-m.bottom,height:r}):(t.box={top:m.top+o,height:r},m.top+=r+o)):(n+=u,i=="left"?(t.box={left:m.left+o,width:n},m.left+=n+o):(m.right+=n+o,t.box={left:f.width-m.right,width:n})),t.position=i,t.tickLength=s,t.box.padding=u,t.innermost=h}function I(e){e.direction=="x"?(e.box.left=m.left-e.labelWidth/2,e.box.width=f.width-m.left-m.right+e.labelWidth):(e.box.top=m.top-e.labelHeight/2,e.box.height=f.height-m.bottom-m.top+e.labelHeight)}function q(){var t=a.grid.minBorderMargin,n={x:0,y:0},r,i;if(t==null){t=0;for(r=0;r<u.length;++r)t=Math.max(t,2*(u[r].points.radius+u[r].points.lineWidth/2))}n.x=n.y=Math.ceil(t),e.each(k(),function(e,t){var r=t.direction;t.reserveSpace&&(n[r]=Math.ceil(Math.max(n[r],(r=="x"?t.labelWidth:t.labelHeight)/2)))}),m.left=Math.max(n.x,m.left),m.right=Math.max(n.x,m.right),m.top=Math.max(n.y,m.top),m.bottom=Math.max(n.y,m.bottom)}function R(){var t,n=k(),r=a.grid.show;for(var i in m){var s=a.grid.margin||0;m[i]=typeof s=="number"?s:s[i]||0}E(b.processOffset,[m]);for(var i in m)typeof a.grid.borderWidth=="object"?m[i]+=r?a.grid.borderWidth[i]:0:m[i]+=r?a.grid.borderWidth:0;e.each(n,function(e,t){t.show=t.options.show,t.show==null&&(t.show=t.used),t.reserveSpace=t.show||t.options.reserveSpace,U(t)});if(r){var o=e.grep(n,function(e){return e.reserveSpace});e.each(o,function(e,t){z(t),W(t),X(t,t.ticks),j(t)});for(t=o.length-1;t>=0;--t)F(o[t]);q(),e.each(o,function(e,t){I(t)})}g=f.width-m.left-m.right,y=f.height-m.bottom-m.top,e.each(n,function(e,t){B(t)}),r&&G(),it()}function U(e){var t=e.options,n=+(t.min!=null?t.min:e.datamin),r=+(t.max!=null?t.max:e.datamax),i=r-n;if(i==0){var s=r==0?1:.01;t.min==null&&(n-=s);if(t.max==null||t.min!=null)r+=s}else{var o=t.autoscaleMargin;o!=null&&(t.min==null&&(n-=i*o,n<0&&e.datamin!=null&&e.datamin>=0&&(n=0)),t.max==null&&(r+=i*o,r>0&&e.datamax!=null&&e.datamax<=0&&(r=0)))}e.min=n,e.max=r}function z(t){var n=t.options,r;typeof n.ticks=="number"&&n.ticks>0?r=n.ticks:r=.3*Math.sqrt(t.direction=="x"?f.width:f.height);var s=(t.max-t.min)/r,o=-Math.floor(Math.log(s)/Math.LN10),u=n.tickDecimals;u!=null&&o>u&&(o=u);var a=Math.pow(10,-o),l=s/a,c;l<1.5?c=1:l<3?(c=2,l>2.25&&(u==null||o+1<=u)&&(c=2.5,++o)):l<7.5?c=5:c=10,c*=a,n.minTickSize!=null&&c<n.minTickSize&&(c=n.minTickSize),t.delta=s,t.tickDecimals=Math.max(0,u!=null?u:o),t.tickSize=n.tickSize||c;if(n.mode=="time"&&!t.tickGenerator)throw new Error("Time mode requires the flot.time plugin.");t.tickGenerator||(t.tickGenerator=function(e){var t=[],n=i(e.min,e.tickSize),r=0,s=Number.NaN,o;do o=s,s=n+r*e.tickSize,t.push(s),++r;while(s<e.max&&s!=o);return t},t.tickFormatter=function(e,t){var n=t.tickDecimals?Math.pow(10,t.tickDecimals):1,r=""+Math.round(e*n)/n;if(t.tickDecimals!=null){var i=r.indexOf("."),s=i==-1?0:r.length-i-1;if(s<t.tickDecimals)return(s?r:r+".")+(""+n).substr(1,t.tickDecimals-s)}return r}),e.isFunction(n.tickFormatter)&&(t.tickFormatter=function(e,t){return""+n.tickFormatter(e,t)});if(n.alignTicksWithAxis!=null){var h=(t.direction=="x"?d:v)[n.alignTicksWithAxis-1];if(h&&h.used&&h!=t){var p=t.tickGenerator(t);p.length>0&&(n.min==null&&(t.min=Math.min(t.min,p[0])),n.max==null&&p.length>1&&(t.max=Math.max(t.max,p[p.length-1]))),t.tickGenerator=function(e){var t=[],n,r;for(r=0;r<h.ticks.length;++r)n=(h.ticks[r].v-h.min)/(h.max-h.min),n=e.min+n*(e.max-e.min),t.push(n);return t};if(!t.mode&&n.tickDecimals==null){var m=Math.max(0,-Math.floor(Math.log(t.delta)/Math.LN10)+1),g=t.tickGenerator(t);g.length>1&&/\..*0$/.test((g[1]-g[0]).toFixed(m))||(t.tickDecimals=m)}}}}function W(t){var n=t.options.ticks,r=[];n==null||typeof n=="number"&&n>0?r=t.tickGenerator(t):n&&(e.isFunction(n)?r=n(t):r=n);var i,s;t.ticks=[];for(i=0;i<r.length;++i){var o=null,u=r[i];typeof u=="object"?(s=+u[0],u.length>1&&(o=u[1])):s=+u,o==null&&(o=t.tickFormatter(s,t)),isNaN(s)||t.ticks.push({v:s,label:o})}}function X(e,t){e.options.autoscaleMargin&&t.length>0&&(e.options.min==null&&(e.min=Math.min(e.min,t[0].v)),e.options.max==null&&t.length>1&&(e.max=Math.max(e.max,t[t.length-1].v)))}function V(){f.clear(),E(b.drawBackground,[h]);var e=a.grid;e.show&&e.backgroundColor&&K(),e.show&&!e.aboveData&&Q();for(var t=0;t<u.length;++t)E(b.drawSeries,[h,u[t]]),Y(u[t]);E(b.draw,[h]),e.show&&e.aboveData&&Q(),f.render(),ht()}function J(e,t){var n,r,i,s,o=k();for(var u=0;u<o.length;++u){n=o[u];if(n.direction==t){s=t+n.n+"axis",!e[s]&&n.n==1&&(s=t+"axis");if(e[s]){r=e[s].from,i=e[s].to;break}}}e[s]||(n=t=="x"?d[0]:v[0],r=e[t+"1"],i=e[t+"2"]);if(r!=null&&i!=null&&r>i){var a=r;r=i,i=a}return{from:r,to:i,axis:n}}function K(){h.save(),h.translate(m.left,m.top),h.fillStyle=bt(a.grid.backgroundColor,y,0,"rgba(255, 255, 255, 0)"),h.fillRect(0,0,g,y),h.restore()}function Q(){var t,n,r,i;h.save(),h.translate(m.left,m.top);var s=a.grid.markings;if(s){e.isFunction(s)&&(n=w.getAxes(),n.xmin=n.xaxis.min,n.xmax=n.xaxis.max,n.ymin=n.yaxis.min,n.ymax=n.yaxis.max,s=s(n));for(t=0;t<s.length;++t){var o=s[t],u=J(o,"x"),f=J(o,"y");u.from==null&&(u.from=u.axis.min),u.to==null&&(u.to=u.axis.max),f.from==null&&(f.from=f.axis.min),f.to==null&&(f.to=f.axis.max);if(u.to<u.axis.min||u.from>u.axis.max||f.to<f.axis.min||f.from>f.axis.max)continue;u.from=Math.max(u.from,u.axis.min),u.to=Math.min(u.to,u.axis.max),f.from=Math.max(f.from,f.axis.min),f.to=Math.min(f.to,f.axis.max);if(u.from==u.to&&f.from==f.to)continue;u.from=u.axis.p2c(u.from),u.to=u.axis.p2c(u.to),f.from=f.axis.p2c(f.from),f.to=f.axis.p2c(f.to),u.from==u.to||f.from==f.to?(h.beginPath(),h.strokeStyle=o.color||a.grid.markingsColor,h.lineWidth=o.lineWidth||a.grid.markingsLineWidth,h.moveTo(u.from,f.from),h.lineTo(u.to,f.to),h.stroke()):(h.fillStyle=o.color||a.grid.markingsColor,h.fillRect(u.from,f.to,u.to-u.from,f.from-f.to))}}n=k(),r=a.grid.borderWidth;for(var l=0;l<n.length;++l){var c=n[l],p=c.box,d=c.tickLength,v,b,E,S;if(!c.show||c.ticks.length==0)continue;h.lineWidth=1,c.direction=="x"?(v=0,d=="full"?b=c.position=="top"?0:y:b=p.top-m.top+(c.position=="top"?p.height:0)):(b=0,d=="full"?v=c.position=="left"?0:g:v=p.left-m.left+(c.position=="left"?p.width:0)),c.innermost||(h.strokeStyle=c.options.color,h.beginPath(),E=S=0,c.direction=="x"?E=g+1:S=y+1,h.lineWidth==1&&(c.direction=="x"?b=Math.floor(b)+.5:v=Math.floor(v)+.5),h.moveTo(v,b),h.lineTo(v+E,b+S),h.stroke()),h.strokeStyle=c.options.tickColor,h.beginPath();for(t=0;t<c.ticks.length;++t){var x=c.ticks[t].v;E=S=0;if(isNaN(x)||x<c.min||x>c.max||d=="full"&&(typeof r=="object"&&r[c.position]>0||r>0)&&(x==c.min||x==c.max))continue;c.direction=="x"?(v=c.p2c(x),S=d=="full"?-y:d,c.position=="top"&&(S=-S)):(b=c.p2c(x),E=d=="full"?-g:d,c.position=="left"&&(E=-E)),h.lineWidth==1&&(c.direction=="x"?v=Math.floor(v)+.5:b=Math.floor(b)+.5),h.moveTo(v,b),h.lineTo(v+E,b+S)}h.stroke()}r&&(i=a.grid.borderColor,typeof r=="object"||typeof i=="object"?(typeof r!="object"&&(r={top:r,right:r,bottom:r,left:r}),typeof i!="object"&&(i={top:i,right:i,bottom:i,left:i}),r.top>0&&(h.strokeStyle=i.top,h.lineWidth=r.top,h.beginPath(),h.moveTo(0-r.left,0-r.top/2),h.lineTo(g,0-r.top/2),h.stroke()),r.right>0&&(h.strokeStyle=i.right,h.lineWidth=r.right,h.beginPath(),h.moveTo(g+r.right/2,0-r.top),h.lineTo(g+r.right/2,y),h.stroke()),r.bottom>0&&(h.strokeStyle=i.bottom,h.lineWidth=r.bottom,h.beginPath(),h.moveTo(g+r.right,y+r.bottom/2),h.lineTo(0,y+r.bottom/2),h.stroke()),r.left>0&&(h.strokeStyle=i.left,h.lineWidth=r.left,h.beginPath(),h.moveTo(0-r.left/2,y+r.bottom),h.lineTo(0-r.left/2,0),h.stroke())):(h.lineWidth=r,h.strokeStyle=a.grid.borderColor,h.strokeRect(-r/2,-r/2,g+r,y+r))),h.restore()}function G(){e.each(k(),function(e,t){if(!t.show||t.ticks.length==0)return;var n=t.box,r=t.direction+"Axis "+t.direction+t.n+"Axis",i="flot-"+t.direction+"-axis flot-"+t.direction+t.n+"-axis "+r,s=t.options.font||"flot-tick-label tickLabel",o,u,a,l,c;f.removeText(i);for(var h=0;h<t.ticks.length;++h){o=t.ticks[h];if(!o.label||o.v<t.min||o.v>t.max)continue;t.direction=="x"?(l="center",u=m.left+t.p2c(o.v),t.position=="bottom"?a=n.top+n.padding:(a=n.top+n.height-n.padding,c="bottom")):(c="middle",a=m.top+t.p2c(o.v),t.position=="left"?(u=n.left+n.width-n.padding,l="right"):u=n.left+n.padding),f.addText(i,u,a,o.label,s,null,null,l,c)}})}function Y(e){e.lines.show&&Z(e),e.bars.show&&nt(e),e.points.show&&et(e)}function Z(e){function t(e,t,n,r,i){var s=e.points,o=e.pointsize,u=null,a=null;h.beginPath();for(var f=o;f<s.length;f+=o){var l=s[f-o],c=s[f-o+1],p=s[f],d=s[f+1];if(l==null||p==null)continue;if(c<=d&&c<i.min){if(d<i.min)continue;l=(i.min-c)/(d-c)*(p-l)+l,c=i.min}else if(d<=c&&d<i.min){if(c<i.min)continue;p=(i.min-c)/(d-c)*(p-l)+l,d=i.min}if(c>=d&&c>i.max){if(d>i.max)continue;l=(i.max-c)/(d-c)*(p-l)+l,c=i.max}else if(d>=c&&d>i.max){if(c>i.max)continue;p=(i.max-c)/(d-c)*(p-l)+l,d=i.max}if(l<=p&&l<r.min){if(p<r.min)continue;c=(r.min-l)/(p-l)*(d-c)+c,l=r.min}else if(p<=l&&p<r.min){if(l<r.min)continue;d=(r.min-l)/(p-l)*(d-c)+c,p=r.min}if(l>=p&&l>r.max){if(p>r.max)continue;c=(r.max-l)/(p-l)*(d-c)+c,l=r.max}else if(p>=l&&p>r.max){if(l>r.max)continue;d=(r.max-l)/(p-l)*(d-c)+c,p=r.max}(l!=u||c!=a)&&h.moveTo(r.p2c(l)+t,i.p2c(c)+n),u=p,a=d,h.lineTo(r.p2c(p)+t,i.p2c(d)+n)}h.stroke()}function n(e,t,n){var r=e.points,i=e.pointsize,s=Math.min(Math.max(0,n.min),n.max),o=0,u,a=!1,f=1,l=0,c=0;for(;;){if(i>0&&o>r.length+i)break;o+=i;var p=r[o-i],d=r[o-i+f],v=r[o],m=r[o+f];if(a){if(i>0&&p!=null&&v==null){c=o,i=-i,f=2;continue}if(i<0&&o==l+i){h.fill(),a=!1,i=-i,f=1,o=l=c+i;continue}}if(p==null||v==null)continue;if(p<=v&&p<t.min){if(v<t.min)continue;d=(t.min-p)/(v-p)*(m-d)+d,p=t.min}else if(v<=p&&v<t.min){if(p<t.min)continue;m=(t.min-p)/(v-p)*(m-d)+d,v=t.min}if(p>=v&&p>t.max){if(v>t.max)continue;d=(t.max-p)/(v-p)*(m-d)+d,p=t.max}else if(v>=p&&v>t.max){if(p>t.max)continue;m=(t.max-p)/(v-p)*(m-d)+d,v=t.max}a||(h.beginPath(),h.moveTo(t.p2c(p),n.p2c(s)),a=!0);if(d>=n.max&&m>=n.max){h.lineTo(t.p2c(p),n.p2c(n.max)),h.lineTo(t.p2c(v),n.p2c(n.max));continue}if(d<=n.min&&m<=n.min){h.lineTo(t.p2c(p),n.p2c(n.min)),h.lineTo(t.p2c(v),n.p2c(n.min));continue}var g=p,y=v;d<=m&&d<n.min&&m>=n.min?(p=(n.min-d)/(m-d)*(v-p)+p,d=n.min):m<=d&&m<n.min&&d>=n.min&&(v=(n.min-d)/(m-d)*(v-p)+p,m=n.min),d>=m&&d>n.max&&m<=n.max?(p=(n.max-d)/(m-d)*(v-p)+p,d=n.max):m>=d&&m>n.max&&d<=n.max&&(v=(n.max-d)/(m-d)*(v-p)+p,m=n.max),p!=g&&h.lineTo(t.p2c(g),n.p2c(d)),h.lineTo(t.p2c(p),n.p2c(d)),h.lineTo(t.p2c(v),n.p2c(m)),v!=y&&(h.lineTo(t.p2c(v),n.p2c(m)),h.lineTo(t.p2c(y),n.p2c(m)))}}h.save(),h.translate(m.left,m.top),h.lineJoin="round";var r=e.lines.lineWidth,i=e.shadowSize;if(r>0&&i>0){h.lineWidth=i,h.strokeStyle="rgba(0,0,0,0.1)";var s=Math.PI/18;t(e.datapoints,Math.sin(s)*(r/2+i/2),Math.cos(s)*(r/2+i/2),e.xaxis,e.yaxis),h.lineWidth=i/2,t(e.datapoints,Math.sin(s)*(r/2+i/4),Math.cos(s)*(r/2+i/4),e.xaxis,e.yaxis)}h.lineWidth=r,h.strokeStyle=e.color;var o=rt(e.lines,e.color,0,y);o&&(h.fillStyle=o,n(e.datapoints,e.xaxis,e.yaxis)),r>0&&t(e.datapoints,0,0,e.xaxis,e.yaxis),h.restore()}function et(e){function t(e,t,n,r,i,s,o,u){var a=e.points,f=e.pointsize;for(var l=0;l<a.length;l+=f){var c=a[l],p=a[l+1];if(c==null||c<s.min||c>s.max||p<o.min||p>o.max)continue;h.beginPath(),c=s.p2c(c),p=o.p2c(p)+r,u=="circle"?h.arc(c,p,t,0,i?Math.PI:Math.PI*2,!1):u(h,c,p,t,i),h.closePath(),n&&(h.fillStyle=n,h.fill()),h.stroke()}}h.save(),h.translate(m.left,m.top);var n=e.points.lineWidth,r=e.shadowSize,i=e.points.radius,s=e.points.symbol;n==0&&(n=1e-4);if(n>0&&r>0){var o=r/2;h.lineWidth=o,h.strokeStyle="rgba(0,0,0,0.1)",t(e.datapoints,i,null,o+o/2,!0,e.xaxis,e.yaxis,s),h.strokeStyle="rgba(0,0,0,0.2)",t(e.datapoints,i,null,o/2,!0,e.xaxis,e.yaxis,s)}h.lineWidth=n,h.strokeStyle=e.color,t(e.datapoints,i,rt(e.points,e.color),0,!1,e.xaxis,e.yaxis,s),h.restore()}function tt(e,t,n,r,i,s,o,u,a,f,l,c){var h,p,d,v,m,g,y,b,w;l?(b=g=y=!0,m=!1,h=n,p=e,v=t+r,d=t+i,p<h&&(w=p,p=h,h=w,m=!0,g=!1)):(m=g=y=!0,b=!1,h=e+r,p=e+i,d=n,v=t,v<d&&(w=v,v=d,d=w,b=!0,y=!1));if(p<u.min||h>u.max||v<a.min||d>a.max)return;h<u.min&&(h=u.min,m=!1),p>u.max&&(p=u.max,g=!1),d<a.min&&(d=a.min,b=!1),v>a.max&&(v=a.max,y=!1),h=u.p2c(h),d=a.p2c(d),p=u.p2c(p),v=a.p2c(v),o&&(f.beginPath(),f.moveTo(h,d),f.lineTo(h,v),f.lineTo(p,v),f.lineTo(p,d),f.fillStyle=o(d,v),f.fill()),c>0&&(m||g||y||b)&&(f.beginPath(),f.moveTo(h,d+s),m?f.lineTo(h,v+s):f.moveTo(h,v+s),y?f.lineTo(p,v+s):f.moveTo(p,v+s),g?f.lineTo(p,d+s):f.moveTo(p,d+s),b?f.lineTo(h,d+s):f.moveTo(h,d+s),f.stroke())}function nt(e){function t(t,n,r,i,s,o,u){var a=t.points,f=t.pointsize;for(var l=0;l<a.length;l+=f){if(a[l]==null)continue;tt(a[l],a[l+1],a[l+2],n,r,i,s,o,u,h,e.bars.horizontal,e.bars.lineWidth)}}h.save(),h.translate(m.left,m.top),h.lineWidth=e.bars.lineWidth,h.strokeStyle=e.color;var n;switch(e.bars.align){case"left":n=0;break;case"right":n=-e.bars.barWidth;break;case"center":n=-e.bars.barWidth/2;break;default:throw new Error("Invalid bar alignment: "+e.bars.align)}var r=e.bars.fill?function(t,n){return rt(e.bars,e.color,t,n)}:null;t(e.datapoints,n,n+e.bars.barWidth,0,r,e.xaxis,e.yaxis),h.restore()}function rt(t,n,r,i){var s=t.fill;if(!s)return null;if(t.fillColor)return bt(t.fillColor,r,i,n);var o=e.color.parse(n);return o.a=typeof s=="number"?s:.4,o.normalize(),o.toString()}function it(){t.find(".legend").remove();if(!a.legend.show)return;var n=[],r=[],i=!1,s=a.legend.labelFormatter,o,f;for(var l=0;l<u.length;++l)o=u[l],o.label&&(f=s?s(o.label,o):o.label,f&&r.push({label:f,color:o.color}));if(a.legend.sorted)if(e.isFunction(a.legend.sorted))r.sort(a.legend.sorted);else if(a.legend.sorted=="reverse")r.reverse();else{var c=a.legend.sorted!="descending";r.sort(function(e,t){return e.label==t.label?0:e.label<t.label!=c?1:-1})}for(var l=0;l<r.length;++l){var h=r[l];l%a.legend.noColumns==0&&(i&&n.push("</tr>"),n.push("<tr>"),i=!0),n.push('<td class="legendColorBox"><div style="border:1px solid '+a.legend.labelBoxBorderColor+';padding:1px"><div style="width:4px;height:0;border:5px solid '+h.color+';overflow:hidden"></div></div></td>'+'<td class="legendLabel">'+h.label+"</td>")}i&&n.push("</tr>");if(n.length==0)return;var p='<table style="font-size:smaller;color:'+a.grid.color+'">'+n.join("")+"</table>";if(a.legend.container!=null)e(a.legend.container).html(p);else{var d="",v=a.legend.position,g=a.legend.margin;g[0]==null&&(g=[g,g]),v.charAt(0)=="n"?d+="top:"+(g[1]+m.top)+"px;":v.charAt(0)=="s"&&(d+="bottom:"+(g[1]+m.bottom)+"px;"),v.charAt(1)=="e"?d+="right:"+(g[0]+m.right)+"px;":v.charAt(1)=="w"&&(d+="left:"+(g[0]+m.left)+"px;");var y=e('<div class="legend">'+p.replace('style="','style="position:absolute;'+d+";")+"</div>").appendTo(t);if(a.legend.backgroundOpacity!=0){var b=a.legend.backgroundColor;b==null&&(b=a.grid.backgroundColor,b&&typeof b=="string"?b=e.color.parse(b):b=e.color.extract(y,"background-color"),b.a=1,b=b.toString());var w=y.children();e('<div style="position:absolute;width:'+w.width()+"px;height:"+w.height()+"px;"+d+"background-color:"+b+';"> </div>').prependTo(y).css("opacity",a.legend.backgroundOpacity)}}}function ut(e,t,n){var r=a.grid.mouseActiveRadius,i=r*r+1,s=null,o=!1,f,l,c;for(f=u.length-1;f>=0;--f){if(!n(u[f]))continue;var h=u[f],p=h.xaxis,d=h.yaxis,v=h.datapoints.points,m=p.c2p(e),g=d.c2p(t),y=r/p.scale,b=r/d.scale;c=h.datapoints.pointsize,p.options.inverseTransform&&(y=Number.MAX_VALUE),d.options.inverseTransform&&(b=Number.MAX_VALUE);if(h.lines.show||h.points.show)for(l=0;l<v.length;l+=c){var w=v[l],E=v[l+1];if(w==null)continue;if(w-m>y||w-m<-y||E-g>b||E-g<-b)continue;var S=Math.abs(p.p2c(w)-e),x=Math.abs(d.p2c(E)-t),T=S*S+x*x;T<i&&(i=T,s=[f,l/c])}if(h.bars.show&&!s){var N=h.bars.align=="left"?0:-h.bars.barWidth/2,C=N+h.bars.barWidth;for(l=0;l<v.length;l+=c){var w=v[l],E=v[l+1],k=v[l+2];if(w==null)continue;if(u[f].bars.horizontal?m<=Math.max(k,w)&&m>=Math.min(k,w)&&g>=E+N&&g<=E+C:m>=w+N&&m<=w+C&&g>=Math.min(k,E)&&g<=Math.max(k,E))s=[f,l/c]}}}return s?(f=s[0],l=s[1],c=u[f].datapoints.pointsize,{datapoint:u[f].datapoints.points.slice(l*c,(l+1)*c),dataIndex:l,series:u[f],seriesIndex:f}):null}function at(e){a.grid.hoverable&&ct("plothover",e,function(e){return e["hoverable"]!=0})}function ft(e){a.grid.hoverable&&ct("plothover",e,function(e){return!1})}function lt(e){ct("plotclick",e,function(e){return e["clickable"]!=0})}function ct(e,n,r){var i=c.offset(),s=n.pageX-i.left-m.left,o=n.pageY-i.top-m.top,u=L({left:s,top:o});u.pageX=n.pageX,u.pageY=n.pageY;var f=ut(s,o,r);f&&(f.pageX=parseInt(f.series.xaxis.p2c(f.datapoint[0])+i.left+m.left,10),f.pageY=parseInt(f.series.yaxis.p2c(f.datapoint[1])+i.top+m.top,10));if(a.grid.autoHighlight){for(var l=0;l<st.length;++l){var h=st[l];h.auto==e&&(!f||h.series!=f.series||h.point[0]!=f.datapoint[0]||h.point[1]!=f.datapoint[1])&&vt(h.series,h.point)}f&&dt(f.series,f.datapoint,e)}t.trigger(e,[u,f])}function ht(){var e=a.interaction.redrawOverlayInterval;if(e==-1){pt();return}ot||(ot=setTimeout(pt,e))}function pt(){ot=null,p.save(),l.clear(),p.translate(m.left,m.top);var e,t;for(e=0;e<st.length;++e)t=st[e],t.series.bars.show?yt(t.series,t.point):gt(t.series,t.point);p.restore(),E(b.drawOverlay,[p])}function dt(e,t,n){typeof e=="number"&&(e=u[e]);if(typeof t=="number"){var r=e.datapoints.pointsize;t=e.datapoints.points.slice(r*t,r*(t+1))}var i=mt(e,t);i==-1?(st.push({series:e,point:t,auto:n}),ht()):n||(st[i].auto=!1)}function vt(e,t){if(e==null&&t==null){st=[],ht();return}typeof e=="number"&&(e=u[e]);if(typeof t=="number"){var n=e.datapoints.pointsize;t=e.datapoints.points.slice(n*t,n*(t+1))}var r=mt(e,t);r!=-1&&(st.splice(r,1),ht())}function mt(e,t){for(var n=0;n<st.length;++n){var r=st[n];if(r.series==e&&r.point[0]==t[0]&&r.point[1]==t[1])return n}return-1}function gt(t,n){var r=n[0],i=n[1],s=t.xaxis,o=t.yaxis,u=typeof t.highlightColor=="string"?t.highlightColor:e.color.parse(t.color).scale("a",.5).toString();if(r<s.min||r>s.max||i<o.min||i>o.max)return;var a=t.points.radius+t.points.lineWidth/2;p.lineWidth=a,p.strokeStyle=u;var f=1.5*a;r=s.p2c(r),i=o.p2c(i),p.beginPath(),t.points.symbol=="circle"?p.arc(r,i,f,0,2*Math.PI,!1):t.points.symbol(p,r,i,f,!1),p.closePath(),p.stroke()}function yt(t,n){var r=typeof t.highlightColor=="string"?t.highlightColor:e.color.parse(t.color).scale("a",.5).toString(),i=r,s=t.bars.align=="left"?0:-t.bars.barWidth/2;p.lineWidth=t.bars.lineWidth,p.strokeStyle=r,tt(n[0],n[1],n[2]||0,s,s+t.bars.barWidth,0,function(){return i},t.xaxis,t.yaxis,p,t.bars.horizontal,t.bars.lineWidth)}function bt(t,n,r,i){if(typeof t=="string")return t;var s=h.createLinearGradient(0,r,0,n);for(var o=0,u=t.colors.length;o<u;++o){var a=t.colors[o];if(typeof a!="string"){var f=e.color.parse(i);a.brightness!=null&&(f=f.scale("rgb",a.brightness)),a.opacity!=null&&(f.a*=a.opacity),a=f.toString()}s.addColorStop(o/(u-1),a)}return s}var u=[],a={colors:["#edc240","#afd8f8","#cb4b4b","#4da74d","#9440ed"],legend:{show:!0,noColumns:1,labelFormatter:null,labelBoxBorderColor:"#ccc",container:null,position:"ne",margin:5,backgroundColor:null,backgroundOpacity:.85,sorted:null},xaxis:{show:null,position:"bottom",mode:null,font:null,color:null,tickColor:null,transform:null,inverseTransform:null,min:null,max:null,autoscaleMargin:null,ticks:null,tickFormatter:null,labelWidth:null,labelHeight:null,reserveSpace:null,tickLength:null,alignTicksWithAxis:null,tickDecimals:null,tickSize:null,minTickSize:null},yaxis:{autoscaleMargin:.02,position:"left"},xaxes:[],yaxes:[],series:{points:{show:!1,radius:3,lineWidth:2,fill:!0,fillColor:"#ffffff",symbol:"circle"},lines:{lineWidth:2,fill:!1,fillColor:null,steps:!1},bars:{show:!1,lineWidth:2,barWidth:1,fill:!0,fillColor:null,align:"left",horizontal:!1,zero:!0},shadowSize:3,highlightColor:null},grid:{show:!0,aboveData:!1,color:"#545454",backgroundColor:null,borderColor:null,tickColor:null,margin:0,labelMargin:5,axisMargin:8,borderWidth:2,minBorderMargin:null,markings:null,markingsColor:"#f4f4f4",markingsLineWidth:2,clickable:!1,hoverable:!1,autoHighlight:!0,mouseActiveRadius:10},interaction:{redrawOverlayInterval:1e3/60},hooks:{}},f=null,l=null,c=null,h=null,p=null,d=[],v=[],m={left:0,right:0,top:0,bottom +:0},g=0,y=0,b={processOptions:[],processRawData:[],processDatapoints:[],processOffset:[],drawBackground:[],drawSeries:[],draw:[],bindEvents:[],drawOverlay:[],shutdown:[]},w=this;w.setData=T,w.setupGrid=R,w.draw=V,w.getPlaceholder=function(){return t},w.getCanvas=function(){return f.element},w.getPlotOffset=function(){return m},w.width=function(){return g},w.height=function(){return y},w.offset=function(){var e=c.offset();return e.left+=m.left,e.top+=m.top,e},w.getData=function(){return u},w.getAxes=function(){var t={},n;return e.each(d.concat(v),function(e,n){n&&(t[n.direction+(n.n!=1?n.n:"")+"axis"]=n)}),t},w.getXAxes=function(){return d},w.getYAxes=function(){return v},w.c2p=L,w.p2c=A,w.getOptions=function(){return a},w.highlight=dt,w.unhighlight=vt,w.triggerRedrawOverlay=ht,w.pointOffset=function(e){return{left:parseInt(d[C(e,"x")-1].p2c(+e.x)+m.left,10),top:parseInt(v[C(e,"y")-1].p2c(+e.y)+m.top,10)}},w.shutdown=H,w.resize=function(){var e=t.width(),n=t.height();f.resize(e,n),l.resize(e,n)},w.hooks=b,S(w),x(s),D(),T(r),R(),V(),P();var st=[],ot=null}function i(e,t){return t*Math.floor(e/t)}var t=Object.prototype.hasOwnProperty;n.prototype.resize=function(e,t){if(e<=0||t<=0)throw new Error("Invalid dimensions for plot, width = "+e+", height = "+t);var n=this.element,r=this.context,i=this.pixelRatio;this.width!=e&&(n.width=e*i,n.style.width=e+"px",this.width=e),this.height!=t&&(n.height=t*i,n.style.height=t+"px",this.height=t),r.restore(),r.save(),r.scale(i,i)},n.prototype.clear=function(){this.context.clearRect(0,0,this.width,this.height)},n.prototype.render=function(){var e=this._textCache;for(var n in e)if(t.call(e,n)){var r=this.getTextLayer(n),i=e[n];r.hide();for(var s in i)if(t.call(i,s)){var o=i[s];for(var u in o)if(t.call(o,u)){var a=o[u].positions;for(var f=0,l;l=a[f];f++)l.active?l.rendered||(r.append(l.element),l.rendered=!0):(a.splice(f--,1),l.rendered&&l.element.detach());a.length==0&&delete o[u]}}r.show()}},n.prototype.getTextLayer=function(t){var n=this.text[t];return n==null&&(this.textContainer==null&&(this.textContainer=e("<div class='flot-text'></div>").css({position:"absolute",top:0,left:0,bottom:0,right:0,"font-size":"smaller",color:"#545454"}).insertAfter(this.element)),n=this.text[t]=e("<div></div>").addClass(t).css({position:"absolute",top:0,left:0,bottom:0,right:0}).appendTo(this.textContainer)),n},n.prototype.getTextInfo=function(t,n,r,i,s){var o,u,a,f;n=""+n,typeof r=="object"?o=r.style+" "+r.variant+" "+r.weight+" "+r.size+"px/"+r.lineHeight+"px "+r.family:o=r,u=this._textCache[t],u==null&&(u=this._textCache[t]={}),a=u[o],a==null&&(a=u[o]={}),f=a[n];if(f==null){var l=e("<div></div>").html(n).css({position:"absolute","max-width":s,top:-9999}).appendTo(this.getTextLayer(t));typeof r=="object"?l.css({font:o,color:r.color}):typeof r=="string"&&l.addClass(r),f=a[n]={width:l.outerWidth(!0),height:l.outerHeight(!0),element:l,positions:[]},l.detach()}return f},n.prototype.addText=function(e,t,n,r,i,s,o,u,a){var f=this.getTextInfo(e,r,i,s,o),l=f.positions;u=="center"?t-=f.width/2:u=="right"&&(t-=f.width),a=="middle"?n-=f.height/2:a=="bottom"&&(n-=f.height);for(var c=0,h;h=l[c];c++)if(h.x==t&&h.y==n){h.active=!0;return}h={active:!0,rendered:!1,element:l.length?f.element.clone():f.element,x:t,y:n},l.push(h),h.element.css({top:Math.round(n),left:Math.round(t),"text-align":u})},n.prototype.removeText=function(e,n,r,i,s,o){if(i==null){var u=this._textCache[e];if(u!=null)for(var a in u)if(t.call(u,a)){var f=u[a];for(var l in f)if(t.call(f,l)){var c=f[l].positions;for(var h=0,p;p=c[h];h++)p.active=!1}}}else{var c=this.getTextInfo(e,i,s,o).positions;for(var h=0,p;p=c[h];h++)p.x==n&&p.y==r&&(p.active=!1)}},e.plot=function(t,n,i){var s=new r(e(t),n,i,e.plot.plugins);return s},e.plot.version="0.8.1",e.plot.plugins=[],e.fn.plot=function(t,n){return this.each(function(){e.plot(this,t,n)})}}(jQuery);
\ No newline at end of file diff --git a/public/javascripts/jquery_ujs.js b/public/javascripts/jquery_ujs.js new file mode 100644 index 000000000..50121d6ed --- /dev/null +++ b/public/javascripts/jquery_ujs.js @@ -0,0 +1,393 @@ +(function($, undefined) { + +/** + * Unobtrusive scripting adapter for jQuery + * https://github.com/rails/jquery-ujs + * + * Requires jQuery 1.7.0 or later. + * + * Released under the MIT license + * + */ + + // Cut down on the number of issues from people inadvertently including jquery_ujs twice + // by detecting and raising an error when it happens. + if ( $.rails !== undefined ) { + $.error('jquery-ujs has already been loaded!'); + } + + // Shorthand to make it a little easier to call public rails functions from within rails.js + var rails; + + $.rails = rails = { + // Link elements bound by jquery-ujs + linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote], a[data-disable-with]', + + // Button elements boud jquery-ujs + buttonClickSelector: 'button[data-remote]', + + // Select elements bound by jquery-ujs + inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]', + + // Form elements bound by jquery-ujs + formSubmitSelector: 'form', + + // Form input elements bound by jquery-ujs + formInputClickSelector: 'form input[type=submit], form input[type=image], form button[type=submit], form button:not([type])', + + // Form input elements disabled during form submission + disableSelector: 'input[data-disable-with], button[data-disable-with], textarea[data-disable-with]', + + // Form input elements re-enabled after form submission + enableSelector: 'input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled', + + // Form required input elements + requiredInputSelector: 'input[name][required]:not([disabled]),textarea[name][required]:not([disabled])', + + // Form file input elements + fileInputSelector: 'input[type=file]', + + // Link onClick disable selector with possible reenable after remote submission + linkDisableSelector: 'a[data-disable-with]', + + // Make sure that every Ajax request sends the CSRF token + CSRFProtection: function(xhr) { + var token = $('meta[name="csrf-token"]').attr('content'); + if (token) xhr.setRequestHeader('X-CSRF-Token', token); + }, + + // Triggers an event on an element and returns false if the event result is false + fire: function(obj, name, data) { + var event = $.Event(name); + obj.trigger(event, data); + return event.result !== false; + }, + + // Default confirm dialog, may be overridden with custom confirm dialog in $.rails.confirm + confirm: function(message) { + return confirm(message); + }, + + // Default ajax function, may be overridden with custom function in $.rails.ajax + ajax: function(options) { + return $.ajax(options); + }, + + // Default way to get an element's href. May be overridden at $.rails.href. + href: function(element) { + return element.attr('href'); + }, + + // Submits "remote" forms and links with ajax + handleRemote: function(element) { + var method, url, data, elCrossDomain, crossDomain, withCredentials, dataType, options; + + if (rails.fire(element, 'ajax:before')) { + elCrossDomain = element.data('cross-domain'); + crossDomain = elCrossDomain === undefined ? null : elCrossDomain; + withCredentials = element.data('with-credentials') || null; + dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType); + + if (element.is('form')) { + method = element.attr('method'); + url = element.attr('action'); + data = element.serializeArray(); + // memoized value from clicked submit button + var button = element.data('ujs:submit-button'); + if (button) { + data.push(button); + element.data('ujs:submit-button', null); + } + } else if (element.is(rails.inputChangeSelector)) { + method = element.data('method'); + url = element.data('url'); + data = element.serialize(); + if (element.data('params')) data = data + "&" + element.data('params'); + } else if (element.is(rails.buttonClickSelector)) { + method = element.data('method') || 'get'; + url = element.data('url'); + data = element.serialize(); + if (element.data('params')) data = data + "&" + element.data('params'); + } else { + method = element.data('method'); + url = rails.href(element); + data = element.data('params') || null; + } + + options = { + type: method || 'GET', data: data, dataType: dataType, + // stopping the "ajax:beforeSend" event will cancel the ajax request + beforeSend: function(xhr, settings) { + if (settings.dataType === undefined) { + xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script); + } + return rails.fire(element, 'ajax:beforeSend', [xhr, settings]); + }, + success: function(data, status, xhr) { + element.trigger('ajax:success', [data, status, xhr]); + }, + complete: function(xhr, status) { + element.trigger('ajax:complete', [xhr, status]); + }, + error: function(xhr, status, error) { + element.trigger('ajax:error', [xhr, status, error]); + }, + crossDomain: crossDomain + }; + + // There is no withCredentials for IE6-8 when + // "Enable native XMLHTTP support" is disabled + if (withCredentials) { + options.xhrFields = { + withCredentials: withCredentials + }; + } + + // Only pass url to `ajax` options if not blank + if (url) { options.url = url; } + + var jqxhr = rails.ajax(options); + element.trigger('ajax:send', jqxhr); + return jqxhr; + } else { + return false; + } + }, + + // Handles "data-method" on links such as: + // <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a> + handleMethod: function(link) { + var href = rails.href(link), + method = link.data('method'), + target = link.attr('target'), + csrf_token = $('meta[name=csrf-token]').attr('content'), + csrf_param = $('meta[name=csrf-param]').attr('content'), + form = $('<form method="post" action="' + href + '"></form>'), + metadata_input = '<input name="_method" value="' + method + '" type="hidden" />'; + + if (csrf_param !== undefined && csrf_token !== undefined) { + metadata_input += '<input name="' + csrf_param + '" value="' + csrf_token + '" type="hidden" />'; + } + + if (target) { form.attr('target', target); } + + form.hide().append(metadata_input).appendTo('body'); + form.submit(); + }, + + /* Disables form elements: + - Caches element value in 'ujs:enable-with' data store + - Replaces element text with value of 'data-disable-with' attribute + - Sets disabled property to true + */ + disableFormElements: function(form) { + form.find(rails.disableSelector).each(function() { + var element = $(this), method = element.is('button') ? 'html' : 'val'; + element.data('ujs:enable-with', element[method]()); + element[method](element.data('disable-with')); + element.prop('disabled', true); + }); + }, + + /* Re-enables disabled form elements: + - Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`) + - Sets disabled property to false + */ + enableFormElements: function(form) { + form.find(rails.enableSelector).each(function() { + var element = $(this), method = element.is('button') ? 'html' : 'val'; + if (element.data('ujs:enable-with')) element[method](element.data('ujs:enable-with')); + element.prop('disabled', false); + }); + }, + + /* For 'data-confirm' attribute: + - Fires `confirm` event + - Shows the confirmation dialog + - Fires the `confirm:complete` event + + Returns `true` if no function stops the chain and user chose yes; `false` otherwise. + Attaching a handler to the element's `confirm` event that returns a `falsy` value cancels the confirmation dialog. + Attaching a handler to the element's `confirm:complete` event that returns a `falsy` value makes this function + return false. The `confirm:complete` event is fired whether or not the user answered true or false to the dialog. + */ + allowAction: function(element) { + var message = element.data('confirm'), + answer = false, callback; + if (!message) { return true; } + + if (rails.fire(element, 'confirm')) { + answer = rails.confirm(message); + callback = rails.fire(element, 'confirm:complete', [answer]); + } + return answer && callback; + }, + + // Helper function which checks for blank inputs in a form that match the specified CSS selector + blankInputs: function(form, specifiedSelector, nonBlank) { + var inputs = $(), input, valueToCheck, + selector = specifiedSelector || 'input,textarea', + allInputs = form.find(selector); + + allInputs.each(function() { + input = $(this); + valueToCheck = input.is('input[type=checkbox],input[type=radio]') ? input.is(':checked') : input.val(); + // If nonBlank and valueToCheck are both truthy, or nonBlank and valueToCheck are both falsey + if (!valueToCheck === !nonBlank) { + + // Don't count unchecked required radio if other radio with same name is checked + if (input.is('input[type=radio]') && allInputs.filter('input[type=radio]:checked[name="' + input.attr('name') + '"]').length) { + return true; // Skip to next input + } + + inputs = inputs.add(input); + } + }); + return inputs.length ? inputs : false; + }, + + // Helper function which checks for non-blank inputs in a form that match the specified CSS selector + nonBlankInputs: function(form, specifiedSelector) { + return rails.blankInputs(form, specifiedSelector, true); // true specifies nonBlank + }, + + // Helper function, needed to provide consistent behavior in IE + stopEverything: function(e) { + $(e.target).trigger('ujs:everythingStopped'); + e.stopImmediatePropagation(); + return false; + }, + + // replace element's html with the 'data-disable-with' after storing original html + // and prevent clicking on it + disableElement: function(element) { + element.data('ujs:enable-with', element.html()); // store enabled state + element.html(element.data('disable-with')); // set to disabled state + element.bind('click.railsDisable', function(e) { // prevent further clicking + return rails.stopEverything(e); + }); + }, + + // restore element to its original state which was disabled by 'disableElement' above + enableElement: function(element) { + if (element.data('ujs:enable-with') !== undefined) { + element.html(element.data('ujs:enable-with')); // set to old enabled state + element.removeData('ujs:enable-with'); // clean up cache + } + element.unbind('click.railsDisable'); // enable element + } + + }; + + if (rails.fire($(document), 'rails:attachBindings')) { + + $.ajaxPrefilter(function(options, originalOptions, xhr){ if ( !options.crossDomain ) { rails.CSRFProtection(xhr); }}); + + $(document).delegate(rails.linkDisableSelector, 'ajax:complete', function() { + rails.enableElement($(this)); + }); + + $(document).delegate(rails.linkClickSelector, 'click.rails', function(e) { + var link = $(this), method = link.data('method'), data = link.data('params'); + if (!rails.allowAction(link)) return rails.stopEverything(e); + + if (link.is(rails.linkDisableSelector)) rails.disableElement(link); + + if (link.data('remote') !== undefined) { + if ( (e.metaKey || e.ctrlKey) && (!method || method === 'GET') && !data ) { return true; } + + var handleRemote = rails.handleRemote(link); + // response from rails.handleRemote() will either be false or a deferred object promise. + if (handleRemote === false) { + rails.enableElement(link); + } else { + handleRemote.error( function() { rails.enableElement(link); } ); + } + return false; + + } else if (link.data('method')) { + rails.handleMethod(link); + return false; + } + }); + + $(document).delegate(rails.buttonClickSelector, 'click.rails', function(e) { + var button = $(this); + if (!rails.allowAction(button)) return rails.stopEverything(e); + + rails.handleRemote(button); + return false; + }); + + $(document).delegate(rails.inputChangeSelector, 'change.rails', function(e) { + var link = $(this); + if (!rails.allowAction(link)) return rails.stopEverything(e); + + rails.handleRemote(link); + return false; + }); + + $(document).delegate(rails.formSubmitSelector, 'submit.rails', function(e) { + var form = $(this), + remote = form.data('remote') !== undefined, + blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector), + nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector); + + if (!rails.allowAction(form)) return rails.stopEverything(e); + + // skip other logic when required values are missing or file upload is present + if (blankRequiredInputs && form.attr("novalidate") == undefined && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) { + return rails.stopEverything(e); + } + + if (remote) { + if (nonBlankFileInputs) { + // slight timeout so that the submit button gets properly serialized + // (make it easy for event handler to serialize form without disabled values) + setTimeout(function(){ rails.disableFormElements(form); }, 13); + var aborted = rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]); + + // re-enable form elements if event bindings return false (canceling normal form submission) + if (!aborted) { setTimeout(function(){ rails.enableFormElements(form); }, 13); } + + return aborted; + } + + rails.handleRemote(form); + return false; + + } else { + // slight timeout so that the submit button gets properly serialized + setTimeout(function(){ rails.disableFormElements(form); }, 13); + } + }); + + $(document).delegate(rails.formInputClickSelector, 'click.rails', function(event) { + var button = $(this); + + if (!rails.allowAction(button)) return rails.stopEverything(event); + + // register the pressed submit button + var name = button.attr('name'), + data = name ? {name:name, value:button.val()} : null; + + button.closest('form').data('ujs:submit-button', data); + }); + + $(document).delegate(rails.formSubmitSelector, 'ajax:beforeSend.rails', function(event) { + if (this == event.target) rails.disableFormElements($(this)); + }); + + $(document).delegate(rails.formSubmitSelector, 'ajax:complete.rails', function(event) { + if (this == event.target) rails.enableFormElements($(this)); + }); + + $(function(){ + // making sure that all forms have actual up-to-date token(cached forms contain old one) + var csrf_token = $('meta[name=csrf-token]').attr('content'); + var csrf_param = $('meta[name=csrf-param]').attr('content'); + $('form input[name="' + csrf_param + '"]').val(csrf_token); + }); + } + +})( jQuery ); diff --git a/public/javascripts/prototype.js b/public/javascripts/prototype.js deleted file mode 100644 index 06249a6ae..000000000 --- a/public/javascripts/prototype.js +++ /dev/null @@ -1,6001 +0,0 @@ -/* Prototype JavaScript framework, version 1.7_rc2 - * (c) 2005-2010 Sam Stephenson - * - * Prototype is freely distributable under the terms of an MIT-style license. - * For details, see the Prototype web site: http://www.prototypejs.org/ - * - *--------------------------------------------------------------------------*/ - -var Prototype = { - - Version: '1.7_rc2', - - Browser: (function(){ - var ua = navigator.userAgent; - var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; - return { - IE: !!window.attachEvent && !isOpera, - Opera: isOpera, - WebKit: ua.indexOf('AppleWebKit/') > -1, - Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, - MobileSafari: /Apple.*Mobile/.test(ua) - } - })(), - - BrowserFeatures: { - XPath: !!document.evaluate, - - SelectorsAPI: !!document.querySelector, - - ElementExtensions: (function() { - var constructor = window.Element || window.HTMLElement; - return !!(constructor && constructor.prototype); - })(), - SpecificElementExtensions: (function() { - if (typeof window.HTMLDivElement !== 'undefined') - return true; - - var div = document.createElement('div'), - form = document.createElement('form'), - isSupported = false; - - if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { - isSupported = true; - } - - div = form = null; - - return isSupported; - })() - }, - - ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>', - JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, - - emptyFunction: function() { }, - - K: function(x) { return x } -}; - -if (Prototype.Browser.MobileSafari) - Prototype.BrowserFeatures.SpecificElementExtensions = false; - - -var Abstract = { }; - - -var Try = { - these: function() { - var returnValue; - - for (var i = 0, length = arguments.length; i < length; i++) { - var lambda = arguments[i]; - try { - returnValue = lambda(); - break; - } catch (e) { } - } - - return returnValue; - } -}; - -/* Based on Alex Arnell's inheritance implementation. */ - -var Class = (function() { - - var IS_DONTENUM_BUGGY = (function(){ - for (var p in { toString: 1 }) { - if (p === 'toString') return false; - } - return true; - })(); - - function subclass() {}; - function create() { - var parent = null, properties = $A(arguments); - if (Object.isFunction(properties[0])) - parent = properties.shift(); - - function klass() { - this.initialize.apply(this, arguments); - } - - Object.extend(klass, Class.Methods); - klass.superclass = parent; - klass.subclasses = []; - - if (parent) { - subclass.prototype = parent.prototype; - klass.prototype = new subclass; - parent.subclasses.push(klass); - } - - for (var i = 0, length = properties.length; i < length; i++) - klass.addMethods(properties[i]); - - if (!klass.prototype.initialize) - klass.prototype.initialize = Prototype.emptyFunction; - - klass.prototype.constructor = klass; - return klass; - } - - function addMethods(source) { - var ancestor = this.superclass && this.superclass.prototype, - properties = Object.keys(source); - - if (IS_DONTENUM_BUGGY) { - if (source.toString != Object.prototype.toString) - properties.push("toString"); - if (source.valueOf != Object.prototype.valueOf) - properties.push("valueOf"); - } - - for (var i = 0, length = properties.length; i < length; i++) { - var property = properties[i], value = source[property]; - if (ancestor && Object.isFunction(value) && - value.argumentNames()[0] == "$super") { - var method = value; - value = (function(m) { - return function() { return ancestor[m].apply(this, arguments); }; - })(property).wrap(method); - - value.valueOf = method.valueOf.bind(method); - value.toString = method.toString.bind(method); - } - this.prototype[property] = value; - } - - return this; - } - - return { - create: create, - Methods: { - addMethods: addMethods - } - }; -})(); -(function() { - - var _toString = Object.prototype.toString, - NULL_TYPE = 'Null', - UNDEFINED_TYPE = 'Undefined', - BOOLEAN_TYPE = 'Boolean', - NUMBER_TYPE = 'Number', - STRING_TYPE = 'String', - OBJECT_TYPE = 'Object', - BOOLEAN_CLASS = '[object Boolean]', - NUMBER_CLASS = '[object Number]', - STRING_CLASS = '[object String]', - ARRAY_CLASS = '[object Array]', - NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON && - typeof JSON.stringify === 'function' && - JSON.stringify(0) === '0' && - typeof JSON.stringify(Prototype.K) === 'undefined'; - - function Type(o) { - switch(o) { - case null: return NULL_TYPE; - case (void 0): return UNDEFINED_TYPE; - } - var type = typeof o; - switch(type) { - case 'boolean': return BOOLEAN_TYPE; - case 'number': return NUMBER_TYPE; - case 'string': return STRING_TYPE; - } - return OBJECT_TYPE; - } - - function extend(destination, source) { - for (var property in source) - destination[property] = source[property]; - return destination; - } - - function inspect(object) { - try { - if (isUndefined(object)) return 'undefined'; - if (object === null) return 'null'; - return object.inspect ? object.inspect() : String(object); - } catch (e) { - if (e instanceof RangeError) return '...'; - throw e; - } - } - - function toJSON(value) { - return Str('', { '': value }, []); - } - - function Str(key, holder, stack) { - var value = holder[key], - type = typeof value; - - if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') { - value = value.toJSON(key); - } - - var _class = _toString.call(value); - - switch (_class) { - case NUMBER_CLASS: - case BOOLEAN_CLASS: - case STRING_CLASS: - value = value.valueOf(); - } - - switch (value) { - case null: return 'null'; - case true: return 'true'; - case false: return 'false'; - } - - type = typeof value; - switch (type) { - case 'string': - return value.inspect(true); - case 'number': - return isFinite(value) ? String(value) : 'null'; - case 'object': - - for (var i = 0, length = stack.length; i < length; i++) { - if (stack[i] === value) { throw new TypeError(); } - } - stack.push(value); - - var partial = []; - if (_class === ARRAY_CLASS) { - for (var i = 0, length = value.length; i < length; i++) { - var str = Str(i, value, stack); - partial.push(typeof str === 'undefined' ? 'null' : str); - } - partial = '[' + partial.join(',') + ']'; - } else { - var keys = Object.keys(value); - for (var i = 0, length = keys.length; i < length; i++) { - var key = keys[i], str = Str(key, value, stack); - if (typeof str !== "undefined") { - partial.push(key.inspect(true)+ ':' + str); - } - } - partial = '{' + partial.join(',') + '}'; - } - stack.pop(); - return partial; - } - } - - function stringify(object) { - return JSON.stringify(object); - } - - function toQueryString(object) { - return $H(object).toQueryString(); - } - - function toHTML(object) { - return object && object.toHTML ? object.toHTML() : String.interpret(object); - } - - function keys(object) { - if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); } - var results = []; - for (var property in object) { - if (object.hasOwnProperty(property)) { - results.push(property); - } - } - return results; - } - - function values(object) { - var results = []; - for (var property in object) - results.push(object[property]); - return results; - } - - function clone(object) { - return extend({ }, object); - } - - function isElement(object) { - return !!(object && object.nodeType == 1); - } - - function isArray(object) { - return _toString.call(object) === ARRAY_CLASS; - } - - var hasNativeIsArray = (typeof Array.isArray == 'function') - && Array.isArray([]) && !Array.isArray({}); - - if (hasNativeIsArray) { - isArray = Array.isArray; - } - - function isHash(object) { - return object instanceof Hash; - } - - function isFunction(object) { - return typeof object === "function"; - } - - function isString(object) { - return _toString.call(object) === STRING_CLASS; - } - - function isNumber(object) { - return _toString.call(object) === NUMBER_CLASS; - } - - function isUndefined(object) { - return typeof object === "undefined"; - } - - extend(Object, { - extend: extend, - inspect: inspect, - toJSON: NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON, - toQueryString: toQueryString, - toHTML: toHTML, - keys: Object.keys || keys, - values: values, - clone: clone, - isElement: isElement, - isArray: isArray, - isHash: isHash, - isFunction: isFunction, - isString: isString, - isNumber: isNumber, - isUndefined: isUndefined - }); -})(); -Object.extend(Function.prototype, (function() { - var slice = Array.prototype.slice; - - function update(array, args) { - var arrayLength = array.length, length = args.length; - while (length--) array[arrayLength + length] = args[length]; - return array; - } - - function merge(array, args) { - array = slice.call(array, 0); - return update(array, args); - } - - function argumentNames() { - var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] - .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') - .replace(/\s+/g, '').split(','); - return names.length == 1 && !names[0] ? [] : names; - } - - function bind(context) { - if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; - var __method = this, args = slice.call(arguments, 1); - return function() { - var a = merge(args, arguments); - return __method.apply(context, a); - } - } - - function bindAsEventListener(context) { - var __method = this, args = slice.call(arguments, 1); - return function(event) { - var a = update([event || window.event], args); - return __method.apply(context, a); - } - } - - function curry() { - if (!arguments.length) return this; - var __method = this, args = slice.call(arguments, 0); - return function() { - var a = merge(args, arguments); - return __method.apply(this, a); - } - } - - function delay(timeout) { - var __method = this, args = slice.call(arguments, 1); - timeout = timeout * 1000; - return window.setTimeout(function() { - return __method.apply(__method, args); - }, timeout); - } - - function defer() { - var args = update([0.01], arguments); - return this.delay.apply(this, args); - } - - function wrap(wrapper) { - var __method = this; - return function() { - var a = update([__method.bind(this)], arguments); - return wrapper.apply(this, a); - } - } - - function methodize() { - if (this._methodized) return this._methodized; - var __method = this; - return this._methodized = function() { - var a = update([this], arguments); - return __method.apply(null, a); - }; - } - - return { - argumentNames: argumentNames, - bind: bind, - bindAsEventListener: bindAsEventListener, - curry: curry, - delay: delay, - defer: defer, - wrap: wrap, - methodize: methodize - } -})()); - - - -(function(proto) { - - - function toISOString() { - return this.getUTCFullYear() + '-' + - (this.getUTCMonth() + 1).toPaddedString(2) + '-' + - this.getUTCDate().toPaddedString(2) + 'T' + - this.getUTCHours().toPaddedString(2) + ':' + - this.getUTCMinutes().toPaddedString(2) + ':' + - this.getUTCSeconds().toPaddedString(2) + 'Z'; - } - - - function toJSON() { - return this.toISOString(); - } - - if (!proto.toISOString) proto.toISOString = toISOString; - if (!proto.toJSON) proto.toJSON = toJSON; - -})(Date.prototype); - - -RegExp.prototype.match = RegExp.prototype.test; - -RegExp.escape = function(str) { - return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); -}; -var PeriodicalExecuter = Class.create({ - initialize: function(callback, frequency) { - this.callback = callback; - this.frequency = frequency; - this.currentlyExecuting = false; - - this.registerCallback(); - }, - - registerCallback: function() { - this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - execute: function() { - this.callback(this); - }, - - stop: function() { - if (!this.timer) return; - clearInterval(this.timer); - this.timer = null; - }, - - onTimerEvent: function() { - if (!this.currentlyExecuting) { - try { - this.currentlyExecuting = true; - this.execute(); - this.currentlyExecuting = false; - } catch(e) { - this.currentlyExecuting = false; - throw e; - } - } - } -}); -Object.extend(String, { - interpret: function(value) { - return value == null ? '' : String(value); - }, - specialChar: { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '\\': '\\\\' - } -}); - -Object.extend(String.prototype, (function() { - var NATIVE_JSON_PARSE_SUPPORT = window.JSON && - typeof JSON.parse === 'function' && - JSON.parse('{"test": true}').test; - - function prepareReplacement(replacement) { - if (Object.isFunction(replacement)) return replacement; - var template = new Template(replacement); - return function(match) { return template.evaluate(match) }; - } - - function gsub(pattern, replacement) { - var result = '', source = this, match; - replacement = prepareReplacement(replacement); - - if (Object.isString(pattern)) - pattern = RegExp.escape(pattern); - - if (!(pattern.length || pattern.source)) { - replacement = replacement(''); - return replacement + source.split('').join(replacement) + replacement; - } - - while (source.length > 0) { - if (match = source.match(pattern)) { - result += source.slice(0, match.index); - result += String.interpret(replacement(match)); - source = source.slice(match.index + match[0].length); - } else { - result += source, source = ''; - } - } - return result; - } - - function sub(pattern, replacement, count) { - replacement = prepareReplacement(replacement); - count = Object.isUndefined(count) ? 1 : count; - - return this.gsub(pattern, function(match) { - if (--count < 0) return match[0]; - return replacement(match); - }); - } - - function scan(pattern, iterator) { - this.gsub(pattern, iterator); - return String(this); - } - - function truncate(length, truncation) { - length = length || 30; - truncation = Object.isUndefined(truncation) ? '...' : truncation; - return this.length > length ? - this.slice(0, length - truncation.length) + truncation : String(this); - } - - function strip() { - return this.replace(/^\s+/, '').replace(/\s+$/, ''); - } - - function stripTags() { - return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); - } - - function stripScripts() { - return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); - } - - function extractScripts() { - var matchAll = new RegExp(Prototype.ScriptFragment, 'img'), - matchOne = new RegExp(Prototype.ScriptFragment, 'im'); - return (this.match(matchAll) || []).map(function(scriptTag) { - return (scriptTag.match(matchOne) || ['', ''])[1]; - }); - } - - function evalScripts() { - return this.extractScripts().map(function(script) { return eval(script) }); - } - - function escapeHTML() { - return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); - } - - function unescapeHTML() { - return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); - } - - - function toQueryParams(separator) { - var match = this.strip().match(/([^?#]*)(#.*)?$/); - if (!match) return { }; - - return match[1].split(separator || '&').inject({ }, function(hash, pair) { - if ((pair = pair.split('='))[0]) { - var key = decodeURIComponent(pair.shift()), - value = pair.length > 1 ? pair.join('=') : pair[0]; - - if (value != undefined) value = decodeURIComponent(value); - - if (key in hash) { - if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; - hash[key].push(value); - } - else hash[key] = value; - } - return hash; - }); - } - - function toArray() { - return this.split(''); - } - - function succ() { - return this.slice(0, this.length - 1) + - String.fromCharCode(this.charCodeAt(this.length - 1) + 1); - } - - function times(count) { - return count < 1 ? '' : new Array(count + 1).join(this); - } - - function camelize() { - return this.replace(/-+(.)?/g, function(match, chr) { - return chr ? chr.toUpperCase() : ''; - }); - } - - function capitalize() { - return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); - } - - function underscore() { - return this.replace(/::/g, '/') - .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') - .replace(/([a-z\d])([A-Z])/g, '$1_$2') - .replace(/-/g, '_') - .toLowerCase(); - } - - function dasherize() { - return this.replace(/_/g, '-'); - } - - function inspect(useDoubleQuotes) { - var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { - if (character in String.specialChar) { - return String.specialChar[character]; - } - return '\\u00' + character.charCodeAt().toPaddedString(2, 16); - }); - if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; - return "'" + escapedString.replace(/'/g, '\\\'') + "'"; - } - - function unfilterJSON(filter) { - return this.replace(filter || Prototype.JSONFilter, '$1'); - } - - function isJSON() { - var str = this; - if (str.blank()) return false; - str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'); - str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'); - str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, ''); - return (/^[\],:{}\s]*$/).test(str); - } - - function evalJSON(sanitize) { - var json = this.unfilterJSON(), - cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; - if (cx.test(json)) { - json = json.replace(cx, function (a) { - return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }); - } - try { - if (!sanitize || json.isJSON()) return eval('(' + json + ')'); - } catch (e) { } - throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); - } - - function parseJSON() { - var json = this.unfilterJSON(); - return JSON.parse(json); - } - - function include(pattern) { - return this.indexOf(pattern) > -1; - } - - function startsWith(pattern) { - return this.lastIndexOf(pattern, 0) === 0; - } - - function endsWith(pattern) { - var d = this.length - pattern.length; - return d >= 0 && this.indexOf(pattern, d) === d; - } - - function empty() { - return this == ''; - } - - function blank() { - return /^\s*$/.test(this); - } - - function interpolate(object, pattern) { - return new Template(this, pattern).evaluate(object); - } - - return { - gsub: gsub, - sub: sub, - scan: scan, - truncate: truncate, - strip: String.prototype.trim || strip, - stripTags: stripTags, - stripScripts: stripScripts, - extractScripts: extractScripts, - evalScripts: evalScripts, - escapeHTML: escapeHTML, - unescapeHTML: unescapeHTML, - toQueryParams: toQueryParams, - parseQuery: toQueryParams, - toArray: toArray, - succ: succ, - times: times, - camelize: camelize, - capitalize: capitalize, - underscore: underscore, - dasherize: dasherize, - inspect: inspect, - unfilterJSON: unfilterJSON, - isJSON: isJSON, - evalJSON: NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON, - include: include, - startsWith: startsWith, - endsWith: endsWith, - empty: empty, - blank: blank, - interpolate: interpolate - }; -})()); - -var Template = Class.create({ - initialize: function(template, pattern) { - this.template = template.toString(); - this.pattern = pattern || Template.Pattern; - }, - - evaluate: function(object) { - if (object && Object.isFunction(object.toTemplateReplacements)) - object = object.toTemplateReplacements(); - - return this.template.gsub(this.pattern, function(match) { - if (object == null) return (match[1] + ''); - - var before = match[1] || ''; - if (before == '\\') return match[2]; - - var ctx = object, expr = match[3], - pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; - - match = pattern.exec(expr); - if (match == null) return before; - - while (match != null) { - var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; - ctx = ctx[comp]; - if (null == ctx || '' == match[3]) break; - expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); - match = pattern.exec(expr); - } - - return before + String.interpret(ctx); - }); - } -}); -Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; - -var $break = { }; - -var Enumerable = (function() { - function each(iterator, context) { - var index = 0; - try { - this._each(function(value) { - iterator.call(context, value, index++); - }); - } catch (e) { - if (e != $break) throw e; - } - return this; - } - - function eachSlice(number, iterator, context) { - var index = -number, slices = [], array = this.toArray(); - if (number < 1) return array; - while ((index += number) < array.length) - slices.push(array.slice(index, index+number)); - return slices.collect(iterator, context); - } - - function all(iterator, context) { - iterator = iterator || Prototype.K; - var result = true; - this.each(function(value, index) { - result = result && !!iterator.call(context, value, index); - if (!result) throw $break; - }); - return result; - } - - function any(iterator, context) { - iterator = iterator || Prototype.K; - var result = false; - this.each(function(value, index) { - if (result = !!iterator.call(context, value, index)) - throw $break; - }); - return result; - } - - function collect(iterator, context) { - iterator = iterator || Prototype.K; - var results = []; - this.each(function(value, index) { - results.push(iterator.call(context, value, index)); - }); - return results; - } - - function detect(iterator, context) { - var result; - this.each(function(value, index) { - if (iterator.call(context, value, index)) { - result = value; - throw $break; - } - }); - return result; - } - - function findAll(iterator, context) { - var results = []; - this.each(function(value, index) { - if (iterator.call(context, value, index)) - results.push(value); - }); - return results; - } - - function grep(filter, iterator, context) { - iterator = iterator || Prototype.K; - var results = []; - - if (Object.isString(filter)) - filter = new RegExp(RegExp.escape(filter)); - - this.each(function(value, index) { - if (filter.match(value)) - results.push(iterator.call(context, value, index)); - }); - return results; - } - - function include(object) { - if (Object.isFunction(this.indexOf)) - if (this.indexOf(object) != -1) return true; - - var found = false; - this.each(function(value) { - if (value == object) { - found = true; - throw $break; - } - }); - return found; - } - - function inGroupsOf(number, fillWith) { - fillWith = Object.isUndefined(fillWith) ? null : fillWith; - return this.eachSlice(number, function(slice) { - while(slice.length < number) slice.push(fillWith); - return slice; - }); - } - - function inject(memo, iterator, context) { - this.each(function(value, index) { - memo = iterator.call(context, memo, value, index); - }); - return memo; - } - - function invoke(method) { - var args = $A(arguments).slice(1); - return this.map(function(value) { - return value[method].apply(value, args); - }); - } - - function max(iterator, context) { - iterator = iterator || Prototype.K; - var result; - this.each(function(value, index) { - value = iterator.call(context, value, index); - if (result == null || value >= result) - result = value; - }); - return result; - } - - function min(iterator, context) { - iterator = iterator || Prototype.K; - var result; - this.each(function(value, index) { - value = iterator.call(context, value, index); - if (result == null || value < result) - result = value; - }); - return result; - } - - function partition(iterator, context) { - iterator = iterator || Prototype.K; - var trues = [], falses = []; - this.each(function(value, index) { - (iterator.call(context, value, index) ? - trues : falses).push(value); - }); - return [trues, falses]; - } - - function pluck(property) { - var results = []; - this.each(function(value) { - results.push(value[property]); - }); - return results; - } - - function reject(iterator, context) { - var results = []; - this.each(function(value, index) { - if (!iterator.call(context, value, index)) - results.push(value); - }); - return results; - } - - function sortBy(iterator, context) { - return this.map(function(value, index) { - return { - value: value, - criteria: iterator.call(context, value, index) - }; - }).sort(function(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - }).pluck('value'); - } - - function toArray() { - return this.map(); - } - - function zip() { - var iterator = Prototype.K, args = $A(arguments); - if (Object.isFunction(args.last())) - iterator = args.pop(); - - var collections = [this].concat(args).map($A); - return this.map(function(value, index) { - return iterator(collections.pluck(index)); - }); - } - - function size() { - return this.toArray().length; - } - - function inspect() { - return '#<Enumerable:' + this.toArray().inspect() + '>'; - } - - - - - - - - - - return { - each: each, - eachSlice: eachSlice, - all: all, - every: all, - any: any, - some: any, - collect: collect, - map: collect, - detect: detect, - findAll: findAll, - select: findAll, - filter: findAll, - grep: grep, - include: include, - member: include, - inGroupsOf: inGroupsOf, - inject: inject, - invoke: invoke, - max: max, - min: min, - partition: partition, - pluck: pluck, - reject: reject, - sortBy: sortBy, - toArray: toArray, - entries: toArray, - zip: zip, - size: size, - inspect: inspect, - find: detect - }; -})(); - -function $A(iterable) { - if (!iterable) return []; - if ('toArray' in Object(iterable)) return iterable.toArray(); - var length = iterable.length || 0, results = new Array(length); - while (length--) results[length] = iterable[length]; - return results; -} - - -function $w(string) { - if (!Object.isString(string)) return []; - string = string.strip(); - return string ? string.split(/\s+/) : []; -} - -Array.from = $A; - - -(function() { - var arrayProto = Array.prototype, - slice = arrayProto.slice, - _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available - - function each(iterator) { - for (var i = 0, length = this.length; i < length; i++) - iterator(this[i]); - } - if (!_each) _each = each; - - function clear() { - this.length = 0; - return this; - } - - function first() { - return this[0]; - } - - function last() { - return this[this.length - 1]; - } - - function compact() { - return this.select(function(value) { - return value != null; - }); - } - - function flatten() { - return this.inject([], function(array, value) { - if (Object.isArray(value)) - return array.concat(value.flatten()); - array.push(value); - return array; - }); - } - - function without() { - var values = slice.call(arguments, 0); - return this.select(function(value) { - return !values.include(value); - }); - } - - function reverse(inline) { - return (inline === false ? this.toArray() : this)._reverse(); - } - - function uniq(sorted) { - return this.inject([], function(array, value, index) { - if (0 == index || (sorted ? array.last() != value : !array.include(value))) - array.push(value); - return array; - }); - } - - function intersect(array) { - return this.uniq().findAll(function(item) { - return array.detect(function(value) { return item === value }); - }); - } - - - function clone() { - return slice.call(this, 0); - } - - function size() { - return this.length; - } - - function inspect() { - return '[' + this.map(Object.inspect).join(', ') + ']'; - } - - function indexOf(item, i) { - i || (i = 0); - var length = this.length; - if (i < 0) i = length + i; - for (; i < length; i++) - if (this[i] === item) return i; - return -1; - } - - function lastIndexOf(item, i) { - i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; - var n = this.slice(0, i).reverse().indexOf(item); - return (n < 0) ? n : i - n - 1; - } - - function concat() { - var array = slice.call(this, 0), item; - for (var i = 0, length = arguments.length; i < length; i++) { - item = arguments[i]; - if (Object.isArray(item) && !('callee' in item)) { - for (var j = 0, arrayLength = item.length; j < arrayLength; j++) - array.push(item[j]); - } else { - array.push(item); - } - } - return array; - } - - Object.extend(arrayProto, Enumerable); - - if (!arrayProto._reverse) - arrayProto._reverse = arrayProto.reverse; - - Object.extend(arrayProto, { - _each: _each, - clear: clear, - first: first, - last: last, - compact: compact, - flatten: flatten, - without: without, - reverse: reverse, - uniq: uniq, - intersect: intersect, - clone: clone, - toArray: clone, - size: size, - inspect: inspect - }); - - var CONCAT_ARGUMENTS_BUGGY = (function() { - return [].concat(arguments)[0][0] !== 1; - })(1,2) - - if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat; - - if (!arrayProto.indexOf) arrayProto.indexOf = indexOf; - if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf; -})(); -function $H(object) { - return new Hash(object); -}; - -var Hash = Class.create(Enumerable, (function() { - function initialize(object) { - this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); - } - - - function _each(iterator) { - for (var key in this._object) { - var value = this._object[key], pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - } - - function set(key, value) { - return this._object[key] = value; - } - - function get(key) { - if (this._object[key] !== Object.prototype[key]) - return this._object[key]; - } - - function unset(key) { - var value = this._object[key]; - delete this._object[key]; - return value; - } - - function toObject() { - return Object.clone(this._object); - } - - - - function keys() { - return this.pluck('key'); - } - - function values() { - return this.pluck('value'); - } - - function index(value) { - var match = this.detect(function(pair) { - return pair.value === value; - }); - return match && match.key; - } - - function merge(object) { - return this.clone().update(object); - } - - function update(object) { - return new Hash(object).inject(this, function(result, pair) { - result.set(pair.key, pair.value); - return result; - }); - } - - function toQueryPair(key, value) { - if (Object.isUndefined(value)) return key; - return key + '=' + encodeURIComponent(String.interpret(value)); - } - - function toQueryString() { - return this.inject([], function(results, pair) { - var key = encodeURIComponent(pair.key), values = pair.value; - - if (values && typeof values == 'object') { - if (Object.isArray(values)) - return results.concat(values.map(toQueryPair.curry(key))); - } else results.push(toQueryPair(key, values)); - return results; - }).join('&'); - } - - function inspect() { - return '#<Hash:{' + this.map(function(pair) { - return pair.map(Object.inspect).join(': '); - }).join(', ') + '}>'; - } - - function clone() { - return new Hash(this); - } - - return { - initialize: initialize, - _each: _each, - set: set, - get: get, - unset: unset, - toObject: toObject, - toTemplateReplacements: toObject, - keys: keys, - values: values, - index: index, - merge: merge, - update: update, - toQueryString: toQueryString, - inspect: inspect, - toJSON: toObject, - clone: clone - }; -})()); - -Hash.from = $H; -Object.extend(Number.prototype, (function() { - function toColorPart() { - return this.toPaddedString(2, 16); - } - - function succ() { - return this + 1; - } - - function times(iterator, context) { - $R(0, this, true).each(iterator, context); - return this; - } - - function toPaddedString(length, radix) { - var string = this.toString(radix || 10); - return '0'.times(length - string.length) + string; - } - - function abs() { - return Math.abs(this); - } - - function round() { - return Math.round(this); - } - - function ceil() { - return Math.ceil(this); - } - - function floor() { - return Math.floor(this); - } - - return { - toColorPart: toColorPart, - succ: succ, - times: times, - toPaddedString: toPaddedString, - abs: abs, - round: round, - ceil: ceil, - floor: floor - }; -})()); - -function $R(start, end, exclusive) { - return new ObjectRange(start, end, exclusive); -} - -var ObjectRange = Class.create(Enumerable, (function() { - function initialize(start, end, exclusive) { - this.start = start; - this.end = end; - this.exclusive = exclusive; - } - - function _each(iterator) { - var value = this.start; - while (this.include(value)) { - iterator(value); - value = value.succ(); - } - } - - function include(value) { - if (value < this.start) - return false; - if (this.exclusive) - return value < this.end; - return value <= this.end; - } - - return { - initialize: initialize, - _each: _each, - include: include - }; -})()); - - - -var Ajax = { - getTransport: function() { - return Try.these( - function() {return new XMLHttpRequest()}, - function() {return new ActiveXObject('Msxml2.XMLHTTP')}, - function() {return new ActiveXObject('Microsoft.XMLHTTP')} - ) || false; - }, - - activeRequestCount: 0 -}; - -Ajax.Responders = { - responders: [], - - _each: function(iterator) { - this.responders._each(iterator); - }, - - register: function(responder) { - if (!this.include(responder)) - this.responders.push(responder); - }, - - unregister: function(responder) { - this.responders = this.responders.without(responder); - }, - - dispatch: function(callback, request, transport, json) { - this.each(function(responder) { - if (Object.isFunction(responder[callback])) { - try { - responder[callback].apply(responder, [request, transport, json]); - } catch (e) { } - } - }); - } -}; - -Object.extend(Ajax.Responders, Enumerable); - -Ajax.Responders.register({ - onCreate: function() { Ajax.activeRequestCount++ }, - onComplete: function() { Ajax.activeRequestCount-- } -}); -Ajax.Base = Class.create({ - initialize: function(options) { - this.options = { - method: 'post', - asynchronous: true, - contentType: 'application/x-www-form-urlencoded', - encoding: 'UTF-8', - parameters: '', - evalJSON: true, - evalJS: true - }; - Object.extend(this.options, options || { }); - - this.options.method = this.options.method.toLowerCase(); - - if (Object.isString(this.options.parameters)) - this.options.parameters = this.options.parameters.toQueryParams(); - else if (Object.isHash(this.options.parameters)) - this.options.parameters = this.options.parameters.toObject(); - } -}); -Ajax.Request = Class.create(Ajax.Base, { - _complete: false, - - initialize: function($super, url, options) { - $super(options); - this.transport = Ajax.getTransport(); - this.request(url); - }, - - request: function(url) { - this.url = url; - this.method = this.options.method; - var params = Object.clone(this.options.parameters); - - if (!['get', 'post'].include(this.method)) { - params['_method'] = this.method; - this.method = 'post'; - } - - this.parameters = params; - - if (params = Object.toQueryString(params)) { - if (this.method == 'get') - this.url += (this.url.include('?') ? '&' : '?') + params; - else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) - params += '&_='; - } - - try { - var response = new Ajax.Response(this); - if (this.options.onCreate) this.options.onCreate(response); - Ajax.Responders.dispatch('onCreate', this, response); - - this.transport.open(this.method.toUpperCase(), this.url, - this.options.asynchronous); - - if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); - - this.transport.onreadystatechange = this.onStateChange.bind(this); - this.setRequestHeaders(); - - this.body = this.method == 'post' ? (this.options.postBody || params) : null; - this.transport.send(this.body); - - /* Force Firefox to handle ready state 4 for synchronous requests */ - if (!this.options.asynchronous && this.transport.overrideMimeType) - this.onStateChange(); - - } - catch (e) { - this.dispatchException(e); - } - }, - - onStateChange: function() { - var readyState = this.transport.readyState; - if (readyState > 1 && !((readyState == 4) && this._complete)) - this.respondToReadyState(this.transport.readyState); - }, - - setRequestHeaders: function() { - var headers = { - 'X-Requested-With': 'XMLHttpRequest', - 'X-Prototype-Version': Prototype.Version, - 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' - }; - - if (this.method == 'post') { - headers['Content-type'] = this.options.contentType + - (this.options.encoding ? '; charset=' + this.options.encoding : ''); - - /* Force "Connection: close" for older Mozilla browsers to work - * around a bug where XMLHttpRequest sends an incorrect - * Content-length header. See Mozilla Bugzilla #246651. - */ - if (this.transport.overrideMimeType && - (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) - headers['Connection'] = 'close'; - } - - if (typeof this.options.requestHeaders == 'object') { - var extras = this.options.requestHeaders; - - if (Object.isFunction(extras.push)) - for (var i = 0, length = extras.length; i < length; i += 2) - headers[extras[i]] = extras[i+1]; - else - $H(extras).each(function(pair) { headers[pair.key] = pair.value }); - } - - for (var name in headers) - this.transport.setRequestHeader(name, headers[name]); - }, - - success: function() { - var status = this.getStatus(); - return !status || (status >= 200 && status < 300); - }, - - getStatus: function() { - try { - return this.transport.status || 0; - } catch (e) { return 0 } - }, - - respondToReadyState: function(readyState) { - var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); - - if (state == 'Complete') { - try { - this._complete = true; - (this.options['on' + response.status] - || this.options['on' + (this.success() ? 'Success' : 'Failure')] - || Prototype.emptyFunction)(response, response.headerJSON); - } catch (e) { - this.dispatchException(e); - } - - var contentType = response.getHeader('Content-type'); - if (this.options.evalJS == 'force' - || (this.options.evalJS && this.isSameOrigin() && contentType - && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) - this.evalResponse(); - } - - try { - (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); - Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); - } catch (e) { - this.dispatchException(e); - } - - if (state == 'Complete') { - this.transport.onreadystatechange = Prototype.emptyFunction; - } - }, - - isSameOrigin: function() { - var m = this.url.match(/^\s*https?:\/\/[^\/]*/); - return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ - protocol: location.protocol, - domain: document.domain, - port: location.port ? ':' + location.port : '' - })); - }, - - getHeader: function(name) { - try { - return this.transport.getResponseHeader(name) || null; - } catch (e) { return null; } - }, - - evalResponse: function() { - try { - return eval((this.transport.responseText || '').unfilterJSON()); - } catch (e) { - this.dispatchException(e); - } - }, - - dispatchException: function(exception) { - (this.options.onException || Prototype.emptyFunction)(this, exception); - Ajax.Responders.dispatch('onException', this, exception); - } -}); - -Ajax.Request.Events = - ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; - - - - - - - - -Ajax.Response = Class.create({ - initialize: function(request){ - this.request = request; - var transport = this.transport = request.transport, - readyState = this.readyState = transport.readyState; - - if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { - this.status = this.getStatus(); - this.statusText = this.getStatusText(); - this.responseText = String.interpret(transport.responseText); - this.headerJSON = this._getHeaderJSON(); - } - - if (readyState == 4) { - var xml = transport.responseXML; - this.responseXML = Object.isUndefined(xml) ? null : xml; - this.responseJSON = this._getResponseJSON(); - } - }, - - status: 0, - - statusText: '', - - getStatus: Ajax.Request.prototype.getStatus, - - getStatusText: function() { - try { - return this.transport.statusText || ''; - } catch (e) { return '' } - }, - - getHeader: Ajax.Request.prototype.getHeader, - - getAllHeaders: function() { - try { - return this.getAllResponseHeaders(); - } catch (e) { return null } - }, - - getResponseHeader: function(name) { - return this.transport.getResponseHeader(name); - }, - - getAllResponseHeaders: function() { - return this.transport.getAllResponseHeaders(); - }, - - _getHeaderJSON: function() { - var json = this.getHeader('X-JSON'); - if (!json) return null; - json = decodeURIComponent(escape(json)); - try { - return json.evalJSON(this.request.options.sanitizeJSON || - !this.request.isSameOrigin()); - } catch (e) { - this.request.dispatchException(e); - } - }, - - _getResponseJSON: function() { - var options = this.request.options; - if (!options.evalJSON || (options.evalJSON != 'force' && - !(this.getHeader('Content-type') || '').include('application/json')) || - this.responseText.blank()) - return null; - try { - return this.responseText.evalJSON(options.sanitizeJSON || - !this.request.isSameOrigin()); - } catch (e) { - this.request.dispatchException(e); - } - } -}); - -Ajax.Updater = Class.create(Ajax.Request, { - initialize: function($super, container, url, options) { - this.container = { - success: (container.success || container), - failure: (container.failure || (container.success ? null : container)) - }; - - options = Object.clone(options); - var onComplete = options.onComplete; - options.onComplete = (function(response, json) { - this.updateContent(response.responseText); - if (Object.isFunction(onComplete)) onComplete(response, json); - }).bind(this); - - $super(url, options); - }, - - updateContent: function(responseText) { - var receiver = this.container[this.success() ? 'success' : 'failure'], - options = this.options; - - if (!options.evalScripts) responseText = responseText.stripScripts(); - - if (receiver = $(receiver)) { - if (options.insertion) { - if (Object.isString(options.insertion)) { - var insertion = { }; insertion[options.insertion] = responseText; - receiver.insert(insertion); - } - else options.insertion(receiver, responseText); - } - else receiver.update(responseText); - } - } -}); - -Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { - initialize: function($super, container, url, options) { - $super(options); - this.onComplete = this.options.onComplete; - - this.frequency = (this.options.frequency || 2); - this.decay = (this.options.decay || 1); - - this.updater = { }; - this.container = container; - this.url = url; - - this.start(); - }, - - start: function() { - this.options.onComplete = this.updateComplete.bind(this); - this.onTimerEvent(); - }, - - stop: function() { - this.updater.options.onComplete = undefined; - clearTimeout(this.timer); - (this.onComplete || Prototype.emptyFunction).apply(this, arguments); - }, - - updateComplete: function(response) { - if (this.options.decay) { - this.decay = (response.responseText == this.lastText ? - this.decay * this.options.decay : 1); - - this.lastText = response.responseText; - } - this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); - }, - - onTimerEvent: function() { - this.updater = new Ajax.Updater(this.container, this.url, this.options); - } -}); - - -function $(element) { - if (arguments.length > 1) { - for (var i = 0, elements = [], length = arguments.length; i < length; i++) - elements.push($(arguments[i])); - return elements; - } - if (Object.isString(element)) - element = document.getElementById(element); - return Element.extend(element); -} - -if (Prototype.BrowserFeatures.XPath) { - document._getElementsByXPath = function(expression, parentElement) { - var results = []; - var query = document.evaluate(expression, $(parentElement) || document, - null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); - for (var i = 0, length = query.snapshotLength; i < length; i++) - results.push(Element.extend(query.snapshotItem(i))); - return results; - }; -} - -/*--------------------------------------------------------------------------*/ - -if (!Node) var Node = { }; - -if (!Node.ELEMENT_NODE) { - Object.extend(Node, { - ELEMENT_NODE: 1, - ATTRIBUTE_NODE: 2, - TEXT_NODE: 3, - CDATA_SECTION_NODE: 4, - ENTITY_REFERENCE_NODE: 5, - ENTITY_NODE: 6, - PROCESSING_INSTRUCTION_NODE: 7, - COMMENT_NODE: 8, - DOCUMENT_NODE: 9, - DOCUMENT_TYPE_NODE: 10, - DOCUMENT_FRAGMENT_NODE: 11, - NOTATION_NODE: 12 - }); -} - - - -(function(global) { - - var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){ - try { - var el = document.createElement('<input name="x">'); - return el.tagName.toLowerCase() === 'input' && el.name === 'x'; - } - catch(err) { - return false; - } - })(); - - var element = global.Element; - - global.Element = function(tagName, attributes) { - attributes = attributes || { }; - tagName = tagName.toLowerCase(); - var cache = Element.cache; - if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) { - tagName = '<' + tagName + ' name="' + attributes.name + '">'; - delete attributes.name; - return Element.writeAttribute(document.createElement(tagName), attributes); - } - if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); - return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); - }; - - Object.extend(global.Element, element || { }); - if (element) global.Element.prototype = element.prototype; - -})(this); - -Element.idCounter = 1; -Element.cache = { }; - -function purgeElement(element) { - var uid = element._prototypeUID; - if (uid) { - Element.stopObserving(element); - element._prototypeUID = void 0; - delete Element.Storage[uid]; - } -} - -Element.Methods = { - visible: function(element) { - return $(element).style.display != 'none'; - }, - - toggle: function(element) { - element = $(element); - Element[Element.visible(element) ? 'hide' : 'show'](element); - return element; - }, - - hide: function(element) { - element = $(element); - element.style.display = 'none'; - return element; - }, - - show: function(element) { - element = $(element); - element.style.display = ''; - return element; - }, - - remove: function(element) { - element = $(element); - element.parentNode.removeChild(element); - return element; - }, - - update: (function(){ - - var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){ - var el = document.createElement("select"), - isBuggy = true; - el.innerHTML = "<option value=\"test\">test</option>"; - if (el.options && el.options[0]) { - isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"; - } - el = null; - return isBuggy; - })(); - - var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){ - try { - var el = document.createElement("table"); - if (el && el.tBodies) { - el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>"; - var isBuggy = typeof el.tBodies[0] == "undefined"; - el = null; - return isBuggy; - } - } catch (e) { - return true; - } - })(); - - var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () { - var s = document.createElement("script"), - isBuggy = false; - try { - s.appendChild(document.createTextNode("")); - isBuggy = !s.firstChild || - s.firstChild && s.firstChild.nodeType !== 3; - } catch (e) { - isBuggy = true; - } - s = null; - return isBuggy; - })(); - - function update(element, content) { - element = $(element); - - var descendants = element.getElementsByTagName('*'), - i = descendants.length; - while (i--) purgeElement(descendants[i]); - - if (content && content.toElement) - content = content.toElement(); - - if (Object.isElement(content)) - return element.update().insert(content); - - content = Object.toHTML(content); - - var tagName = element.tagName.toUpperCase(); - - if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) { - element.text = content; - return element; - } - - if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) { - if (tagName in Element._insertionTranslations.tags) { - while (element.firstChild) { - element.removeChild(element.firstChild); - } - Element._getContentFromAnonymousElement(tagName, content.stripScripts()) - .each(function(node) { - element.appendChild(node) - }); - } - else { - element.innerHTML = content.stripScripts(); - } - } - else { - element.innerHTML = content.stripScripts(); - } - - content.evalScripts.bind(content).defer(); - return element; - } - - return update; - })(), - - replace: function(element, content) { - element = $(element); - if (content && content.toElement) content = content.toElement(); - else if (!Object.isElement(content)) { - content = Object.toHTML(content); - var range = element.ownerDocument.createRange(); - range.selectNode(element); - content.evalScripts.bind(content).defer(); - content = range.createContextualFragment(content.stripScripts()); - } - element.parentNode.replaceChild(content, element); - return element; - }, - - insert: function(element, insertions) { - element = $(element); - - if (Object.isString(insertions) || Object.isNumber(insertions) || - Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) - insertions = {bottom:insertions}; - - var content, insert, tagName, childNodes; - - for (var position in insertions) { - content = insertions[position]; - position = position.toLowerCase(); - insert = Element._insertionTranslations[position]; - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) { - insert(element, content); - continue; - } - - content = Object.toHTML(content); - - tagName = ((position == 'before' || position == 'after') - ? element.parentNode : element).tagName.toUpperCase(); - - childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); - - if (position == 'top' || position == 'after') childNodes.reverse(); - childNodes.each(insert.curry(element)); - - content.evalScripts.bind(content).defer(); - } - - return element; - }, - - wrap: function(element, wrapper, attributes) { - element = $(element); - if (Object.isElement(wrapper)) - $(wrapper).writeAttribute(attributes || { }); - else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); - else wrapper = new Element('div', wrapper); - if (element.parentNode) - element.parentNode.replaceChild(wrapper, element); - wrapper.appendChild(element); - return wrapper; - }, - - inspect: function(element) { - element = $(element); - var result = '<' + element.tagName.toLowerCase(); - $H({'id': 'id', 'className': 'class'}).each(function(pair) { - var property = pair.first(), - attribute = pair.last(), - value = (element[property] || '').toString(); - if (value) result += ' ' + attribute + '=' + value.inspect(true); - }); - return result + '>'; - }, - - recursivelyCollect: function(element, property, maximumLength) { - element = $(element); - maximumLength = maximumLength || -1; - var elements = []; - - while (element = element[property]) { - if (element.nodeType == 1) - elements.push(Element.extend(element)); - if (elements.length == maximumLength) - break; - } - - return elements; - }, - - ancestors: function(element) { - return Element.recursivelyCollect(element, 'parentNode'); - }, - - descendants: function(element) { - return Element.select(element, "*"); - }, - - firstDescendant: function(element) { - element = $(element).firstChild; - while (element && element.nodeType != 1) element = element.nextSibling; - return $(element); - }, - - immediateDescendants: function(element) { - var results = [], child = $(element).firstChild; - while (child) { - if (child.nodeType === 1) { - results.push(Element.extend(child)); - } - child = child.nextSibling; - } - return results; - }, - - previousSiblings: function(element, maximumLength) { - return Element.recursivelyCollect(element, 'previousSibling'); - }, - - nextSiblings: function(element) { - return Element.recursivelyCollect(element, 'nextSibling'); - }, - - siblings: function(element) { - element = $(element); - return Element.previousSiblings(element).reverse() - .concat(Element.nextSiblings(element)); - }, - - match: function(element, selector) { - element = $(element); - if (Object.isString(selector)) - return Prototype.Selector.match(element, selector); - return selector.match(element); - }, - - up: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(element.parentNode); - var ancestors = Element.ancestors(element); - return Object.isNumber(expression) ? ancestors[expression] : - Prototype.Selector.find(ancestors, expression, index); - }, - - down: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return Element.firstDescendant(element); - return Object.isNumber(expression) ? Element.descendants(element)[expression] : - Element.select(element, expression)[index || 0]; - }, - - previous: function(element, expression, index) { - element = $(element); - if (Object.isNumber(expression)) index = expression, expression = false; - if (!Object.isNumber(index)) index = 0; - - if (expression) { - return Prototype.Selector.find(element.previousSiblings(), expression, index); - } else { - return element.recursivelyCollect("previousSibling", index + 1)[index]; - } - }, - - next: function(element, expression, index) { - element = $(element); - if (Object.isNumber(expression)) index = expression, expression = false; - if (!Object.isNumber(index)) index = 0; - - if (expression) { - return Prototype.Selector.find(element.nextSiblings(), expression, index); - } else { - var maximumLength = Object.isNumber(index) ? index + 1 : 1; - return element.recursivelyCollect("nextSibling", index + 1)[index]; - } - }, - - - select: function(element) { - element = $(element); - var expressions = Array.prototype.slice.call(arguments, 1).join(', '); - return Prototype.Selector.select(expressions, element); - }, - - adjacent: function(element) { - element = $(element); - var expressions = Array.prototype.slice.call(arguments, 1).join(', '); - return Prototype.Selector.select(expressions, element.parentNode).without(element); - }, - - identify: function(element) { - element = $(element); - var id = Element.readAttribute(element, 'id'); - if (id) return id; - do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id)); - Element.writeAttribute(element, 'id', id); - return id; - }, - - readAttribute: function(element, name) { - element = $(element); - if (Prototype.Browser.IE) { - var t = Element._attributeTranslations.read; - if (t.values[name]) return t.values[name](element, name); - if (t.names[name]) name = t.names[name]; - if (name.include(':')) { - return (!element.attributes || !element.attributes[name]) ? null : - element.attributes[name].value; - } - } - return element.getAttribute(name); - }, - - writeAttribute: function(element, name, value) { - element = $(element); - var attributes = { }, t = Element._attributeTranslations.write; - - if (typeof name == 'object') attributes = name; - else attributes[name] = Object.isUndefined(value) ? true : value; - - for (var attr in attributes) { - name = t.names[attr] || attr; - value = attributes[attr]; - if (t.values[attr]) name = t.values[attr](element, value); - if (value === false || value === null) - element.removeAttribute(name); - else if (value === true) - element.setAttribute(name, name); - else element.setAttribute(name, value); - } - return element; - }, - - getHeight: function(element) { - return Element.getDimensions(element).height; - }, - - getWidth: function(element) { - return Element.getDimensions(element).width; - }, - - classNames: function(element) { - return new Element.ClassNames(element); - }, - - hasClassName: function(element, className) { - if (!(element = $(element))) return; - var elementClassName = element.className; - return (elementClassName.length > 0 && (elementClassName == className || - new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); - }, - - addClassName: function(element, className) { - if (!(element = $(element))) return; - if (!Element.hasClassName(element, className)) - element.className += (element.className ? ' ' : '') + className; - return element; - }, - - removeClassName: function(element, className) { - if (!(element = $(element))) return; - element.className = element.className.replace( - new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); - return element; - }, - - toggleClassName: function(element, className) { - if (!(element = $(element))) return; - return Element[Element.hasClassName(element, className) ? - 'removeClassName' : 'addClassName'](element, className); - }, - - cleanWhitespace: function(element) { - element = $(element); - var node = element.firstChild; - while (node) { - var nextNode = node.nextSibling; - if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) - element.removeChild(node); - node = nextNode; - } - return element; - }, - - empty: function(element) { - return $(element).innerHTML.blank(); - }, - - descendantOf: function(element, ancestor) { - element = $(element), ancestor = $(ancestor); - - if (element.compareDocumentPosition) - return (element.compareDocumentPosition(ancestor) & 8) === 8; - - if (ancestor.contains) - return ancestor.contains(element) && ancestor !== element; - - while (element = element.parentNode) - if (element == ancestor) return true; - - return false; - }, - - scrollTo: function(element) { - element = $(element); - var pos = Element.cumulativeOffset(element); - window.scrollTo(pos[0], pos[1]); - return element; - }, - - getStyle: function(element, style) { - element = $(element); - style = style == 'float' ? 'cssFloat' : style.camelize(); - var value = element.style[style]; - if (!value || value == 'auto') { - var css = document.defaultView.getComputedStyle(element, null); - value = css ? css[style] : null; - } - if (style == 'opacity') return value ? parseFloat(value) : 1.0; - return value == 'auto' ? null : value; - }, - - getOpacity: function(element) { - return $(element).getStyle('opacity'); - }, - - setStyle: function(element, styles) { - element = $(element); - var elementStyle = element.style, match; - if (Object.isString(styles)) { - element.style.cssText += ';' + styles; - return styles.include('opacity') ? - element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; - } - for (var property in styles) - if (property == 'opacity') element.setOpacity(styles[property]); - else - elementStyle[(property == 'float' || property == 'cssFloat') ? - (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : - property] = styles[property]; - - return element; - }, - - setOpacity: function(element, value) { - element = $(element); - element.style.opacity = (value == 1 || value === '') ? '' : - (value < 0.00001) ? 0 : value; - return element; - }, - - makePositioned: function(element) { - element = $(element); - var pos = Element.getStyle(element, 'position'); - if (pos == 'static' || !pos) { - element._madePositioned = true; - element.style.position = 'relative'; - if (Prototype.Browser.Opera) { - element.style.top = 0; - element.style.left = 0; - } - } - return element; - }, - - undoPositioned: function(element) { - element = $(element); - if (element._madePositioned) { - element._madePositioned = undefined; - element.style.position = - element.style.top = - element.style.left = - element.style.bottom = - element.style.right = ''; - } - return element; - }, - - makeClipping: function(element) { - element = $(element); - if (element._overflow) return element; - element._overflow = Element.getStyle(element, 'overflow') || 'auto'; - if (element._overflow !== 'hidden') - element.style.overflow = 'hidden'; - return element; - }, - - undoClipping: function(element) { - element = $(element); - if (!element._overflow) return element; - element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; - element._overflow = null; - return element; - }, - - cumulativeOffset: function(element) { - var valueT = 0, valueL = 0; - if (element.parentNode) { - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - } while (element); - } - return Element._returnOffset(valueL, valueT); - }, - - positionedOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - if (element) { - if (element.tagName.toUpperCase() == 'BODY') break; - var p = Element.getStyle(element, 'position'); - if (p !== 'static') break; - } - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - absolutize: function(element) { - element = $(element); - if (Element.getStyle(element, 'position') == 'absolute') return element; - - var offsets = Element.positionedOffset(element), - top = offsets[1], - left = offsets[0], - width = element.clientWidth, - height = element.clientHeight; - - element._originalLeft = left - parseFloat(element.style.left || 0); - element._originalTop = top - parseFloat(element.style.top || 0); - element._originalWidth = element.style.width; - element._originalHeight = element.style.height; - - element.style.position = 'absolute'; - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.width = width + 'px'; - element.style.height = height + 'px'; - return element; - }, - - relativize: function(element) { - element = $(element); - if (Element.getStyle(element, 'position') == 'relative') return element; - - element.style.position = 'relative'; - var top = parseFloat(element.style.top || 0) - (element._originalTop || 0), - left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); - - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.height = element._originalHeight; - element.style.width = element._originalWidth; - return element; - }, - - cumulativeScrollOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.scrollTop || 0; - valueL += element.scrollLeft || 0; - element = element.parentNode; - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - getOffsetParent: function(element) { - if (element.offsetParent) return $(element.offsetParent); - if (element == document.body) return $(element); - - while ((element = element.parentNode) && element != document.body) - if (Element.getStyle(element, 'position') != 'static') - return $(element); - - return $(document.body); - }, - - viewportOffset: function(forElement) { - var valueT = 0, - valueL = 0, - element = forElement; - - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - - if (element.offsetParent == document.body && - Element.getStyle(element, 'position') == 'absolute') break; - - } while (element = element.offsetParent); - - element = forElement; - do { - if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) { - valueT -= element.scrollTop || 0; - valueL -= element.scrollLeft || 0; - } - } while (element = element.parentNode); - - return Element._returnOffset(valueL, valueT); - }, - - clonePosition: function(element, source) { - var options = Object.extend({ - setLeft: true, - setTop: true, - setWidth: true, - setHeight: true, - offsetTop: 0, - offsetLeft: 0 - }, arguments[2] || { }); - - source = $(source); - var p = Element.viewportOffset(source), delta = [0, 0], parent = null; - - element = $(element); - - if (Element.getStyle(element, 'position') == 'absolute') { - parent = Element.getOffsetParent(element); - delta = Element.viewportOffset(parent); - } - - if (parent == document.body) { - delta[0] -= document.body.offsetLeft; - delta[1] -= document.body.offsetTop; - } - - if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; - if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; - if (options.setWidth) element.style.width = source.offsetWidth + 'px'; - if (options.setHeight) element.style.height = source.offsetHeight + 'px'; - return element; - } -}; - -Object.extend(Element.Methods, { - getElementsBySelector: Element.Methods.select, - - childElements: Element.Methods.immediateDescendants -}); - -Element._attributeTranslations = { - write: { - names: { - className: 'class', - htmlFor: 'for' - }, - values: { } - } -}; - -if (Prototype.Browser.Opera) { - Element.Methods.getStyle = Element.Methods.getStyle.wrap( - function(proceed, element, style) { - switch (style) { - case 'left': case 'top': case 'right': case 'bottom': - if (proceed(element, 'position') === 'static') return null; - case 'height': case 'width': - if (!Element.visible(element)) return null; - - var dim = parseInt(proceed(element, style), 10); - - if (dim !== element['offset' + style.capitalize()]) - return dim + 'px'; - - var properties; - if (style === 'height') { - properties = ['border-top-width', 'padding-top', - 'padding-bottom', 'border-bottom-width']; - } - else { - properties = ['border-left-width', 'padding-left', - 'padding-right', 'border-right-width']; - } - return properties.inject(dim, function(memo, property) { - var val = proceed(element, property); - return val === null ? memo : memo - parseInt(val, 10); - }) + 'px'; - default: return proceed(element, style); - } - } - ); - - Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( - function(proceed, element, attribute) { - if (attribute === 'title') return element.title; - return proceed(element, attribute); - } - ); -} - -else if (Prototype.Browser.IE) { - Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( - function(proceed, element) { - element = $(element); - if (!element.parentNode) return $(document.body); - var position = element.getStyle('position'); - if (position !== 'static') return proceed(element); - element.setStyle({ position: 'relative' }); - var value = proceed(element); - element.setStyle({ position: position }); - return value; - } - ); - - $w('positionedOffset viewportOffset').each(function(method) { - Element.Methods[method] = Element.Methods[method].wrap( - function(proceed, element) { - element = $(element); - if (!element.parentNode) return Element._returnOffset(0, 0); - var position = element.getStyle('position'); - if (position !== 'static') return proceed(element); - var offsetParent = element.getOffsetParent(); - if (offsetParent && offsetParent.getStyle('position') === 'fixed') - offsetParent.setStyle({ zoom: 1 }); - element.setStyle({ position: 'relative' }); - var value = proceed(element); - element.setStyle({ position: position }); - return value; - } - ); - }); - - Element.Methods.getStyle = function(element, style) { - element = $(element); - style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); - var value = element.style[style]; - if (!value && element.currentStyle) value = element.currentStyle[style]; - - if (style == 'opacity') { - if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) - if (value[1]) return parseFloat(value[1]) / 100; - return 1.0; - } - - if (value == 'auto') { - if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) - return element['offset' + style.capitalize()] + 'px'; - return null; - } - return value; - }; - - Element.Methods.setOpacity = function(element, value) { - function stripAlpha(filter){ - return filter.replace(/alpha\([^\)]*\)/gi,''); - } - element = $(element); - var currentStyle = element.currentStyle; - if ((currentStyle && !currentStyle.hasLayout) || - (!currentStyle && element.style.zoom == 'normal')) - element.style.zoom = 1; - - var filter = element.getStyle('filter'), style = element.style; - if (value == 1 || value === '') { - (filter = stripAlpha(filter)) ? - style.filter = filter : style.removeAttribute('filter'); - return element; - } else if (value < 0.00001) value = 0; - style.filter = stripAlpha(filter) + - 'alpha(opacity=' + (value * 100) + ')'; - return element; - }; - - Element._attributeTranslations = (function(){ - - var classProp = 'className', - forProp = 'for', - el = document.createElement('div'); - - el.setAttribute(classProp, 'x'); - - if (el.className !== 'x') { - el.setAttribute('class', 'x'); - if (el.className === 'x') { - classProp = 'class'; - } - } - el = null; - - el = document.createElement('label'); - el.setAttribute(forProp, 'x'); - if (el.htmlFor !== 'x') { - el.setAttribute('htmlFor', 'x'); - if (el.htmlFor === 'x') { - forProp = 'htmlFor'; - } - } - el = null; - - return { - read: { - names: { - 'class': classProp, - 'className': classProp, - 'for': forProp, - 'htmlFor': forProp - }, - values: { - _getAttr: function(element, attribute) { - return element.getAttribute(attribute); - }, - _getAttr2: function(element, attribute) { - return element.getAttribute(attribute, 2); - }, - _getAttrNode: function(element, attribute) { - var node = element.getAttributeNode(attribute); - return node ? node.value : ""; - }, - _getEv: (function(){ - - var el = document.createElement('div'), f; - el.onclick = Prototype.emptyFunction; - var value = el.getAttribute('onclick'); - - if (String(value).indexOf('{') > -1) { - f = function(element, attribute) { - attribute = element.getAttribute(attribute); - if (!attribute) return null; - attribute = attribute.toString(); - attribute = attribute.split('{')[1]; - attribute = attribute.split('}')[0]; - return attribute.strip(); - }; - } - else if (value === '') { - f = function(element, attribute) { - attribute = element.getAttribute(attribute); - if (!attribute) return null; - return attribute.strip(); - }; - } - el = null; - return f; - })(), - _flag: function(element, attribute) { - return $(element).hasAttribute(attribute) ? attribute : null; - }, - style: function(element) { - return element.style.cssText.toLowerCase(); - }, - title: function(element) { - return element.title; - } - } - } - } - })(); - - Element._attributeTranslations.write = { - names: Object.extend({ - cellpadding: 'cellPadding', - cellspacing: 'cellSpacing' - }, Element._attributeTranslations.read.names), - values: { - checked: function(element, value) { - element.checked = !!value; - }, - - style: function(element, value) { - element.style.cssText = value ? value : ''; - } - } - }; - - Element._attributeTranslations.has = {}; - - $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + - 'encType maxLength readOnly longDesc frameBorder').each(function(attr) { - Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; - Element._attributeTranslations.has[attr.toLowerCase()] = attr; - }); - - (function(v) { - Object.extend(v, { - href: v._getAttr2, - src: v._getAttr2, - type: v._getAttr, - action: v._getAttrNode, - disabled: v._flag, - checked: v._flag, - readonly: v._flag, - multiple: v._flag, - onload: v._getEv, - onunload: v._getEv, - onclick: v._getEv, - ondblclick: v._getEv, - onmousedown: v._getEv, - onmouseup: v._getEv, - onmouseover: v._getEv, - onmousemove: v._getEv, - onmouseout: v._getEv, - onfocus: v._getEv, - onblur: v._getEv, - onkeypress: v._getEv, - onkeydown: v._getEv, - onkeyup: v._getEv, - onsubmit: v._getEv, - onreset: v._getEv, - onselect: v._getEv, - onchange: v._getEv - }); - })(Element._attributeTranslations.read.values); - - if (Prototype.BrowserFeatures.ElementExtensions) { - (function() { - function _descendants(element) { - var nodes = element.getElementsByTagName('*'), results = []; - for (var i = 0, node; node = nodes[i]; i++) - if (node.tagName !== "!") // Filter out comment nodes. - results.push(node); - return results; - } - - Element.Methods.down = function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return element.firstDescendant(); - return Object.isNumber(expression) ? _descendants(element)[expression] : - Element.select(element, expression)[index || 0]; - } - })(); - } - -} - -else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { - Element.Methods.setOpacity = function(element, value) { - element = $(element); - element.style.opacity = (value == 1) ? 0.999999 : - (value === '') ? '' : (value < 0.00001) ? 0 : value; - return element; - }; -} - -else if (Prototype.Browser.WebKit) { - Element.Methods.setOpacity = function(element, value) { - element = $(element); - element.style.opacity = (value == 1 || value === '') ? '' : - (value < 0.00001) ? 0 : value; - - if (value == 1) - if (element.tagName.toUpperCase() == 'IMG' && element.width) { - element.width++; element.width--; - } else try { - var n = document.createTextNode(' '); - element.appendChild(n); - element.removeChild(n); - } catch (e) { } - - return element; - }; - - Element.Methods.cumulativeOffset = function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - if (element.offsetParent == document.body) - if (Element.getStyle(element, 'position') == 'absolute') break; - - element = element.offsetParent; - } while (element); - - return Element._returnOffset(valueL, valueT); - }; -} - -if ('outerHTML' in document.documentElement) { - Element.Methods.replace = function(element, content) { - element = $(element); - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) { - element.parentNode.replaceChild(content, element); - return element; - } - - content = Object.toHTML(content); - var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); - - if (Element._insertionTranslations.tags[tagName]) { - var nextSibling = element.next(), - fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); - parent.removeChild(element); - if (nextSibling) - fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); - else - fragments.each(function(node) { parent.appendChild(node) }); - } - else element.outerHTML = content.stripScripts(); - - content.evalScripts.bind(content).defer(); - return element; - }; -} - -Element._returnOffset = function(l, t) { - var result = [l, t]; - result.left = l; - result.top = t; - return result; -}; - -Element._getContentFromAnonymousElement = function(tagName, html) { - var div = new Element('div'), - t = Element._insertionTranslations.tags[tagName]; - if (t) { - div.innerHTML = t[0] + html + t[1]; - for (var i = t[2]; i--; ) { - div = div.firstChild; - } - } - else { - div.innerHTML = html; - } - return $A(div.childNodes); -}; - -Element._insertionTranslations = { - before: function(element, node) { - element.parentNode.insertBefore(node, element); - }, - top: function(element, node) { - element.insertBefore(node, element.firstChild); - }, - bottom: function(element, node) { - element.appendChild(node); - }, - after: function(element, node) { - element.parentNode.insertBefore(node, element.nextSibling); - }, - tags: { - TABLE: ['<table>', '</table>', 1], - TBODY: ['<table><tbody>', '</tbody></table>', 2], - TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3], - TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4], - SELECT: ['<select>', '</select>', 1] - } -}; - -(function() { - var tags = Element._insertionTranslations.tags; - Object.extend(tags, { - THEAD: tags.TBODY, - TFOOT: tags.TBODY, - TH: tags.TD - }); -})(); - -Element.Methods.Simulated = { - hasAttribute: function(element, attribute) { - attribute = Element._attributeTranslations.has[attribute] || attribute; - var node = $(element).getAttributeNode(attribute); - return !!(node && node.specified); - } -}; - -Element.Methods.ByTag = { }; - -Object.extend(Element, Element.Methods); - -(function(div) { - - if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) { - window.HTMLElement = { }; - window.HTMLElement.prototype = div['__proto__']; - Prototype.BrowserFeatures.ElementExtensions = true; - } - - div = null; - -})(document.createElement('div')); - -Element.extend = (function() { - - function checkDeficiency(tagName) { - if (typeof window.Element != 'undefined') { - var proto = window.Element.prototype; - if (proto) { - var id = '_' + (Math.random()+'').slice(2), - el = document.createElement(tagName); - proto[id] = 'x'; - var isBuggy = (el[id] !== 'x'); - delete proto[id]; - el = null; - return isBuggy; - } - } - return false; - } - - function extendElementWith(element, methods) { - for (var property in methods) { - var value = methods[property]; - if (Object.isFunction(value) && !(property in element)) - element[property] = value.methodize(); - } - } - - var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object'); - - if (Prototype.BrowserFeatures.SpecificElementExtensions) { - if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) { - return function(element) { - if (element && typeof element._extendedByPrototype == 'undefined') { - var t = element.tagName; - if (t && (/^(?:object|applet|embed)$/i.test(t))) { - extendElementWith(element, Element.Methods); - extendElementWith(element, Element.Methods.Simulated); - extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]); - } - } - return element; - } - } - return Prototype.K; - } - - var Methods = { }, ByTag = Element.Methods.ByTag; - - var extend = Object.extend(function(element) { - if (!element || typeof element._extendedByPrototype != 'undefined' || - element.nodeType != 1 || element == window) return element; - - var methods = Object.clone(Methods), - tagName = element.tagName.toUpperCase(); - - if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); - - extendElementWith(element, methods); - - element._extendedByPrototype = Prototype.emptyFunction; - return element; - - }, { - refresh: function() { - if (!Prototype.BrowserFeatures.ElementExtensions) { - Object.extend(Methods, Element.Methods); - Object.extend(Methods, Element.Methods.Simulated); - } - } - }); - - extend.refresh(); - return extend; -})(); - -if (document.documentElement.hasAttribute) { - Element.hasAttribute = function(element, attribute) { - return element.hasAttribute(attribute); - }; -} -else { - Element.hasAttribute = Element.Methods.Simulated.hasAttribute; -} - -Element.addMethods = function(methods) { - var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; - - if (!methods) { - Object.extend(Form, Form.Methods); - Object.extend(Form.Element, Form.Element.Methods); - Object.extend(Element.Methods.ByTag, { - "FORM": Object.clone(Form.Methods), - "INPUT": Object.clone(Form.Element.Methods), - "SELECT": Object.clone(Form.Element.Methods), - "TEXTAREA": Object.clone(Form.Element.Methods) - }); - } - - if (arguments.length == 2) { - var tagName = methods; - methods = arguments[1]; - } - - if (!tagName) Object.extend(Element.Methods, methods || { }); - else { - if (Object.isArray(tagName)) tagName.each(extend); - else extend(tagName); - } - - function extend(tagName) { - tagName = tagName.toUpperCase(); - if (!Element.Methods.ByTag[tagName]) - Element.Methods.ByTag[tagName] = { }; - Object.extend(Element.Methods.ByTag[tagName], methods); - } - - function copy(methods, destination, onlyIfAbsent) { - onlyIfAbsent = onlyIfAbsent || false; - for (var property in methods) { - var value = methods[property]; - if (!Object.isFunction(value)) continue; - if (!onlyIfAbsent || !(property in destination)) - destination[property] = value.methodize(); - } - } - - function findDOMClass(tagName) { - var klass; - var trans = { - "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", - "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", - "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", - "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", - "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": - "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": - "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": - "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": - "FrameSet", "IFRAME": "IFrame" - }; - if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; - if (window[klass]) return window[klass]; - klass = 'HTML' + tagName + 'Element'; - if (window[klass]) return window[klass]; - klass = 'HTML' + tagName.capitalize() + 'Element'; - if (window[klass]) return window[klass]; - - var element = document.createElement(tagName), - proto = element['__proto__'] || element.constructor.prototype; - - element = null; - return proto; - } - - var elementPrototype = window.HTMLElement ? HTMLElement.prototype : - Element.prototype; - - if (F.ElementExtensions) { - copy(Element.Methods, elementPrototype); - copy(Element.Methods.Simulated, elementPrototype, true); - } - - if (F.SpecificElementExtensions) { - for (var tag in Element.Methods.ByTag) { - var klass = findDOMClass(tag); - if (Object.isUndefined(klass)) continue; - copy(T[tag], klass.prototype); - } - } - - Object.extend(Element, Element.Methods); - delete Element.ByTag; - - if (Element.extend.refresh) Element.extend.refresh(); - Element.cache = { }; -}; - - -document.viewport = { - - getDimensions: function() { - return { width: this.getWidth(), height: this.getHeight() }; - }, - - getScrollOffsets: function() { - return Element._returnOffset( - window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, - window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); - } -}; - -(function(viewport) { - var B = Prototype.Browser, doc = document, element, property = {}; - - function getRootElement() { - if (B.WebKit && !doc.evaluate) - return document; - - if (B.Opera && window.parseFloat(window.opera.version()) < 9.5) - return document.body; - - return document.documentElement; - } - - function define(D) { - if (!element) element = getRootElement(); - - property[D] = 'client' + D; - - viewport['get' + D] = function() { return element[property[D]] }; - return viewport['get' + D](); - } - - viewport.getWidth = define.curry('Width'); - - viewport.getHeight = define.curry('Height'); -})(document.viewport); - - -Element.Storage = { - UID: 1 -}; - -Element.addMethods({ - getStorage: function(element) { - if (!(element = $(element))) return; - - var uid; - if (element === window) { - uid = 0; - } else { - if (typeof element._prototypeUID === "undefined") - element._prototypeUID = Element.Storage.UID++; - uid = element._prototypeUID; - } - - if (!Element.Storage[uid]) - Element.Storage[uid] = $H(); - - return Element.Storage[uid]; - }, - - store: function(element, key, value) { - if (!(element = $(element))) return; - - if (arguments.length === 2) { - Element.getStorage(element).update(key); - } else { - Element.getStorage(element).set(key, value); - } - - return element; - }, - - retrieve: function(element, key, defaultValue) { - if (!(element = $(element))) return; - var hash = Element.getStorage(element), value = hash.get(key); - - if (Object.isUndefined(value)) { - hash.set(key, defaultValue); - value = defaultValue; - } - - return value; - }, - - clone: function(element, deep) { - if (!(element = $(element))) return; - var clone = element.cloneNode(deep); - clone._prototypeUID = void 0; - if (deep) { - var descendants = Element.select(clone, '*'), - i = descendants.length; - while (i--) { - descendants[i]._prototypeUID = void 0; - } - } - return Element.extend(clone); - }, - - purge: function(element) { - if (!(element = $(element))) return; - purgeElement(element); - - var descendants = element.getElementsByTagName('*'), - i = descendants.length; - - while (i--) purgeElement(descendants[i]); - - return null; - } -}); - -(function() { - - function toDecimal(pctString) { - var match = pctString.match(/^(\d+)%?$/i); - if (!match) return null; - return (Number(match[1]) / 100); - } - - function getPixelValue(value, property) { - if (Object.isElement(value)) { - element = value; - value = element.getStyle(property); - } - if (value === null) { - return null; - } - - if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) { - return window.parseFloat(value); - } - - if (/\d/.test(value) && element.runtimeStyle) { - var style = element.style.left, rStyle = element.runtimeStyle.left; - element.runtimeStyle.left = element.currentStyle.left; - element.style.left = value || 0; - value = element.style.pixelLeft; - element.style.left = style; - element.runtimeStyle.left = rStyle; - - return value; - } - - if (value.include('%')) { - var decimal = toDecimal(value); - var whole; - if (property.include('left') || property.include('right') || - property.include('width')) { - whole = $(element.parentNode).measure('width'); - } else if (property.include('top') || property.include('bottom') || - property.include('height')) { - whole = $(element.parentNode).measure('height'); - } - - return whole * decimal; - } - - return 0; - } - - function toCSSPixels(number) { - if (Object.isString(number) && number.endsWith('px')) { - return number; - } - return number + 'px'; - } - - function isDisplayed(element) { - var originalElement = element; - while (element && element.parentNode) { - var display = element.getStyle('display'); - if (display === 'none') { - return false; - } - element = $(element.parentNode); - } - return true; - } - - var hasLayout = Prototype.K; - if ('currentStyle' in document.documentElement) { - hasLayout = function(element) { - if (!element.currentStyle.hasLayout) { - element.style.zoom = 1; - } - return element; - }; - } - - function cssNameFor(key) { - if (key.include('border')) key = key + '-width'; - return key.camelize(); - } - - Element.Layout = Class.create(Hash, { - initialize: function($super, element, preCompute) { - $super(); - this.element = $(element); - - Element.Layout.PROPERTIES.each( function(property) { - this._set(property, null); - }, this); - - if (preCompute) { - this._preComputing = true; - this._begin(); - Element.Layout.PROPERTIES.each( this._compute, this ); - this._end(); - this._preComputing = false; - } - }, - - _set: function(property, value) { - return Hash.prototype.set.call(this, property, value); - }, - - set: function(property, value) { - throw "Properties of Element.Layout are read-only."; - }, - - get: function($super, property) { - var value = $super(property); - return value === null ? this._compute(property) : value; - }, - - _begin: function() { - if (this._prepared) return; - - var element = this.element; - if (isDisplayed(element)) { - this._prepared = true; - return; - } - - var originalStyles = { - position: element.style.position || '', - width: element.style.width || '', - visibility: element.style.visibility || '', - display: element.style.display || '' - }; - - element.store('prototype_original_styles', originalStyles); - - var position = element.getStyle('position'), - width = element.getStyle('width'); - - element.setStyle({ - position: 'absolute', - visibility: 'hidden', - display: 'block' - }); - - var positionedWidth = element.getStyle('width'); - - var newWidth; - if (width && (positionedWidth === width)) { - newWidth = getPixelValue(width); - } else if (width && (position === 'absolute' || position === 'fixed')) { - newWidth = getPixelValue(width); - } else { - var parent = element.parentNode, pLayout = $(parent).getLayout(); - - newWidth = pLayout.get('width') - - this.get('margin-left') - - this.get('border-left') - - this.get('padding-left') - - this.get('padding-right') - - this.get('border-right') - - this.get('margin-right'); - } - - element.setStyle({ width: newWidth + 'px' }); - - this._prepared = true; - }, - - _end: function() { - var element = this.element; - var originalStyles = element.retrieve('prototype_original_styles'); - element.store('prototype_original_styles', null); - element.setStyle(originalStyles); - this._prepared = false; - }, - - _compute: function(property) { - var COMPUTATIONS = Element.Layout.COMPUTATIONS; - if (!(property in COMPUTATIONS)) { - throw "Property not found."; - } - return this._set(property, COMPUTATIONS[property].call(this, this.element)); - }, - - toObject: function() { - var args = $A(arguments); - var keys = (args.length === 0) ? Element.Layout.PROPERTIES : - args.join(' ').split(' '); - var obj = {}; - keys.each( function(key) { - if (!Element.Layout.PROPERTIES.include(key)) return; - var value = this.get(key); - if (value != null) obj[key] = value; - }, this); - return obj; - }, - - toHash: function() { - var obj = this.toObject.apply(this, arguments); - return new Hash(obj); - }, - - toCSS: function() { - var args = $A(arguments); - var keys = (args.length === 0) ? Element.Layout.PROPERTIES : - args.join(' ').split(' '); - var css = {}; - - keys.each( function(key) { - if (!Element.Layout.PROPERTIES.include(key)) return; - if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return; - - var value = this.get(key); - if (value != null) css[cssNameFor(key)] = value + 'px'; - }, this); - return css; - }, - - inspect: function() { - return "#<Element.Layout>"; - } - }); - - Object.extend(Element.Layout, { - PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'), - - COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'), - - COMPUTATIONS: { - 'height': function(element) { - if (!this._preComputing) this._begin(); - - var bHeight = this.get('border-box-height'); - if (bHeight <= 0) return 0; - - var bTop = this.get('border-top'), - bBottom = this.get('border-bottom'); - - var pTop = this.get('padding-top'), - pBottom = this.get('padding-bottom'); - - if (!this._preComputing) this._end(); - - return bHeight - bTop - bBottom - pTop - pBottom; - }, - - 'width': function(element) { - if (!this._preComputing) this._begin(); - - var bWidth = this.get('border-box-width'); - if (bWidth <= 0) return 0; - - var bLeft = this.get('border-left'), - bRight = this.get('border-right'); - - var pLeft = this.get('padding-left'), - pRight = this.get('padding-right'); - - if (!this._preComputing) this._end(); - - return bWidth - bLeft - bRight - pLeft - pRight; - }, - - 'padding-box-height': function(element) { - var height = this.get('height'), - pTop = this.get('padding-top'), - pBottom = this.get('padding-bottom'); - - return height + pTop + pBottom; - }, - - 'padding-box-width': function(element) { - var width = this.get('width'), - pLeft = this.get('padding-left'), - pRight = this.get('padding-right'); - - return width + pLeft + pRight; - }, - - 'border-box-height': function(element) { - return element.offsetHeight; - }, - - 'border-box-width': function(element) { - return element.offsetWidth; - }, - - 'margin-box-height': function(element) { - var bHeight = this.get('border-box-height'), - mTop = this.get('margin-top'), - mBottom = this.get('margin-bottom'); - - if (bHeight <= 0) return 0; - - return bHeight + mTop + mBottom; - }, - - 'margin-box-width': function(element) { - var bWidth = this.get('border-box-width'), - mLeft = this.get('margin-left'), - mRight = this.get('margin-right'); - - if (bWidth <= 0) return 0; - - return bWidth + mLeft + mRight; - }, - - 'top': function(element) { - var offset = element.positionedOffset(); - return offset.top; - }, - - 'bottom': function(element) { - var offset = element.positionedOffset(), - parent = element.getOffsetParent(), - pHeight = parent.measure('height'); - - var mHeight = this.get('border-box-height'); - - return pHeight - mHeight - offset.top; - }, - - 'left': function(element) { - var offset = element.positionedOffset(); - return offset.left; - }, - - 'right': function(element) { - var offset = element.positionedOffset(), - parent = element.getOffsetParent(), - pWidth = parent.measure('width'); - - var mWidth = this.get('border-box-width'); - - return pWidth - mWidth - offset.left; - }, - - 'padding-top': function(element) { - return getPixelValue(element, 'paddingTop'); - }, - - 'padding-bottom': function(element) { - return getPixelValue(element, 'paddingBottom'); - }, - - 'padding-left': function(element) { - return getPixelValue(element, 'paddingLeft'); - }, - - 'padding-right': function(element) { - return getPixelValue(element, 'paddingRight'); - }, - - 'border-top': function(element) { - return Object.isNumber(element.clientTop) ? element.clientTop : - getPixelValue(element, 'borderTopWidth'); - }, - - 'border-bottom': function(element) { - return Object.isNumber(element.clientBottom) ? element.clientBottom : - getPixelValue(element, 'borderBottomWidth'); - }, - - 'border-left': function(element) { - return Object.isNumber(element.clientLeft) ? element.clientLeft : - getPixelValue(element, 'borderLeftWidth'); - }, - - 'border-right': function(element) { - return Object.isNumber(element.clientRight) ? element.clientRight : - getPixelValue(element, 'borderRightWidth'); - }, - - 'margin-top': function(element) { - return getPixelValue(element, 'marginTop'); - }, - - 'margin-bottom': function(element) { - return getPixelValue(element, 'marginBottom'); - }, - - 'margin-left': function(element) { - return getPixelValue(element, 'marginLeft'); - }, - - 'margin-right': function(element) { - return getPixelValue(element, 'marginRight'); - } - } - }); - - if ('getBoundingClientRect' in document.documentElement) { - Object.extend(Element.Layout.COMPUTATIONS, { - 'right': function(element) { - var parent = hasLayout(element.getOffsetParent()); - var rect = element.getBoundingClientRect(), - pRect = parent.getBoundingClientRect(); - - return (pRect.right - rect.right).round(); - }, - - 'bottom': function(element) { - var parent = hasLayout(element.getOffsetParent()); - var rect = element.getBoundingClientRect(), - pRect = parent.getBoundingClientRect(); - - return (pRect.bottom - rect.bottom).round(); - } - }); - } - - Element.Offset = Class.create({ - initialize: function(left, top) { - this.left = left.round(); - this.top = top.round(); - - this[0] = this.left; - this[1] = this.top; - }, - - relativeTo: function(offset) { - return new Element.Offset( - this.left - offset.left, - this.top - offset.top - ); - }, - - inspect: function() { - return "#<Element.Offset left: #{left} top: #{top}>".interpolate(this); - }, - - toString: function() { - return "[#{left}, #{top}]".interpolate(this); - }, - - toArray: function() { - return [this.left, this.top]; - } - }); - - function getLayout(element, preCompute) { - return new Element.Layout(element, preCompute); - } - - function measure(element, property) { - return $(element).getLayout().get(property); - } - - function getDimensions(element) { - var layout = $(element).getLayout(); - return { - width: layout.get('width'), - height: layout.get('height') - }; - } - - function getOffsetParent(element) { - if (isDetached(element)) return $(document.body); - - var isInline = (Element.getStyle(element, 'display') === 'inline'); - if (!isInline && element.offsetParent) return $(element.offsetParent); - if (element === document.body) return $(element); - - while ((element = element.parentNode) && element !== document.body) { - if (Element.getStyle(element, 'position') !== 'static') { - return (element.nodeName === 'HTML') ? $(document.body) : $(element); - } - } - - return $(document.body); - } - - - function cumulativeOffset(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - } while (element); - return new Element.Offset(valueL, valueT); - } - - function positionedOffset(element) { - var layout = element.getLayout(); - - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - if (element) { - if (isBody(element)) break; - var p = Element.getStyle(element, 'position'); - if (p !== 'static') break; - } - } while (element); - - valueL -= layout.get('margin-top'); - valueT -= layout.get('margin-left'); - - return new Element.Offset(valueL, valueT); - } - - function cumulativeScrollOffset(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.scrollTop || 0; - valueL += element.scrollLeft || 0; - element = element.parentNode; - } while (element); - return new Element.Offset(valueL, valueT); - } - - function viewportOffset(forElement) { - var valueT = 0, valueL = 0, docBody = document.body; - - var element = forElement; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - if (element.offsetParent == docBody && - Element.getStyle(element, 'position') == 'absolute') break; - } while (element = element.offsetParent); - - element = forElement; - do { - if (element != docBody) { - valueT -= element.scrollTop || 0; - valueL -= element.scrollLeft || 0; - } - } while (element = element.parentNode); - return new Element.Offset(valueL, valueT); - } - - function absolutize(element) { - element = $(element); - - if (Element.getStyle(element, 'position') === 'absolute') { - return element; - } - - var offsetParent = getOffsetParent(element); - var eOffset = element.viewportOffset(), - pOffset = offsetParent.viewportOffset(); - - var offset = eOffset.relativeTo(pOffset); - var layout = element.getLayout(); - - element.store('prototype_absolutize_original_styles', { - left: element.getStyle('left'), - top: element.getStyle('top'), - width: element.getStyle('width'), - height: element.getStyle('height') - }); - - element.setStyle({ - position: 'absolute', - top: offset.top + 'px', - left: offset.left + 'px', - width: layout.get('width') + 'px', - height: layout.get('height') + 'px' - }); - - return element; - } - - function relativize(element) { - element = $(element); - if (Element.getStyle(element, 'position') === 'relative') { - return element; - } - - var originalStyles = - element.retrieve('prototype_absolutize_original_styles'); - - if (originalStyles) element.setStyle(originalStyles); - return element; - } - - Element.addMethods({ - getLayout: getLayout, - measure: measure, - getDimensions: getDimensions, - getOffsetParent: getOffsetParent, - cumulativeOffset: cumulativeOffset, - positionedOffset: positionedOffset, - cumulativeScrollOffset: cumulativeScrollOffset, - viewportOffset: viewportOffset, - absolutize: absolutize, - relativize: relativize - }); - - function isBody(element) { - return element.nodeName.toUpperCase() === 'BODY'; - } - - function isDetached(element) { - return element !== document.body && - !Element.descendantOf(element, document.body); - } - - if ('getBoundingClientRect' in document.documentElement) { - Element.addMethods({ - viewportOffset: function(element) { - element = $(element); - if (isDetached(element)) return new Element.Offset(0, 0); - - var rect = element.getBoundingClientRect(), - docEl = document.documentElement; - return new Element.Offset(rect.left - docEl.clientLeft, - rect.top - docEl.clientTop); - }, - - positionedOffset: function(element) { - element = $(element); - var parent = element.getOffsetParent(); - if (isDetached(element)) return new Element.Offset(0, 0); - - if (element.offsetParent && - element.offsetParent.nodeName.toUpperCase() === 'HTML') { - return positionedOffset(element); - } - - var eOffset = element.viewportOffset(), - pOffset = isBody(parent) ? viewportOffset(parent) : - parent.viewportOffset(); - var retOffset = eOffset.relativeTo(pOffset); - - var layout = element.getLayout(); - var top = retOffset.top - layout.get('margin-top'); - var left = retOffset.left - layout.get('margin-left'); - - return new Element.Offset(left, top); - } - }); - } -})(); -window.$$ = function() { - var expression = $A(arguments).join(', '); - return Prototype.Selector.select(expression, document); -}; - -Prototype.Selector = (function() { - - function select() { - throw new Error('Method "Prototype.Selector.select" must be defined.'); - } - - function match() { - throw new Error('Method "Prototype.Selector.match" must be defined.'); - } - - function find(elements, expression, index) { - index = index || 0; - var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i; - - for (i = 0; i < length; i++) { - if (match(elements[i], expression) && index == matchIndex++) { - return Element.extend(elements[i]); - } - } - } - - function extendElements(elements) { - for (var i = 0, length = elements.length; i < length; i++) { - Element.extend(elements[i]); - } - return elements; - } - - - var K = Prototype.K; - - return { - select: select, - match: match, - find: find, - extendElements: (Element.extend === K) ? K : extendElements, - extendElement: Element.extend - }; -})(); -Prototype._original_property = window.Sizzle; -/*! - * Sizzle CSS Selector Engine - v1.0 - * Copyright 2009, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){ - -var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, - done = 0, - toString = Object.prototype.toString, - hasDuplicate = false, - baseHasDuplicate = true; - -[0, 0].sort(function(){ - baseHasDuplicate = false; - return 0; -}); - -var Sizzle = function(selector, context, results, seed) { - results = results || []; - var origContext = context = context || document; - - if ( context.nodeType !== 1 && context.nodeType !== 9 ) { - return []; - } - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context), - soFar = selector; - - while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) { - soFar = m[3]; - - parts.push( m[1] ); - - if ( m[2] ) { - extra = m[3]; - break; - } - } - - if ( parts.length > 1 && origPOS.exec( selector ) ) { - if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { - set = posProcess( parts[0] + parts[1], context ); - } else { - set = Expr.relative[ parts[0] ] ? - [ context ] : - Sizzle( parts.shift(), context ); - - while ( parts.length ) { - selector = parts.shift(); - - if ( Expr.relative[ selector ] ) - selector += parts.shift(); - - set = posProcess( selector, set ); - } - } - } else { - if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && - Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { - var ret = Sizzle.find( parts.shift(), context, contextXML ); - context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; - } - - if ( context ) { - var ret = seed ? - { expr: parts.pop(), set: makeArray(seed) } : - Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); - set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; - - if ( parts.length > 0 ) { - checkSet = makeArray(set); - } else { - prune = false; - } - - while ( parts.length ) { - var cur = parts.pop(), pop = cur; - - if ( !Expr.relative[ cur ] ) { - cur = ""; - } else { - pop = parts.pop(); - } - - if ( pop == null ) { - pop = context; - } - - Expr.relative[ cur ]( checkSet, pop, contextXML ); - } - } else { - checkSet = parts = []; - } - } - - if ( !checkSet ) { - checkSet = set; - } - - if ( !checkSet ) { - throw "Syntax error, unrecognized expression: " + (cur || selector); - } - - if ( toString.call(checkSet) === "[object Array]" ) { - if ( !prune ) { - results.push.apply( results, checkSet ); - } else if ( context && context.nodeType === 1 ) { - for ( var i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { - results.push( set[i] ); - } - } - } else { - for ( var i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && checkSet[i].nodeType === 1 ) { - results.push( set[i] ); - } - } - } - } else { - makeArray( checkSet, results ); - } - - if ( extra ) { - Sizzle( extra, origContext, results, seed ); - Sizzle.uniqueSort( results ); - } - - return results; -}; - -Sizzle.uniqueSort = function(results){ - if ( sortOrder ) { - hasDuplicate = baseHasDuplicate; - results.sort(sortOrder); - - if ( hasDuplicate ) { - for ( var i = 1; i < results.length; i++ ) { - if ( results[i] === results[i-1] ) { - results.splice(i--, 1); - } - } - } - } - - return results; -}; - -Sizzle.matches = function(expr, set){ - return Sizzle(expr, null, null, set); -}; - -Sizzle.find = function(expr, context, isXML){ - var set, match; - - if ( !expr ) { - return []; - } - - for ( var i = 0, l = Expr.order.length; i < l; i++ ) { - var type = Expr.order[i], match; - - if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { - var left = match[1]; - match.splice(1,1); - - if ( left.substr( left.length - 1 ) !== "\\" ) { - match[1] = (match[1] || "").replace(/\\/g, ""); - set = Expr.find[ type ]( match, context, isXML ); - if ( set != null ) { - expr = expr.replace( Expr.match[ type ], "" ); - break; - } - } - } - } - - if ( !set ) { - set = context.getElementsByTagName("*"); - } - - return {set: set, expr: expr}; -}; - -Sizzle.filter = function(expr, set, inplace, not){ - var old = expr, result = [], curLoop = set, match, anyFound, - isXMLFilter = set && set[0] && isXML(set[0]); - - while ( expr && set.length ) { - for ( var type in Expr.filter ) { - if ( (match = Expr.match[ type ].exec( expr )) != null ) { - var filter = Expr.filter[ type ], found, item; - anyFound = false; - - if ( curLoop == result ) { - result = []; - } - - if ( Expr.preFilter[ type ] ) { - match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); - - if ( !match ) { - anyFound = found = true; - } else if ( match === true ) { - continue; - } - } - - if ( match ) { - for ( var i = 0; (item = curLoop[i]) != null; i++ ) { - if ( item ) { - found = filter( item, match, i, curLoop ); - var pass = not ^ !!found; - - if ( inplace && found != null ) { - if ( pass ) { - anyFound = true; - } else { - curLoop[i] = false; - } - } else if ( pass ) { - result.push( item ); - anyFound = true; - } - } - } - } - - if ( found !== undefined ) { - if ( !inplace ) { - curLoop = result; - } - - expr = expr.replace( Expr.match[ type ], "" ); - - if ( !anyFound ) { - return []; - } - - break; - } - } - } - - if ( expr == old ) { - if ( anyFound == null ) { - throw "Syntax error, unrecognized expression: " + expr; - } else { - break; - } - } - - old = expr; - } - - return curLoop; -}; - -var Expr = Sizzle.selectors = { - order: [ "ID", "NAME", "TAG" ], - match: { - ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/, - CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/, - NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/, - ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, - TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/, - CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, - POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, - PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/ - }, - leftMatch: {}, - attrMap: { - "class": "className", - "for": "htmlFor" - }, - attrHandle: { - href: function(elem){ - return elem.getAttribute("href"); - } - }, - relative: { - "+": function(checkSet, part, isXML){ - var isPartStr = typeof part === "string", - isTag = isPartStr && !/\W/.test(part), - isPartStrNotTag = isPartStr && !isTag; - - if ( isTag && !isXML ) { - part = part.toUpperCase(); - } - - for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { - if ( (elem = checkSet[i]) ) { - while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} - - checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ? - elem || false : - elem === part; - } - } - - if ( isPartStrNotTag ) { - Sizzle.filter( part, checkSet, true ); - } - }, - ">": function(checkSet, part, isXML){ - var isPartStr = typeof part === "string"; - - if ( isPartStr && !/\W/.test(part) ) { - part = isXML ? part : part.toUpperCase(); - - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - if ( elem ) { - var parent = elem.parentNode; - checkSet[i] = parent.nodeName === part ? parent : false; - } - } - } else { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - if ( elem ) { - checkSet[i] = isPartStr ? - elem.parentNode : - elem.parentNode === part; - } - } - - if ( isPartStr ) { - Sizzle.filter( part, checkSet, true ); - } - } - }, - "": function(checkSet, part, isXML){ - var doneName = done++, checkFn = dirCheck; - - if ( !/\W/.test(part) ) { - var nodeCheck = part = isXML ? part : part.toUpperCase(); - checkFn = dirNodeCheck; - } - - checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); - }, - "~": function(checkSet, part, isXML){ - var doneName = done++, checkFn = dirCheck; - - if ( typeof part === "string" && !/\W/.test(part) ) { - var nodeCheck = part = isXML ? part : part.toUpperCase(); - checkFn = dirNodeCheck; - } - - checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); - } - }, - find: { - ID: function(match, context, isXML){ - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - return m ? [m] : []; - } - }, - NAME: function(match, context, isXML){ - if ( typeof context.getElementsByName !== "undefined" ) { - var ret = [], results = context.getElementsByName(match[1]); - - for ( var i = 0, l = results.length; i < l; i++ ) { - if ( results[i].getAttribute("name") === match[1] ) { - ret.push( results[i] ); - } - } - - return ret.length === 0 ? null : ret; - } - }, - TAG: function(match, context){ - return context.getElementsByTagName(match[1]); - } - }, - preFilter: { - CLASS: function(match, curLoop, inplace, result, not, isXML){ - match = " " + match[1].replace(/\\/g, "") + " "; - - if ( isXML ) { - return match; - } - - for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { - if ( elem ) { - if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) { - if ( !inplace ) - result.push( elem ); - } else if ( inplace ) { - curLoop[i] = false; - } - } - } - - return false; - }, - ID: function(match){ - return match[1].replace(/\\/g, ""); - }, - TAG: function(match, curLoop){ - for ( var i = 0; curLoop[i] === false; i++ ){} - return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase(); - }, - CHILD: function(match){ - if ( match[1] == "nth" ) { - var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( - match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" || - !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); - - match[2] = (test[1] + (test[2] || 1)) - 0; - match[3] = test[3] - 0; - } - - match[0] = done++; - - return match; - }, - ATTR: function(match, curLoop, inplace, result, not, isXML){ - var name = match[1].replace(/\\/g, ""); - - if ( !isXML && Expr.attrMap[name] ) { - match[1] = Expr.attrMap[name]; - } - - if ( match[2] === "~=" ) { - match[4] = " " + match[4] + " "; - } - - return match; - }, - PSEUDO: function(match, curLoop, inplace, result, not){ - if ( match[1] === "not" ) { - if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { - match[3] = Sizzle(match[3], null, null, curLoop); - } else { - var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); - if ( !inplace ) { - result.push.apply( result, ret ); - } - return false; - } - } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { - return true; - } - - return match; - }, - POS: function(match){ - match.unshift( true ); - return match; - } - }, - filters: { - enabled: function(elem){ - return elem.disabled === false && elem.type !== "hidden"; - }, - disabled: function(elem){ - return elem.disabled === true; - }, - checked: function(elem){ - return elem.checked === true; - }, - selected: function(elem){ - elem.parentNode.selectedIndex; - return elem.selected === true; - }, - parent: function(elem){ - return !!elem.firstChild; - }, - empty: function(elem){ - return !elem.firstChild; - }, - has: function(elem, i, match){ - return !!Sizzle( match[3], elem ).length; - }, - header: function(elem){ - return /h\d/i.test( elem.nodeName ); - }, - text: function(elem){ - return "text" === elem.type; - }, - radio: function(elem){ - return "radio" === elem.type; - }, - checkbox: function(elem){ - return "checkbox" === elem.type; - }, - file: function(elem){ - return "file" === elem.type; - }, - password: function(elem){ - return "password" === elem.type; - }, - submit: function(elem){ - return "submit" === elem.type; - }, - image: function(elem){ - return "image" === elem.type; - }, - reset: function(elem){ - return "reset" === elem.type; - }, - button: function(elem){ - return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON"; - }, - input: function(elem){ - return /input|select|textarea|button/i.test(elem.nodeName); - } - }, - setFilters: { - first: function(elem, i){ - return i === 0; - }, - last: function(elem, i, match, array){ - return i === array.length - 1; - }, - even: function(elem, i){ - return i % 2 === 0; - }, - odd: function(elem, i){ - return i % 2 === 1; - }, - lt: function(elem, i, match){ - return i < match[3] - 0; - }, - gt: function(elem, i, match){ - return i > match[3] - 0; - }, - nth: function(elem, i, match){ - return match[3] - 0 == i; - }, - eq: function(elem, i, match){ - return match[3] - 0 == i; - } - }, - filter: { - PSEUDO: function(elem, match, i, array){ - var name = match[1], filter = Expr.filters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - } else if ( name === "contains" ) { - return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0; - } else if ( name === "not" ) { - var not = match[3]; - - for ( var i = 0, l = not.length; i < l; i++ ) { - if ( not[i] === elem ) { - return false; - } - } - - return true; - } - }, - CHILD: function(elem, match){ - var type = match[1], node = elem; - switch (type) { - case 'only': - case 'first': - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) return false; - } - if ( type == 'first') return true; - node = elem; - case 'last': - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) return false; - } - return true; - case 'nth': - var first = match[2], last = match[3]; - - if ( first == 1 && last == 0 ) { - return true; - } - - var doneName = match[0], - parent = elem.parentNode; - - if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { - var count = 0; - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - node.nodeIndex = ++count; - } - } - parent.sizcache = doneName; - } - - var diff = elem.nodeIndex - last; - if ( first == 0 ) { - return diff == 0; - } else { - return ( diff % first == 0 && diff / first >= 0 ); - } - } - }, - ID: function(elem, match){ - return elem.nodeType === 1 && elem.getAttribute("id") === match; - }, - TAG: function(elem, match){ - return (match === "*" && elem.nodeType === 1) || elem.nodeName === match; - }, - CLASS: function(elem, match){ - return (" " + (elem.className || elem.getAttribute("class")) + " ") - .indexOf( match ) > -1; - }, - ATTR: function(elem, match){ - var name = match[1], - result = Expr.attrHandle[ name ] ? - Expr.attrHandle[ name ]( elem ) : - elem[ name ] != null ? - elem[ name ] : - elem.getAttribute( name ), - value = result + "", - type = match[2], - check = match[4]; - - return result == null ? - type === "!=" : - type === "=" ? - value === check : - type === "*=" ? - value.indexOf(check) >= 0 : - type === "~=" ? - (" " + value + " ").indexOf(check) >= 0 : - !check ? - value && result !== false : - type === "!=" ? - value != check : - type === "^=" ? - value.indexOf(check) === 0 : - type === "$=" ? - value.substr(value.length - check.length) === check : - type === "|=" ? - value === check || value.substr(0, check.length + 1) === check + "-" : - false; - }, - POS: function(elem, match, i, array){ - var name = match[2], filter = Expr.setFilters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - } - } - } -}; - -var origPOS = Expr.match.POS; - -for ( var type in Expr.match ) { - Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); - Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source ); -} - -var makeArray = function(array, results) { - array = Array.prototype.slice.call( array, 0 ); - - if ( results ) { - results.push.apply( results, array ); - return results; - } - - return array; -}; - -try { - Array.prototype.slice.call( document.documentElement.childNodes, 0 ); - -} catch(e){ - makeArray = function(array, results) { - var ret = results || []; - - if ( toString.call(array) === "[object Array]" ) { - Array.prototype.push.apply( ret, array ); - } else { - if ( typeof array.length === "number" ) { - for ( var i = 0, l = array.length; i < l; i++ ) { - ret.push( array[i] ); - } - } else { - for ( var i = 0; array[i]; i++ ) { - ret.push( array[i] ); - } - } - } - - return ret; - }; -} - -var sortOrder; - -if ( document.documentElement.compareDocumentPosition ) { - sortOrder = function( a, b ) { - if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { - if ( a == b ) { - hasDuplicate = true; - } - return 0; - } - - var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; - if ( ret === 0 ) { - hasDuplicate = true; - } - return ret; - }; -} else if ( "sourceIndex" in document.documentElement ) { - sortOrder = function( a, b ) { - if ( !a.sourceIndex || !b.sourceIndex ) { - if ( a == b ) { - hasDuplicate = true; - } - return 0; - } - - var ret = a.sourceIndex - b.sourceIndex; - if ( ret === 0 ) { - hasDuplicate = true; - } - return ret; - }; -} else if ( document.createRange ) { - sortOrder = function( a, b ) { - if ( !a.ownerDocument || !b.ownerDocument ) { - if ( a == b ) { - hasDuplicate = true; - } - return 0; - } - - var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); - aRange.setStart(a, 0); - aRange.setEnd(a, 0); - bRange.setStart(b, 0); - bRange.setEnd(b, 0); - var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange); - if ( ret === 0 ) { - hasDuplicate = true; - } - return ret; - }; -} - -(function(){ - var form = document.createElement("div"), - id = "script" + (new Date).getTime(); - form.innerHTML = "<a name='" + id + "'/>"; - - var root = document.documentElement; - root.insertBefore( form, root.firstChild ); - - if ( !!document.getElementById( id ) ) { - Expr.find.ID = function(match, context, isXML){ - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; - } - }; - - Expr.filter.ID = function(elem, match){ - var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); - return elem.nodeType === 1 && node && node.nodeValue === match; - }; - } - - root.removeChild( form ); - root = form = null; // release memory in IE -})(); - -(function(){ - - var div = document.createElement("div"); - div.appendChild( document.createComment("") ); - - if ( div.getElementsByTagName("*").length > 0 ) { - Expr.find.TAG = function(match, context){ - var results = context.getElementsByTagName(match[1]); - - if ( match[1] === "*" ) { - var tmp = []; - - for ( var i = 0; results[i]; i++ ) { - if ( results[i].nodeType === 1 ) { - tmp.push( results[i] ); - } - } - - results = tmp; - } - - return results; - }; - } - - div.innerHTML = "<a href='#'></a>"; - if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && - div.firstChild.getAttribute("href") !== "#" ) { - Expr.attrHandle.href = function(elem){ - return elem.getAttribute("href", 2); - }; - } - - div = null; // release memory in IE -})(); - -if ( document.querySelectorAll ) (function(){ - var oldSizzle = Sizzle, div = document.createElement("div"); - div.innerHTML = "<p class='TEST'></p>"; - - if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { - return; - } - - Sizzle = function(query, context, extra, seed){ - context = context || document; - - if ( !seed && context.nodeType === 9 && !isXML(context) ) { - try { - return makeArray( context.querySelectorAll(query), extra ); - } catch(e){} - } - - return oldSizzle(query, context, extra, seed); - }; - - for ( var prop in oldSizzle ) { - Sizzle[ prop ] = oldSizzle[ prop ]; - } - - div = null; // release memory in IE -})(); - -if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){ - var div = document.createElement("div"); - div.innerHTML = "<div class='test e'></div><div class='test'></div>"; - - if ( div.getElementsByClassName("e").length === 0 ) - return; - - div.lastChild.className = "e"; - - if ( div.getElementsByClassName("e").length === 1 ) - return; - - Expr.order.splice(1, 0, "CLASS"); - Expr.find.CLASS = function(match, context, isXML) { - if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { - return context.getElementsByClassName(match[1]); - } - }; - - div = null; // release memory in IE -})(); - -function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - var sibDir = dir == "previousSibling" && !isXML; - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - if ( elem ) { - if ( sibDir && elem.nodeType === 1 ){ - elem.sizcache = doneName; - elem.sizset = i; - } - elem = elem[dir]; - var match = false; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 && !isXML ){ - elem.sizcache = doneName; - elem.sizset = i; - } - - if ( elem.nodeName === cur ) { - match = elem; - break; - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - var sibDir = dir == "previousSibling" && !isXML; - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - if ( elem ) { - if ( sibDir && elem.nodeType === 1 ) { - elem.sizcache = doneName; - elem.sizset = i; - } - elem = elem[dir]; - var match = false; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 ) { - if ( !isXML ) { - elem.sizcache = doneName; - elem.sizset = i; - } - if ( typeof cur !== "string" ) { - if ( elem === cur ) { - match = true; - break; - } - - } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { - match = elem; - break; - } - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -var contains = document.compareDocumentPosition ? function(a, b){ - return a.compareDocumentPosition(b) & 16; -} : function(a, b){ - return a !== b && (a.contains ? a.contains(b) : true); -}; - -var isXML = function(elem){ - return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || - !!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML"; -}; - -var posProcess = function(selector, context){ - var tmpSet = [], later = "", match, - root = context.nodeType ? [context] : context; - - while ( (match = Expr.match.PSEUDO.exec( selector )) ) { - later += match[0]; - selector = selector.replace( Expr.match.PSEUDO, "" ); - } - - selector = Expr.relative[selector] ? selector + "*" : selector; - - for ( var i = 0, l = root.length; i < l; i++ ) { - Sizzle( selector, root[i], tmpSet ); - } - - return Sizzle.filter( later, tmpSet ); -}; - - -window.Sizzle = Sizzle; - -})(); - -;(function(engine) { - var extendElements = Prototype.Selector.extendElements; - - function select(selector, scope) { - return extendElements(engine(selector, scope || document)); - } - - function match(element, selector) { - return engine.matches(selector, [element]).length == 1; - } - - Prototype.Selector.engine = engine; - Prototype.Selector.select = select; - Prototype.Selector.match = match; -})(Sizzle); - -window.Sizzle = Prototype._original_property; -delete Prototype._original_property; - -var Form = { - reset: function(form) { - form = $(form); - form.reset(); - return form; - }, - - serializeElements: function(elements, options) { - if (typeof options != 'object') options = { hash: !!options }; - else if (Object.isUndefined(options.hash)) options.hash = true; - var key, value, submitted = false, submit = options.submit; - - var data = elements.inject({ }, function(result, element) { - if (!element.disabled && element.name) { - key = element.name; value = $(element).getValue(); - if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && - submit !== false && (!submit || key == submit) && (submitted = true)))) { - if (key in result) { - if (!Object.isArray(result[key])) result[key] = [result[key]]; - result[key].push(value); - } - else result[key] = value; - } - } - return result; - }); - - return options.hash ? data : Object.toQueryString(data); - } -}; - -Form.Methods = { - serialize: function(form, options) { - return Form.serializeElements(Form.getElements(form), options); - }, - - getElements: function(form) { - var elements = $(form).getElementsByTagName('*'), - element, - arr = [ ], - serializers = Form.Element.Serializers; - for (var i = 0; element = elements[i]; i++) { - arr.push(element); - } - return arr.inject([], function(elements, child) { - if (serializers[child.tagName.toLowerCase()]) - elements.push(Element.extend(child)); - return elements; - }) - }, - - getInputs: function(form, typeName, name) { - form = $(form); - var inputs = form.getElementsByTagName('input'); - - if (!typeName && !name) return $A(inputs).map(Element.extend); - - for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { - var input = inputs[i]; - if ((typeName && input.type != typeName) || (name && input.name != name)) - continue; - matchingInputs.push(Element.extend(input)); - } - - return matchingInputs; - }, - - disable: function(form) { - form = $(form); - Form.getElements(form).invoke('disable'); - return form; - }, - - enable: function(form) { - form = $(form); - Form.getElements(form).invoke('enable'); - return form; - }, - - findFirstElement: function(form) { - var elements = $(form).getElements().findAll(function(element) { - return 'hidden' != element.type && !element.disabled; - }); - var firstByIndex = elements.findAll(function(element) { - return element.hasAttribute('tabIndex') && element.tabIndex >= 0; - }).sortBy(function(element) { return element.tabIndex }).first(); - - return firstByIndex ? firstByIndex : elements.find(function(element) { - return /^(?:input|select|textarea)$/i.test(element.tagName); - }); - }, - - focusFirstElement: function(form) { - form = $(form); - form.findFirstElement().activate(); - return form; - }, - - request: function(form, options) { - form = $(form), options = Object.clone(options || { }); - - var params = options.parameters, action = form.readAttribute('action') || ''; - if (action.blank()) action = window.location.href; - options.parameters = form.serialize(true); - - if (params) { - if (Object.isString(params)) params = params.toQueryParams(); - Object.extend(options.parameters, params); - } - - if (form.hasAttribute('method') && !options.method) - options.method = form.method; - - return new Ajax.Request(action, options); - } -}; - -/*--------------------------------------------------------------------------*/ - - -Form.Element = { - focus: function(element) { - $(element).focus(); - return element; - }, - - select: function(element) { - $(element).select(); - return element; - } -}; - -Form.Element.Methods = { - - serialize: function(element) { - element = $(element); - if (!element.disabled && element.name) { - var value = element.getValue(); - if (value != undefined) { - var pair = { }; - pair[element.name] = value; - return Object.toQueryString(pair); - } - } - return ''; - }, - - getValue: function(element) { - element = $(element); - var method = element.tagName.toLowerCase(); - return Form.Element.Serializers[method](element); - }, - - setValue: function(element, value) { - element = $(element); - var method = element.tagName.toLowerCase(); - Form.Element.Serializers[method](element, value); - return element; - }, - - clear: function(element) { - $(element).value = ''; - return element; - }, - - present: function(element) { - return $(element).value != ''; - }, - - activate: function(element) { - element = $(element); - try { - element.focus(); - if (element.select && (element.tagName.toLowerCase() != 'input' || - !(/^(?:button|reset|submit)$/i.test(element.type)))) - element.select(); - } catch (e) { } - return element; - }, - - disable: function(element) { - element = $(element); - element.disabled = true; - return element; - }, - - enable: function(element) { - element = $(element); - element.disabled = false; - return element; - } -}; - -/*--------------------------------------------------------------------------*/ - -var Field = Form.Element; - -var $F = Form.Element.Methods.getValue; - -/*--------------------------------------------------------------------------*/ - -Form.Element.Serializers = { - input: function(element, value) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - return Form.Element.Serializers.inputSelector(element, value); - default: - return Form.Element.Serializers.textarea(element, value); - } - }, - - inputSelector: function(element, value) { - if (Object.isUndefined(value)) return element.checked ? element.value : null; - else element.checked = !!value; - }, - - textarea: function(element, value) { - if (Object.isUndefined(value)) return element.value; - else element.value = value; - }, - - select: function(element, value) { - if (Object.isUndefined(value)) - return this[element.type == 'select-one' ? - 'selectOne' : 'selectMany'](element); - else { - var opt, currentValue, single = !Object.isArray(value); - for (var i = 0, length = element.length; i < length; i++) { - opt = element.options[i]; - currentValue = this.optionValue(opt); - if (single) { - if (currentValue == value) { - opt.selected = true; - return; - } - } - else opt.selected = value.include(currentValue); - } - } - }, - - selectOne: function(element) { - var index = element.selectedIndex; - return index >= 0 ? this.optionValue(element.options[index]) : null; - }, - - selectMany: function(element) { - var values, length = element.length; - if (!length) return null; - - for (var i = 0, values = []; i < length; i++) { - var opt = element.options[i]; - if (opt.selected) values.push(this.optionValue(opt)); - } - return values; - }, - - optionValue: function(opt) { - return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; - } -}; - -/*--------------------------------------------------------------------------*/ - - -Abstract.TimedObserver = Class.create(PeriodicalExecuter, { - initialize: function($super, element, frequency, callback) { - $super(callback, frequency); - this.element = $(element); - this.lastValue = this.getValue(); - }, - - execute: function() { - var value = this.getValue(); - if (Object.isString(this.lastValue) && Object.isString(value) ? - this.lastValue != value : String(this.lastValue) != String(value)) { - this.callback(this.element, value); - this.lastValue = value; - } - } -}); - -Form.Element.Observer = Class.create(Abstract.TimedObserver, { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.Observer = Class.create(Abstract.TimedObserver, { - getValue: function() { - return Form.serialize(this.element); - } -}); - -/*--------------------------------------------------------------------------*/ - -Abstract.EventObserver = Class.create({ - initialize: function(element, callback) { - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - if (this.element.tagName.toLowerCase() == 'form') - this.registerFormCallbacks(); - else - this.registerCallback(this.element); - }, - - onElementEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - }, - - registerFormCallbacks: function() { - Form.getElements(this.element).each(this.registerCallback, this); - }, - - registerCallback: function(element) { - if (element.type) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - Event.observe(element, 'click', this.onElementEvent.bind(this)); - break; - default: - Event.observe(element, 'change', this.onElementEvent.bind(this)); - break; - } - } - } -}); - -Form.Element.EventObserver = Class.create(Abstract.EventObserver, { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.EventObserver = Class.create(Abstract.EventObserver, { - getValue: function() { - return Form.serialize(this.element); - } -}); -(function() { - - var Event = { - KEY_BACKSPACE: 8, - KEY_TAB: 9, - KEY_RETURN: 13, - KEY_ESC: 27, - KEY_LEFT: 37, - KEY_UP: 38, - KEY_RIGHT: 39, - KEY_DOWN: 40, - KEY_DELETE: 46, - KEY_HOME: 36, - KEY_END: 35, - KEY_PAGEUP: 33, - KEY_PAGEDOWN: 34, - KEY_INSERT: 45, - - cache: {} - }; - - var docEl = document.documentElement; - var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl - && 'onmouseleave' in docEl; - - var _isButton; - if (Prototype.Browser.IE) { - var buttonMap = { 0: 1, 1: 4, 2: 2 }; - _isButton = function(event, code) { - return event.button === buttonMap[code]; - }; - } else if (Prototype.Browser.WebKit) { - _isButton = function(event, code) { - switch (code) { - case 0: return event.which == 1 && !event.metaKey; - case 1: return event.which == 1 && event.metaKey; - default: return false; - } - }; - } else { - _isButton = function(event, code) { - return event.which ? (event.which === code + 1) : (event.button === code); - }; - } - - function isLeftClick(event) { return _isButton(event, 0) } - - function isMiddleClick(event) { return _isButton(event, 1) } - - function isRightClick(event) { return _isButton(event, 2) } - - function element(event) { - event = Event.extend(event); - - var node = event.target, type = event.type, - currentTarget = event.currentTarget; - - if (currentTarget && currentTarget.tagName) { - if (type === 'load' || type === 'error' || - (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' - && currentTarget.type === 'radio')) - node = currentTarget; - } - - if (node.nodeType == Node.TEXT_NODE) - node = node.parentNode; - - return Element.extend(node); - } - - function findElement(event, expression) { - var element = Event.element(event); - if (!expression) return element; - while (element) { - if (Object.isElement(element) && Prototype.Selector.match(element, expression)) { - return Element.extend(element); - } - element = element.parentNode; - } - } - - function pointer(event) { - return { x: pointerX(event), y: pointerY(event) }; - } - - function pointerX(event) { - var docElement = document.documentElement, - body = document.body || { scrollLeft: 0 }; - - return event.pageX || (event.clientX + - (docElement.scrollLeft || body.scrollLeft) - - (docElement.clientLeft || 0)); - } - - function pointerY(event) { - var docElement = document.documentElement, - body = document.body || { scrollTop: 0 }; - - return event.pageY || (event.clientY + - (docElement.scrollTop || body.scrollTop) - - (docElement.clientTop || 0)); - } - - - function stop(event) { - Event.extend(event); - event.preventDefault(); - event.stopPropagation(); - - event.stopped = true; - } - - Event.Methods = { - isLeftClick: isLeftClick, - isMiddleClick: isMiddleClick, - isRightClick: isRightClick, - - element: element, - findElement: findElement, - - pointer: pointer, - pointerX: pointerX, - pointerY: pointerY, - - stop: stop - }; - - - var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { - m[name] = Event.Methods[name].methodize(); - return m; - }); - - if (Prototype.Browser.IE) { - function _relatedTarget(event) { - var element; - switch (event.type) { - case 'mouseover': element = event.fromElement; break; - case 'mouseout': element = event.toElement; break; - default: return null; - } - return Element.extend(element); - } - - Object.extend(methods, { - stopPropagation: function() { this.cancelBubble = true }, - preventDefault: function() { this.returnValue = false }, - inspect: function() { return '[object Event]' } - }); - - Event.extend = function(event, element) { - if (!event) return false; - if (event._extendedByPrototype) return event; - - event._extendedByPrototype = Prototype.emptyFunction; - var pointer = Event.pointer(event); - - Object.extend(event, { - target: event.srcElement || element, - relatedTarget: _relatedTarget(event), - pageX: pointer.x, - pageY: pointer.y - }); - - return Object.extend(event, methods); - }; - } else { - Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__; - Object.extend(Event.prototype, methods); - Event.extend = Prototype.K; - } - - function _createResponder(element, eventName, handler) { - var registry = Element.retrieve(element, 'prototype_event_registry'); - - if (Object.isUndefined(registry)) { - CACHE.push(element); - registry = Element.retrieve(element, 'prototype_event_registry', $H()); - } - - var respondersForEvent = registry.get(eventName); - if (Object.isUndefined(respondersForEvent)) { - respondersForEvent = []; - registry.set(eventName, respondersForEvent); - } - - if (respondersForEvent.pluck('handler').include(handler)) return false; - - var responder; - if (eventName.include(":")) { - responder = function(event) { - if (Object.isUndefined(event.eventName)) - return false; - - if (event.eventName !== eventName) - return false; - - Event.extend(event, element); - handler.call(element, event); - }; - } else { - if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && - (eventName === "mouseenter" || eventName === "mouseleave")) { - if (eventName === "mouseenter" || eventName === "mouseleave") { - responder = function(event) { - Event.extend(event, element); - - var parent = event.relatedTarget; - while (parent && parent !== element) { - try { parent = parent.parentNode; } - catch(e) { parent = element; } - } - - if (parent === element) return; - - handler.call(element, event); - }; - } - } else { - responder = function(event) { - Event.extend(event, element); - handler.call(element, event); - }; - } - } - - responder.handler = handler; - respondersForEvent.push(responder); - return responder; - } - - function _destroyCache() { - for (var i = 0, length = CACHE.length; i < length; i++) { - Event.stopObserving(CACHE[i]); - CACHE[i] = null; - } - } - - var CACHE = []; - - if (Prototype.Browser.IE) - window.attachEvent('onunload', _destroyCache); - - if (Prototype.Browser.WebKit) - window.addEventListener('unload', Prototype.emptyFunction, false); - - - var _getDOMEventName = Prototype.K, - translations = { mouseenter: "mouseover", mouseleave: "mouseout" }; - - if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) { - _getDOMEventName = function(eventName) { - return (translations[eventName] || eventName); - }; - } - - function observe(element, eventName, handler) { - element = $(element); - - var responder = _createResponder(element, eventName, handler); - - if (!responder) return element; - - if (eventName.include(':')) { - if (element.addEventListener) - element.addEventListener("dataavailable", responder, false); - else { - element.attachEvent("ondataavailable", responder); - element.attachEvent("onfilterchange", responder); - } - } else { - var actualEventName = _getDOMEventName(eventName); - - if (element.addEventListener) - element.addEventListener(actualEventName, responder, false); - else - element.attachEvent("on" + actualEventName, responder); - } - - return element; - } - - function stopObserving(element, eventName, handler) { - element = $(element); - - var registry = Element.retrieve(element, 'prototype_event_registry'); - if (!registry) return element; - - if (!eventName) { - registry.each( function(pair) { - var eventName = pair.key; - stopObserving(element, eventName); - }); - return element; - } - - var responders = registry.get(eventName); - if (!responders) return element; - - if (!handler) { - responders.each(function(r) { - stopObserving(element, eventName, r.handler); - }); - return element; - } - - var responder = responders.find( function(r) { return r.handler === handler; }); - if (!responder) return element; - - if (eventName.include(':')) { - if (element.removeEventListener) - element.removeEventListener("dataavailable", responder, false); - else { - element.detachEvent("ondataavailable", responder); - element.detachEvent("onfilterchange", responder); - } - } else { - var actualEventName = _getDOMEventName(eventName); - if (element.removeEventListener) - element.removeEventListener(actualEventName, responder, false); - else - element.detachEvent('on' + actualEventName, responder); - } - - registry.set(eventName, responders.without(responder)); - - return element; - } - - function fire(element, eventName, memo, bubble) { - element = $(element); - - if (Object.isUndefined(bubble)) - bubble = true; - - if (element == document && document.createEvent && !element.dispatchEvent) - element = document.documentElement; - - var event; - if (document.createEvent) { - event = document.createEvent('HTMLEvents'); - event.initEvent('dataavailable', true, true); - } else { - event = document.createEventObject(); - event.eventType = bubble ? 'ondataavailable' : 'onfilterchange'; - } - - event.eventName = eventName; - event.memo = memo || { }; - - if (document.createEvent) - element.dispatchEvent(event); - else - element.fireEvent(event.eventType, event); - - return Event.extend(event); - } - - Event.Handler = Class.create({ - initialize: function(element, eventName, selector, callback) { - this.element = $(element); - this.eventName = eventName; - this.selector = selector; - this.callback = callback; - this.handler = this.handleEvent.bind(this); - }, - - start: function() { - Event.observe(this.element, this.eventName, this.handler); - return this; - }, - - stop: function() { - Event.stopObserving(this.element, this.eventName, this.handler); - return this; - }, - - handleEvent: function(event) { - var element = event.findElement(this.selector); - if (element) this.callback.call(this.element, event, element); - } - }); - - function on(element, eventName, selector, callback) { - element = $(element); - if (Object.isFunction(selector) && Object.isUndefined(callback)) { - callback = selector, selector = null; - } - - return new Event.Handler(element, eventName, selector, callback).start(); - } - - Object.extend(Event, Event.Methods); - - Object.extend(Event, { - fire: fire, - observe: observe, - stopObserving: stopObserving, - on: on - }); - - Element.addMethods({ - fire: fire, - - observe: observe, - - stopObserving: stopObserving, - - on: on - }); - - Object.extend(document, { - fire: fire.methodize(), - - observe: observe.methodize(), - - stopObserving: stopObserving.methodize(), - - on: on.methodize(), - - loaded: false - }); - - if (window.Event) Object.extend(window.Event, Event); - else window.Event = Event; -})(); - -(function() { - /* Support for the DOMContentLoaded event is based on work by Dan Webb, - Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ - - var timer; - - function fireContentLoadedEvent() { - if (document.loaded) return; - if (timer) window.clearTimeout(timer); - document.loaded = true; - document.fire('dom:loaded'); - } - - function checkReadyState() { - if (document.readyState === 'complete') { - document.stopObserving('readystatechange', checkReadyState); - fireContentLoadedEvent(); - } - } - - function pollDoScroll() { - try { document.documentElement.doScroll('left'); } - catch(e) { - timer = pollDoScroll.defer(); - return; - } - fireContentLoadedEvent(); - } - - if (document.addEventListener) { - document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); - } else { - document.observe('readystatechange', checkReadyState); - if (window == top) - timer = pollDoScroll.defer(); - } - - Event.observe(window, 'load', fireContentLoadedEvent); -})(); - -Element.addMethods(); - -/*------------------------------- DEPRECATED -------------------------------*/ - -Hash.toQueryString = Object.toQueryString; - -var Toggle = { display: Element.toggle }; - -Element.Methods.childOf = Element.Methods.descendantOf; - -var Insertion = { - Before: function(element, content) { - return Element.insert(element, {before:content}); - }, - - Top: function(element, content) { - return Element.insert(element, {top:content}); - }, - - Bottom: function(element, content) { - return Element.insert(element, {bottom:content}); - }, - - After: function(element, content) { - return Element.insert(element, {after:content}); - } -}; - -var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); - -var Position = { - includeScrollOffsets: false, - - prepare: function() { - this.deltaX = window.pageXOffset - || document.documentElement.scrollLeft - || document.body.scrollLeft - || 0; - this.deltaY = window.pageYOffset - || document.documentElement.scrollTop - || document.body.scrollTop - || 0; - }, - - within: function(element, x, y) { - if (this.includeScrollOffsets) - return this.withinIncludingScrolloffsets(element, x, y); - this.xcomp = x; - this.ycomp = y; - this.offset = Element.cumulativeOffset(element); - - return (y >= this.offset[1] && - y < this.offset[1] + element.offsetHeight && - x >= this.offset[0] && - x < this.offset[0] + element.offsetWidth); - }, - - withinIncludingScrolloffsets: function(element, x, y) { - var offsetcache = Element.cumulativeScrollOffset(element); - - this.xcomp = x + offsetcache[0] - this.deltaX; - this.ycomp = y + offsetcache[1] - this.deltaY; - this.offset = Element.cumulativeOffset(element); - - return (this.ycomp >= this.offset[1] && - this.ycomp < this.offset[1] + element.offsetHeight && - this.xcomp >= this.offset[0] && - this.xcomp < this.offset[0] + element.offsetWidth); - }, - - overlap: function(mode, element) { - if (!mode) return 0; - if (mode == 'vertical') - return ((this.offset[1] + element.offsetHeight) - this.ycomp) / - element.offsetHeight; - if (mode == 'horizontal') - return ((this.offset[0] + element.offsetWidth) - this.xcomp) / - element.offsetWidth; - }, - - - cumulativeOffset: Element.Methods.cumulativeOffset, - - positionedOffset: Element.Methods.positionedOffset, - - absolutize: function(element) { - Position.prepare(); - return Element.absolutize(element); - }, - - relativize: function(element) { - Position.prepare(); - return Element.relativize(element); - }, - - realOffset: Element.Methods.cumulativeScrollOffset, - - offsetParent: Element.Methods.getOffsetParent, - - page: Element.Methods.viewportOffset, - - clone: function(source, target, options) { - options = options || { }; - return Element.clonePosition(target, source, options); - } -}; - -/*--------------------------------------------------------------------------*/ - -if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ - function iter(name) { - return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; - } - - instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? - function(element, className) { - className = className.toString().strip(); - var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); - return cond ? document._getElementsByXPath('.//*' + cond, element) : []; - } : function(element, className) { - className = className.toString().strip(); - var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); - if (!classNames && !className) return elements; - - var nodes = $(element).getElementsByTagName('*'); - className = ' ' + className + ' '; - - for (var i = 0, child, cn; child = nodes[i]; i++) { - if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || - (classNames && classNames.all(function(name) { - return !name.toString().blank() && cn.include(' ' + name + ' '); - })))) - elements.push(Element.extend(child)); - } - return elements; - }; - - return function(className, parentElement) { - return $(parentElement || document.body).getElementsByClassName(className); - }; -}(Element.Methods); - -/*--------------------------------------------------------------------------*/ - -Element.ClassNames = Class.create(); -Element.ClassNames.prototype = { - initialize: function(element) { - this.element = $(element); - }, - - _each: function(iterator) { - this.element.className.split(/\s+/).select(function(name) { - return name.length > 0; - })._each(iterator); - }, - - set: function(className) { - this.element.className = className; - }, - - add: function(classNameToAdd) { - if (this.include(classNameToAdd)) return; - this.set($A(this).concat(classNameToAdd).join(' ')); - }, - - remove: function(classNameToRemove) { - if (!this.include(classNameToRemove)) return; - this.set($A(this).without(classNameToRemove).join(' ')); - }, - - toString: function() { - return $A(this).join(' '); - } -}; - -Object.extend(Element.ClassNames.prototype, Enumerable); - -/*--------------------------------------------------------------------------*/ - -(function() { - window.Selector = Class.create({ - initialize: function(expression) { - this.expression = expression.strip(); - }, - - findElements: function(rootElement) { - return Prototype.Selector.select(this.expression, rootElement); - }, - - match: function(element) { - return Prototype.Selector.match(element, this.expression); - }, - - toString: function() { - return this.expression; - }, - - inspect: function() { - return "#<Selector: " + this.expression + ">"; - } - }); - - Object.extend(Selector, { - matchElements: function(elements, expression) { - var match = Prototype.Selector.match, - results = []; - - for (var i = 0, length = elements.length; i < length; i++) { - var element = elements[i]; - if (match(element, expression)) { - results.push(Element.extend(element)); - } - } - return results; - }, - - findElement: function(elements, expression, index) { - index = index || 0; - var matchIndex = 0, element; - for (var i = 0, length = elements.length; i < length; i++) { - element = elements[i]; - if (Prototype.Selector.match(element, expression) && index === matchIndex++) { - return Element.extend(element); - } - } - }, - - findChildElements: function(element, expressions) { - var selector = expressions.toArray().join(', '); - return Prototype.Selector.select(selector, element || document); - } - }); -})(); diff --git a/public/javascripts/rails.js b/public/javascripts/rails.js deleted file mode 100644 index 5cea13c15..000000000 --- a/public/javascripts/rails.js +++ /dev/null @@ -1,202 +0,0 @@ -(function() { - Ajax.Responders.register({ - onCreate: function(request) { - var token = $$('meta[name=csrf-token]')[0]; - if (token) { - if (!request.options.requestHeaders) request.options.requestHeaders = {}; - request.options.requestHeaders['X-CSRF-Token'] = token.readAttribute('content'); - } - } - }); - - // Technique from Juriy Zaytsev - // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ - function isEventSupported(eventName) { - var el = document.createElement('div'); - eventName = 'on' + eventName; - var isSupported = (eventName in el); - if (!isSupported) { - el.setAttribute(eventName, 'return;'); - isSupported = typeof el[eventName] == 'function'; - } - el = null; - return isSupported; - } - - function isForm(element) { - return Object.isElement(element) && element.nodeName.toUpperCase() == 'FORM'; - } - - function isInput(element) { - if (Object.isElement(element)) { - var name = element.nodeName.toUpperCase(); - return name == 'INPUT' || name == 'SELECT' || name == 'TEXTAREA'; - } - else return false; - } - - var submitBubbles = isEventSupported('submit'), - changeBubbles = isEventSupported('change'); - - if (!submitBubbles || !changeBubbles) { - // augment the Event.Handler class to observe custom events when needed - Event.Handler.prototype.initialize = Event.Handler.prototype.initialize.wrap( - function(init, element, eventName, selector, callback) { - init(element, eventName, selector, callback); - // is the handler being attached to an element that doesn't support this event? - if ( (!submitBubbles && this.eventName == 'submit' && !isForm(this.element)) || - (!changeBubbles && this.eventName == 'change' && !isInput(this.element)) ) { - // "submit" => "emulated:submit" - this.eventName = 'emulated:' + this.eventName; - } - } - ); - } - - if (!submitBubbles) { - // discover forms on the page by observing focus events which always bubble - document.on('focusin', 'form', function(focusEvent, form) { - // special handler for the real "submit" event (one-time operation) - if (!form.retrieve('emulated:submit')) { - form.on('submit', function(submitEvent) { - var emulated = form.fire('emulated:submit', submitEvent, true); - // if custom event received preventDefault, cancel the real one too - if (emulated.returnValue === false) submitEvent.preventDefault(); - }); - form.store('emulated:submit', true); - } - }); - } - - if (!changeBubbles) { - // discover form inputs on the page - document.on('focusin', 'input, select, textarea', function(focusEvent, input) { - // special handler for real "change" events - if (!input.retrieve('emulated:change')) { - input.on('change', function(changeEvent) { - input.fire('emulated:change', changeEvent, true); - }); - input.store('emulated:change', true); - } - }); - } - - function handleRemote(element) { - var method, url, params; - - var event = element.fire("ajax:before"); - if (event.stopped) return false; - - if (element.tagName.toLowerCase() === 'form') { - method = element.readAttribute('method') || 'post'; - url = element.readAttribute('action'); - // serialize the form with respect to the submit button that was pressed - params = element.serialize({ submit: element.retrieve('rails:submit-button') }); - // clear the pressed submit button information - element.store('rails:submit-button', null); - } else { - method = element.readAttribute('data-method') || 'get'; - url = element.readAttribute('href'); - params = {}; - } - - new Ajax.Request(url, { - method: method, - parameters: params, - evalScripts: true, - - onCreate: function(response) { element.fire("ajax:create", response); }, - onComplete: function(response) { element.fire("ajax:complete", response); }, - onSuccess: function(response) { element.fire("ajax:success", response); }, - onFailure: function(response) { element.fire("ajax:failure", response); } - }); - - element.fire("ajax:after"); - } - - function insertHiddenField(form, name, value) { - form.insert(new Element('input', { type: 'hidden', name: name, value: value })); - } - - function handleMethod(element) { - var method = element.readAttribute('data-method'), - url = element.readAttribute('href'), - csrf_param = $$('meta[name=csrf-param]')[0], - csrf_token = $$('meta[name=csrf-token]')[0]; - - var form = new Element('form', { method: "POST", action: url, style: "display: none;" }); - $(element.parentNode).insert(form); - - if (method !== 'post') { - insertHiddenField(form, '_method', method); - } - - if (csrf_param) { - insertHiddenField(form, csrf_param.readAttribute('content'), csrf_token.readAttribute('content')); - } - - form.submit(); - } - - function disableFormElements(form) { - form.select('input[type=submit][data-disable-with]').each(function(input) { - input.store('rails:original-value', input.getValue()); - input.setValue(input.readAttribute('data-disable-with')).disable(); - }); - } - - function enableFormElements(form) { - form.select('input[type=submit][data-disable-with]').each(function(input) { - input.setValue(input.retrieve('rails:original-value')).enable(); - }); - } - - function allowAction(element) { - var message = element.readAttribute('data-confirm'); - return !message || confirm(message); - } - - document.on('click', 'a[data-confirm], a[data-remote], a[data-method]', function(event, link) { - if (!allowAction(link)) { - event.stop(); - return false; - } - - if (link.readAttribute('data-remote')) { - handleRemote(link); - event.stop(); - } else if (link.readAttribute('data-method')) { - handleMethod(link); - event.stop(); - } - }); - - document.on("click", "form input[type=submit], form button[type=submit], form button:not([type])", function(event, button) { - // register the pressed submit button - event.findElement('form').store('rails:submit-button', button.name || false); - }); - - document.on("submit", function(event) { - var form = event.findElement(); - - if (!allowAction(form)) { - event.stop(); - return false; - } - - if (form.readAttribute('data-remote')) { - handleRemote(form); - event.stop(); - } else { - disableFormElements(form); - } - }); - - document.on('ajax:create', 'form', function(event, form) { - if (form == event.findElement()) disableFormElements(form); - }); - - document.on('ajax:complete', 'form', function(event, form) { - if (form == event.findElement()) enableFormElements(form); - }); -})(); diff --git a/public/javascripts/stats-graphs.js b/public/javascripts/stats-graphs.js new file mode 100644 index 000000000..73e19a6fc --- /dev/null +++ b/public/javascripts/stats-graphs.js @@ -0,0 +1,87 @@ +/* From http://stackoverflow.com/a/10284006/223092 */ +function zip(arrays) { + return arrays[0].map(function(_,i){ + return arrays.map(function(array){return array[i]}) + }); +} + +$(document).ready(function() { + $.each(graphs_data, function(index, graph_data) { + var graph_id = graph_data.id, + dataset, + plot, + graph_data, + graph_div = $('#' + graph_id); + + if (!graph_data.x_values) { + /* Then there's no data for this graph */ + return true; + } + + graph_div.css('width', '700px'); + graph_div.css('height', '400px'); + + dataset = [ + {'color': 'orange', + 'bars': { + 'show': true, + 'barWidth': 0.5, + 'align': 'center' + }, + 'data': zip([graph_data.x_values, + graph_data.y_values]) + } + ] + + if (graph_data.errorbars) { + dataset.push({ + 'color': 'orange', + 'points': { + // Don't show these, just draw error bars: + 'radius': 0, + 'errorbars': 'y', + 'yerr': { + 'asymmetric': true, + 'show': true, + 'upperCap': "-", + 'lowerCap': "-", + 'radius': 5 + } + }, + 'data': zip([graph_data.x_values, + graph_data.y_values, + graph_data.cis_below, + graph_data.cis_above]) + }); + } + + options = { + 'xaxis': { + 'ticks': graph_data.x_ticks, + }, + 'yaxis': { + 'min': 0, + 'max': graph_data.y_max + }, + 'xaxes': [{ + 'axisLabel': graph_data.x_axis, + 'axisLabelPadding': 20, + 'axisLabelColour': 'black' + }], + 'yaxes': [{ + 'axisLabel': graph_data.y_axis, + 'axisLabelPadding': 20, + 'axisLabelColour': 'black' + }], + 'series': { + 'lines': { + 'show': false + } + }, + } + + plot = $.plot(graph_div, + dataset, + options); + }); +}); diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css deleted file mode 100644 index 7f8d646d3..000000000 --- a/public/stylesheets/admin.css +++ /dev/null @@ -1,77 +0,0 @@ -/* FOIFA admin CSS */ - -h2 { - margin-top: 0.2em; - margin-bottom: 0.5em; -} - -table { - border-collapse: collapse; - margin-bottom: 1em; -} - -td, th { - border: solid 1px #000000; -} -td { - vertical-align: top -} -td { - max-width: 30em; - overflow: auto; -} - -tr.odd { - background-color: #bbbbbb; -} - -tr.even { - background-color: #dddddd; -} - -.entry_changed { - font-weight: bold; -} - -form { - margin-bottom: 1em; -} - -#notice { - color: green; - border: solid 1px green; - padding: 1em; -} -#error, #errorExplanation { - color: red; - border: solid 1px red; - padding: 1em; -} -#tag_help { - float: right; - width: 25%; - margin-top: 0; -} -#public_body_form { - float: left; - width: 70%; -} - -.forms_on_one_line { - display: inline; -} - -.user_photo_on_admin { - float: right; -} - -.user_photo_on_admin img { - width: 96px; - height: 96px; - vertical-align: middle; - border: 1px solid #dddddd; - margin-right: 5px; - padding: 2px; -} - - diff --git a/public/stylesheets/alt.css b/public/stylesheets/alt.css deleted file mode 100644 index bf6ba2d16..000000000 --- a/public/stylesheets/alt.css +++ /dev/null @@ -1,232 +0,0 @@ -/*------------------------------------------------ global */ -body -{ - padding: 0px; - margin: 0px; - text-align: center; - font-family: Tahoma, Geneva, sans-serif; -} - -/*------------------------------------------------ banner */ - -#banner -{ - position: relative; - top: 0px; - left: 0px; - width: 100%; - height: 200px; - margin: 0px; - background-color: #F0F0F0; - background-image: url(../images/navimg/bnnr-ifyoudontask.png); - background-repeat: no-repeat; - background-position: center top; - border-color: #993233; - border-width: 0 0 3px 0; - border-style: solid; -} - -/*------------------------------------------------ header; not needed? */ -#header -{ display: none; } - -/*------------------------------------------------ search */ - -#navigation_search -{ - position: absolute; - width: 100%; - left: 0px; - top: 175px; - z-index: 150; - text-align: right; - -moz-opacity: 0.7!important; - filter: alpha(opacity= 70)!important; - opacity: 0.7!important; -} - #navigation_search input - { - border-color: #010101; - border-width: 1px; - border-style: solid; - background-color: #fff; - color: #000; - } - #navigation_search input#navigation_search_query - { - width: 8em; - } - -#navigation_search p { margin: 0 0.6em 0 0; } - -/*------------------------------------------------ topnav */ -#topnav -{ - position: relative; - top: 0px; - left: 0px; - width: 100%; - height: auto; - overflow: auto; - padding: 0px 0px 0px 0px; - z-index: 100; - background-color: #000; - font-size: 0.9em; -} - - #topnav ul - { - list-style: none; - margin: 0px; - padding: 0px; - } - - #topnav li - { - float: left; - } - - #topnav li a, #topnav li a:visited - { - display: block; - margin: 0px; - padding: 0.15em 0.6em 0.25em 0.8em; - color: #ADADAD; - text-decoration: none; - } - - #topnav li a:hover - { color: #fff; } - - #topnav li a:active { } - - #topnav li a.on, #topnav li a.on:visited - { - font-weight: bold; - color: #000; - } - - #topnav li a.on:hover {} - - #topnav li a.on:active {} - -/*-------------------------- login/signup */ -#logged_in_bar -{ - float: right; - clear: none; - font-size: 0.9em; - z-index: 200; - padding: 0.20em 10px 0.25em 1em; - color: #FFF; -} - #logged_in_bar a, #logged_in_bar a:visited { color: #92B3FF; } - -/*------------------------------------------------ temp stuff */ -#staging, #alpha_notice -{ display: none;} - -#staging -{ - border-color: #FF201D; - border-width: 1px; - border-style: dotted; - clear: both; - text-align: center; - color: #FF201D; - margin-top: 40px; -} - -#alpha_notice -{ - padding: 0 20px 0 20px; - border-color: #FF201D; - border-width: 1px; - border-style: dotted; - background-color: #f0f0f0; -} - -/*------------------------------------------------ wrapper*/ - -#wrapper -{ - position: relative; - clear: both; - top: 0em; - padding: 0px; - margin: 0px auto 1.2em auto; - max-width: 50em; - /* = 800px at default size? so 1em = 16px*/ - _width: 50em; - text-align: left; -} - -/*------------------------------------------------ content */ - -#content -{ - position: relative; - padding: 2em 1em 1em 1em; -} - -h1, h2, h3 -{ - font-family: Trebuchet, Trebuchet MS, Helvetica, sans-serif; - /*Arial Black, Gadget, sans-serif*/ - font-weight: bold; - line-height: 1em; - letter-spacing: 0em; - color: #555; -} - h1 { font-size: 1.8em;} - h2 { font-size: 1.4em;} - h3 { font-size: 1em;} - -h4, h5, h6 -{} - - -/*---------------- content : recent requests sidebar */ -#find_information -{ - width: 10.5em; - float: right; - clear: none; - background-color: #e0e0e0; - background-image: url(../images/navimg/sidebag-bg-wide.png); - background-repeat: no-repeat; - background-position: center top; - padding: 105px 0.25em 0.25em 0.35em; -} - #find_information h1 - { font-size: 1.2em; line-height: 0.85em; margin-top: 0px;} - - #find_information p - { font-size: 0.8em; line-height: 1em; } - - #find_information input#query - { width: 12em; } - -/*---------------- content : find body */ -#make_requests -{ - float: left; - clear: none; - width: 34em; - text-align: center; -} - -/*------------------------------------------------ footer */ - -#footer -{ - clear: both; - position: relative; - background-color: #F0F0F0; - border-color: #993233; - border-width: 3px 0 0 0; - border-style: solid; - margin: 1em 0 0 0; - padding: 0.5em 0 0.5em 0; - font-size: 0.85em; -}
\ No newline at end of file diff --git a/public/stylesheets/main.css b/public/stylesheets/main.css index 6f6d7b365..21d0735e0 100644 --- a/public/stylesheets/main.css +++ b/public/stylesheets/main.css @@ -1742,3 +1742,38 @@ text-decoration:none; .big { font-size: larger; } + +.public-body-ranking { + margin-bottom: 40px; +} + +.public-body-ranking-title { + margin-top: 25px; + margin-bottom: 10px; +} + +.public-body-ranking table { + margin-top: 20px; + margin-left: 30px; +} + +.public-body-ranking td, th { + border: 0px; + padding: 5px; + padding-right: 20px; +} + +.public-body-ranking td.statistic { + text-align: center; +} + +.public-body-ranking .axisLabels { + /* Justification for using !important hereL the axis label color is + set in the style attribute in Flot's Javascript to the same + colour as the grid background. Changing this requires quite + invasive changes to the Javascript, and is likely to be + irrelevant in the next version of Flot anyway, which will have + core support for axis labels. So, just use !important to make + the axes black rather than transparent grey for the moment: */ + color: #000 !important; +} diff --git a/public/stylesheets/print.css b/public/stylesheets/print.css index 89be21019..6f29c18da 100644 --- a/public/stylesheets/print.css +++ b/public/stylesheets/print.css @@ -18,9 +18,11 @@ p.event_actions, div#after_actions, #right_column, #banner, +.admin .navbar, #header_right, #describe_state_form_1, -#describe_state_form_2 input[type=submit], +#describe_state_form_2, +.attachment_image, #footer { display: none; } diff --git a/script/generate_pot.sh b/script/generate_pot.sh deleted file mode 100755 index c0540c3d9..000000000 --- a/script/generate_pot.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -echo "This is NOT a completed script! Just use it as reference for what to do from the command line, or fix it until it works!" -exit 1 - -cd `dirname $0` -# grab latest po files from Transifex -tx pull -a -f -git status | grep app.po | awk '{print $3}' | xargs git add -git commit -m "Backup latest po files from Transifex" - -# now regenerate POT and PO files from Alaveteli source -bundle exec rake gettext:store_model_attributes -bundle exec rake gettext:findpot - -# upload the result to Transifex -tx push -t - -# re-download (it removes the fuzzy strings and normalises it to the format last committed) -tx pull -a -f -git status | grep app.po | awk '{print $3}' | xargs git add -git commit -m "Updated POT" diff --git a/script/rails-post-deploy b/script/rails-post-deploy index 6eca2f68f..de950311c 100755 --- a/script/rails-post-deploy +++ b/script/rails-post-deploy @@ -46,12 +46,6 @@ else fi mkdir -p log fi -# link the "downloads" directory in the cache to somewhere it can be served -if [ ! -e "$TOP_DIR/public/download" ] -then - mkdir -p "$TOP_DIR/cache/zips/download" - ln -s "../cache/zips/download" "$TOP_DIR/public/" -fi cd log touch development.log fastcgi.crash.log production.log test.log diff --git a/script/update-public-body-stats b/script/update-public-body-stats new file mode 100755 index 000000000..71c2d248c --- /dev/null +++ b/script/update-public-body-stats @@ -0,0 +1,4 @@ +#!/bin/bash + +cd `dirname $0` +bundle exec rake --silent stats:update_public_bodies_stats diff --git a/spec/controllers/admin_incoming_message_controller_spec.rb b/spec/controllers/admin_incoming_message_controller_spec.rb new file mode 100644 index 000000000..b969a8a3f --- /dev/null +++ b/spec/controllers/admin_incoming_message_controller_spec.rb @@ -0,0 +1,144 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe AdminIncomingMessageController, "when administering incoming messages" do + + describe 'when destroying an incoming message' do + + before(:each) do + basic_auth_login @request + load_raw_emails_data + end + + before do + @im = incoming_messages(:useless_incoming_message) + @controller.stub!(:expire_for_request) + end + + it "destroys the raw email file" do + raw_email = @im.raw_email.filepath + assert_equal File.exists?(raw_email), true + post :destroy, :incoming_message_id => @im.id + assert_equal File.exists?(raw_email), false + end + + it 'asks the incoming message to fully destroy itself' do + IncomingMessage.stub!(:find).and_return(@im) + @im.should_receive(:fully_destroy) + post :destroy, :incoming_message_id => @im.id + end + + it 'expires the file cache for the associated info_request' do + @controller.should_receive(:expire_for_request).with(@im.info_request) + post :destroy, :incoming_message_id => @im.id + end + + end + + describe 'when redelivering an incoming message' do + + before(:each) do + basic_auth_login @request + load_raw_emails_data + end + + it 'expires the file cache for the previous request' do + current_info_request = info_requests(:fancy_dog_request) + destination_info_request = info_requests(:naughty_chicken_request) + incoming_message = incoming_messages(:useless_incoming_message) + @controller.should_receive(:expire_for_request).with(current_info_request) + post :redeliver, :redeliver_incoming_message_id => incoming_message.id, + :url_title => destination_info_request.url_title + end + + + end + + describe 'when editing an incoming message' do + + before do + @incoming = FactoryGirl.create(:incoming_message) + end + + it 'should be successful' do + get :edit, :id => @incoming.id + response.should be_success + end + + it 'should assign the incoming message to the view' do + get :edit, :id => @incoming.id + assigns[:incoming_message].should == @incoming + end + + end + + describe 'when updating an incoming message' do + + before do + @incoming = FactoryGirl.create(:incoming_message, :prominence => 'normal') + @default_params = {:id => @incoming.id, + :incoming_message => {:prominence => 'hidden', + :prominence_reason => 'dull'} } + end + + def make_request(params=@default_params) + post :update, params + end + + it 'should save the prominence of the message' do + make_request + @incoming.reload + @incoming.prominence.should == 'hidden' + end + + it 'should save a prominence reason for the message' do + make_request + @incoming.reload + @incoming.prominence_reason.should == 'dull' + end + + it 'should log an "edit_incoming" event on the info_request' do + @controller.stub!(:admin_current_user).and_return("Admin user") + make_request + @incoming.reload + last_event = @incoming.info_request_events.last + last_event.event_type.should == 'edit_incoming' + last_event.params.should == { :incoming_message_id => @incoming.id, + :editor => "Admin user", + :old_prominence => "normal", + :prominence => "hidden", + :old_prominence_reason => nil, + :prominence_reason => "dull" } + end + + it 'should expire the file cache for the info request' do + @controller.should_receive(:expire_for_request).with(@incoming.info_request) + make_request + end + + context 'if the incoming message saves correctly' do + + it 'should redirect to the admin info request view' do + make_request + response.should redirect_to admin_request_show_url(@incoming.info_request) + end + + it 'should show a message that the incoming message has been updated' do + make_request + flash[:notice].should == 'Incoming message successfully updated.' + end + + end + + context 'if the incoming message is not valid' do + + it 'should render the edit template' do + make_request({:id => @incoming.id, + :incoming_message => {:prominence => 'fantastic', + :prominence_reason => 'dull'}}) + response.should render_template("edit") + end + + end + end + +end diff --git a/spec/controllers/admin_outgoing_message_controller_spec.rb b/spec/controllers/admin_outgoing_message_controller_spec.rb new file mode 100644 index 000000000..0dde53b86 --- /dev/null +++ b/spec/controllers/admin_outgoing_message_controller_spec.rb @@ -0,0 +1,105 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe AdminOutgoingMessageController do + + describe 'when editing an outgoing message' do + + before do + @info_request = FactoryGirl.create(:info_request) + @outgoing = @info_request.outgoing_messages.first + end + + it 'should be successful' do + get :edit, :id => @outgoing.id + response.should be_success + end + + it 'should assign the incoming message to the view' do + get :edit, :id => @outgoing.id + assigns[:outgoing_message].should == @outgoing + end + + end + + describe 'when updating an outgoing message' do + + before do + @info_request = FactoryGirl.create(:info_request) + @outgoing = @info_request.outgoing_messages.first + @default_params = {:id => @outgoing.id, + :outgoing_message => {:prominence => 'hidden', + :prominence_reason => 'dull', + :body => 'changed body'} } + end + + def make_request(params=@default_params) + post :update, params + end + + it 'should save a change to the body of the message' do + make_request + @outgoing.reload + @outgoing.body.should == 'changed body' + end + + it 'should save the prominence of the message' do + make_request + @outgoing.reload + @outgoing.prominence.should == 'hidden' + end + + it 'should save a prominence reason for the message' do + make_request + @outgoing.reload + @outgoing.prominence_reason.should == 'dull' + end + + it 'should log an "edit_outgoing" event on the info_request' do + @controller.stub!(:admin_current_user).and_return("Admin user") + make_request + @info_request.reload + last_event = @info_request.info_request_events.last + last_event.event_type.should == 'edit_outgoing' + last_event.params.should == { :outgoing_message_id => @outgoing.id, + :editor => "Admin user", + :old_prominence => "normal", + :prominence => "hidden", + :old_prominence_reason => nil, + :old_body => 'Some information please', + :body => 'changed body', + :prominence_reason => "dull" } + end + + it 'should expire the file cache for the info request' do + @controller.should_receive(:expire_for_request).with(@info_request) + make_request + end + + context 'if the outgoing message saves correctly' do + + it 'should redirect to the admin info request view' do + make_request + response.should redirect_to admin_request_show_url(@info_request) + end + + it 'should show a message that the incoming message has been updated' do + make_request + flash[:notice].should == 'Outgoing message successfully updated.' + end + + end + + context 'if the incoming message is not valid' do + + it 'should render the edit template' do + make_request({:id => @outgoing.id, + :outgoing_message => {:prominence => 'fantastic', + :prominence_reason => 'dull', + :body => 'Some information please'}}) + response.should render_template("edit") + end + + end + end + +end diff --git a/spec/controllers/admin_request_controller_spec.rb b/spec/controllers/admin_request_controller_spec.rb index b7b726507..63b219c88 100644 --- a/spec/controllers/admin_request_controller_spec.rb +++ b/spec/controllers/admin_request_controller_spec.rb @@ -52,18 +52,6 @@ describe AdminRequestController, "when administering requests" do end - it "edits an outgoing message" do - get :edit_outgoing, :id => outgoing_messages(:useless_outgoing_message) - end - - it "saves edits to an outgoing_message" do - outgoing_messages(:useless_outgoing_message).body.should include("fancy dog") - post :update_outgoing, { :id => outgoing_messages(:useless_outgoing_message), :outgoing_message => { :body => "Why do you have such a delicious cat?" } } - request.flash[:notice].should include('successful') - ir = OutgoingMessage.find(outgoing_messages(:useless_outgoing_message).id) - ir.body.should include("delicious cat") - end - describe 'when fully destroying a request' do it 'expires the file cache for that request' do @@ -89,59 +77,10 @@ describe AdminRequestController, "when administering the holding pen" do ir.handle_rejected_responses = 'holding_pen' ir.save! receive_incoming_mail('incoming-request-plain.email', ir.incoming_email, "frob@nowhere.com") - get :show_raw_email, :id => InfoRequest.holding_pen_request.get_last_response.raw_email.id + get :show_raw_email, :id => InfoRequest.holding_pen_request.get_last_public_response.raw_email.id response.should contain "Only the authority can reply to this request" end - it "allows redelivery even to a closed request" do - ir = info_requests(:fancy_dog_request) - ir.allow_new_responses_from = 'nobody' - ir.handle_rejected_responses = 'holding_pen' - ir.save! - InfoRequest.holding_pen_request.incoming_messages.length.should == 0 - ir.incoming_messages.length.should == 1 - receive_incoming_mail('incoming-request-plain.email', ir.incoming_email, "frob@nowhere.com") - InfoRequest.holding_pen_request.incoming_messages.length.should == 1 - new_im = InfoRequest.holding_pen_request.incoming_messages[0] - ir.incoming_messages.length.should == 1 - post :redeliver_incoming, :redeliver_incoming_message_id => new_im.id, :url_title => ir.url_title - ir = InfoRequest.find_by_url_title(ir.url_title) - ir.incoming_messages.length.should == 2 - response.should redirect_to(:controller=>'admin_request', :action=>'show', :id=>101) - InfoRequest.holding_pen_request.incoming_messages.length.should == 0 - end - - it "allows redelivery to more than one request" do - ir1 = info_requests(:fancy_dog_request) - ir1.allow_new_responses_from = 'nobody' - ir1.handle_rejected_responses = 'holding_pen' - ir1.save! - ir1.incoming_messages.length.should == 1 - ir2 = info_requests(:another_boring_request) - ir2.incoming_messages.length.should == 1 - - receive_incoming_mail('incoming-request-plain.email', ir1.incoming_email, "frob@nowhere.com") - InfoRequest.holding_pen_request.incoming_messages.length.should == 1 - - new_im = InfoRequest.holding_pen_request.incoming_messages[0] - post :redeliver_incoming, :redeliver_incoming_message_id => new_im.id, :url_title => "#{ir1.url_title},#{ir2.url_title}" - ir1.reload - ir1.incoming_messages.length.should == 2 - ir2.reload - ir2.incoming_messages.length.should == 2 - response.should redirect_to(:controller=>'admin_request', :action=>'show', :id=>ir2.id) - InfoRequest.holding_pen_request.incoming_messages.length.should == 0 - end - - it 'expires the file cache for the previous request' do - current_info_request = info_requests(:fancy_dog_request) - destination_info_request = info_requests(:naughty_chicken_request) - incoming_message = incoming_messages(:useless_incoming_message) - @controller.should_receive(:expire_for_request).with(current_info_request) - post :redeliver_incoming, :redeliver_incoming_message_id => incoming_message.id, - :url_title => destination_info_request.url_title - end - it "guesses a misdirected request" do ir = info_requests(:fancy_dog_request) ir.handle_rejected_responses = 'holding_pen' @@ -149,7 +88,7 @@ describe AdminRequestController, "when administering the holding pen" do ir.save! mail_to = "request-#{ir.id}-asdfg@example.com" receive_incoming_mail('incoming-request-plain.email', mail_to) - interesting_email = InfoRequest.holding_pen_request.get_last_response.raw_email.id + interesting_email = InfoRequest.holding_pen_request.get_last_public_response.raw_email.id # now we add another message to the queue, which we're not interested in receive_incoming_mail('incoming-request-plain.email', ir.incoming_email, "") InfoRequest.holding_pen_request.incoming_messages.length.should == 2 @@ -158,32 +97,7 @@ describe AdminRequestController, "when administering the holding pen" do assigns[:info_requests][0].should == ir end - describe 'when destroying an incoming message' do - - before do - @im = incoming_messages(:useless_incoming_message) - @controller.stub!(:expire_for_request) - end - - it "destroys the raw email file" do - raw_email = @im.raw_email.filepath - assert_equal File.exists?(raw_email), true - post :destroy_incoming, :incoming_message_id => @im.id - assert_equal File.exists?(raw_email), false - end - - it 'asks the incoming message to fully destroy itself' do - IncomingMessage.stub!(:find).and_return(@im) - @im.should_receive(:fully_destroy) - post :destroy_incoming, :incoming_message_id => @im.id - end - it 'expires the file cache for the associated info_request' do - @controller.should_receive(:expire_for_request).with(@im.info_request) - post :destroy_incoming, :incoming_message_id => @im.id - end - - end it "shows a suitable default 'your email has been hidden' message" do ir = info_requests(:fancy_dog_request) diff --git a/spec/controllers/public_body_controller_spec.rb b/spec/controllers/public_body_controller_spec.rb index 4e1841164..2d1b1466f 100644 --- a/spec/controllers/public_body_controller_spec.rb +++ b/spec/controllers/public_body_controller_spec.rb @@ -1,6 +1,8 @@ # coding: utf-8 require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require 'nokogiri' + describe PublicBodyController, "when showing a body" do render_views @@ -78,24 +80,80 @@ describe PublicBodyController, "when listing bodies" do response.should be_success end - it "should list all bodies from default locale, even when there are no translations for selected locale" do - I18n.with_locale(:en) do - @english_only = PublicBody.new(:name => 'English only', - :short_name => 'EO', - :request_email => 'english@flourish.org', - :last_edit_editor => 'test', - :last_edit_comment => '') - @english_only.save + def make_single_language_example(locale) + result = nil + I18n.with_locale(locale) do + case locale + when :en + result = PublicBody.new(:name => 'English only', + :short_name => 'EO') + when :es + result = PublicBody.new(:name => 'Español Solamente', + :short_name => 'ES') + else + raise StandardError.new "Unknown locale #{locale}" + end + result.request_email = "#{locale}@example.org" + result.last_edit_editor = 'test' + result.last_edit_comment = '' + result.save end + result + end + + it "with no fallback, should only return bodies from the current locale" do + @english_only = make_single_language_example :en + @spanish_only = make_single_language_example :es + get :list, {:locale => 'es'} + assigns[:public_bodies].include?(@english_only).should == false + assigns[:public_bodies].include?(@spanish_only).should == true + end + + it "if fallback is requested, should list all bodies from default locale, even when there are no translations for selected locale" do + AlaveteliConfiguration.stub!(:public_body_list_fallback_to_default_locale).and_return(true) + @english_only = make_single_language_example :en get :list, {:locale => 'es'} assigns[:public_bodies].include?(@english_only).should == true end + it 'if fallback is requested, should still list public bodies only with translations in the current locale' do + AlaveteliConfiguration.stub!(:public_body_list_fallback_to_default_locale).and_return(true) + @spanish_only = make_single_language_example :es + get :list, {:locale => 'es'} + assigns[:public_bodies].include?(@spanish_only).should == true + end + + it "if fallback is requested, make sure that there are no duplicates listed" do + AlaveteliConfiguration.stub!(:public_body_list_fallback_to_default_locale).and_return(true) + get :list, {:locale => 'es'} + pb_ids = assigns[:public_bodies].map { |pb| pb.id } + unique_pb_ids = pb_ids.uniq + pb_ids.sort.should === unique_pb_ids.sort + end + it 'should show public body names in the selected locale language if present' do get :list, {:locale => 'es'} response.should contain('El Department for Humpadinking') end + it 'should not show the internal admin authority' do + PublicBody.internal_admin_body + get :list, {:locale => 'en'} + response.should_not contain('Internal admin authority') + end + + it 'should order on the translated name, even with the fallback' do + # The names of each public body is in: + # <span class="head"><a>Public Body Name</a></span> + # ... eo extract all of those, and check that they are ordered: + AlaveteliConfiguration.stub!(:public_body_list_fallback_to_default_locale).and_return(true) + get :list, {:locale => 'es'} + parsed = Nokogiri::HTML(response.body) + public_body_names = parsed.xpath '//span[@class="head"]/a/text()' + public_body_names = public_body_names.map { |pb| pb.to_s } + public_body_names.should == public_body_names.sort + end + it 'should show public body names in the selected locale language if present for a locale with underscores' do AlaveteliLocalization.set_locales('he_IL en', 'en') get :list, {:locale => 'he_IL'} @@ -208,6 +266,41 @@ describe PublicBodyController, "when showing JSON version for API" do end +describe PublicBodyController, "when showing public body statistics" do + + it "should render the right template with the right data" do + config = MySociety::Config.load_default() + config['MINIMUM_REQUESTS_FOR_STATISTICS'] = 1 + config['PUBLIC_BODY_STATISTICS_PAGE'] = true + get :statistics + response.should render_template('public_body/statistics') + # There are 5 different graphs we're creating at the moment. + assigns[:graph_list].length.should == 5 + # The first is the only one with raw values, the rest are + # percentages with error bars: + assigns[:graph_list].each_with_index do |graph, index| + if index == 0 + graph['errorbars'].should be_false + graph['x_values'].length.should == 4 + graph['x_values'].should == [0, 1, 2, 3] + graph['y_values'].should == [1, 2, 2, 4] + else + graph['errorbars'].should be_true + # Just check the first one: + if index == 1 + graph['x_values'].should == [0, 1, 2, 3] + graph['y_values'].should == [0, 50, 100, 100] + end + # Check that at least every confidence interval value is + # a Float (rather than NilClass, say): + graph['cis_below'].each { |v| v.should be_instance_of(Float) } + graph['cis_above'].each { |v| v.should be_instance_of(Float) } + end + end + end + +end + describe PublicBodyController, "when doing type ahead searches" do render_views diff --git a/spec/controllers/request_controller_spec.rb b/spec/controllers/request_controller_spec.rb index 2c605a139..def9dfc7e 100644 --- a/spec/controllers/request_controller_spec.rb +++ b/spec/controllers/request_controller_spec.rb @@ -174,7 +174,7 @@ describe RequestController, "when changing things that appear on the request pag ir.save! PurgeRequest.all().first.model_id.should == ir.id end - it "should not create more than one entry for any given resourcce" do + it "should not create more than one entry for any given resource" do ir = info_requests(:fancy_dog_request) ir.prominence = 'hidden' ir.save! @@ -191,7 +191,6 @@ describe RequestController, "when showing one request" do before(:each) do load_raw_emails_data - FileUtils.rm_rf File.join(File.dirname(__FILE__), "../../cache/zips") end it "should be successful" do @@ -768,194 +767,221 @@ describe RequestController, "when showing one request" do end end - describe 'when making a zipfile available' do - it 'should return a 410 for a request that is hidden' do - title = 'why_do_you_have_such_a_fancy_dog' - ir = info_requests(:fancy_dog_request) - ir.prominence = 'hidden' - ir.save! - get :download_entire_request, {:url_title => title}, { :user_id => ir.user.id } - response.should render_template('request/hidden') - response.code.should == '410' - end - - it "should have a different zipfile URL when the request changes" do - title = 'why_do_you_have_such_a_fancy_dog' - ir = info_requests(:fancy_dog_request) - session[:user_id] = ir.user.id # bob_smith_user - get :download_entire_request, :url_title => title - assigns[:url_path].should contain /#{title}.zip$/ - old_path = assigns[:url_path] - response.location.should contain /#{assigns[:url_path]}$/ - zipfile = Zip::ZipFile.open(File.join(File.dirname(__FILE__), "../../cache/zips", old_path)) { |zipfile| - zipfile.count.should == 1 # just the message - } - receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) - get :download_entire_request, :url_title => title - assigns[:url_path].should contain /#{title}.zip$/ - old_path = assigns[:url_path] - response.location.should contain /#{assigns[:url_path]}$/ - zipfile = Zip::ZipFile.open(File.join(File.dirname(__FILE__), "../../cache/zips", old_path)) { |zipfile| - zipfile.count.should == 3 # the message plus two "hello-world.txt" files - } - - # The path of the zip file is based on the hash of the timestamp of the last request - # in the thread, so we wait for a second to make sure this one will have a different - # timestamp than the previous. - sleep 1 - receive_incoming_mail('incoming-request-attachment-unknown-extension.email', ir.incoming_email) - get :download_entire_request, :url_title => title - assigns[:url_path].should contain /#{title}.zip$/ - assigns[:url_path].should_not == old_path - response.location.should contain assigns[:url_path] - zipfile = Zip::ZipFile.open(File.join(File.dirname(__FILE__), "../../cache/zips", assigns[:url_path])) { |zipfile| - zipfile.count.should == 4 # the message, two hello-world.txt plus the unknown attachment - } - end - - it 'should successfully make a zipfile for an external request' do - info_request = info_requests(:external_request) - get :download_entire_request, { :url_title => info_request.url_title }, - { :user_id => users(:bob_smith_user) } - response.location.should contain /#{assigns[:url_path]}$/ - end - end end end -describe RequestController, "when changing prominence of a request" do - before(:each) do - load_raw_emails_data +describe RequestController, "when handling prominence" do + + def expect_hidden(hidden_template) + response.content_type.should == "text/html" + response.should render_template(hidden_template) + response.code.should == '403' end - it "should not show hidden requests" do - ir = info_requests(:fancy_dog_request) - ir.prominence = 'hidden' - ir.save! + context 'when the request is hidden' do - get :show, :url_title => 'why_do_you_have_such_a_fancy_dog' - response.should render_template('hidden') - end + before(:each) do + @info_request = FactoryGirl.create(:info_request_with_incoming_attachments, + :prominence => 'hidden') + end - it "should not show hidden requests even if logged in as their owner" do - ir = info_requests(:fancy_dog_request) - ir.prominence = 'hidden' - ir.save! + it "should not show request if you're not logged in" do + get :show, :url_title => @info_request.url_title + expect_hidden('hidden') + end - session[:user_id] = ir.user.id # bob_smith_user - get :show, :url_title => 'why_do_you_have_such_a_fancy_dog' - response.should render_template('hidden') - end + it "should not show request even if logged in as their owner" do + session[:user_id] = @info_request.user.id + get :show, :url_title => @info_request.url_title + expect_hidden('hidden') + end - it 'should not show hidden requests if requested using json' do - ir = info_requests(:fancy_dog_request) - ir.prominence = 'hidden' - ir.save! + it 'should not show request if requested using json' do + session[:user_id] = @info_request.user.id + get :show, :url_title => @info_request.url_title, :format => 'json' + response.code.should == '403' + end - session[:user_id] = ir.user.id # bob_smith_user - get :show, :url_title => 'why_do_you_have_such_a_fancy_dog', :format => 'json' - response.code.should == '410' - end + it "should show request if logged in as super user" do + session[:user_id] = FactoryGirl.create(:admin_user) + get :show, :url_title => @info_request.url_title + response.should render_template('show') + end - it "should show hidden requests if logged in as super user" do - ir = info_requests(:fancy_dog_request) - ir.prominence = 'hidden' - ir.save! + it "should not download attachments" do + incoming_message = @info_request.incoming_messages.first + get :get_attachment, :incoming_message_id => incoming_message.id, + :id => @info_request.id, + :part => 2, + :file_name => 'interesting.pdf', + :skip_cache => 1 + expect_hidden('request/hidden') + end + + it 'should not generate an HTML version of an attachment for a request whose prominence + is hidden even for an admin but should return a 404' do + session[:user_id] = FactoryGirl.create(:admin_user) + incoming_message = @info_request.incoming_messages.first + lambda do + get :get_attachment_as_html, :incoming_message_id => incoming_message.id, + :id => @info_request.id, + :part => 2, + :file_name => 'interesting.pdf' + end.should raise_error(ActiveRecord::RecordNotFound) + end - session[:user_id] = users(:admin_user) - get :show, :url_title => 'why_do_you_have_such_a_fancy_dog' - response.should render_template('show') end - it "should not show requester_only requests if you're not logged in" do - ir = info_requests(:fancy_dog_request) - ir.prominence = 'requester_only' - ir.save! + context 'when the request is requester_only' do - get :show, :url_title => 'why_do_you_have_such_a_fancy_dog' - response.should render_template('hidden') - end + before(:each) do + @info_request = FactoryGirl.create(:info_request_with_incoming_attachments, + :prominence => 'requester_only') + end - it "should show requester_only requests to requester and admin if logged in" do - ir = info_requests(:fancy_dog_request) - ir.prominence = 'requester_only' - ir.save! + it "should not show request if you're not logged in" do + get :show, :url_title => @info_request.url_title + expect_hidden('hidden') + end - session[:user_id] = users(:silly_name_user).id - get :show, :url_title => 'why_do_you_have_such_a_fancy_dog' - response.should render_template('hidden') + it "should show request to requester and admin if logged in" do + session[:user_id] = FactoryGirl.create(:user).id + get :show, :url_title => @info_request.url_title + expect_hidden('hidden') - session[:user_id] = ir.user.id # bob_smith_user - get :show, :url_title => 'why_do_you_have_such_a_fancy_dog' - response.should render_template('show') + session[:user_id] = @info_request.user.id + get :show, :url_title => @info_request.url_title + response.should render_template('show') - session[:user_id] = users(:admin_user).id - get :show, :url_title => 'why_do_you_have_such_a_fancy_dog' - response.should render_template('show') - end + session[:user_id] = FactoryGirl.create(:admin_user).id + get :show, :url_title => @info_request.url_title + response.should render_template('show') + end - it 'should not cache an attachment on a request whose prominence is requester_only when showing - the request to the requester or admin' do - ir = info_requests(:fancy_dog_request) - ir.prominence = 'requester_only' - ir.save! - session[:user_id] = ir.user.id # bob_smith_user - @controller.should_not_receive(:foi_fragment_cache_write) - get :show, :url_title => 'why_do_you_have_such_a_fancy_dog' + it 'should not cache an attachment when showing an attachment to the requester or admin' do + session[:user_id] = @info_request.user.id + incoming_message = @info_request.incoming_messages.first + @controller.should_not_receive(:foi_fragment_cache_write) + get :get_attachment, :incoming_message_id => incoming_message.id, + :id => @info_request.id, + :part => 2, + :file_name => 'interesting.pdf' + end end - it "should not download attachments if hidden" do - ir = info_requests(:fancy_dog_request) - ir.prominence = 'hidden' - ir.save! - receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) + context 'when the incoming message has prominence hidden' do + + before(:each) do + @incoming_message = FactoryGirl.create(:incoming_message_with_attachments, + :prominence => 'hidden') + @info_request = @incoming_message.info_request + end + + it "should not download attachments for a non-logged in user" do + get :get_attachment, :incoming_message_id => @incoming_message.id, + :id => @info_request.id, + :part => 2, + :file_name => 'interesting.pdf', + :skip_cache => 1 + expect_hidden('request/hidden_correspondence') + end + + it 'should not download attachments for the request owner' do + session[:user_id] = @info_request.user.id + get :get_attachment, :incoming_message_id => @incoming_message.id, + :id => @info_request.id, + :part => 2, + :file_name => 'interesting.pdf', + :skip_cache => 1 + expect_hidden('request/hidden_correspondence') + end + + it 'should download attachments for an admin user', :focus => true do + session[:user_id] = FactoryGirl.create(:admin_user).id + get :get_attachment, :incoming_message_id => @incoming_message.id, + :id => @info_request.id, + :part => 2, + :file_name => 'interesting.pdf', + :skip_cache => 1 + response.content_type.should == 'application/pdf' + response.should be_success + end + + it 'should not generate an HTML version of an attachment for a request whose prominence + is hidden even for an admin but should return a 404' do + session[:user_id] = FactoryGirl.create(:admin_user).id + lambda do + get :get_attachment_as_html, :incoming_message_id => @incoming_message.id, + :id => @info_request.id, + :part => 2, + :file_name => 'interesting.pdf', + :skip_cache => 1 + end.should raise_error(ActiveRecord::RecordNotFound) + end + + it 'should not cache an attachment when showing an attachment to the requester or admin' do + session[:user_id] = @info_request.user.id + @controller.should_not_receive(:foi_fragment_cache_write) + get :get_attachment, :incoming_message_id => @incoming_message.id, + :id => @info_request.id, + :part => 2, + :file_name => 'interesting.pdf' + end - get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, - :id => ir.id, - :part => 2, - :skip_cache => 1 - response.content_type.should == "text/html" - response.should_not contain "Second hello" - response.should render_template('request/hidden') - get :get_attachment, :incoming_message_id => ir.incoming_messages[1].id, - :id => ir.id, - :part => 3, - :skip_cache => 1 - response.content_type.should == "text/html" - response.should_not contain "First hello" - response.should render_template('request/hidden') - response.code.should == '410' end - it 'should not generate an HTML version of an attachment whose prominence is hidden/requester - only even for the requester or an admin but should return a 404' do - ir = info_requests(:fancy_dog_request) - ir.prominence = 'hidden' - ir.save! - receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) - session[:user_id] = users(:admin_user).id - lambda do - get :get_attachment_as_html, :incoming_message_id => ir.incoming_messages[1].id, - :id => ir.id, - :part => 2, - :file_name => 'hello world.txt' - end.should raise_error(ActiveRecord::RecordNotFound) - end - - it 'should not generate an HTML version of an attachment whose prominence is hidden/requester - only even for the requester or an admin but should return a 404' do - ir = info_requests(:fancy_dog_request) - ir.prominence = 'hidden' - ir.save! - receive_incoming_mail('incoming-request-two-same-name.email', ir.incoming_email) - session[:user_id] = users(:admin_user).id - lambda do - get :get_attachment_as_html, :incoming_message_id => ir.incoming_messages[1].id, - :id => ir.id, - :part => 2, - :file_name => 'hello world.txt' - end.should raise_error(ActiveRecord::RecordNotFound) + context 'when the incoming message has prominence requester_only' do + + before(:each) do + @incoming_message = FactoryGirl.create(:incoming_message_with_attachments, + :prominence => 'requester_only') + @info_request = @incoming_message.info_request + end + + it "should not download attachments for a non-logged in user" do + get :get_attachment, :incoming_message_id => @incoming_message.id, + :id => @info_request.id, + :part => 2, + :file_name => 'interesting.pdf', + :skip_cache => 1 + expect_hidden('request/hidden_correspondence') + end + + it 'should download attachments for the request owner' do + session[:user_id] = @info_request.user.id + get :get_attachment, :incoming_message_id => @incoming_message.id, + :id => @info_request.id, + :part => 2, + :file_name => 'interesting.pdf', + :skip_cache => 1 + response.content_type.should == 'application/pdf' + response.should be_success + end + + it 'should download attachments for an admin user', :focus => true do + session[:user_id] = FactoryGirl.create(:admin_user).id + get :get_attachment, :incoming_message_id => @incoming_message.id, + :id => @info_request.id, + :part => 2, + :file_name => 'interesting.pdf', + :skip_cache => 1 + response.content_type.should == 'application/pdf' + response.should be_success + end + + it 'should not generate an HTML version of an attachment for a request whose prominence + is hidden even for an admin but should return a 404' do + session[:user_id] = FactoryGirl.create(:admin_user) + lambda do + get :get_attachment_as_html, :incoming_message_id => @incoming_message.id, + :id => @info_request.id, + :part => 2, + :file_name => 'interesting.pdf', + :skip_cache => 1 + end.should raise_error(ActiveRecord::RecordNotFound) + end + end end @@ -1039,6 +1065,14 @@ describe RequestController, "when creating a new request" do response.should render_template('new') end + it 'should display one meaningful error message when no message body is added' do + post :new, :info_request => { :public_body_id => @body.id }, + :outgoing_message => { :body => "" }, + :submitted_new_request => 1, :preview => 1 + assigns[:info_request].errors.full_messages.should_not include('Outgoing messages is invalid') + assigns[:outgoing_message].errors.full_messages.should include('Body Please enter your letter requesting information') + end + it "should give an error and render 'new' template when a summary isn't given" do post :new, :info_request => { :public_body_id => @body.id }, :outgoing_message => { :body => "This is a silly letter. It is too short to be interesting." }, @@ -1293,12 +1327,12 @@ describe RequestController, "when viewing an individual response for reply/follo response.should render_template('request/hidden') end - it 'should respond to a json request for a hidden request with a 410 code and no body' do + it 'should respond to a json request for a hidden request with a 403 code and no body' do get :show_response, :id => info_requests(:fancy_dog_request).id, :incoming_message_id => incoming_messages(:useless_incoming_message), :format => 'json' - response.code.should == '410' + response.code.should == '403' end end @@ -1572,7 +1606,7 @@ describe RequestController, "when classifying an information request" do @dog_request.reload @dog_request.awaiting_description.should == false @dog_request.described_state.should == 'rejected' - @dog_request.get_last_response_event.should == info_request_events(:useless_incoming_message_event) + @dog_request.get_last_public_response_event.should == info_request_events(:useless_incoming_message_event) @dog_request.info_request_events.last.event_type.should == "status_update" @dog_request.info_request_events.last.calculated_state.should == 'rejected' end @@ -1725,13 +1759,13 @@ describe RequestController, "when classifying an information request" do it 'should redirect to the "response url" when there is a last response' do incoming_message = mock_model(IncomingMessage) - @dog_request.stub!(:get_last_response).and_return(incoming_message) + @dog_request.stub!(:get_last_public_response).and_return(incoming_message) expect_redirect('waiting_clarification', "request/#{@dog_request.id}/response/#{incoming_message.id}") end it 'should redirect to the "response no followup url" when there are no events needing description' do - @dog_request.stub!(:get_last_response).and_return(nil) + @dog_request.stub!(:get_last_public_response).and_return(nil) expect_redirect('waiting_clarification', "request/#{@dog_request.id}/response") end @@ -1770,7 +1804,7 @@ describe RequestController, "when classifying an information request" do context 'when status is updated to "gone postal"' do it 'should redirect to the "respond to last url"' do - expect_redirect('gone_postal', "request/#{@dog_request.id}/response/#{@dog_request.get_last_response.id}?gone_postal=1") + expect_redirect('gone_postal', "request/#{@dog_request.id}/response/#{@dog_request.get_last_public_response.id}?gone_postal=1") end end @@ -1812,7 +1846,7 @@ describe RequestController, "when classifying an information request" do context 'when status is updated to "user_withdrawn"' do it 'should redirect to the "respond to last url url" ' do - expect_redirect('user_withdrawn', "request/#{@dog_request.id}/response/#{@dog_request.get_last_response.id}") + expect_redirect('user_withdrawn', "request/#{@dog_request.id}/response/#{@dog_request.get_last_public_response.id}") end end @@ -1865,7 +1899,7 @@ describe RequestController, "when sending a followup message" do # fake that this is a clarification info_requests(:fancy_dog_request).set_described_state('waiting_clarification') info_requests(:fancy_dog_request).described_state.should == 'waiting_clarification' - info_requests(:fancy_dog_request).get_last_response_event.calculated_state.should == 'waiting_clarification' + info_requests(:fancy_dog_request).get_last_public_response_event.calculated_state.should == 'waiting_clarification' # make the followup session[:user_id] = users(:bob_smith_user).id @@ -1883,7 +1917,7 @@ describe RequestController, "when sending a followup message" do # and that the status changed info_requests(:fancy_dog_request).reload info_requests(:fancy_dog_request).described_state.should == 'waiting_response' - info_requests(:fancy_dog_request).get_last_response_event.calculated_state.should == 'waiting_clarification' + info_requests(:fancy_dog_request).get_last_public_response_event.calculated_state.should == 'waiting_clarification' end it "should give an error if the same followup is submitted twice" do @@ -2456,7 +2490,9 @@ describe RequestController, "when caching fragments" do :info_request_id => 132, :id => 44, :get_attachments_for_display => nil, - :html_mask_stuff! => nil) + :html_mask_stuff! => nil, + :user_can_view? => true, + :all_can_view? => true) attachment = mock(FoiAttachment, :display_filename => long_name, :body_as_html => ['some text', 'wrapper']) IncomingMessage.stub!(:find).with("44").and_return(incoming_message) diff --git a/spec/factories.rb b/spec/factories.rb new file mode 100644 index 000000000..653525920 --- /dev/null +++ b/spec/factories.rb @@ -0,0 +1,140 @@ +FactoryGirl.define do + + sequence(:email) { |n| "person#{n}@example.com" } + sequence(:name) { |n| "Example Public Body #{n}" } + sequence(:short_name) { |n| "Example Body #{n}" } + + factory :foi_attachment do + factory :body_text do + content_type 'text/plain' + body { 'hereisthetext' } + end + factory :pdf_attachment do + content_type 'application/pdf' + filename 'interesting.pdf' + body { load_file_fixture('interesting.pdf') } + end + end + + factory :incoming_message do + info_request + raw_email + last_parsed { 1.week.ago } + sent_at { 1.week.ago } + + after_create do |incoming_message, evaluator| + FactoryGirl.create(:body_text, + :incoming_message => incoming_message, + :url_part_number => 1) + end + + factory :plain_incoming_message do + last_parsed { nil } + sent_at { nil } + after_create do |incoming_message, evaluator| + data = load_file_fixture('incoming-request-plain.email') + data.gsub!('EMAIL_FROM', 'Bob Responder <bob@example.com>') + incoming_message.raw_email.data = data + incoming_message.raw_email.save! + end + end + + factory :incoming_message_with_attachments do + # foi_attachments_count is declared as an ignored attribute and available in + # attributes on the factory, as well as the callback via the evaluator + ignore do + foi_attachments_count 2 + end + + # the after(:create) yields two values; the incoming_message instance itself and the + # evaluator, which stores all values from the factory, including ignored + # attributes; + after_create do |incoming_message, evaluator| + evaluator.foi_attachments_count.times do |count| + FactoryGirl.create(:pdf_attachment, + :incoming_message => incoming_message, + :url_part_number => count+2) + end + end + end + end + + factory :raw_email + + factory :outgoing_message do + factory :initial_request do + ignore do + status 'ready' + message_type 'initial_request' + body 'Some information please' + what_doing 'normal_sort' + end + initialize_with { OutgoingMessage.new({ :status => status, + :message_type => message_type, + :body => body, + :what_doing => what_doing }) } + after_create do |outgoing_message| + outgoing_message.send_message + end + end + end + + factory :info_request do + title "Example Title" + public_body + user + + after_create do |info_request, evaluator| + FactoryGirl.create(:initial_request, :info_request => info_request) + end + + factory :info_request_with_incoming do + after_create do |info_request, evaluator| + incoming_message = FactoryGirl.create(:incoming_message, :info_request => info_request) + info_request.log_event("response", {:incoming_message_id => incoming_message.id}) + end + end + + factory :info_request_with_plain_incoming do + after_create do |info_request, evaluator| + incoming_message = FactoryGirl.create(:plain_incoming_message, :info_request => info_request) + info_request.log_event("response", {:incoming_message_id => incoming_message.id}) + end + end + + factory :info_request_with_incoming_attachments do + after_create do |info_request, evaluator| + incoming_message = FactoryGirl.create(:incoming_message_with_attachments, :info_request => info_request) + info_request.log_event("response", {:incoming_message_id => incoming_message.id}) + end + end + + factory :external_request do + user nil + external_user_name 'External User' + external_url 'http://www.example.org/request/external' + end + + end + + factory :user do + name 'Example User' + email + salt "-6116981980.392287733335677" + hashed_password '6b7cd45a5f35fd83febc0452a799530398bfb6e8' # jonespassword + email_confirmed true + factory :admin_user do + name 'Admin User' + admin_level 'super' + end + end + + factory :public_body do + name + short_name + request_email 'request@example.com' + last_edit_editor "admin user" + last_edit_comment "Making an edit" + end + +end diff --git a/spec/fixtures/comments.yml b/spec/fixtures/comments.yml index b73385a55..44db44d54 100644 --- a/spec/fixtures/comments.yml +++ b/spec/fixtures/comments.yml @@ -1,3 +1,18 @@ +# == Schema Information +# +# Table name: comments +# +# id :integer not null, primary key +# user_id :integer not null +# comment_type :string(255) default("internal_error"), not null +# info_request_id :integer +# body :text not null +# visible :boolean default(TRUE), not null +# created_at :datetime not null +# updated_at :datetime not null +# locale :text default(""), not null +# + silly_comment: visible: t updated_at: 2008-08-13 01:25:17.486939 diff --git a/spec/fixtures/files/interesting.pdf b/spec/fixtures/files/interesting.pdf Binary files differnew file mode 100644 index 000000000..17f543455 --- /dev/null +++ b/spec/fixtures/files/interesting.pdf diff --git a/spec/fixtures/holidays.yml b/spec/fixtures/holidays.yml index 5a3d018bc..e6b8889c3 100644 --- a/spec/fixtures/holidays.yml +++ b/spec/fixtures/holidays.yml @@ -1,3 +1,12 @@ +# == Schema Information +# +# Table name: holidays +# +# id :integer not null, primary key +# day :date +# description :text +# + date20071130: id: '1' day: '2007-11-30' diff --git a/spec/fixtures/incoming_messages.yml b/spec/fixtures/incoming_messages.yml index fca5c716c..0bf392be1 100644 --- a/spec/fixtures/incoming_messages.yml +++ b/spec/fixtures/incoming_messages.yml @@ -1,3 +1,25 @@ +# == Schema Information +# +# Table name: incoming_messages +# +# id :integer not null, primary key +# info_request_id :integer not null +# created_at :datetime not null +# updated_at :datetime not null +# raw_email_id :integer not null +# cached_attachment_text_clipped :text +# cached_main_body_text_folded :text +# cached_main_body_text_unfolded :text +# subject :text +# mail_from_domain :text +# valid_to_reply_to :boolean +# last_parsed :datetime +# mail_from :text +# sent_at :datetime +# prominence :string(255) default("normal"), not null +# prominence_reason :text +# + useless_incoming_message: id: 1 info_request_id: 101 diff --git a/spec/fixtures/info_request_events.yml b/spec/fixtures/info_request_events.yml index 3907703d8..b2f40cc37 100644 --- a/spec/fixtures/info_request_events.yml +++ b/spec/fixtures/info_request_events.yml @@ -1,3 +1,20 @@ +# == Schema Information +# +# Table name: info_request_events +# +# id :integer not null, primary key +# info_request_id :integer not null +# event_type :text not null +# params_yaml :text not null +# created_at :datetime not null +# described_state :string(255) +# calculated_state :string(255) +# last_described_at :datetime +# incoming_message_id :integer +# outgoing_message_id :integer +# comment_id :integer +# + useless_outgoing_message_event: id: 900 params_yaml: "--- \n\ diff --git a/spec/fixtures/info_requests.yml b/spec/fixtures/info_requests.yml index 97effd036..d64807a49 100644 --- a/spec/fixtures/info_requests.yml +++ b/spec/fixtures/info_requests.yml @@ -1,3 +1,27 @@ +# == Schema Information +# +# Table name: info_requests +# +# id :integer not null, primary key +# title :text not null +# user_id :integer +# public_body_id :integer not null +# created_at :datetime not null +# updated_at :datetime not null +# described_state :string(255) not null +# awaiting_description :boolean default(FALSE), not null +# prominence :string(255) default("normal"), not null +# url_title :text not null +# law_used :string(255) default("foi"), not null +# allow_new_responses_from :string(255) default("anybody"), not null +# handle_rejected_responses :string(255) default("bounce"), not null +# idhash :string(255) not null +# external_user_name :string(255) +# external_url :string(255) +# attention_requested :boolean default(FALSE) +# comments_allowed :boolean default(TRUE), not null +# + fancy_dog_request: id: 101 title: Why do you have & such a fancy dog? diff --git a/spec/fixtures/locale/en/app.po b/spec/fixtures/locale/en/app.po index ee5c8d9c8..6d5bca1f9 100644 --- a/spec/fixtures/locale/en/app.po +++ b/spec/fixtures/locale/en/app.po @@ -1417,10 +1417,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -#: locale/model_attributes.rb:41 -msgid "InfoRequestEvent|Prominence" -msgstr "" - #: locale/model_attributes.rb:102 msgid "InfoRequest|Allow new responses from" msgstr "" diff --git a/spec/fixtures/locale/en_GB/app.po b/spec/fixtures/locale/en_GB/app.po index 84997a319..f106273a0 100644 --- a/spec/fixtures/locale/en_GB/app.po +++ b/spec/fixtures/locale/en_GB/app.po @@ -1417,10 +1417,6 @@ msgstr "" msgid "InfoRequestEvent|Params yaml" msgstr "" -#: locale/model_attributes.rb:41 -msgid "InfoRequestEvent|Prominence" -msgstr "" - #: locale/model_attributes.rb:102 msgid "InfoRequest|Allow new responses from" msgstr "" diff --git a/spec/fixtures/locale/es/app.po b/spec/fixtures/locale/es/app.po index d45d9b3b1..2e0f4302a 100644 --- a/spec/fixtures/locale/es/app.po +++ b/spec/fixtures/locale/es/app.po @@ -1553,10 +1553,6 @@ msgstr "InfoRequestEvent|Last described at" msgid "InfoRequestEvent|Params yaml" msgstr "InfoRequestEvent|Params yaml" -#: locale/model_attributes.rb:41 -msgid "InfoRequestEvent|Prominence" -msgstr "InfoRequestEvent|Prominence" - #: locale/model_attributes.rb:102 msgid "InfoRequest|Allow new responses from" msgstr "InfoRequest|Allow new responses from" diff --git a/spec/fixtures/outgoing_messages.yml b/spec/fixtures/outgoing_messages.yml index c71ee08bf..971ce0cc5 100644 --- a/spec/fixtures/outgoing_messages.yml +++ b/spec/fixtures/outgoing_messages.yml @@ -1,3 +1,19 @@ +# == Schema Information +# +# Table name: outgoing_messages +# +# id :integer not null, primary key +# info_request_id :integer not null +# body :text not null +# status :string(255) not null +# message_type :string(255) not null +# created_at :datetime not null +# updated_at :datetime not null +# last_sent_at :datetime +# incoming_message_followup_id :integer +# what_doing :string(255) not null +# + useless_outgoing_message: id: 1 info_request_id: 101 diff --git a/spec/fixtures/public_bodies.yml b/spec/fixtures/public_bodies.yml index 65cba4b28..1fa016d3a 100644 --- a/spec/fixtures/public_bodies.yml +++ b/spec/fixtures/public_bodies.yml @@ -1,3 +1,26 @@ +# == Schema Information +# +# Table name: public_bodies +# +# id :integer not null, primary key +# name :text not null +# short_name :text not null +# request_email :text not null +# version :integer not null +# last_edit_editor :string(255) not null +# last_edit_comment :text not null +# created_at :datetime not null +# updated_at :datetime not null +# url_name :text not null +# home_page :text default(""), not null +# notes :text default(""), not null +# first_letter :string(255) not null +# publication_scheme :text default(""), not null +# api_key :string(255) not null +# info_requests_count :integer default(0), not null +# disclosure_log :text default(""), not null +# + geraldine_public_body: name: The Geraldine Quango first_letter: T @@ -12,6 +35,9 @@ geraldine_public_body: created_at: 2007-10-24 10:51:01.161639 api_key: 1 info_requests_count: 4 + info_requests_successful_count: 0 + info_requests_not_held_count: 0 + info_requests_overdue_count: 3 humpadink_public_body: name: "Department for Humpadinking" first_letter: D @@ -27,6 +53,9 @@ humpadink_public_body: notes: An albatross told me!!! api_key: 2 info_requests_count: 2 + info_requests_successful_count: 1 + info_requests_not_held_count: 0 + info_requests_overdue_count: 1 forlorn_public_body: name: "Department of Loneliness" first_letter: D @@ -42,6 +71,9 @@ forlorn_public_body: notes: A very lonely public body that no one has corresponded with api_key: 3 info_requests_count: 0 + info_requests_successful_count: 0 + info_requests_not_held_count: 0 + info_requests_overdue_count: 0 silly_walks_public_body: id: 5 version: 1 @@ -57,6 +89,9 @@ silly_walks_public_body: notes: You know the one. api_key: 4 info_requests_count: 2 + info_requests_successful_count: 2 + info_requests_not_held_count: 0 + info_requests_overdue_count: 0 sensible_walks_public_body: id: 6 version: 1 @@ -72,6 +107,9 @@ sensible_walks_public_body: created_at: 2008-10-25 10:51:01.161639 api_key: 5 info_requests_count: 1 + info_requests_successful_count: 1 + info_requests_not_held_count: 0 + info_requests_overdue_count: 0 other_public_body: id: 7 version: 1 @@ -87,3 +125,6 @@ other_public_body: created_at: 2008-10-25 10:51:01.161639 api_key: 6 info_requests_count: 0 + info_requests_successful_count: 0 + info_requests_not_held_count: 0 + info_requests_overdue_count: 0 diff --git a/spec/fixtures/raw_emails.yml b/spec/fixtures/raw_emails.yml index ad2bc0a63..efdadde7b 100644 --- a/spec/fixtures/raw_emails.yml +++ b/spec/fixtures/raw_emails.yml @@ -1,3 +1,10 @@ +# == Schema Information +# +# Table name: raw_emails +# +# id :integer not null, primary key +# + # The actual email messages are in fixtures/files/raw_emails # # Note that the words "money" and "bob" are used in some tests diff --git a/spec/fixtures/track_things.yml b/spec/fixtures/track_things.yml index 1c4b323fd..61f1ed532 100644 --- a/spec/fixtures/track_things.yml +++ b/spec/fixtures/track_things.yml @@ -1,3 +1,19 @@ +# == Schema Information +# +# Table name: track_things +# +# id :integer not null, primary key +# tracking_user_id :integer not null +# track_query :string(255) not null +# info_request_id :integer +# tracked_user_id :integer +# public_body_id :integer +# track_medium :string(255) not null +# track_type :string(255) default("internal_error"), not null +# created_at :datetime +# updated_at :datetime +# + track_fancy_dog_request: id: "10" track_query: request:why_do_you_have_such_a_fancy_dog diff --git a/spec/fixtures/users.yml b/spec/fixtures/users.yml index c9730d855..d996fd31e 100644 --- a/spec/fixtures/users.yml +++ b/spec/fixtures/users.yml @@ -1,3 +1,29 @@ +# == Schema Information +# +# Table name: users +# +# id :integer not null, primary key +# email :string(255) not null +# name :string(255) not null +# hashed_password :string(255) not null +# salt :string(255) not null +# created_at :datetime not null +# updated_at :datetime not null +# email_confirmed :boolean default(FALSE), not null +# url_name :text not null +# last_daily_track_email :datetime default(2000-01-01 00:00:00 UTC) +# admin_level :string(255) default("none"), not null +# ban_text :text default(""), not null +# about_me :text default(""), not null +# locale :string(255) +# email_bounced_at :datetime +# email_bounce_message :text default(""), not null +# no_limit :boolean default(FALSE), not null +# receive_email_alerts :boolean default(TRUE), not null +# address :string(255) +# dob :date +# + bob_smith_user: id: "1" name: Bob Smith diff --git a/spec/integration/admin_spec.rb b/spec/integration/admin_spec.rb index 8a5e59ba2..8e6351d2c 100644 --- a/spec/integration/admin_spec.rb +++ b/spec/integration/admin_spec.rb @@ -1,21 +1,74 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') - -require "base64" +require File.expand_path(File.dirname(__FILE__) + '/alaveteli_dsl') describe "When administering the site" do + + before do + AlaveteliConfiguration.stub!(:skip_admin_auth).and_return(false) + end + it "allows an admin to log in as another user" do # First log in as Joe Admin - admin_user = users(:admin_user) - admin_user.email_confirmed = true - admin_user.save! - post_via_redirect "/profile/sign_in", :user_signin => {:email => admin_user.email, :password => "jonespassword"} - response.should be_success - + confirm(:admin_user) + admin = login(:admin_user) + # Now fetch the "log in as" link to log in as Bob - get_via_redirect "/admin/user/login_as/#{users(:bob_smith_user).id}", nil, { - "Authorization" => "Basic " + Base64.encode64("#{AlaveteliConfiguration::admin_username}:#{AlaveteliConfiguration::admin_password}").strip - } - response.should be_success - session[:user_id].should == users(:bob_smith_user).id + admin.get_via_redirect "/en/admin/user/login_as/#{users(:bob_smith_user).id}" + admin.response.should be_success + admin.session[:user_id].should == users(:bob_smith_user).id + end + + it 'does not allow a non-admin user to login as another user' do + robin = login(:robin_user) + robin.get_via_redirect "/en/admin/user/login_as/#{users(:bob_smith_user).id}" + robin.response.should be_success + robin.session[:user_id].should_not == users(:bob_smith_user).id + end + + it "allows redelivery of an incoming message to a closed request" do + confirm(:admin_user) + admin = login(:admin_user) + ir = info_requests(:fancy_dog_request) + close_request(ir) + InfoRequest.holding_pen_request.incoming_messages.length.should == 0 + ir.incoming_messages.length.should == 1 + receive_incoming_mail('incoming-request-plain.email', ir.incoming_email, "frob@nowhere.com") + InfoRequest.holding_pen_request.incoming_messages.length.should == 1 + new_im = InfoRequest.holding_pen_request.incoming_messages[0] + ir.incoming_messages.length.should == 1 + post_params = {'redeliver_incoming_message_id' => new_im.id, + 'url_title' => ir.url_title} + admin.post '/en/admin/incoming/redeliver', post_params + admin.response.location.should == 'http://www.example.com/en/admin/request/show/101' + ir = InfoRequest.find_by_url_title(ir.url_title) + ir.incoming_messages.length.should == 2 + + InfoRequest.holding_pen_request.incoming_messages.length.should == 0 + end + + it "allows redelivery of an incoming message to more than one request" do + confirm(:admin_user) + admin = login(:admin_user) + + ir1 = info_requests(:fancy_dog_request) + close_request(ir1) + ir1.incoming_messages.length.should == 1 + ir2 = info_requests(:another_boring_request) + ir2.incoming_messages.length.should == 1 + + receive_incoming_mail('incoming-request-plain.email', ir1.incoming_email, "frob@nowhere.com") + InfoRequest.holding_pen_request.incoming_messages.length.should == 1 + + new_im = InfoRequest.holding_pen_request.incoming_messages[0] + post_params = {'redeliver_incoming_message_id' => new_im.id, + 'url_title' => "#{ir1.url_title},#{ir2.url_title}"} + admin.post '/en/admin/incoming/redeliver', post_params + ir1.reload + ir1.incoming_messages.length.should == 2 + ir2.reload + ir2.incoming_messages.length.should == 2 + admin.response.location.should == 'http://www.example.com/en/admin/request/show/106' + InfoRequest.holding_pen_request.incoming_messages.length.should == 0 end + end diff --git a/spec/integration/alaveteli_dsl.rb b/spec/integration/alaveteli_dsl.rb new file mode 100644 index 000000000..119bb05a0 --- /dev/null +++ b/spec/integration/alaveteli_dsl.rb @@ -0,0 +1,68 @@ +module AlaveteliDsl + + def browses_request(url_title) + get "/request/#{url_title}" + assert_response :success + end + + def creates_request_unregistered + params = { :info_request => { :public_body_id => public_bodies(:geraldine_public_body).id, + :title => "Why is your quango called Geraldine?", + :tag_string => "" }, + :outgoing_message => { :body => "This is a silly letter. It is too short to be interesting." }, + :submitted_new_request => 1, + :preview => 0 + } + + # Initially we are not logged in. Try to create a new request. + post "/new", params + # We expect to be redirected to the login page + post_redirect = PostRedirect.get_last_post_redirect + response.should redirect_to(:controller => 'user', :action => 'signin', :token => post_redirect.token) + follow_redirect! + response.should render_template("user/sign") + response.body.should match(/To send your FOI request, please sign in or make a new account./) + end + +end + +def login(user) + open_session do |sess| + # Make sure we get a fresh empty session - there seems to be some + # problem with session leakage otherwise + sess.reset! + sess.extend(AlaveteliDsl) + + if user.is_a? User + u = user + else + u = users(user) + end + sess.visit signin_path + sess.fill_in "Your e-mail:", :with => u.email + sess.fill_in "Password:", :with => "jonespassword" + sess.click_button "Sign in" + assert sess.session[:user_id] == u.id + end +end + +def without_login + open_session do |sess| + sess.extend(AlaveteliDsl) + end +end + +def confirm(user) + u = users(user) + u.email_confirmed = true + u.save! +end + +def close_request(request) + request.allow_new_responses_from = 'nobody' + request.handle_rejected_responses = 'holding_pen' + request.save! +end + + + diff --git a/spec/integration/create_request_spec.rb b/spec/integration/create_request_spec.rb index 4efbf94ee..84fad12f9 100644 --- a/spec/integration/create_request_spec.rb +++ b/spec/integration/create_request_spec.rb @@ -1,51 +1,36 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require File.expand_path(File.dirname(__FILE__) + '/alaveteli_dsl') describe "When creating requests" do - def create_request_unregistered - params = { :info_request => { :public_body_id => public_bodies(:geraldine_public_body).id, - :title => "Why is your quango called Geraldine?", - :tag_string => "" }, - :outgoing_message => { :body => "This is a silly letter. It is too short to be interesting." }, - :submitted_new_request => 1, - :preview => 0 - } - - # Initially we are not logged in. Try to create a new request. - post "/new", params - # We expect to be redirected to the login page - post_redirect = PostRedirect.get_last_post_redirect - response.should redirect_to(:controller => 'user', :action => 'signin', :token => post_redirect.token) - follow_redirect! - response.should render_template("user/sign") - response.body.should match(/To send your FOI request, please sign in or make a new account./) - end + it "should associate the request with the requestor, even if it is approved by an admin" do + + unregistered = without_login # This is a test for https://github.com/mysociety/alaveteli/issues/446 - create_request_unregistered + unregistered.creates_request_unregistered post_redirect = PostRedirect.get_last_post_redirect # Now log in as an unconfirmed user. - post "/profile/sign_in", :user_signin => {:email => users(:unconfirmed_user).email, :password => "jonespassword"}, :token => post_redirect.token + unregistered.post "/profile/sign_in", :user_signin => {:email => users(:unconfirmed_user).email, :password => "jonespassword"}, :token => post_redirect.token # This will trigger a confirmation mail. Get the PostRedirect for later. - response.should render_template("user/confirm") + unregistered.response.body.should match('Now check your email!') post_redirect = PostRedirect.get_last_post_redirect + # Now log in as an admin user, then follow the confirmation link in the email that was sent to the unconfirmed user - admin_user = users(:admin_user) - admin_user.email_confirmed = true - admin_user.save! - post_via_redirect "/profile/sign_in", :user_signin => {:email => admin_user.email, :password => "jonespassword"} - response.should be_success - get "/c/" + post_redirect.email_token - follow_redirect! - response.location.should =~ %r(/request/(.+)/new) - response.location =~ %r(/request/(.+)/new) + confirm(:admin_user) + admin = login(:admin_user) + admin.get "/c/" + post_redirect.email_token + admin.follow_redirect! + admin.response.location.should =~ %r(/request/(.+)/new) + admin.response.location =~ %r(/request/(.+)/new) url_title = $1 info_request = InfoRequest.find_by_url_title(url_title) info_request.should_not be_nil # Make sure the request is still owned by the user who made it, not the admin who confirmed it info_request.user_id.should == users(:unconfirmed_user).id + end end diff --git a/spec/integration/download_request_spec.rb b/spec/integration/download_request_spec.rb new file mode 100644 index 000000000..638198cde --- /dev/null +++ b/spec/integration/download_request_spec.rb @@ -0,0 +1,324 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require File.expand_path(File.dirname(__FILE__) + '/alaveteli_dsl') + +describe 'when making a zipfile available' do + + after do + FileUtils.rm_rf(InfoRequest.download_zip_dir) + end + + def inspect_zip_download(session, info_request) + session.get_via_redirect "request/#{info_request.url_title}/download" + session.response.should be_success + Tempfile.open('download') do |f| + f.binmode + f.write(session.response.body) + f.flush + Zip::ZipFile::open(f.path) do |zip| + yield zip + end + end + end + + def sleep_and_receive_mail(name, info_request) + # The path of the zip file is based on the hash of the timestamp of the last request + # in the thread, so we wait for a second to make sure this one will have a different + # timestamp than the previous. + sleep 1 + receive_incoming_mail(name, info_request.incoming_email) + end + + context 'when an html to pdf converter is supplied' do + + before do + # We want to test the contents of the pdf, and we don't know whether a particular + # instance will have a working html_to_pdf tool, so just copy the HTML rendered + # to the PDF file for the purposes of checking it doesn't contain anything that + # shouldn't be there. + AlaveteliConfiguration.stub!(:html_to_pdf_command).and_return('/bin/cp') + end + + context 'when an incoming message is made "requester_only"' do + + it 'should not include the incoming message or attachments in a download of the entire request + by a non-request owner but should retain them for owner and admin' do + + # Non-owner can download zip with incoming and attachments + non_owner = login(FactoryGirl.create(:user)) + info_request = FactoryGirl.create(:info_request_with_incoming_attachments) + + inspect_zip_download(non_owner, info_request) do |zip| + zip.count.should == 3 + zip.read('correspondence.pdf').should match('hereisthetext') + end + + # Admin makes the incoming message requester only + admin = login(FactoryGirl.create(:admin_user)) + post_data = {:incoming_message => {:prominence => 'requester_only', + :prominence_reason => 'boring'}} + admin.post_via_redirect "/en/admin/incoming/update/#{info_request.incoming_messages.first.id}", post_data + admin.response.should be_success + + # Admin retains the requester only things + inspect_zip_download(admin, info_request) do |zip| + zip.count.should == 3 + zip.read('correspondence.pdf').should match('hereisthetext') + end + + # Zip for non owner is now without requester_only things + inspect_zip_download(non_owner, info_request) do |zip| + zip.count.should == 1 + correspondence_text = zip.read('correspondence.pdf') + correspondence_text.should_not match('hereisthetext') + expected_text = "This message has been hidden.\n boring" + correspondence_text.should match(expected_text) + end + + # Requester retains the requester only things + owner = login(info_request.user) + inspect_zip_download(owner, info_request) do |zip| + zip.count.should == 3 + zip.read('correspondence.pdf').should match('hereisthetext') + end + + end + + end + + context 'when an outgoing message is made "requester_only"' do + + it 'should not include the outgoing message in a download of the entire request + by a non-request owner but should retain them for owner and admin' do + + # Non-owner can download zip with outgoing + non_owner = login(FactoryGirl.create(:user)) + info_request = FactoryGirl.create(:info_request) + + inspect_zip_download(non_owner, info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.pdf').should match('Some information please') + end + + # Admin makes the incoming message requester only + admin = login(FactoryGirl.create(:admin_user)) + post_data = {:outgoing_message => {:prominence => 'requester_only', + :prominence_reason => 'boring', + :body => 'Some information please'}} + admin.post_via_redirect "/en/admin/outgoing/update/#{info_request.outgoing_messages.first.id}", post_data + admin.response.should be_success + + # Admin retains the requester only things + inspect_zip_download(admin, info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.pdf').should match('Some information please') + end + + # Zip for non owner is now without requester_only things + inspect_zip_download(non_owner, info_request) do |zip| + zip.count.should == 1 + correspondence_text = zip.read('correspondence.pdf') + correspondence_text.should_not match('Some information please') + expected_text = "This message has been hidden.\n boring" + correspondence_text.should match(expected_text) + end + + # Requester retains the requester only things + owner = login(info_request.user) + inspect_zip_download(owner, info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.pdf').should match('Some information please') + end + + end + + end + + end + + context 'when no html to pdf converter is supplied' do + + before do + AlaveteliConfiguration.stub!(:html_to_pdf_command).and_return('') + end + + it "should update the contents of the zipfile when the request changes" do + + info_request = FactoryGirl.create(:info_request_with_incoming) + request_owner = login(info_request.user) + inspect_zip_download(request_owner, info_request) do |zip| + zip.count.should == 1 # just the message + expected = 'This is a plain-text version of the Freedom of Information request "Example Title"' + zip.read('correspondence.txt').should match expected + end + + sleep_and_receive_mail('incoming-request-two-same-name.email', info_request) + + inspect_zip_download(request_owner, info_request) do |zip| + zip.count.should == 3 # the message plus two "hello-world.txt" files + zip.read('2_2_hello world.txt').should match('Second hello') + zip.read('2_3_hello world.txt').should match('First hello') + end + + sleep_and_receive_mail('incoming-request-attachment-unknown-extension.email', info_request) + + inspect_zip_download(request_owner, info_request) do |zip| + zip.count.should == 4 # the message plus two "hello-world.txt" files, and the new attachment + zip.read('3_2_hello.qwglhm').should match('This is an unusual') + end + end + + context 'when a request is "requester_only"' do + + before do + @non_owner = login(FactoryGirl.create(:user)) + @info_request = FactoryGirl.create(:info_request_with_incoming, + :prominence => 'requester_only') + @request_owner = login(@info_request.user) + @admin = login(FactoryGirl.create(:admin_user)) + end + + + it 'should allow a download of the request by the request owner and admin only' do + # Requester can access the zip + inspect_zip_download(@request_owner, @info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.txt').should match('hereisthetext') + end + # Non-owner can't + @non_owner.get_via_redirect "request/#{@info_request.url_title}/download" + @non_owner.response.code.should == '403' + # Admin can + inspect_zip_download(@admin, @info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.txt').should match('hereisthetext') + end + end + end + + context 'when a request is "hidden"' do + + it 'should not allow a download of the request by an admin only' do + @non_owner = login(FactoryGirl.create(:user)) + @info_request = FactoryGirl.create(:info_request_with_incoming, + :prominence => 'hidden') + @request_owner = login(@info_request.user) + @admin = login(FactoryGirl.create(:admin_user)) + + # Requester can't access the zip + @request_owner.get_via_redirect "request/#{@info_request.url_title}/download" + @request_owner.response.code.should == '403' + # Non-owner can't + @non_owner.get_via_redirect "request/#{@info_request.url_title}/download" + @non_owner.response.code.should == '403' + # Admin can + inspect_zip_download(@admin, @info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.txt').should match('hereisthetext') + end + end + + end + + context 'when an incoming message is made "requester_only"' do + + it 'should not include the incoming message or attachments in a download of the entire request + by a non-request owner but should retain them for owner and admin' do + + # Non-owner can download zip with outgoing + non_owner = login(FactoryGirl.create(:user)) + info_request = FactoryGirl.create(:info_request_with_incoming_attachments) + + inspect_zip_download(non_owner, info_request) do |zip| + zip.count.should == 3 + zip.read('correspondence.txt').should match('hereisthetext') + end + + # Admin makes the incoming message requester only + admin = login(FactoryGirl.create(:admin_user)) + post_data = {:incoming_message => {:prominence => 'requester_only', + :prominence_reason => 'boring'}} + admin.post_via_redirect "/en/admin/incoming/update/#{info_request.incoming_messages.first.id}", post_data + admin.response.should be_success + + # Admin retains the requester only things + inspect_zip_download(admin, info_request) do |zip| + zip.count.should == 3 + zip.read('correspondence.txt').should match('hereisthetext') + end + + # Zip for non owner is now without requester_only things + inspect_zip_download(non_owner, info_request) do |zip| + zip.count.should == 1 + correspondence_text = zip.read('correspondence.txt') + correspondence_text.should_not match('hereisthetext') + expected_text = 'This message has been hidden. boring' + correspondence_text.should match(expected_text) + end + + # Requester retains the requester only things + owner = login(info_request.user) + inspect_zip_download(owner, info_request) do |zip| + zip.count.should == 3 + zip.read('correspondence.txt').should match('hereisthetext') + end + + end + + end + + context 'when an outgoing message is made "requester_only"' do + + it 'should not include the outgoing message in a download of the entire request + by a non-request owner but should retain them for owner and admin' do + + # Non-owner can download zip with incoming and attachments + non_owner = login(FactoryGirl.create(:user)) + info_request = FactoryGirl.create(:info_request) + + inspect_zip_download(non_owner, info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.txt').should match('Some information please') + end + + # Admin makes the incoming message requester only + admin = login(FactoryGirl.create(:admin_user)) + post_data = {:outgoing_message => {:prominence => 'requester_only', + :prominence_reason => 'boring', + :body => 'Some information please'}} + admin.post_via_redirect "/en/admin/outgoing/update/#{info_request.outgoing_messages.first.id}", post_data + admin.response.should be_success + + # Admin retains the requester only things + inspect_zip_download(admin, info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.txt').should match('Some information please') + end + + # Zip for non owner is now without requester_only things + inspect_zip_download(non_owner, info_request) do |zip| + zip.count.should == 1 + correspondence_text = zip.read('correspondence.txt') + correspondence_text.should_not match('Some information please') + expected_text = 'This message has been hidden. boring' + correspondence_text.should match(expected_text) + end + + # Requester retains the requester only things + owner = login(info_request.user) + inspect_zip_download(owner, info_request) do |zip| + zip.count.should == 1 + zip.read('correspondence.txt').should match('Some information please') + end + + end + + end + + it 'should successfully make a zipfile for an external request' do + external_request = FactoryGirl.create(:external_request) + user = login(FactoryGirl.create(:user)) + inspect_zip_download(user, external_request){ |zip| zip.count.should == 1 } + end + end + +end diff --git a/spec/integration/request_controller_spec.rb b/spec/integration/request_controller_spec.rb index 9e585448b..f5de692b8 100644 --- a/spec/integration/request_controller_spec.rb +++ b/spec/integration/request_controller_spec.rb @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require File.expand_path(File.dirname(__FILE__) + '/alaveteli_dsl') describe RequestController, "when classifying an information request" do @@ -16,26 +17,22 @@ describe RequestController, "when classifying an information request" do describe 'when logged in as the requestor' do before :each do - @request_owner = @dog_request.user - visit signin_path - fill_in "Your e-mail:", :with => @request_owner.email - fill_in "Password:", :with => "jonespassword" - click_button "Sign in" + @bob = login(:bob_smith_user) end it "should send an email including the message" do - visit describe_state_message_path(:url_title => @dog_request.url_title, + @bob.visit describe_state_message_path(:url_title => @dog_request.url_title, :described_state => "requires_admin") - fill_in "Please tell us more:", :with => "Okay. I don't quite understand." - click_button "Submit status and send message" + @bob.fill_in "Please tell us more:", :with => "Okay. I don't quite understand." + @bob.click_button "Submit status and send message" - response.should contain "Thank you! We'll look into what happened and try and fix it up." + @bob.response.should contain "Thank you! We'll look into what happened and try and fix it up." deliveries = ActionMailer::Base.deliveries deliveries.size.should == 1 mail = deliveries[0] mail.body.should =~ /as needing admin/ - mail.body.should =~ /Okay. I don't quite understand./ + mail.body.should =~ /Okay. I don't quite understand./ end end end diff --git a/spec/integration/view_request_spec.rb b/spec/integration/view_request_spec.rb index 3d646cfe7..814e20fb3 100644 --- a/spec/integration/view_request_spec.rb +++ b/spec/integration/view_request_spec.rb @@ -1,23 +1,169 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require File.expand_path(File.dirname(__FILE__) + '/alaveteli_dsl') describe "When viewing requests" do - before(:each) do - load_raw_emails_data + before do + @info_request = FactoryGirl.create(:info_request) + @unregistered = without_login end it "should not make endlessly recursive JSON <link>s" do - @dog_request = info_requests(:fancy_dog_request) - get "request/#{@dog_request.url_title}?unfold=1" - response.body.should_not include("dog?unfold=1.json") - response.body.should include("dog.json?unfold=1") + @unregistered.browses_request("#{@info_request.url_title}?unfold=1") + @unregistered.response.body.should_not include("#{@info_request.url_title}?unfold=1.json") + @unregistered.response.body.should include("#{@info_request.url_title}.json?unfold=1") end it 'should not raise a routing error when making a json link for a request with an "action" querystring param' do - @dog_request = info_requests(:fancy_dog_request) - get "request/#{@dog_request.url_title}?action=add" - response.should be_success + @unregistered.browses_request("#{@info_request.url_title}?action=add") + end + + context 'when a response has prominence "normal"' do + + before do + @info_request = FactoryGirl.create(:info_request_with_incoming) + end + + it 'should show the message itself to any user' do + + # unregistered + unregistered = without_login + unregistered.browses_request(@info_request.url_title) + unregistered.response.body.should include("hereisthetext") + unregistered.response.body.should_not include("This message has been hidden.") + unregistered.response.body.should_not include("sign in</a> to view the message.") + + # requester + owner = login(@info_request.user) + owner.browses_request(@info_request.url_title) + owner.response.body.should include("hereisthetext") + owner.response.body.should_not include("This message has been hidden.") + + # admin + admin_user = login(FactoryGirl.create(:admin_user)) + admin_user.browses_request(@info_request.url_title) + admin_user.response.body.should include("hereisthetext") + admin_user.response.body.should_not include("This message has prominence \'hidden\'.") + + end + + end + + context 'when a response has prominence "hidden"' do + + before do + @info_request = FactoryGirl.create(:info_request_with_incoming) + message = @info_request.incoming_messages.first + message.prominence = 'hidden' + message.prominence_reason = 'It is too irritating.' + message.save! + end + + it 'should show a hidden notice, not the message, to an unregistered user or the requester and + the message itself to an admin ' do + + # unregistered + unregistered = without_login + unregistered.browses_request(@info_request.url_title) + unregistered.response.body.should include("This message has been hidden.") + unregistered.response.body.should include("It is too irritating.") + unregistered.response.body.should_not include("sign in</a> to view the message.") + unregistered.response.body.should_not include("hereisthetext") + + # requester + owner = login(@info_request.user) + owner.browses_request(@info_request.url_title) + owner.response.body.should include("This message has been hidden.") + owner.response.body.should include("It is too irritating") + owner.response.body.should_not include("hereisthetext") + + # admin + admin_user = login(FactoryGirl.create(:admin_user)) + admin_user.browses_request(@info_request.url_title) + admin_user.response.body.should include('hereisthetext') + admin_user.response.body.should include("This message has prominence \'hidden\'.") + admin_user.response.body.should include("It is too irritating.") + admin_user.response.body.should include("You can only see it because you are logged in as a super user.") + + end + + end + + context 'when a response has prominence "requester_only"' do + + before do + @info_request = FactoryGirl.create(:info_request_with_incoming) + message = @info_request.incoming_messages.first + message.prominence = 'requester_only' + message.prominence_reason = 'It is too irritating.' + message.save! + end + + it 'should show a hidden notice with login link to an unregistered user, and the message itself + with a hidden note to the requester or an admin' do + + # unregistered + unregistered = without_login + unregistered.browses_request(@info_request.url_title) + unregistered.response.body.should include("This message has been hidden.") + unregistered.response.body.should include("It is too irritating") + unregistered.response.body.should include("sign in</a> to view the message.") + unregistered.response.body.should_not include("hereisthetext") + + # requester + owner = login(@info_request.user) + owner.browses_request(@info_request.url_title) + owner.response.body.should include("hereisthetext") + owner.response.body.should include("This message is hidden, so that only you, the requester, can see it.") + owner.response.body.should include("It is too irritating.") + + # admin + admin_user = login(FactoryGirl.create(:admin_user)) + admin_user.browses_request(@info_request.url_title) + admin_user.response.body.should include('hereisthetext') + admin_user.response.body.should_not include("This message has been hidden.") + admin_user.response.body.should include("This message is hidden, so that only you, the requester, can see it.") + end + + end + + context 'when an outgoing message has prominence "requester_only"' do + + before do + @info_request = FactoryGirl.create(:info_request) + message = @info_request.outgoing_messages.first + message.prominence = 'requester_only' + message.prominence_reason = 'It is too irritating.' + message.save! + end + + it 'should show a hidden notice with login link to an unregistered user, and the message itself + with a hidden note to the requester or an admin' do + + # unregistered + unregistered = without_login + unregistered.browses_request(@info_request.url_title) + unregistered.response.body.should include("This message has been hidden.") + unregistered.response.body.should include("It is too irritating") + unregistered.response.body.should include("sign in</a> to view the message.") + unregistered.response.body.should_not include("Some information please") + + # requester + owner = login(@info_request.user) + owner.browses_request(@info_request.url_title) + owner.response.body.should include("Some information please") + owner.response.body.should include("This message is hidden, so that only you, the requester, can see it.") + owner.response.body.should include("It is too irritating.") + + # admin + admin_user = login(FactoryGirl.create(:admin_user)) + admin_user.browses_request(@info_request.url_title) + admin_user.response.body.should include('Some information please') + admin_user.response.body.should_not include("This message has been hidden.") + admin_user.response.body.should include("This message is hidden, so that only you, the requester, can see it.") + end + end end diff --git a/spec/lib/confidence_intervals.rb b/spec/lib/confidence_intervals.rb new file mode 100644 index 000000000..cb8717f3d --- /dev/null +++ b/spec/lib/confidence_intervals.rb @@ -0,0 +1,30 @@ +require 'confidence_intervals' + +describe "ci_bounds" do + + describe "when passed all successes" do + it "should never return a high CI above 1" do + ci = ci_bounds 16, 16, 0.01 + ci[1].should be <= 1 + end + end + + describe "when passed all failures" do + it "should never return a low CI below 0" do + ci = ci_bounds 0, 10, 0.05 + ci[0].should be >= 0 + end + end + + describe "when passed 4 out of 10 successes (with 0.05 power)" do + it "should return the correct Wilson's interval" do + # The expected results here were taken from an online + # calculator: + # http://www.vassarstats.net/prop1.html + ci = ci_bounds 7, 10, 0.05 + ci[0].should be_within(0.001).of(0.3968) + ci[1].should be_within(0.001).of(0.8922) + end + end + +end diff --git a/spec/mailers/request_mailer_spec.rb b/spec/mailers/request_mailer_spec.rb index 23806b35b..4e0765921 100644 --- a/spec/mailers/request_mailer_spec.rb +++ b/spec/mailers/request_mailer_spec.rb @@ -204,10 +204,10 @@ describe RequestMailer, "when sending reminders to requesters to classify a resp before do Time.stub!(:now).and_return(Time.utc(2007, 11, 12, 23, 59)) @mock_event = mock_model(InfoRequestEvent) - @mock_response = mock_model(IncomingMessage) + @mock_response = mock_model(IncomingMessage, :user_can_view? => true) @mock_user = mock_model(User) - @mock_request = mock_model(InfoRequest, :get_last_response_event_id => @mock_event.id, - :get_last_response => @mock_response, + @mock_request = mock_model(InfoRequest, :get_last_public_response_event_id => @mock_event.id, + :get_last_public_response => @mock_response, :user_id => 2, :url_title => 'test_title', :user => @mock_user) @@ -230,10 +230,12 @@ describe RequestMailer, "when sending reminders to requesters to classify a resp it 'should ask for all requests that are awaiting description and whose latest response is older than the number of days given and that are not the holding pen' do expected_conditions = [ "awaiting_description = ? - AND (SELECT created_at - FROM info_request_events - WHERE info_request_events.info_request_id = info_requests.id - AND info_request_events.event_type = 'response' + AND (SELECT info_request_events.created_at + FROM info_request_events, incoming_messages + WHERE info_request_events.info_request_id = info_requests.id + AND info_request_events.event_type = 'response' + AND incoming_messages.id = info_request_events.incoming_message_id + AND incoming_messages.prominence = 'normal' ORDER BY created_at desc LIMIT 1) < ? AND url_title != 'holding_pen' AND user_id IS NOT NULL".split(' ').join(' '), @@ -252,7 +254,7 @@ describe RequestMailer, "when sending reminders to requesters to classify a resp end it 'should raise an error if a request does not have a last response event id' do - @mock_request.stub!(:get_last_response_event_id).and_return(nil) + @mock_request.stub!(:get_last_public_response_event_id).and_return(nil) expected_message = "internal error, no last response while making alert new response reminder, request id #{@mock_request.id}" lambda{ send_alerts }.should raise_error(expected_message) end @@ -289,7 +291,7 @@ describe RequestMailer, "when sending reminders to requesters to classify a resp mock_sent_alert.should_receive(:info_request=).with(@mock_request) mock_sent_alert.should_receive(:user=).with(@mock_user) mock_sent_alert.should_receive(:alert_type=).with('new_response_reminder_1') - mock_sent_alert.should_receive(:info_request_event_id=).with(@mock_request.get_last_response_event_id) + mock_sent_alert.should_receive(:info_request_event_id=).with(@mock_request.get_last_public_response_event_id) mock_sent_alert.should_receive(:save!) send_alerts end diff --git a/spec/models/censor_rule_spec.rb b/spec/models/censor_rule_spec.rb index 3782cc630..5b41cc0d4 100644 --- a/spec/models/censor_rule_spec.rb +++ b/spec/models/censor_rule_spec.rb @@ -1,3 +1,20 @@ +# == Schema Information +# +# Table name: censor_rules +# +# id :integer not null, primary key +# info_request_id :integer +# user_id :integer +# public_body_id :integer +# text :text not null +# replacement :text not null +# last_edit_editor :string(255) not null +# last_edit_comment :text not null +# created_at :datetime not null +# updated_at :datetime not null +# regexp :boolean +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe CensorRule, "substituting things" do diff --git a/spec/models/foi_attachment_spec.rb b/spec/models/foi_attachment_spec.rb index 9b0115c44..882723d1e 100644 --- a/spec/models/foi_attachment_spec.rb +++ b/spec/models/foi_attachment_spec.rb @@ -1,3 +1,18 @@ +# == Schema Information +# +# Table name: foi_attachments +# +# id :integer not null, primary key +# content_type :text +# filename :text +# charset :text +# display_size :text +# url_part_number :integer +# within_rfc822_subject :text +# incoming_message_id :integer +# hexdigest :string(32) +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe FoiAttachment do diff --git a/spec/models/holiday_spec.rb b/spec/models/holiday_spec.rb index 5d3f76d24..89849abb7 100644 --- a/spec/models/holiday_spec.rb +++ b/spec/models/holiday_spec.rb @@ -1,3 +1,12 @@ +# == Schema Information +# +# Table name: holidays +# +# id :integer not null, primary key +# day :date +# description :text +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe Holiday, " when calculating due date" do diff --git a/spec/models/incoming_message_spec.rb b/spec/models/incoming_message_spec.rb index ff6a8e34e..c0a7e5340 100644 --- a/spec/models/incoming_message_spec.rb +++ b/spec/models/incoming_message_spec.rb @@ -1,6 +1,140 @@ # coding: utf-8 +# == Schema Information +# +# Table name: incoming_messages +# +# id :integer not null, primary key +# info_request_id :integer not null +# created_at :datetime not null +# updated_at :datetime not null +# raw_email_id :integer not null +# cached_attachment_text_clipped :text +# cached_main_body_text_folded :text +# cached_main_body_text_unfolded :text +# subject :text +# mail_from_domain :text +# valid_to_reply_to :boolean +# last_parsed :datetime +# mail_from :text +# sent_at :datetime +# prominence :string(255) default("normal"), not null +# prominence_reason :text +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +describe IncomingMessage, 'when validating' do + + it 'should be valid with valid prominence values' do + ['hidden', 'requester_only', 'normal'].each do |prominence| + incoming_message = IncomingMessage.new(:raw_email => RawEmail.new, + :info_request => InfoRequest.new, + :prominence => prominence) + incoming_message.valid?.should be_true + end + end + + it 'should not be valid with an invalid prominence value' do + incoming_message = IncomingMessage.new(:raw_email => RawEmail.new, + :info_request => InfoRequest.new, + :prominence => 'norman') + incoming_message.valid?.should be_false + end + +end + +describe IncomingMessage, 'when getting a response event' do + + it 'should return an event with event_type "response"' do + incoming_message = IncomingMessage.new + ['comment', 'response'].each do |event_type| + incoming_message.info_request_events << InfoRequestEvent.new(:event_type => event_type) + end + incoming_message.response_event.event_type.should == 'response' + end + +end + +describe IncomingMessage, 'when asked if a user can view it' do + + before do + @user = mock_model(User) + @info_request = mock_model(InfoRequest) + @incoming_message = IncomingMessage.new(:info_request => @info_request) + end + + context 'if the prominence is hidden' do + + before do + @incoming_message.prominence = 'hidden' + end + + it 'should return true if the user can view hidden things' do + User.stub!(:view_hidden?).with(@user).and_return(true) + @incoming_message.user_can_view?(@user).should be_true + end + + it 'should return false if the user cannot view hidden things' do + User.stub!(:view_hidden?).with(@user).and_return(false) + @incoming_message.user_can_view?(@user).should be_false + end + + end + + context 'if the prominence is requester_only' do + + before do + @incoming_message.prominence = 'requester_only' + end + + it 'should return true if the user owns the associated request' do + @info_request.stub!(:is_owning_user?).with(@user).and_return(true) + @incoming_message.user_can_view?(@user).should be_true + end + + it 'should return false if the user does not own the associated request' do + @info_request.stub!(:is_owning_user?).with(@user).and_return(false) + @incoming_message.user_can_view?(@user).should be_false + end + end + + context 'if the prominence is normal' do + + before do + @incoming_message.prominence = 'normal' + end + + it 'should return true' do + @incoming_message.user_can_view?(@user).should be_true + end + + end + +end + +describe 'when asked if it is indexed by search' do + + before do + @incoming_message = IncomingMessage.new + end + + it 'should return false if it has prominence "hidden"' do + @incoming_message.prominence = 'hidden' + @incoming_message.indexed_by_search?.should be_false + end + + it 'should return false if it has prominence "requester_only"' do + @incoming_message.prominence = 'requester_only' + @incoming_message.indexed_by_search?.should be_false + end + + it 'should return true if it has prominence "normal"' do + @incoming_message.prominence = 'normal' + @incoming_message.indexed_by_search?.should be_true + end + +end + describe IncomingMessage, " when dealing with incoming mail" do before(:each) do diff --git a/spec/models/info_request_event_spec.rb b/spec/models/info_request_event_spec.rb index eb0de8c86..53c83bd46 100644 --- a/spec/models/info_request_event_spec.rb +++ b/spec/models/info_request_event_spec.rb @@ -1,4 +1,21 @@ # coding: utf-8 +# == Schema Information +# +# Table name: info_request_events +# +# id :integer not null, primary key +# info_request_id :integer not null +# event_type :text not null +# params_yaml :text not null +# created_at :datetime not null +# described_state :string(255) +# calculated_state :string(255) +# last_described_at :datetime +# incoming_message_id :integer +# outgoing_message_id :integer +# comment_id :integer +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe InfoRequestEvent do @@ -15,6 +32,64 @@ describe InfoRequestEvent do end + describe 'when deciding if it is indexed by search' do + + before do + @comment = mock_model(Comment) + @incoming_message = mock_model(IncomingMessage) + @outgoing_message = mock_model(OutgoingMessage) + @info_request = mock_model(InfoRequest, :indexed_by_search? => true) + end + + it 'should return false for a comment that is not visible' do + @comment.stub!(:visible).and_return(false) + @info_request_event = InfoRequestEvent.new(:event_type => 'comment', + :comment => @comment, + :info_request => @info_request) + @info_request_event.indexed_by_search?.should be_false + end + + it 'should return true for a comment that is visible' do + @comment.stub!(:visible).and_return(true) + @info_request_event = InfoRequestEvent.new(:event_type => 'comment', + :comment => @comment, + :info_request => @info_request) + @info_request_event.indexed_by_search?.should be_true + end + + it 'should return false for an incoming message that is not indexed by search' do + @incoming_message.stub!(:indexed_by_search?).and_return false + @info_request_event = InfoRequestEvent.new(:event_type => 'response', + :incoming_message => @incoming_message, + :info_request => @info_request) + @info_request_event.indexed_by_search?.should be_false + end + + it 'should return true for an incoming message that is indexed by search' do + @incoming_message.stub!(:indexed_by_search?).and_return true + @info_request_event = InfoRequestEvent.new(:event_type => 'response', + :incoming_message => @incoming_message, + :info_request => @info_request) + @info_request_event.indexed_by_search?.should be_true + end + + it 'should return false for an outgoing message that is not indexed by search' do + @outgoing_message.stub!(:indexed_by_search?).and_return false + @info_request_event = InfoRequestEvent.new(:event_type => 'followup_sent', + :outgoing_message => @outgoing_message, + :info_request => @info_request) + @info_request_event.indexed_by_search?.should be_false + end + + it 'should return true for an outgoing message that is indexed by search' do + @outgoing_message.stub!(:indexed_by_search?).and_return true + @info_request_event = InfoRequestEvent.new(:event_type => 'followup_sent', + :outgoing_message => @outgoing_message, + :info_request => @info_request) + @info_request_event.indexed_by_search?.should be_true + end + end + describe 'after saving' do it 'should mark the model for reindexing in xapian if there is no no_xapian_reindex flag on the object' do diff --git a/spec/models/info_request_spec.rb b/spec/models/info_request_spec.rb index 5b9460ae7..7281b74b6 100644 --- a/spec/models/info_request_spec.rb +++ b/spec/models/info_request_spec.rb @@ -1,7 +1,53 @@ +# encoding: utf-8 +# == Schema Information +# +# Table name: info_requests +# +# id :integer not null, primary key +# title :text not null +# user_id :integer +# public_body_id :integer not null +# created_at :datetime not null +# updated_at :datetime not null +# described_state :string(255) not null +# awaiting_description :boolean default(FALSE), not null +# prominence :string(255) default("normal"), not null +# url_title :text not null +# law_used :string(255) default("foi"), not null +# allow_new_responses_from :string(255) default("anybody"), not null +# handle_rejected_responses :string(255) default("bounce"), not null +# idhash :string(255) not null +# external_user_name :string(255) +# external_url :string(255) +# attention_requested :boolean default(FALSE) +# comments_allowed :boolean default(TRUE), not null +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe InfoRequest do + describe 'when validating', :focus => true do + + it 'should accept a summary with ascii characters' do + info_request = InfoRequest.new(:title => 'abcde') + info_request.valid? + info_request.errors[:title].should be_empty + end + + it 'should accept a summary with unicode characters' do + info_request = InfoRequest.new(:title => 'кажете') + info_request.valid? + info_request.errors[:title].should be_empty + end + + it 'should not accept a summary with no ascii or unicode characters' do + info_request = InfoRequest.new(:title => '55555') + info_request.valid? + info_request.errors[:title].should_not be_empty + end + end + describe 'when generating a user name slug' do before do @@ -376,10 +422,12 @@ describe InfoRequest do it 'should add extra conditions if supplied' do expected_conditions = ["awaiting_description = ? - AND (SELECT created_at - FROM info_request_events + AND (SELECT info_request_events.created_at + FROM info_request_events, incoming_messages WHERE info_request_events.info_request_id = info_requests.id AND info_request_events.event_type = 'response' + AND incoming_messages.id = info_request_events.incoming_message_id + AND incoming_messages.prominence = 'normal' ORDER BY created_at desc LIMIT 1) < ? AND url_title != 'holding_pen' AND user_id IS NOT NULL @@ -394,21 +442,25 @@ describe InfoRequest do InfoRequest.find_old_unclassified({:conditions => ["prominence != 'backpage'"]}) end - it 'should ask the database for requests that are awaiting description, have a last response older + it 'should ask the database for requests that are awaiting description, have a last public response older than 21 days old, have a user, are not the holding pen and are not backpaged' do expected_conditions = ["awaiting_description = ? - AND (SELECT created_at - FROM info_request_events + AND (SELECT info_request_events.created_at + FROM info_request_events, incoming_messages WHERE info_request_events.info_request_id = info_requests.id AND info_request_events.event_type = 'response' + AND incoming_messages.id = info_request_events.incoming_message_id + AND incoming_messages.prominence = 'normal' ORDER BY created_at desc LIMIT 1) < ? AND url_title != 'holding_pen' AND user_id IS NOT NULL".split(' ').join(' '), true, Time.now - 21.days] - expected_select = "*, (SELECT created_at - FROM info_request_events + expected_select = "*, (SELECT info_request_events.created_at + FROM info_request_events, incoming_messages WHERE info_request_events.info_request_id = info_requests.id AND info_request_events.event_type = 'response' + AND incoming_messages.id = info_request_events.incoming_message_id + AND incoming_messages.prominence = 'normal' ORDER BY created_at desc LIMIT 1) AS last_response_time".split(' ').join(' ') InfoRequest.should_receive(:find) do |all, query_params| @@ -464,8 +516,14 @@ describe InfoRequest do before do Time.stub!(:now).and_return(Time.utc(2007, 11, 9, 23, 59)) - @mock_comment_event = mock_model(InfoRequestEvent, :created_at => Time.now - 23.days, :event_type => 'comment', :response? => false) - @mock_response_event = mock_model(InfoRequestEvent, :created_at => Time.now - 22.days, :event_type => 'response', :response? => true) + @mock_comment_event = mock_model(InfoRequestEvent, :created_at => Time.now - 23.days, + :event_type => 'comment', + :response? => false) + mock_incoming_message = mock_model(IncomingMessage, :all_can_view? => true) + @mock_response_event = mock_model(InfoRequestEvent, :created_at => Time.now - 22.days, + :event_type => 'response', + :response? => true, + :incoming_message => mock_incoming_message) @info_request = InfoRequest.new(:prominence => 'normal', :awaiting_description => true, :info_request_events => [@mock_response_event, @mock_comment_event]) @@ -602,6 +660,96 @@ describe InfoRequest do end end + describe 'when asked for the last public response event' do + + before do + @info_request = FactoryGirl.create(:info_request_with_incoming) + @incoming_message = @info_request.incoming_messages.first + end + + it 'should not return an event with a hidden prominence message' do + @incoming_message.prominence = 'hidden' + @incoming_message.save! + @info_request.get_last_public_response_event.should == nil + end + + it 'should not return an event with a requester_only prominence message' do + @incoming_message.prominence = 'requester_only' + @incoming_message.save! + @info_request.get_last_public_response_event.should == nil + end + + it 'should return an event with a normal prominence message' do + @incoming_message.prominence = 'normal' + @incoming_message.save! + @info_request.get_last_public_response_event.should == @incoming_message.response_event + end + end + + describe 'when asked for the last public outgoing event' do + + before do + @info_request = FactoryGirl.create(:info_request) + @outgoing_message = @info_request.outgoing_messages.first + end + + it 'should not return an event with a hidden prominence message' do + @outgoing_message.prominence = 'hidden' + @outgoing_message.save! + @info_request.get_last_public_outgoing_event.should == nil + end + + it 'should not return an event with a requester_only prominence message' do + @outgoing_message.prominence = 'requester_only' + @outgoing_message.save! + @info_request.get_last_public_outgoing_event.should == nil + end + + it 'should return an event with a normal prominence message' do + @outgoing_message.prominence = 'normal' + @outgoing_message.save! + @info_request.get_last_public_outgoing_event.should == @outgoing_message.info_request_events.first + end + + end + + describe 'when asked who can be sent a followup' do + + before do + @info_request = FactoryGirl.create(:info_request_with_plain_incoming) + @incoming_message = @info_request.incoming_messages.first + @public_body = @info_request.public_body + end + + it 'should not include details from a hidden prominence response' do + @incoming_message.prominence = 'hidden' + @incoming_message.save! + @info_request.who_can_followup_to.should == [[@public_body.name, + @public_body.request_email, + nil]] + end + + it 'should not include details from a requester_only prominence response' do + @incoming_message.prominence = 'requester_only' + @incoming_message.save! + @info_request.who_can_followup_to.should == [[@public_body.name, + @public_body.request_email, + nil]] + end + + it 'should include details from a normal prominence response' do + @incoming_message.prominence = 'normal' + @incoming_message.save! + @info_request.who_can_followup_to.should == [[@public_body.name, + @public_body.request_email, + nil], + ['Bob Responder', + "bob@example.com", + @incoming_message.id]] + end + + end + describe 'when generating json for the api' do before do @@ -894,4 +1042,75 @@ describe InfoRequest do end end end + + describe 'when saving an info_request' do + + before do + @info_request = InfoRequest.new(:external_url => 'http://www.example.com', + :external_user_name => 'Example User', + :title => 'Some request or other', + :public_body => public_bodies(:geraldine_public_body)) + end + + it "should call purge_in_cache and update_counter_cache" do + @info_request.should_receive(:purge_in_cache) + # Twice - once for save, once for destroy: + @info_request.should_receive(:update_counter_cache).twice + @info_request.save! + @info_request.destroy + end + + end + + describe 'when destroying an info_request' do + + before do + @info_request = InfoRequest.new(:external_url => 'http://www.example.com', + :external_user_name => 'Example User', + :title => 'Some request or other', + :public_body => public_bodies(:geraldine_public_body)) + end + + it "should call update_counter_cache" do + @info_request.save! + @info_request.should_receive(:update_counter_cache) + @info_request.destroy + end + + end + + describe 'when changing a described_state' do + + it "should change the counts on its PublicBody without saving a new version" do + pb = public_bodies(:geraldine_public_body) + old_version_count = pb.versions.count + old_successful_count = pb.info_requests_successful_count + old_not_held_count = pb.info_requests_not_held_count + ir = InfoRequest.new(:external_url => 'http://www.example.com', + :external_user_name => 'Example User', + :title => 'Some request or other', + :described_state => 'partially_successful', + :public_body => pb) + ir.save! + pb.info_requests_successful_count.should == (old_successful_count + 1) + ir.described_state = 'not_held' + ir.save! + pb.reload + pb.info_requests_successful_count.should == old_successful_count + pb.info_requests_not_held_count.should == (old_not_held_count + 1) + ir.described_state = 'successful' + ir.save! + pb.reload + pb.info_requests_successful_count.should == (old_successful_count + 1) + pb.info_requests_not_held_count.should == old_not_held_count + ir.destroy + pb.reload + pb.info_requests_successful_count.should == old_successful_count + pb.info_requests_successful_count.should == old_not_held_count + pb.versions.count.should == old_version_count + end + + end + + end diff --git a/spec/models/mail_server_log_spec.rb b/spec/models/mail_server_log_spec.rb index 2b44a4559..67709b130 100644 --- a/spec/models/mail_server_log_spec.rb +++ b/spec/models/mail_server_log_spec.rb @@ -1,3 +1,16 @@ +# == Schema Information +# +# Table name: mail_server_logs +# +# id :integer not null, primary key +# mail_server_log_done_id :integer +# info_request_id :integer +# order :integer not null +# line :text not null +# created_at :datetime not null +# updated_at :datetime not null +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe MailServerLog do diff --git a/spec/models/outgoing_message_spec.rb b/spec/models/outgoing_message_spec.rb index 60164fb31..1e05e09f1 100644 --- a/spec/models/outgoing_message_spec.rb +++ b/spec/models/outgoing_message_spec.rb @@ -1,3 +1,19 @@ +# == Schema Information +# +# Table name: outgoing_messages +# +# id :integer not null, primary key +# info_request_id :integer not null +# body :text not null +# status :string(255) not null +# message_type :string(255) not null +# created_at :datetime not null +# updated_at :datetime not null +# last_sent_at :datetime +# incoming_message_followup_id :integer +# what_doing :string(255) not null +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe OutgoingMessage, " when making an outgoing message" do @@ -50,6 +66,81 @@ describe OutgoingMessage, " when making an outgoing message" do outgoing_message.body.should include(expected_text) end + describe 'when asked if a user can view it' do + + before do + @info_request = FactoryGirl.create(:info_request) + @outgoing_message = @info_request.outgoing_messages.first + end + + context 'if the prominence is hidden' do + + before do + @outgoing_message.prominence = 'hidden' + end + + it 'should return true for an admin user' do + @outgoing_message.user_can_view?(FactoryGirl.create(:admin_user)).should be_true + end + + it 'should return false for a non-admin user' do + @outgoing_message.user_can_view?(FactoryGirl.create(:user)).should be_false + end + + end + + context 'if the prominence is requester_only' do + + before do + @outgoing_message.prominence = 'requester_only' + end + + it 'should return true if the user owns the associated request' do + @outgoing_message.user_can_view?(@info_request.user).should be_true + end + + it 'should return false if the user does not own the associated request' do + @outgoing_message.user_can_view?(FactoryGirl.create(:user)).should be_false + end + end + + context 'if the prominence is normal' do + + before do + @outgoing_message.prominence = 'normal' + end + + it 'should return true for a non-admin user' do + @outgoing_message.user_can_view?(FactoryGirl.create(:user)).should be_true + end + + end + + end + + describe 'when asked if it is indexed by search' do + + before do + @info_request = FactoryGirl.create(:info_request) + @outgoing_message = @info_request.outgoing_messages.first + end + + it 'should return false if it has prominence "hidden"' do + @outgoing_message.prominence = 'hidden' + @outgoing_message.indexed_by_search?.should be_false + end + + it 'should return false if it has prominence "requester_only"' do + @outgoing_message.prominence = 'requester_only' + @outgoing_message.indexed_by_search?.should be_false + end + + it 'should return true if it has prominence "normal"' do + @outgoing_message.prominence = 'normal' + @outgoing_message.indexed_by_search?.should be_true + end + + end end @@ -72,5 +163,3 @@ describe IncomingMessage, " when censoring data" do @om.body.should match(/fancy cat/) end end - - diff --git a/spec/models/post_redirect_spec.rb b/spec/models/post_redirect_spec.rb index 5f51b6de5..73740e914 100644 --- a/spec/models/post_redirect_spec.rb +++ b/spec/models/post_redirect_spec.rb @@ -1,3 +1,19 @@ +# == Schema Information +# +# Table name: post_redirects +# +# id :integer not null, primary key +# token :text not null +# uri :text not null +# post_params_yaml :text +# created_at :datetime not null +# updated_at :datetime not null +# email_token :text not null +# reason_params_yaml :text +# user_id :integer +# circumstance :text default("normal"), not null +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe PostRedirect, " when constructing" do diff --git a/spec/models/profile_photo_spec.rb b/spec/models/profile_photo_spec.rb index 892cccd08..0e157e2c5 100644 --- a/spec/models/profile_photo_spec.rb +++ b/spec/models/profile_photo_spec.rb @@ -1,3 +1,13 @@ +# == Schema Information +# +# Table name: profile_photos +# +# id :integer not null, primary key +# data :binary not null +# user_id :integer +# draft :boolean default(FALSE), not null +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe ProfilePhoto, "when constructing a new photo" do diff --git a/spec/models/public_body_spec.rb b/spec/models/public_body_spec.rb index 90affaaaa..582f1430e 100644 --- a/spec/models/public_body_spec.rb +++ b/spec/models/public_body_spec.rb @@ -1,4 +1,27 @@ # encoding: UTF-8 +# == Schema Information +# +# Table name: public_bodies +# +# id :integer not null, primary key +# name :text not null +# short_name :text not null +# request_email :text not null +# version :integer not null +# last_edit_editor :string(255) not null +# last_edit_comment :text not null +# created_at :datetime not null +# updated_at :datetime not null +# url_name :text not null +# home_page :text default(""), not null +# notes :text default(""), not null +# first_letter :string(255) not null +# publication_scheme :text default(""), not null +# api_key :string(255) not null +# info_requests_count :integer default(0), not null +# disclosure_log :text default(""), not null +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe PublicBody, " using tags" do @@ -136,36 +159,32 @@ describe PublicBody, " when saving" do @public_body = PublicBody.new end + def set_default_attributes(public_body) + public_body.name = "Testing Public Body" + public_body.short_name = "TPB" + public_body.request_email = "request@localhost" + public_body.last_edit_editor = "*test*" + public_body.last_edit_comment = "This is a test" + end + it "should not be valid without setting some parameters" do @public_body.should_not be_valid end it "should not be valid with misformatted request email" do - @public_body.name = "Testing Public Body" - @public_body.short_name = "TPB" + set_default_attributes(@public_body) @public_body.request_email = "requestBOOlocalhost" - @public_body.last_edit_editor = "*test*" - @public_body.last_edit_comment = "This is a test" @public_body.should_not be_valid @public_body.should have(1).errors_on(:request_email) end it "should save" do - @public_body.name = "Testing Public Body" - @public_body.short_name = "TPB" - @public_body.request_email = "request@localhost" - @public_body.last_edit_editor = "*test*" - @public_body.last_edit_comment = "This is a test" + set_default_attributes(@public_body) @public_body.save! end it "should update first_letter" do - @public_body.name = "Testing Public Body" - @public_body.short_name = "TPB" - @public_body.request_email = "request@localhost" - @public_body.last_edit_editor = "*test*" - @public_body.last_edit_comment = "This is a test" - + set_default_attributes(@public_body) @public_body.first_letter.should be_nil @public_body.save! @public_body.first_letter.should == 'T' @@ -178,6 +197,26 @@ describe PublicBody, " when saving" do public_body.name.should == "Mark's Public Body" end + + it 'should not create a new version when nothing has changed' do + @public_body.versions.size.should == 0 + set_default_attributes(@public_body) + @public_body.save! + @public_body.versions.size.should == 1 + @public_body.save! + @public_body.versions.size.should == 1 + end + + it 'should create a new version if something has changed' do + @public_body.versions.size.should == 0 + set_default_attributes(@public_body) + @public_body.save! + @public_body.versions.size.should == 1 + @public_body.name = 'Test' + @public_body.save! + @public_body.versions.size.should == 2 + end + end describe PublicBody, "when searching" do diff --git a/spec/models/purge_request_spec.rb b/spec/models/purge_request_spec.rb index 7b67fca52..02b3d685d 100644 --- a/spec/models/purge_request_spec.rb +++ b/spec/models/purge_request_spec.rb @@ -1,3 +1,14 @@ +# == Schema Information +# +# Table name: purge_requests +# +# id :integer not null, primary key +# url :string(255) +# created_at :datetime not null +# model :string(255) not null +# model_id :integer not null +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') require 'fakeweb' diff --git a/spec/models/raw_email_spec.rb b/spec/models/raw_email_spec.rb index ff2830a62..f86b35e99 100644 --- a/spec/models/raw_email_spec.rb +++ b/spec/models/raw_email_spec.rb @@ -1,3 +1,10 @@ +# == Schema Information +# +# Table name: raw_emails +# +# id :integer not null, primary key +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe User, "manipulating a raw email" do diff --git a/spec/models/track_thing_spec.rb b/spec/models/track_thing_spec.rb index c42eb5e8b..86d3c0cda 100644 --- a/spec/models/track_thing_spec.rb +++ b/spec/models/track_thing_spec.rb @@ -1,3 +1,19 @@ +# == Schema Information +# +# Table name: track_things +# +# id :integer not null, primary key +# tracking_user_id :integer not null +# track_query :string(255) not null +# info_request_id :integer +# tracked_user_id :integer +# public_body_id :integer +# track_medium :string(255) not null +# track_type :string(255) default("internal_error"), not null +# created_at :datetime +# updated_at :datetime +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe TrackThing, "when tracking changes" do diff --git a/spec/models/track_things_sent_email_spec.rb b/spec/models/track_things_sent_email_spec.rb index 6166f42ab..4675d0847 100644 --- a/spec/models/track_things_sent_email_spec.rb +++ b/spec/models/track_things_sent_email_spec.rb @@ -1,3 +1,16 @@ +# == Schema Information +# +# Table name: track_things_sent_emails +# +# id :integer not null, primary key +# track_thing_id :integer not null +# info_request_event_id :integer +# user_id :integer +# public_body_id :integer +# created_at :datetime +# updated_at :datetime +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe TrackThingsSentEmail, "when tracking things sent email" do diff --git a/spec/models/user_info_request_sent_alert_spec.rb b/spec/models/user_info_request_sent_alert_spec.rb index 971c5b8c1..69be1092b 100644 --- a/spec/models/user_info_request_sent_alert_spec.rb +++ b/spec/models/user_info_request_sent_alert_spec.rb @@ -1,3 +1,14 @@ +# == Schema Information +# +# Table name: user_info_request_sent_alerts +# +# id :integer not null, primary key +# user_id :integer not null +# info_request_id :integer not null +# alert_type :string(255) not null +# info_request_event_id :integer +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe UserInfoRequestSentAlert, " when blah" do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 96c169604..f380f6f13 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1,3 +1,29 @@ +# == Schema Information +# +# Table name: users +# +# id :integer not null, primary key +# email :string(255) not null +# name :string(255) not null +# hashed_password :string(255) not null +# salt :string(255) not null +# created_at :datetime not null +# updated_at :datetime not null +# email_confirmed :boolean default(FALSE), not null +# url_name :text not null +# last_daily_track_email :datetime default(2000-01-01 00:00:00 UTC) +# admin_level :string(255) default("none"), not null +# ban_text :text default(""), not null +# about_me :text default(""), not null +# locale :string(255) +# email_bounced_at :datetime +# email_bounce_message :text default(""), not null +# no_limit :boolean default(FALSE), not null +# receive_email_alerts :boolean default(TRUE), not null +# address :string(255) +# dob :date +# + require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe User, "making up the URL name" do diff --git a/spec/models/xapian_spec.rb b/spec/models/xapian_spec.rb index 7aab9cdc6..c7c21e3a0 100644 --- a/spec/models/xapian_spec.rb +++ b/spec/models/xapian_spec.rb @@ -400,3 +400,34 @@ describe ActsAsXapian::Search, "#words_to_highlight" do end end + +describe InfoRequestEvent, " when faced with a race condition during xapian_mark_needs_index" do + + before(:each) do + load_raw_emails_data + get_fixtures_xapian_index + # Use the before create job hook to simulate a race condition with another process + # by creating an acts_as_xapian_job record for the same model + class InfoRequestEvent + def xapian_before_create_job_hook(action, model, model_id) + ActsAsXapian::ActsAsXapianJob.create!(:model => model, + :model_id => model_id, + :action => action) + end + end + end + + after(:each) do + # Reset the before create job hook + class InfoRequestEvent + def xapian_before_create_job_hook(action, model, model_id) + end + end + end + + it 'should not raise an error but should fail silently' do + ir = info_requests(:naughty_chicken_request) + ir.reindex_request_events + end + +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 86ca5150a..0d8f8fac5 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -155,5 +155,7 @@ Spork.prefork do end Spork.each_run do + FactoryGirl.definition_file_paths = [ Rails.root.join('spec', 'factories') ] + FactoryGirl.reload # This code will be run each time you run your specs. end diff --git a/spec/views/request/_after_actions.html.erb_spec.rb b/spec/views/request/_after_actions.html.erb_spec.rb index ae398f4ce..833323d68 100644 --- a/spec/views/request/_after_actions.html.erb_spec.rb +++ b/spec/views/request/_after_actions.html.erb_spec.rb @@ -69,24 +69,11 @@ describe 'when displaying actions that can be taken with regard to a request' do end end - describe 'if the request is viewable by all' do - it 'should display the link to download the entire request' do - render :partial => 'request/after_actions' - response.should have_selector('div#anyone_actions') do |div| - div.should have_selector('a', :content => 'Download a zip file of all correspondence') - end - end - end - - describe 'if the request is not viewable by all' do - - it 'should not display the link to download the entire request' do - @mock_request.stub!(:all_can_view?).and_return(false) - render :partial => 'request/after_actions' - response.should have_selector('div#anyone_actions') do |div| - div.should_not have_selector('a', :content => 'Download a zip file of all correspondence') - end + it 'should display the link to download the entire request' do + render :partial => 'request/after_actions' + response.should have_selector('div#anyone_actions') do |div| + div.should have_selector('a', :content => 'Download a zip file of all correspondence') end end diff --git a/spec/views/request/show.html.erb_spec.rb b/spec/views/request/show.html.erb_spec.rb index 4578268b2..6e63b9b43 100644 --- a/spec/views/request/show.html.erb_spec.rb +++ b/spec/views/request/show.html.erb_spec.rb @@ -1,8 +1,8 @@ require File.expand_path(File.join('..', '..', '..', 'spec_helper'), __FILE__) describe 'request/show' do - - before do + + before do @mock_body = mock_model(PublicBody, :name => 'test body', :url_name => 'test_body', :is_school? => false) @@ -10,101 +10,101 @@ describe 'request/show' do :url_name => 'test_user', :profile_photo => nil) @mock_request = mock_model(InfoRequest, :title => 'test request', - :awaiting_description => false, + :awaiting_description => false, :law_used_with_a => 'A Freedom of Information request', :law_used_full => 'Freedom of Information', :public_body => @mock_body, - :user => @mock_user, - :user_name => @mock_user.name, + :user => @mock_user, + :user_name => @mock_user.name, :is_external? => false, - :calculate_status => 'waiting_response', + :calculate_status => 'waiting_response', :date_response_required_by => Date.today, :prominence => 'normal', :comments_allowed? => true, :all_can_view? => true, :url_title => 'test_request') end - + def request_page assign :info_request, @mock_request assign :info_request_events, [] assign :status, @mock_request.calculate_status render end - - describe 'when a status update has been requested' do - - before do + + describe 'when a status update has been requested' do + + before do assign :update_status, true end - + it 'should show the first form for describing the state of the request' do request_page response.should have_selector("div.describe_state_form#describe_state_form_1") - end - + end + end - - describe 'when it is awaiting a description' do - - before do + + describe 'when it is awaiting a description' do + + before do @mock_request.stub!(:awaiting_description).and_return(true) end - + it 'should show the first form for describing the state of the request' do request_page response.should have_selector("div.describe_state_form#describe_state_form_1") end - - it 'should show the second form for describing the state of the request' do + + it 'should show the second form for describing the state of the request' do request_page response.should have_selector("div.describe_state_form#describe_state_form_2") end - + end - - describe 'when the user is the request owner' do - - before do + + describe 'when the user is the request owner' do + + before do assign :is_owning_user, true end - - describe 'when the request status is "waiting clarification"' do - - before do + + describe 'when the request status is "waiting clarification"' do + + before do @mock_request.stub!(:calculate_status).and_return('waiting_clarification') end - - describe 'when there is a last response' do - + + describe 'when there is a last response' do + before do @mock_response = mock_model(IncomingMessage) - @mock_request.stub!(:get_last_response).and_return(@mock_response) + @mock_request.stub!(:get_last_public_response).and_return(@mock_response) end - - it 'should show a link to follow up the last response with clarification' do + + it 'should show a link to follow up the last response with clarification' do request_page expected_url = "/en/request/#{@mock_request.id}/response/#{@mock_response.id}#followup" response.should have_selector("a", :href => expected_url, :content => 'send a follow up message') end - + end - + describe 'when there is no last response' do - - before do - @mock_request.stub!(:get_last_response).and_return(nil) + + before do + @mock_request.stub!(:get_last_public_response).and_return(nil) end - - it 'should show a link to follow up the request without reference to a specific response' do + + it 'should show a link to follow up the request without reference to a specific response' do request_page expected_url = "/en/request/#{@mock_request.id}/response#followup" response.should have_selector("a", :href => expected_url, :content => 'send a follow up message') end end end - + end end diff --git a/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb b/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb index f2cd1075c..fcf7a778d 100644 --- a/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb +++ b/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb @@ -913,16 +913,11 @@ module ActsAsXapian # Used to mark changes needed by batch indexer def xapian_mark_needs_index - model = self.class.base_class.to_s - model_id = self.id - ActiveRecord::Base.transaction do - found = ActsAsXapianJob.delete_all([ "model = ? and model_id = ?", model, model_id]) - job = ActsAsXapianJob.new - job.model = model - job.model_id = model_id - job.action = 'update' - job.save! - end + xapian_create_job('update', self.class.base_class.to_s, self.id) + end + + def xapian_mark_needs_destroy + xapian_create_job('destroy', self.class.base_class.to_s, self.id) end # Allow reindexing to be skipped if a flag is set @@ -931,18 +926,26 @@ module ActsAsXapian xapian_mark_needs_index end - def xapian_mark_needs_destroy - model = self.class.base_class.to_s - model_id = self.id - ActiveRecord::Base.transaction do - found = ActsAsXapianJob.delete_all([ "model = ? and model_id = ?", model, model_id]) - job = ActsAsXapianJob.new - job.model = model - job.model_id = model_id - job.action = 'destroy' - job.save! + def xapian_create_job(action, model, model_id) + begin + ActiveRecord::Base.transaction do + ActsAsXapianJob.delete_all([ "model = ? and model_id = ?", model, model_id]) + xapian_before_create_job_hook(action, model, model_id) + ActsAsXapianJob.create!(:model => model, + :model_id => model_id, + :action => action) + end + rescue ActiveRecord::RecordNotUnique => e + # Given the error handling in ActsAsXapian::update_index, we can just fail silently if + # another process has inserted an acts_as_xapian_jobs record for this model. + raise unless (e.message =~ /duplicate key value violates unique constraint "index_acts_as_xapian_jobs_on_model_and_model_id"/) end end + + # A hook method that can be used in tests to simulate e.g. an external process inserting a record + def xapian_before_create_job_hook(action, model, model_id) + end + end ###################################################################### diff --git a/vendor/plugins/strip_attributes/lib/strip_attributes.rb b/vendor/plugins/strip_attributes/lib/strip_attributes.rb index bb93aa9a7..130d10185 100644 --- a/vendor/plugins/strip_attributes/lib/strip_attributes.rb +++ b/vendor/plugins/strip_attributes/lib/strip_attributes.rb @@ -8,12 +8,15 @@ module StripAttributes attribute_names.each do |attribute_name| value = record[attribute_name] if value.respond_to?(:strip) - record[attribute_name] = (value.nil?) ? nil : value.strip + stripped = value.strip + if stripped != value + record[attribute_name] = (value.nil?) ? nil : stripped + end end end end end - + # Necessary because Rails has removed the narrowing of attributes using :only # and :except on Base#attributes def self.narrow(attribute_names, options) @@ -28,7 +31,7 @@ module StripAttributes attribute_names & only else raise ArgumentError, "Options does not specify :except or :only (#{options.keys.inspect})" - end + end end end end |