social_stream-base 0.9.5 → 0.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. data/app/assets/images/mini-loading.gif +0 -0
  2. data/app/assets/javascripts/preloader.js +6 -0
  3. data/app/assets/javascripts/search.js.erb +1 -0
  4. data/app/assets/stylesheets/search.css +10 -3
  5. data/app/controllers/contacts_controller.rb +17 -9
  6. data/app/controllers/search_controller.rb +33 -33
  7. data/app/helpers/contacts_helper.rb +7 -3
  8. data/app/helpers/search_helper.rb +7 -1
  9. data/app/models/contact.rb +7 -4
  10. data/app/models/relation/single.rb +1 -1
  11. data/app/views/avatars/index.html.erb +1 -1
  12. data/app/views/search/_focus_search.html.erb +3 -2
  13. data/app/views/search/_form.html.erb +27 -5
  14. data/app/views/search/_index.html.erb +1 -1
  15. data/app/views/search/index.js.erb +25 -0
  16. data/config/locales/en.yml +7 -1
  17. data/lib/generators/social_stream/base/templates/sphinx.yml +3 -3
  18. data/lib/social_stream/base/version.rb +1 -1
  19. data/lib/social_stream/migrations/components.rb +19 -0
  20. data/lib/tasks/db/populate.rake +13 -5
  21. data/spec/controllers/comments_controller_spec.rb +1 -1
  22. data/spec/controllers/contacts_controller_spec.rb +24 -1
  23. data/spec/controllers/frontpage_controller_spec.rb +1 -1
  24. data/spec/controllers/groups_controller_spec.rb +1 -1
  25. data/spec/controllers/home_controller_spec.rb +1 -1
  26. data/spec/controllers/likes_controller_spec.rb +1 -1
  27. data/spec/controllers/notifications_controller_spec.rb +2 -2
  28. data/spec/controllers/permissions_controller_spec.rb +1 -1
  29. data/spec/controllers/posts_controller_spec.rb +1 -1
  30. data/spec/controllers/profiles_controller_spec.rb +1 -1
  31. data/spec/controllers/relation_customs_controller_spec.rb +1 -1
  32. data/spec/controllers/representations_spec.rb +1 -1
  33. data/spec/controllers/settings_controller_spec.rb +2 -2
  34. data/spec/controllers/subjects_controller.rb +1 -1
  35. data/spec/controllers/users_controller_spec.rb +1 -1
  36. data/spec/integration/navigation_spec.rb +1 -1
  37. data/spec/models/activity_authorization_spec.rb +1 -1
  38. data/spec/models/activity_spec.rb +1 -1
  39. data/spec/models/actor_spec.rb +1 -1
  40. data/spec/models/contact_spec.rb +1 -1
  41. data/spec/models/group_spec.rb +1 -1
  42. data/spec/models/like_spec.rb +1 -1
  43. data/spec/models/post_spec.rb +1 -1
  44. data/spec/models/profile_spec.rb +1 -1
  45. data/spec/models/relation_spec.rb +1 -1
  46. data/spec/models/tie_spec.rb +1 -1
  47. data/spec/models/user_spec.rb +1 -1
  48. data/vendor/assets/javascripts/jquery.validate.js +1112 -1078
  49. data/vendor/assets/javascripts/jquery.validate.old.js +1132 -0
  50. metadata +9 -5
  51. data/.travis.yml +0 -4
@@ -1,5 +1,5 @@
1
1
  module SocialStream
2
2
  module Base
3
- VERSION = "0.9.5".freeze
3
+ VERSION = "0.9.6".freeze
4
4
  end
5
5
  end
@@ -0,0 +1,19 @@
1
+ require 'social_stream/migrations/base'
2
+
3
+ module SocialStream
4
+ module Migrations
5
+ class Components < Base
6
+ def initialize
7
+ @component = find_migration("social_stream-#{ self.class.name.split('::').last.tableize }")
8
+ end
9
+
10
+ def up(options = {})
11
+ ActiveRecord::Migrator.migrate @component
12
+ end
13
+
14
+ def down(options = {})
15
+ ActiveRecord::Migrator.migrate @component, 0
16
+ end
17
+ end
18
+ end
19
+ end
@@ -11,12 +11,20 @@ namespace :db do
11
11
  task :create => :environment do
12
12
 
13
13
  LOGOS_PATH = File.join(Rails.root, 'lib', 'logos')
14
- USERS = ENV["USERS"].to_i || 9
15
- GROUPS = ENV["GROUPS"].to_i || 10
14
+ USERS = (ENV["USERS"] || 9).to_i
15
+ GROUPS = (ENV["GROUPS"] || 10).to_i
16
16
  if ENV["HARDCORE"].present?
17
17
  USERS = 999
18
18
  GROUPS = 1000
19
- end
19
+ end
20
+ if USERS < 9
21
+ USERS = 9
22
+ puts "WARNING: There should be at least 10 users (Demo user and 9 more). Changing USERS to 9."
23
+ end
24
+ if GROUPS < 10
25
+ GROUPS = 10
26
+ puts "WARNING: There should be at least 10 groups. Changing GROUPS to 10."
27
+ end
20
28
 
21
29
  Mailboxer.setup do |config|
22
30
  config.uses_emails = false
@@ -83,7 +91,7 @@ namespace :db do
83
91
 
84
92
  Group.create! :name => Forgery::Name.company_name,
85
93
  :email => Forgery::Internet.email_address,
86
- :_founder => founder.slug
94
+ :_contact_id => founder.ego_contact.id
87
95
  end
88
96
 
89
97
  set_tags(Group)
@@ -102,7 +110,7 @@ namespace :db do
102
110
  available_actors.each do |a|
103
111
  actors = available_actors.dup - Array(a)
104
112
  relations = a.relations
105
-
113
+ break if actors.size==0
106
114
  Forgery::Basic.number(:at_most => actors.size).times do
107
115
  actor = actors.delete_at((rand * actors.size).to_i)
108
116
  a.contact_to!(actor).relation_ids = Array(Forgery::Extensions::Array.new(relations).random.id)
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe CommentsController do
4
4
  include SocialStream::TestHelpers::Controllers
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe ContactsController do
4
4
 
@@ -78,4 +78,27 @@ describe ContactsController do
78
78
  map(&:id).sort.
79
79
  should == relations.map(&:id).sort
80
80
  end
81
+
82
+ context "with reflexive contact" do
83
+ before do
84
+ @contact = @user.ego_contact
85
+ end
86
+
87
+ it "should redirect edit" do
88
+ sign_in @user
89
+
90
+ get :edit, :id => @contact
91
+
92
+ response.should redirect_to(home_path)
93
+ end
94
+
95
+ it "should render update" do
96
+ sign_in @user
97
+
98
+ put :update, :id => @contact,
99
+ :contact => { "relation_ids" => [ "gotcha", @user.relations.last.id ] }
100
+
101
+ response.should redirect_to(home_path)
102
+ end
103
+ end
81
104
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe FrontpageController do
4
4
  render_views
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe GroupsController do
4
4
  include SocialStream::TestHelpers::Controllers
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe HomeController do
4
4
  include SocialStream::TestHelpers
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe LikesController do
4
4
  render_views
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
 
4
4
  describe NotificationsController do
@@ -43,4 +43,4 @@ describe NotificationsController do
43
43
  assert_response :success
44
44
  end
45
45
 
46
- end
46
+ end
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe PermissionsController do
4
4
  include SocialStream::TestHelpers::Controllers
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
 
4
4
  describe PostsController do
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe ProfilesController do
4
4
  include SocialStream::TestHelpers
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe Relation::CustomsController do
4
4
  render_views
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe HomeController do
4
4
  include ActionController::RecordIdentifier
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe SettingsController do
4
4
  include SocialStream::TestHelpers
@@ -38,4 +38,4 @@ describe SettingsController do
38
38
  @actor.notify_by_email.should==true
39
39
  end
40
40
  end
41
- end
41
+ end
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe SubjectsController do
4
4
  render_views
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe UsersController do
4
4
  render_views
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe "Navigation" do
4
4
  include Capybara
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  module ActivityTestHelper
4
4
  def create_activity(contact, relations)
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe Activity do
4
4
 
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe Actor do
4
4
  it "should generate slug" do
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe Contact do
4
4
  context "inverse" do
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe Group do
4
4
  it "should save description" do
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe Like do
4
4
 
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe Post do
4
4
  before do
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe Profile do
4
4
  context "belonging to a user" do
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe Relation do
4
4
  context "authorization" do
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe Tie do
4
4
  describe "follower_count" do
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe User do
4
4
  before do
@@ -1,1132 +1,1166 @@
1
- /*
2
- * jQuery validation plug-in pre-1.5.2
1
+ /**
2
+ * jQuery Validation Plugin 1.8.1
3
3
  *
4
4
  * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
5
5
  * http://docs.jquery.com/Plugins/Validation
6
6
  *
7
- * Copyright (c) 2006 - 2008 Jörn Zaefferer
8
- *
9
- * $Id: jquery.validate.js 6243 2009-02-19 11:40:49Z joern.zaefferer $
7
+ * Copyright (c) 2006 - 2011 Jörn Zaefferer
10
8
  *
11
9
  * Dual licensed under the MIT and GPL licenses:
12
10
  * http://www.opensource.org/licenses/mit-license.php
13
11
  * http://www.gnu.org/licenses/gpl.html
14
12
  */
15
13
 
16
- /*
17
- * This have been modified: added telephone number and emails validation
18
- */
19
-
20
14
  (function($) {
21
15
 
22
16
  $.extend($.fn, {
23
- // http://docs.jquery.com/Plugins/Validation/validate
24
- validate: function( options ) {
25
-
26
- // if nothing is selected, return nothing; can't chain anyway
27
- if (!this.length) {
28
- options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
29
- return;
30
- }
31
-
32
- // check if a validator for this form was already created
33
- var validator = $.data(this[0], 'validator');
34
- if ( validator ) {
35
- return validator;
36
- }
37
-
38
- validator = new $.validator( options, this[0] );
39
- $.data(this[0], 'validator', validator);
40
-
41
- if ( validator.settings.onsubmit ) {
42
-
43
- // allow suppresing validation by adding a cancel class to the submit button
44
- this.find("input, button").filter(".cancel").click(function() {
45
- validator.cancelSubmit = true;
46
- });
47
-
48
- // validate the form on submit
49
- this.submit( function( event ) {
50
- if ( validator.settings.debug )
51
- // prevent form submit to be able to see console output
52
- event.preventDefault();
53
-
54
- function handle() {
55
- if ( validator.settings.submitHandler ) {
56
- validator.settings.submitHandler.call( validator, validator.currentForm );
57
- return false;
58
- }
59
- return true;
60
- }
61
-
62
- // prevent submit for invalid forms or custom submit handlers
63
- if ( validator.cancelSubmit ) {
64
- validator.cancelSubmit = false;
65
- return handle();
66
- }
67
- if ( validator.form() ) {
68
- if ( validator.pendingRequest ) {
69
- validator.formSubmitted = true;
70
- return false;
71
- }
72
- return handle();
73
- } else {
74
- validator.focusInvalid();
75
- return false;
76
- }
77
- });
78
- }
79
-
80
- return validator;
81
- },
82
- // http://docs.jquery.com/Plugins/Validation/valid
83
- valid: function() {
17
+ // http://docs.jquery.com/Plugins/Validation/validate
18
+ validate: function( options ) {
19
+
20
+ // if nothing is selected, return nothing; can't chain anyway
21
+ if (!this.length) {
22
+ options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
23
+ return;
24
+ }
25
+
26
+ // check if a validator for this form was already created
27
+ var validator = $.data(this[0], 'validator');
28
+ if ( validator ) {
29
+ return validator;
30
+ }
31
+
32
+ validator = new $.validator( options, this[0] );
33
+ $.data(this[0], 'validator', validator);
34
+
35
+ if ( validator.settings.onsubmit ) {
36
+
37
+ // allow suppresing validation by adding a cancel class to the submit button
38
+ this.find("input, button").filter(".cancel").click(function() {
39
+ validator.cancelSubmit = true;
40
+ });
41
+
42
+ // when a submitHandler is used, capture the submitting button
43
+ if (validator.settings.submitHandler) {
44
+ this.find("input, button").filter(":submit").click(function() {
45
+ validator.submitButton = this;
46
+ });
47
+ }
48
+
49
+ // validate the form on submit
50
+ this.submit( function( event ) {
51
+ if ( validator.settings.debug )
52
+ // prevent form submit to be able to see console output
53
+ event.preventDefault();
54
+
55
+ function handle() {
56
+ if ( validator.settings.submitHandler ) {
57
+ if (validator.submitButton) {
58
+ // insert a hidden input as a replacement for the missing submit button
59
+ var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
60
+ }
61
+ validator.settings.submitHandler.call( validator, validator.currentForm );
62
+ if (validator.submitButton) {
63
+ // and clean up afterwards; thanks to no-block-scope, hidden can be referenced
64
+ hidden.remove();
65
+ }
66
+ return false;
67
+ }
68
+ return true;
69
+ }
70
+
71
+ // prevent submit for invalid forms or custom submit handlers
72
+ if ( validator.cancelSubmit ) {
73
+ validator.cancelSubmit = false;
74
+ return handle();
75
+ }
76
+ if ( validator.form() ) {
77
+ if ( validator.pendingRequest ) {
78
+ validator.formSubmitted = true;
79
+ return false;
80
+ }
81
+ return handle();
82
+ } else {
83
+ validator.focusInvalid();
84
+ return false;
85
+ }
86
+ });
87
+ }
88
+
89
+ return validator;
90
+ },
91
+ // http://docs.jquery.com/Plugins/Validation/valid
92
+ valid: function() {
84
93
  if ( $(this[0]).is('form')) {
85
94
  return this.validate().form();
86
95
  } else {
87
- var valid = false;
96
+ var valid = true;
88
97
  var validator = $(this[0].form).validate();
89
98
  this.each(function() {
90
- valid |= validator.element(this);
99
+ valid &= validator.element(this);
91
100
  });
92
101
  return valid;
93
102
  }
94
103
  },
95
- // attributes: space seperated list of attributes to retrieve and remove
96
- removeAttrs: function(attributes) {
97
- var result = {},
98
- $element = this;
99
- $.each(attributes.split(/\s/), function(index, value) {
100
- result[value] = $element.attr(value);
101
- $element.removeAttr(value);
102
- });
103
- return result;
104
- },
105
- // http://docs.jquery.com/Plugins/Validation/rules
106
- rules: function(command, argument) {
107
- var element = this[0];
108
-
109
- if (command) {
110
- var settings = $.data(element.form, 'validator').settings;
111
- var staticRules = settings.rules;
112
- var existingRules = $.validator.staticRules(element);
113
- switch(command) {
114
- case "add":
115
- $.extend(existingRules, $.validator.normalizeRule(argument));
116
- staticRules[element.name] = existingRules;
117
- if (argument.messages)
118
- settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
119
- break;
120
- case "remove":
121
- if (!argument) {
122
- delete staticRules[element.name];
123
- return existingRules;
124
- }
125
- var filtered = {};
126
- $.each(argument.split(/\s/), function(index, method) {
127
- filtered[method] = existingRules[method];
128
- delete existingRules[method];
129
- });
130
- return filtered;
131
- }
132
- }
133
-
134
- var data = $.validator.normalizeRules(
135
- $.extend(
136
- {},
137
- $.validator.metadataRules(element),
138
- $.validator.classRules(element),
139
- $.validator.attributeRules(element),
140
- $.validator.staticRules(element)
141
- ), element);
142
-
143
- // make sure required is at front
144
- if (data.required) {
145
- var param = data.required;
146
- delete data.required;
147
- data = $.extend({required: param}, data);
148
- }
149
-
150
- return data;
151
- }
104
+ // attributes: space seperated list of attributes to retrieve and remove
105
+ removeAttrs: function(attributes) {
106
+ var result = {},
107
+ $element = this;
108
+ $.each(attributes.split(/\s/), function(index, value) {
109
+ result[value] = $element.attr(value);
110
+ $element.removeAttr(value);
111
+ });
112
+ return result;
113
+ },
114
+ // http://docs.jquery.com/Plugins/Validation/rules
115
+ rules: function(command, argument) {
116
+ var element = this[0];
117
+
118
+ if (command) {
119
+ var settings = $.data(element.form, 'validator').settings;
120
+ var staticRules = settings.rules;
121
+ var existingRules = $.validator.staticRules(element);
122
+ switch(command) {
123
+ case "add":
124
+ $.extend(existingRules, $.validator.normalizeRule(argument));
125
+ staticRules[element.name] = existingRules;
126
+ if (argument.messages)
127
+ settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
128
+ break;
129
+ case "remove":
130
+ if (!argument) {
131
+ delete staticRules[element.name];
132
+ return existingRules;
133
+ }
134
+ var filtered = {};
135
+ $.each(argument.split(/\s/), function(index, method) {
136
+ filtered[method] = existingRules[method];
137
+ delete existingRules[method];
138
+ });
139
+ return filtered;
140
+ }
141
+ }
142
+
143
+ var data = $.validator.normalizeRules(
144
+ $.extend(
145
+ {},
146
+ $.validator.metadataRules(element),
147
+ $.validator.classRules(element),
148
+ $.validator.attributeRules(element),
149
+ $.validator.staticRules(element)
150
+ ), element);
151
+
152
+ // make sure required is at front
153
+ if (data.required) {
154
+ var param = data.required;
155
+ delete data.required;
156
+ data = $.extend({required: param}, data);
157
+ }
158
+
159
+ return data;
160
+ }
152
161
  });
153
162
 
154
163
  // Custom selectors
155
164
  $.extend($.expr[":"], {
156
- // http://docs.jquery.com/Plugins/Validation/blank
157
- blank: function(a) {return !$.trim(a.value);},
158
- // http://docs.jquery.com/Plugins/Validation/filled
159
- filled: function(a) {return !!$.trim(a.value);},
160
- // http://docs.jquery.com/Plugins/Validation/unchecked
161
- unchecked: function(a) {return !a.checked;}
165
+ // http://docs.jquery.com/Plugins/Validation/blank
166
+ blank: function(a) {return !$.trim("" + a.value);},
167
+ // http://docs.jquery.com/Plugins/Validation/filled
168
+ filled: function(a) {return !!$.trim("" + a.value);},
169
+ // http://docs.jquery.com/Plugins/Validation/unchecked
170
+ unchecked: function(a) {return !a.checked;}
162
171
  });
163
172
 
164
-
165
- $.format = function(source, params) {
166
- if ( arguments.length == 1 )
167
- return function() {
168
- var args = $.makeArray(arguments);
169
- args.unshift(source);
170
- return $.format.apply( this, args );
171
- };
172
- if ( arguments.length > 2 && params.constructor != Array ) {
173
- params = $.makeArray(arguments).slice(1);
174
- }
175
- if ( params.constructor != Array ) {
176
- params = [ params ];
177
- }
178
- $.each(params, function(i, n) {
179
- source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
180
- });
181
- return source;
182
- };
183
-
184
173
  // constructor for validator
185
174
  $.validator = function( options, form ) {
186
- this.settings = $.extend( {}, $.validator.defaults, options );
187
- this.currentForm = form;
188
- this.init();
175
+ this.settings = $.extend( true, {}, $.validator.defaults, options );
176
+ this.currentForm = form;
177
+ this.init();
178
+ };
179
+
180
+ $.validator.format = function(source, params) {
181
+ if ( arguments.length == 1 )
182
+ return function() {
183
+ var args = $.makeArray(arguments);
184
+ args.unshift(source);
185
+ return $.validator.format.apply( this, args );
186
+ };
187
+ if ( arguments.length > 2 && params.constructor != Array ) {
188
+ params = $.makeArray(arguments).slice(1);
189
+ }
190
+ if ( params.constructor != Array ) {
191
+ params = [ params ];
192
+ }
193
+ $.each(params, function(i, n) {
194
+ source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
195
+ });
196
+ return source;
189
197
  };
190
198
 
191
199
  $.extend($.validator, {
192
200
 
193
- defaults: {
194
- messages: {},
195
- groups: {},
196
- rules: {},
197
- errorClass: "validation_error",
198
- errorElement: "label",
199
- focusInvalid: true,
200
- errorContainer: $( [] ),
201
- errorLabelContainer: $( [] ),
202
- onsubmit: true,
203
- ignore: [],
204
- ignoreTitle: false,
205
- onfocusin: function(element) {
206
- this.lastActive = element;
207
-
208
- // hide error label and remove error class on focus if enabled
209
- if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
210
- this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass );
211
- this.errorsFor(element).hide();
212
- }
213
- },
214
- onfocusout: function(element) {
215
- if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
216
- this.element(element);
217
- }
218
- },
219
- onkeyup: function(element) {
220
- if ( element.name in this.submitted || element == this.lastElement ) {
221
- this.element(element);
222
- }
223
- },
224
- onclick: function(element) {
225
- if ( element.name in this.submitted )
226
- this.element(element);
227
- },
228
- highlight: function( element, errorClass ) {
229
- $( element ).addClass( errorClass );
230
- },
231
- unhighlight: function( element, errorClass ) {
232
- $( element ).removeClass( errorClass );
233
- }
234
- },
235
-
236
- // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
237
- setDefaults: function(settings) {
238
- $.extend( $.validator.defaults, settings );
239
- },
240
-
241
- messages: {
242
- required: " This field is required.",
243
- remote: " Please fix this field.",
244
- email: " Please enter a valid email address.",
245
- emails: " Please enter valid email addresses.",
246
- url: " Please enter a valid URL.",
247
- date: " Please enter a valid date.",
248
- dateISO: " Please enter a valid date (ISO).",
249
- dateDE: " Bitte geben Sie ein gültiges Datum ein.",
250
- number: " Please enter a valid number.",
251
- numberDE: " Bitte geben Sie eine Nummer ein.",
252
- digits: " Please enter only digits",
253
- phone: " Please enter a valid telephone number",
254
- creditcard: " Please enter a valid credit card number.",
255
- equalTo: " Please enter the same value again.",
256
- accept: " Please enter a value with a valid extension.",
257
- maxlength: $.format(" Please enter no more than {0} characters."),
258
- minlength: $.format(" Please enter at least {0} characters."),
259
- rangelength: $.format(" Please enter a value between {0} and {1} characters long."),
260
- range: $.format(" Please enter a value between {0} and {1}."),
261
- max: $.format(" Please enter a value less than or equal to {0}."),
262
- min: $.format(" Please enter a value greater than or equal to {0}.")
263
- },
264
-
265
- autoCreateRanges: false,
266
-
267
- prototype: {
268
-
269
- init: function() {
270
- this.labelContainer = $(this.settings.errorLabelContainer);
271
- this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
272
- this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
273
- this.submitted = {};
274
- this.valueCache = {};
275
- this.pendingRequest = 0;
276
- this.pending = {};
277
- this.invalid = {};
278
- this.reset();
279
-
280
- var groups = (this.groups = {});
281
- $.each(this.settings.groups, function(key, value) {
282
- $.each(value.split(/\s/), function(index, name) {
283
- groups[name] = key;
284
- });
285
- });
286
- var rules = this.settings.rules;
287
- $.each(rules, function(key, value) {
288
- rules[key] = $.validator.normalizeRule(value);
289
- });
290
-
291
- function delegate(event) {
292
- var validator = $.data(this[0].form, "validator");
293
- validator.settings["on" + event.type] && validator.settings["on" + event.type].call(validator, this[0] );
294
- }
295
- $(this.currentForm)
296
- .delegate("focusin focusout keyup", ":text, :password, :file, select, textarea", delegate)
297
- .delegate("click", ":radio, :checkbox", delegate);
298
-
299
- if (this.settings.invalidHandler)
300
- $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
301
- },
201
+ defaults: {
202
+ messages: {},
203
+ groups: {},
204
+ rules: {},
205
+ errorClass: "error",
206
+ validClass: "valid",
207
+ errorElement: "label",
208
+ focusInvalid: true,
209
+ errorContainer: $( [] ),
210
+ errorLabelContainer: $( [] ),
211
+ onsubmit: true,
212
+ ignore: [],
213
+ ignoreTitle: false,
214
+ onfocusin: function(element) {
215
+ this.lastActive = element;
302
216
 
303
- // http://docs.jquery.com/Plugins/Validation/Validator/form
304
- form: function() {
305
- this.checkForm();
306
- $.extend(this.submitted, this.errorMap);
307
- this.invalid = $.extend({}, this.errorMap);
308
- if (!this.valid())
309
- $(this.currentForm).triggerHandler("invalid-form", [this]);
310
- this.showErrors();
311
- return this.valid();
312
- },
313
-
314
- checkForm: function() {
315
- this.prepareForm();
316
- for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
317
- this.check( elements[i] );
318
- }
319
- return this.valid();
320
- },
321
-
322
- // http://docs.jquery.com/Plugins/Validation/Validator/element
323
- element: function( element ) {
324
- element = this.clean( element );
325
- this.lastElement = element;
326
- this.prepareElement( element );
327
- this.currentElements = $(element);
328
- var result = this.check( element );
329
- if ( result ) {
330
- delete this.invalid[element.name];
331
- } else {
332
- this.invalid[element.name] = true;
333
- }
334
- if ( !this.numberOfInvalids() ) {
335
- // Hide error containers on last error
336
- this.toHide = this.toHide.add( this.containers );
337
- }
338
- this.showErrors();
339
- return result;
340
- },
217
+ // hide error label and remove error class on focus if enabled
218
+ if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
219
+ this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
220
+ this.addWrapper(this.errorsFor(element)).hide();
221
+ }
222
+ },
223
+ onfocusout: function(element) {
224
+ if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
225
+ this.element(element);
226
+ }
227
+ },
228
+ onkeyup: function(element) {
229
+ if ( element.name in this.submitted || element == this.lastElement ) {
230
+ this.element(element);
231
+ }
232
+ },
233
+ onclick: function(element) {
234
+ // click on selects, radiobuttons and checkboxes
235
+ if ( element.name in this.submitted )
236
+ this.element(element);
237
+ // or option elements, check parent select in that case
238
+ else if (element.parentNode.name in this.submitted)
239
+ this.element(element.parentNode);
240
+ },
241
+ highlight: function(element, errorClass, validClass) {
242
+ if (element.type === 'radio') {
243
+ this.findByName(element.name).addClass(errorClass).removeClass(validClass);
244
+ } else {
245
+ $(element).addClass(errorClass).removeClass(validClass);
246
+ }
247
+ },
248
+ unhighlight: function(element, errorClass, validClass) {
249
+ if (element.type === 'radio') {
250
+ this.findByName(element.name).removeClass(errorClass).addClass(validClass);
251
+ } else {
252
+ $(element).removeClass(errorClass).addClass(validClass);
253
+ }
254
+ }
255
+ },
341
256
 
342
- // http://docs.jquery.com/Plugins/Validation/Validator/showErrors
343
- showErrors: function(errors) {
344
- if(errors) {
345
- // add items to error list and map
346
- $.extend( this.errorMap, errors );
347
- this.errorList = [];
348
- for ( var name in errors ) {
349
- this.errorList.push({
350
- message: errors[name],
351
- element: this.findByName(name)[0]
352
- });
353
- }
354
- // remove items from success list
355
- this.successList = $.grep( this.successList, function(element) {
356
- return !(element.name in errors);
357
- });
358
- }
359
- this.settings.showErrors
360
- ? this.settings.showErrors.call( this, this.errorMap, this.errorList )
361
- : this.defaultShowErrors();
362
- },
363
-
364
- // http://docs.jquery.com/Plugins/Validation/Validator/resetForm
365
- resetForm: function() {
366
- if ( $.fn.resetForm )
367
- $( this.currentForm ).resetForm();
368
- this.submitted = {};
369
- this.prepareForm();
370
- this.hideErrors();
371
- this.elements().removeClass( this.settings.errorClass );
372
- },
373
-
374
- numberOfInvalids: function() {
375
- return this.objectLength(this.invalid);
376
- },
377
-
378
- objectLength: function( obj ) {
379
- var count = 0;
380
- for ( var i in obj )
381
- count++;
382
- return count;
383
- },
384
-
385
- hideErrors: function() {
386
- this.addWrapper( this.toHide ).hide();
387
- },
388
-
389
- valid: function() {
390
- return this.size() == 0;
391
- },
392
-
393
- size: function() {
394
- return this.errorList.length;
395
- },
396
-
397
- focusInvalid: function() {
398
- if( this.settings.focusInvalid ) {
399
- try {
400
- $(this.findLastActive() || this.errorList.length && this.errorList[0].element || []).filter(":visible").focus();
401
- } catch(e) {
402
- // ignore IE throwing errors when focusing hidden elements
403
- }
404
- }
405
- },
406
-
407
- findLastActive: function() {
408
- var lastActive = this.lastActive;
409
- return lastActive && $.grep(this.errorList, function(n) {
410
- return n.element.name == lastActive.name;
411
- }).length == 1 && lastActive;
412
- },
413
-
414
- elements: function() {
415
- var validator = this,
416
- rulesCache = {};
417
-
418
- // select all valid inputs inside the form (no submit or reset buttons)
419
- // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
420
- return $([]).add(this.currentForm.elements)
421
- .filter(":input")
422
- .not(":submit, :reset, :image, [disabled]")
423
- .not( this.settings.ignore )
424
- .filter(function() {
425
- !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
426
-
427
- // select only the first element for each name, and only those with rules specified
428
- if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
429
- return false;
430
-
431
- rulesCache[this.name] = true;
432
- return true;
433
- });
434
- },
435
-
436
- clean: function( selector ) {
437
- return $( selector )[0];
438
- },
439
-
440
- errors: function() {
441
- return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
442
- },
443
-
444
- reset: function() {
445
- this.successList = [];
446
- this.errorList = [];
447
- this.errorMap = {};
448
- this.toShow = $([]);
449
- this.toHide = $([]);
450
- this.formSubmitted = false;
451
- this.currentElements = $([]);
452
- },
453
-
454
- prepareForm: function() {
455
- this.reset();
456
- this.toHide = this.errors().add( this.containers );
457
- },
458
-
459
- prepareElement: function( element ) {
460
- this.reset();
461
- this.toHide = this.errorsFor(element);
462
- },
463
-
464
- check: function( element ) {
465
- element = this.clean( element );
466
-
467
- // if radio/checkbox, validate first element in group instead
468
- if (this.checkable(element)) {
469
- element = this.findByName( element.name )[0];
470
- }
471
-
472
- var rules = $(element).rules();
473
- var dependencyMismatch = false;
474
- for( method in rules ) {
475
- var rule = { method: method, parameters: rules[method] };
476
- try {
477
- var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
478
-
479
- // if a method indicates that the field is optional and therefore valid,
480
- // don't mark it as valid when there are no other rules
481
- if ( result == "dependency-mismatch" ) {
482
- dependencyMismatch = true;
483
- continue;
484
- }
485
- dependencyMismatch = false;
486
-
487
- if ( result == "pending" ) {
488
- this.toHide = this.toHide.not( this.errorsFor(element) );
489
- return;
490
- }
491
-
492
- if( !result ) {
493
- this.formatAndAdd( element, rule );
494
- return false;
495
- }
496
- } catch(e) {
497
- this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
498
- + ", check the '" + rule.method + "' method");
499
- throw e;
500
- }
501
- }
502
- if (dependencyMismatch)
503
- return;
504
- if ( this.objectLength(rules) )
505
- this.successList.push(element);
506
- return true;
507
- },
508
-
509
- // return the custom message for the given element and validation method
510
- // specified in the element's "messages" metadata
511
- customMetaMessage: function(element, method) {
512
- if (!$.metadata)
513
- return;
514
-
515
- var meta = this.settings.meta
516
- ? $(element).metadata()[this.settings.meta]
517
- : $(element).metadata();
518
-
519
- return meta && meta.messages && meta.messages[method];
520
- },
521
-
522
- // return the custom message for the given element name and validation method
523
- customMessage: function( name, method ) {
524
- var m = this.settings.messages[name];
525
- return m && (m.constructor == String
526
- ? m
527
- : m[method]);
528
- },
529
-
530
- // return the first defined argument, allowing empty strings
531
- findDefined: function() {
532
- for(var i = 0; i < arguments.length; i++) {
533
- if (arguments[i] !== undefined)
534
- return arguments[i];
535
- }
536
- return undefined;
537
- },
538
-
539
- defaultMessage: function( element, method) {
540
- return this.findDefined(
541
- this.customMessage( element.name, method ),
542
- this.customMetaMessage( element, method ),
543
- // title is never undefined, so handle empty string as undefined
544
- !this.settings.ignoreTitle && element.title || undefined,
545
- $.validator.messages[method],
546
- "<strong>Warning: No message defined for " + element.name + "</strong>"
547
- );
548
- },
549
-
550
- formatAndAdd: function( element, rule ) {
551
- var message = this.defaultMessage( element, rule.method );
552
- if ( typeof message == "function" )
553
- message = message.call(this, rule.parameters, element);
554
- this.errorList.push({
555
- message: message,
556
- element: element
557
- });
558
- this.errorMap[element.name] = message;
559
- this.submitted[element.name] = message;
560
- },
561
-
562
- addWrapper: function(toToggle) {
563
- if ( this.settings.wrapper )
564
- toToggle = toToggle.add( toToggle.parents( this.settings.wrapper ) );
565
- return toToggle;
566
- },
567
-
568
- defaultShowErrors: function() {
569
- for ( var i = 0; this.errorList[i]; i++ ) {
570
- var error = this.errorList[i];
571
- this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass );
572
- this.showLabel( error.element, error.message );
573
- }
574
- if( this.errorList.length ) {
575
- this.toShow = this.toShow.add( this.containers );
576
- }
577
- if (this.settings.success) {
578
- for ( var i = 0; this.successList[i]; i++ ) {
579
- this.showLabel( this.successList[i] );
580
- }
581
- }
582
- if (this.settings.unhighlight) {
583
- for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
584
- this.settings.unhighlight.call( this, elements[i], this.settings.errorClass );
585
- }
586
- }
587
- this.toHide = this.toHide.not( this.toShow );
588
- this.hideErrors();
589
- this.addWrapper( this.toShow ).show();
590
- },
591
-
592
- validElements: function() {
593
- return this.currentElements.not(this.invalidElements());
594
- },
595
-
596
- invalidElements: function() {
597
- return $(this.errorList).map(function() {
598
- return this.element;
599
- });
600
- },
601
-
602
- showLabel: function(element, message) {
603
- var label = this.errorsFor( element );
604
- if ( label.length ) {
605
- // refresh error/success class
606
- label.removeClass().addClass( this.settings.errorClass );
607
-
608
- // check if we have a generated label, replace the message then
609
- label.attr("generated") && label.html(message);
610
- } else {
611
- // create label
612
- label = $("<" + this.settings.errorElement + "/>")
613
- .attr({"for": this.idOrName(element), generated: true})
614
- .addClass(this.settings.errorClass)
615
- .html(message || "");
616
- if ( this.settings.wrapper ) {
617
- // make sure the element is visible, even in IE
618
- // actually showing the wrapped element is handled elsewhere
619
- label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
620
- }
621
- if ( !this.labelContainer.append(label).length )
622
- this.settings.errorPlacement
623
- ? this.settings.errorPlacement(label, $(element) )
624
- : label.insertAfter(element);
625
- }
626
- if ( !message && this.settings.success ) {
627
- label.text("");
628
- typeof this.settings.success == "string"
629
- ? label.addClass( this.settings.success )
630
- : this.settings.success( label );
631
- }
632
- this.toShow = this.toShow.add(label);
633
- },
634
-
635
- errorsFor: function(element) {
636
- return this.errors().filter("[for='" + this.idOrName(element) + "']");
637
- },
638
-
639
- idOrName: function(element) {
640
- return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
641
- },
257
+ // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
258
+ setDefaults: function(settings) {
259
+ $.extend( $.validator.defaults, settings );
260
+ },
642
261
 
643
- checkable: function( element ) {
644
- return /radio|checkbox/i.test(element.type);
645
- },
646
-
647
- findByName: function( name ) {
648
- // select by name and filter by form for performance over form.find("[name=...]")
649
- var form = this.currentForm;
650
- return $(document.getElementsByName(name)).map(function(index, element) {
651
- return element.form == form && element.name == name && element || null;
652
- });
653
- },
654
-
655
- getLength: function(value, element) {
656
- switch( element.nodeName.toLowerCase() ) {
657
- case 'select':
658
- return $("option:selected", element).length;
659
- case 'input':
660
- if( this.checkable( element) )
661
- return this.findByName(element.name).filter(':checked').length;
662
- }
663
- return value.length;
664
- },
665
-
666
- depend: function(param, element) {
667
- return this.dependTypes[typeof param]
668
- ? this.dependTypes[typeof param](param, element)
669
- : true;
670
- },
671
-
672
- dependTypes: {
673
- "boolean": function(param, element) {
674
- return param;
675
- },
676
- "string": function(param, element) {
677
- return !!$(param, element.form).length;
678
- },
679
- "function": function(param, element) {
680
- return param(element);
681
- }
682
- },
683
-
684
- optional: function(element) {
685
- return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
686
- },
687
-
688
- startRequest: function(element) {
689
- if (!this.pending[element.name]) {
690
- this.pendingRequest++;
691
- this.pending[element.name] = true;
692
- }
693
- },
694
-
695
- stopRequest: function(element, valid) {
696
- this.pendingRequest--;
697
- // sometimes synchronization fails, make sure pendingRequest is never < 0
698
- if (this.pendingRequest < 0)
699
- this.pendingRequest = 0;
700
- delete this.pending[element.name];
701
- if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
702
- $(this.currentForm).submit();
703
- } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
704
- $(this.currentForm).triggerHandler("invalid-form", [this]);
705
- }
706
- },
707
-
708
- previousValue: function(element) {
709
- return $.data(element, "previousValue") || $.data(element, "previousValue", previous = {
710
- old: null,
711
- valid: true,
712
- message: this.defaultMessage( element, "remote" )
713
- });
714
- }
715
-
716
- },
717
-
718
- classRuleSettings: {
719
- required: {required: true},
720
- email: {email: true},
721
- //ADDED
722
- emails: {emails: true},
723
- url: {url: true},
724
- date: {date: true},
725
- dateISO: {dateISO: true},
726
- dateDE: {dateDE: true},
727
- number: {number: true},
728
- numberDE: {numberDE: true},
729
- digits: {digits: true},
730
- //Added
731
- phone: {phone: true},
732
- creditcard: {creditcard: true}
733
- },
734
-
735
- addClassRules: function(className, rules) {
736
- className.constructor == String ?
737
- this.classRuleSettings[className] = rules :
738
- $.extend(this.classRuleSettings, className);
739
- },
740
-
741
- classRules: function(element) {
742
- var rules = {};
743
- var classes = $(element).attr('class');
744
- classes && $.each(classes.split(' '), function() {
745
- if (this in $.validator.classRuleSettings) {
746
- $.extend(rules, $.validator.classRuleSettings[this]);
747
- }
748
- });
749
- return rules;
750
- },
751
-
752
- attributeRules: function(element) {
753
- var rules = {};
754
- var $element = $(element);
755
-
756
- for (method in $.validator.methods) {
757
- var value = $element.attr(method);
758
- if (value) {
759
- rules[method] = value;
760
- }
761
- }
762
-
763
- // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
764
- if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
765
- delete rules.maxlength;
766
- }
767
-
768
- return rules;
769
- },
770
-
771
- metadataRules: function(element) {
772
- if (!$.metadata) return {};
773
-
774
- var meta = $.data(element.form, 'validator').settings.meta;
775
- return meta ?
776
- $(element).metadata()[meta] :
777
- $(element).metadata();
778
- },
779
-
780
- staticRules: function(element) {
781
- var rules = {};
782
- var validator = $.data(element.form, 'validator');
783
- if (validator.settings.rules) {
784
- rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
785
- }
786
- return rules;
787
- },
788
-
789
- normalizeRules: function(rules, element) {
790
- // handle dependency check
791
- $.each(rules, function(prop, val) {
792
- // ignore rule when param is explicitly false, eg. required:false
793
- if (val === false) {
794
- delete rules[prop];
795
- return;
796
- }
797
- if (val.param || val.depends) {
798
- var keepRule = true;
799
- switch (typeof val.depends) {
800
- case "string":
801
- keepRule = !!$(val.depends, element.form).length;
802
- break;
803
- case "function":
804
- keepRule = val.depends.call(element, element);
805
- break;
806
- }
807
- if (keepRule) {
808
- rules[prop] = val.param !== undefined ? val.param : true;
809
- } else {
810
- delete rules[prop];
811
- }
812
- }
813
- });
814
-
815
- // evaluate parameters
816
- $.each(rules, function(rule, parameter) {
817
- rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
818
- });
819
-
820
- // clean number parameters
821
- $.each(['minlength', 'maxlength', 'min', 'max'], function() {
822
- if (rules[this]) {
823
- rules[this] = Number(rules[this]);
824
- }
825
- });
826
- $.each(['rangelength', 'range'], function() {
827
- if (rules[this]) {
828
- rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
829
- }
830
- });
831
-
832
- if ($.validator.autoCreateRanges) {
833
- // auto-create ranges
834
- if (rules.min && rules.max) {
835
- rules.range = [rules.min, rules.max];
836
- delete rules.min;
837
- delete rules.max;
838
- }
839
- if (rules.minlength && rules.maxlength) {
840
- rules.rangelength = [rules.minlength, rules.maxlength];
841
- delete rules.minlength;
842
- delete rules.maxlength;
843
- }
844
- }
845
-
846
- // To support custom messages in metadata ignore rule methods titled "messages"
847
- if (rules.messages) {
848
- delete rules.messages
849
- }
850
-
851
- return rules;
852
- },
853
-
854
- // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
855
- normalizeRule: function(data) {
856
- if( typeof data == "string" ) {
857
- var transformed = {};
858
- $.each(data.split(/\s/), function() {
859
- transformed[this] = true;
860
- });
861
- data = transformed;
862
- }
863
- return data;
864
- },
865
-
866
- // http://docs.jquery.com/Plugins/Validation/Validator/addMethod
867
- addMethod: function(name, method, message) {
868
- $.validator.methods[name] = method;
869
- $.validator.messages[name] = message;
870
- if (method.length < 3) {
871
- $.validator.addClassRules(name, $.validator.normalizeRule(name));
872
- }
873
- },
874
-
875
- methods: {
876
-
877
- // http://docs.jquery.com/Plugins/Validation/Methods/required
878
- required: function(value, element, param) {
879
- // check if dependency is met
880
- if ( !this.depend(param, element) )
881
- return "dependency-mismatch";
882
- switch( element.nodeName.toLowerCase() ) {
883
- case 'select':
884
- var options = $("option:selected", element);
885
- return options.length > 0 && ( element.type == "select-multiple" || ($.browser.msie && !(options[0].attributes['value'].specified) ? options[0].text : options[0].value).length > 0);
886
- case 'input':
887
- if ( this.checkable(element) )
888
- return this.getLength(value, element) > 0;
889
- default:
890
- return $.trim(value).length > 0;
891
- }
892
- },
893
-
894
- // http://docs.jquery.com/Plugins/Validation/Methods/remote
895
- remote: function(value, element, param) {
896
- if ( this.optional(element) )
897
- return "dependency-mismatch";
898
-
899
- var previous = this.previousValue(element);
900
-
901
- if (!this.settings.messages[element.name] )
902
- this.settings.messages[element.name] = {};
903
- this.settings.messages[element.name].remote = typeof previous.message == "function" ? previous.message(value) : previous.message;
904
-
905
- param = typeof param == "string" && {url:param} || param;
906
-
907
- if ( previous.old !== value ) {
908
- previous.old = value;
909
- var validator = this;
910
- this.startRequest(element);
911
- var data = {};
912
- data[element.name] = value;
913
- $.ajax($.extend(true, {
914
- url: param,
915
- mode: "abort",
916
- port: "validate" + element.name,
917
- dataType: "json",
918
- data: data,
919
- success: function(response) {
920
- if ( response ) {
921
- var submitted = validator.formSubmitted;
922
- validator.prepareElement(element);
923
- validator.formSubmitted = submitted;
924
- validator.successList.push(element);
925
- validator.showErrors();
926
- } else {
927
- var errors = {};
928
- errors[element.name] = response || validator.defaultMessage( element, "remote" );
929
- validator.showErrors(errors);
930
- }
931
- previous.valid = response;
932
- validator.stopRequest(element, response);
933
- }
934
- }, param));
935
- return "pending";
936
- } else if( this.pending[element.name] ) {
937
- return "pending";
938
- }
939
- return previous.valid;
940
- },
262
+ messages: {
263
+ required: "This field is required.",
264
+ remote: "Please fix this field.",
265
+ email: "Please enter a valid email address.",
266
+ url: "Please enter a valid URL.",
267
+ date: "Please enter a valid date.",
268
+ dateISO: "Please enter a valid date (ISO).",
269
+ number: "Please enter a valid number.",
270
+ digits: "Please enter only digits.",
271
+ creditcard: "Please enter a valid credit card number.",
272
+ equalTo: "Please enter the same value again.",
273
+ accept: "Please enter a value with a valid extension.",
274
+ maxlength: $.validator.format("Please enter no more than {0} characters."),
275
+ minlength: $.validator.format("Please enter at least {0} characters."),
276
+ rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
277
+ range: $.validator.format("Please enter a value between {0} and {1}."),
278
+ max: $.validator.format("Please enter a value less than or equal to {0}."),
279
+ min: $.validator.format("Please enter a value greater than or equal to {0}.")
280
+ },
941
281
 
942
- // http://docs.jquery.com/Plugins/Validation/Methods/minlength
943
- minlength: function(value, element, param) {
944
- return this.optional(element) || this.getLength($.trim(value), element) >= param;
945
- },
946
-
947
- // http://docs.jquery.com/Plugins/Validation/Methods/maxlength
948
- maxlength: function(value, element, param) {
949
- return this.optional(element) || this.getLength($.trim(value), element) <= param;
950
- },
951
-
952
- // http://docs.jquery.com/Plugins/Validation/Methods/rangelength
953
- rangelength: function(value, element, param) {
954
- var length = this.getLength($.trim(value), element);
955
- return this.optional(element) || ( length >= param[0] && length <= param[1] );
956
- },
957
-
958
- // http://docs.jquery.com/Plugins/Validation/Methods/min
959
- min: function( value, element, param ) {
960
- return this.optional(element) || value >= param;
961
- },
962
-
963
- // http://docs.jquery.com/Plugins/Validation/Methods/max
964
- max: function( value, element, param ) {
965
- return this.optional(element) || value <= param;
966
- },
967
-
968
- // http://docs.jquery.com/Plugins/Validation/Methods/range
969
- range: function( value, element, param ) {
970
- return this.optional(element) || ( value >= param[0] && value <= param[1] );
971
- },
972
-
973
- // http://docs.jquery.com/Plugins/Validation/Methods/email
974
- email: function(value, element) {
975
- // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
976
- return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
977
- },
978
- //ADDED
979
- emails: function(value, element) {
980
- // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
981
- return this.optional(element) || /^((, *)*((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)+$/i.test(value);
982
- },
983
-
984
- // http://docs.jquery.com/Plugins/Validation/Methods/url
985
- url: function(value, element) {
986
- // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
987
- return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
988
- },
989
-
990
- // http://docs.jquery.com/Plugins/Validation/Methods/date
991
- date: function(value, element) {
992
- return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
993
- },
994
-
995
- // http://docs.jquery.com/Plugins/Validation/Methods/dateISO
996
- dateISO: function(value, element) {
997
- return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
998
- },
999
-
1000
- // http://docs.jquery.com/Plugins/Validation/Methods/dateDE
1001
- dateDE: function(value, element) {
1002
- return this.optional(element) || /^\d\d?\.\d\d?\.\d\d\d?\d?$/.test(value);
1003
- },
1004
-
1005
- // http://docs.jquery.com/Plugins/Validation/Methods/number
1006
- number: function(value, element) {
1007
- return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
1008
- },
1009
-
1010
- // http://docs.jquery.com/Plugins/Validation/Methods/numberDE
1011
- numberDE: function(value, element) {
1012
- return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d+)?$/.test(value);
1013
- },
1014
-
1015
- // http://docs.jquery.com/Plugins/Validation/Methods/digits
1016
- digits: function(value, element) {
1017
- return this.optional(element) || /^\d+$/.test(value);
1018
- },
1019
-
1020
- // Added
1021
- phone: function(value, element) {
1022
- return this.optional(element) || /^((\((\+?)\d+\))?|(\+\d+)?)[ ]*-?(\d+[ ]*\-?[ ]*\d*)+$/.test(value);
1023
- },
1024
-
1025
- // http://docs.jquery.com/Plugins/Validation/Methods/creditcard
1026
- // based on http://en.wikipedia.org/wiki/Luhn
1027
- creditcard: function(value, element) {
1028
- if ( this.optional(element) )
1029
- return "dependency-mismatch";
1030
- // accept only digits and dashes
1031
- if (/[^0-9-]+/.test(value))
1032
- return false;
1033
- var nCheck = 0,
1034
- nDigit = 0,
1035
- bEven = false;
1036
-
1037
- value = value.replace(/\D/g, "");
1038
-
1039
- for (n = value.length - 1; n >= 0; n--) {
1040
- var cDigit = value.charAt(n);
1041
- var nDigit = parseInt(cDigit, 10);
1042
- if (bEven) {
1043
- if ((nDigit *= 2) > 9)
1044
- nDigit -= 9;
1045
- }
1046
- nCheck += nDigit;
1047
- bEven = !bEven;
1048
- }
282
+ autoCreateRanges: false,
283
+
284
+ prototype: {
285
+
286
+ init: function() {
287
+ this.labelContainer = $(this.settings.errorLabelContainer);
288
+ this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
289
+ this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
290
+ this.submitted = {};
291
+ this.valueCache = {};
292
+ this.pendingRequest = 0;
293
+ this.pending = {};
294
+ this.invalid = {};
295
+ this.reset();
296
+
297
+ var groups = (this.groups = {});
298
+ $.each(this.settings.groups, function(key, value) {
299
+ $.each(value.split(/\s/), function(index, name) {
300
+ groups[name] = key;
301
+ });
302
+ });
303
+ var rules = this.settings.rules;
304
+ $.each(rules, function(key, value) {
305
+ rules[key] = $.validator.normalizeRule(value);
306
+ });
307
+
308
+ function delegate(event) {
309
+ var validator = $.data(this[0].form, "validator"),
310
+ eventType = "on" + event.type.replace(/^validate/, "");
311
+ validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] );
312
+ }
313
+ $(this.currentForm)
314
+ .validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate)
315
+ .validateDelegate(":radio, :checkbox, select, option", "click", delegate);
316
+
317
+ if (this.settings.invalidHandler)
318
+ $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
319
+ },
320
+
321
+ // http://docs.jquery.com/Plugins/Validation/Validator/form
322
+ form: function() {
323
+ this.checkForm();
324
+ $.extend(this.submitted, this.errorMap);
325
+ this.invalid = $.extend({}, this.errorMap);
326
+ if (!this.valid())
327
+ $(this.currentForm).triggerHandler("invalid-form", [this]);
328
+ this.showErrors();
329
+ return this.valid();
330
+ },
331
+
332
+ checkForm: function() {
333
+ this.prepareForm();
334
+ for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
335
+ this.check( elements[i] );
336
+ }
337
+ return this.valid();
338
+ },
339
+
340
+ // http://docs.jquery.com/Plugins/Validation/Validator/element
341
+ element: function( element ) {
342
+ element = this.clean( element );
343
+ this.lastElement = element;
344
+ this.prepareElement( element );
345
+ this.currentElements = $(element);
346
+ var result = this.check( element );
347
+ if ( result ) {
348
+ delete this.invalid[element.name];
349
+ } else {
350
+ this.invalid[element.name] = true;
351
+ }
352
+ if ( !this.numberOfInvalids() ) {
353
+ // Hide error containers on last error
354
+ this.toHide = this.toHide.add( this.containers );
355
+ }
356
+ this.showErrors();
357
+ return result;
358
+ },
359
+
360
+ // http://docs.jquery.com/Plugins/Validation/Validator/showErrors
361
+ showErrors: function(errors) {
362
+ if(errors) {
363
+ // add items to error list and map
364
+ $.extend( this.errorMap, errors );
365
+ this.errorList = [];
366
+ for ( var name in errors ) {
367
+ this.errorList.push({
368
+ message: errors[name],
369
+ element: this.findByName(name)[0]
370
+ });
371
+ }
372
+ // remove items from success list
373
+ this.successList = $.grep( this.successList, function(element) {
374
+ return !(element.name in errors);
375
+ });
376
+ }
377
+ this.settings.showErrors
378
+ ? this.settings.showErrors.call( this, this.errorMap, this.errorList )
379
+ : this.defaultShowErrors();
380
+ },
381
+
382
+ // http://docs.jquery.com/Plugins/Validation/Validator/resetForm
383
+ resetForm: function() {
384
+ if ( $.fn.resetForm )
385
+ $( this.currentForm ).resetForm();
386
+ this.submitted = {};
387
+ this.prepareForm();
388
+ this.hideErrors();
389
+ this.elements().removeClass( this.settings.errorClass );
390
+ },
391
+
392
+ numberOfInvalids: function() {
393
+ return this.objectLength(this.invalid);
394
+ },
395
+
396
+ objectLength: function( obj ) {
397
+ var count = 0;
398
+ for ( var i in obj )
399
+ count++;
400
+ return count;
401
+ },
402
+
403
+ hideErrors: function() {
404
+ this.addWrapper( this.toHide ).hide();
405
+ },
406
+
407
+ valid: function() {
408
+ return this.size() == 0;
409
+ },
410
+
411
+ size: function() {
412
+ return this.errorList.length;
413
+ },
414
+
415
+ focusInvalid: function() {
416
+ if( this.settings.focusInvalid ) {
417
+ try {
418
+ $(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
419
+ .filter(":visible")
420
+ .focus()
421
+ // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
422
+ .trigger("focusin");
423
+ } catch(e) {
424
+ // ignore IE throwing errors when focusing hidden elements
425
+ }
426
+ }
427
+ },
428
+
429
+ findLastActive: function() {
430
+ var lastActive = this.lastActive;
431
+ return lastActive && $.grep(this.errorList, function(n) {
432
+ return n.element.name == lastActive.name;
433
+ }).length == 1 && lastActive;
434
+ },
435
+
436
+ elements: function() {
437
+ var validator = this,
438
+ rulesCache = {};
439
+
440
+ // select all valid inputs inside the form (no submit or reset buttons)
441
+ return $(this.currentForm)
442
+ .find("input, select, textarea")
443
+ .not(":submit, :reset, :image, [disabled]")
444
+ .not( this.settings.ignore )
445
+ .filter(function() {
446
+ !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
447
+
448
+ // select only the first element for each name, and only those with rules specified
449
+ if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
450
+ return false;
451
+
452
+ rulesCache[this.name] = true;
453
+ return true;
454
+ });
455
+ },
456
+
457
+ clean: function( selector ) {
458
+ return $( selector )[0];
459
+ },
460
+
461
+ errors: function() {
462
+ return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
463
+ },
464
+
465
+ reset: function() {
466
+ this.successList = [];
467
+ this.errorList = [];
468
+ this.errorMap = {};
469
+ this.toShow = $([]);
470
+ this.toHide = $([]);
471
+ this.currentElements = $([]);
472
+ },
473
+
474
+ prepareForm: function() {
475
+ this.reset();
476
+ this.toHide = this.errors().add( this.containers );
477
+ },
478
+
479
+ prepareElement: function( element ) {
480
+ this.reset();
481
+ this.toHide = this.errorsFor(element);
482
+ },
483
+
484
+ check: function( element ) {
485
+ element = this.clean( element );
486
+
487
+ // if radio/checkbox, validate first element in group instead
488
+ if (this.checkable(element)) {
489
+ element = this.findByName( element.name ).not(this.settings.ignore)[0];
490
+ }
491
+
492
+ var rules = $(element).rules();
493
+ var dependencyMismatch = false;
494
+ for (var method in rules ) {
495
+ var rule = { method: method, parameters: rules[method] };
496
+ try {
497
+ var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
498
+
499
+ // if a method indicates that the field is optional and therefore valid,
500
+ // don't mark it as valid when there are no other rules
501
+ if ( result == "dependency-mismatch" ) {
502
+ dependencyMismatch = true;
503
+ continue;
504
+ }
505
+ dependencyMismatch = false;
506
+
507
+ if ( result == "pending" ) {
508
+ this.toHide = this.toHide.not( this.errorsFor(element) );
509
+ return;
510
+ }
511
+
512
+ if( !result ) {
513
+ this.formatAndAdd( element, rule );
514
+ return false;
515
+ }
516
+ } catch(e) {
517
+ this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
518
+ + ", check the '" + rule.method + "' method", e);
519
+ throw e;
520
+ }
521
+ }
522
+ if (dependencyMismatch)
523
+ return;
524
+ if ( this.objectLength(rules) )
525
+ this.successList.push(element);
526
+ return true;
527
+ },
528
+
529
+ // return the custom message for the given element and validation method
530
+ // specified in the element's "messages" metadata
531
+ customMetaMessage: function(element, method) {
532
+ if (!$.metadata)
533
+ return;
534
+
535
+ var meta = this.settings.meta
536
+ ? $(element).metadata()[this.settings.meta]
537
+ : $(element).metadata();
538
+
539
+ return meta && meta.messages && meta.messages[method];
540
+ },
541
+
542
+ // return the custom message for the given element name and validation method
543
+ customMessage: function( name, method ) {
544
+ var m = this.settings.messages[name];
545
+ return m && (m.constructor == String
546
+ ? m
547
+ : m[method]);
548
+ },
549
+
550
+ // return the first defined argument, allowing empty strings
551
+ findDefined: function() {
552
+ for(var i = 0; i < arguments.length; i++) {
553
+ if (arguments[i] !== undefined)
554
+ return arguments[i];
555
+ }
556
+ return undefined;
557
+ },
558
+
559
+ defaultMessage: function( element, method) {
560
+ return this.findDefined(
561
+ this.customMessage( element.name, method ),
562
+ this.customMetaMessage( element, method ),
563
+ // title is never undefined, so handle empty string as undefined
564
+ !this.settings.ignoreTitle && element.title || undefined,
565
+ $.validator.messages[method],
566
+ "<strong>Warning: No message defined for " + element.name + "</strong>"
567
+ );
568
+ },
569
+
570
+ formatAndAdd: function( element, rule ) {
571
+ var message = this.defaultMessage( element, rule.method ),
572
+ theregex = /\$?\{(\d+)\}/g;
573
+ if ( typeof message == "function" ) {
574
+ message = message.call(this, rule.parameters, element);
575
+ } else if (theregex.test(message)) {
576
+ message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
577
+ }
578
+ this.errorList.push({
579
+ message: message,
580
+ element: element
581
+ });
582
+
583
+ this.errorMap[element.name] = message;
584
+ this.submitted[element.name] = message;
585
+ },
586
+
587
+ addWrapper: function(toToggle) {
588
+ if ( this.settings.wrapper )
589
+ toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
590
+ return toToggle;
591
+ },
592
+
593
+ defaultShowErrors: function() {
594
+ for ( var i = 0; this.errorList[i]; i++ ) {
595
+ var error = this.errorList[i];
596
+ this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
597
+ this.showLabel( error.element, error.message );
598
+ }
599
+ if( this.errorList.length ) {
600
+ this.toShow = this.toShow.add( this.containers );
601
+ }
602
+ if (this.settings.success) {
603
+ for ( var i = 0; this.successList[i]; i++ ) {
604
+ this.showLabel( this.successList[i] );
605
+ }
606
+ }
607
+ if (this.settings.unhighlight) {
608
+ for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
609
+ this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
610
+ }
611
+ }
612
+ this.toHide = this.toHide.not( this.toShow );
613
+ this.hideErrors();
614
+ this.addWrapper( this.toShow ).show();
615
+ },
616
+
617
+ validElements: function() {
618
+ return this.currentElements.not(this.invalidElements());
619
+ },
620
+
621
+ invalidElements: function() {
622
+ return $(this.errorList).map(function() {
623
+ return this.element;
624
+ });
625
+ },
626
+
627
+ showLabel: function(element, message) {
628
+ var label = this.errorsFor( element );
629
+ if ( label.length ) {
630
+ // refresh error/success class
631
+ label.removeClass().addClass( this.settings.errorClass );
632
+
633
+ // check if we have a generated label, replace the message then
634
+ label.attr("generated") && label.html(message);
635
+ } else {
636
+ // create label
637
+ label = $("<" + this.settings.errorElement + "/>")
638
+ .attr({"for": this.idOrName(element), generated: true})
639
+ .addClass(this.settings.errorClass)
640
+ .html(message || "");
641
+ if ( this.settings.wrapper ) {
642
+ // make sure the element is visible, even in IE
643
+ // actually showing the wrapped element is handled elsewhere
644
+ label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
645
+ }
646
+ if ( !this.labelContainer.append(label).length )
647
+ this.settings.errorPlacement
648
+ ? this.settings.errorPlacement(label, $(element) )
649
+ : label.insertAfter(element);
650
+ }
651
+ if ( !message && this.settings.success ) {
652
+ label.text("");
653
+ typeof this.settings.success == "string"
654
+ ? label.addClass( this.settings.success )
655
+ : this.settings.success( label );
656
+ }
657
+ this.toShow = this.toShow.add(label);
658
+ },
659
+
660
+ errorsFor: function(element) {
661
+ var name = this.idOrName(element);
662
+ return this.errors().filter(function() {
663
+ return $(this).attr('for') == name;
664
+ });
665
+ },
666
+
667
+ idOrName: function(element) {
668
+ return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
669
+ },
670
+
671
+ checkable: function( element ) {
672
+ return /radio|checkbox/i.test(element.type);
673
+ },
674
+
675
+ findByName: function( name ) {
676
+ // select by name and filter by form for performance over form.find("[name=...]")
677
+ var form = this.currentForm;
678
+ return $(document.getElementsByName(name)).map(function(index, element) {
679
+ return element.form == form && element.name == name && element || null;
680
+ });
681
+ },
682
+
683
+ getLength: function(value, element) {
684
+ switch( element.nodeName.toLowerCase() ) {
685
+ case 'select':
686
+ return $("option:selected", element).length;
687
+ case 'input':
688
+ if( this.checkable( element) )
689
+ return this.findByName(element.name).filter(':checked').length;
690
+ }
691
+ return value.length;
692
+ },
693
+
694
+ depend: function(param, element) {
695
+ return this.dependTypes[typeof param]
696
+ ? this.dependTypes[typeof param](param, element)
697
+ : true;
698
+ },
699
+
700
+ dependTypes: {
701
+ "boolean": function(param, element) {
702
+ return param;
703
+ },
704
+ "string": function(param, element) {
705
+ return !!$(param, element.form).length;
706
+ },
707
+ "function": function(param, element) {
708
+ return param(element);
709
+ }
710
+ },
711
+
712
+ optional: function(element) {
713
+ return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
714
+ },
715
+
716
+ startRequest: function(element) {
717
+ if (!this.pending[element.name]) {
718
+ this.pendingRequest++;
719
+ this.pending[element.name] = true;
720
+ }
721
+ },
722
+
723
+ stopRequest: function(element, valid) {
724
+ this.pendingRequest--;
725
+ // sometimes synchronization fails, make sure pendingRequest is never < 0
726
+ if (this.pendingRequest < 0)
727
+ this.pendingRequest = 0;
728
+ delete this.pending[element.name];
729
+ if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
730
+ $(this.currentForm).submit();
731
+ this.formSubmitted = false;
732
+ } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
733
+ $(this.currentForm).triggerHandler("invalid-form", [this]);
734
+ this.formSubmitted = false;
735
+ }
736
+ },
737
+
738
+ previousValue: function(element) {
739
+ return $.data(element, "previousValue") || $.data(element, "previousValue", {
740
+ old: null,
741
+ valid: true,
742
+ message: this.defaultMessage( element, "remote" )
743
+ });
744
+ }
745
+
746
+ },
747
+
748
+ classRuleSettings: {
749
+ required: {required: true},
750
+ email: {email: true},
751
+ url: {url: true},
752
+ date: {date: true},
753
+ dateISO: {dateISO: true},
754
+ dateDE: {dateDE: true},
755
+ number: {number: true},
756
+ numberDE: {numberDE: true},
757
+ digits: {digits: true},
758
+ creditcard: {creditcard: true}
759
+ },
760
+
761
+ addClassRules: function(className, rules) {
762
+ className.constructor == String ?
763
+ this.classRuleSettings[className] = rules :
764
+ $.extend(this.classRuleSettings, className);
765
+ },
766
+
767
+ classRules: function(element) {
768
+ var rules = {};
769
+ var classes = $(element).attr('class');
770
+ classes && $.each(classes.split(' '), function() {
771
+ if (this in $.validator.classRuleSettings) {
772
+ $.extend(rules, $.validator.classRuleSettings[this]);
773
+ }
774
+ });
775
+ return rules;
776
+ },
777
+
778
+ attributeRules: function(element) {
779
+ var rules = {};
780
+ var $element = $(element);
781
+
782
+ for (var method in $.validator.methods) {
783
+ var value = $element.attr(method);
784
+ if (value) {
785
+ rules[method] = value;
786
+ }
787
+ }
788
+
789
+ // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
790
+ if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
791
+ delete rules.maxlength;
792
+ }
793
+
794
+ return rules;
795
+ },
796
+
797
+ metadataRules: function(element) {
798
+ if (!$.metadata) return {};
799
+
800
+ var meta = $.data(element.form, 'validator').settings.meta;
801
+ return meta ?
802
+ $(element).metadata()[meta] :
803
+ $(element).metadata();
804
+ },
805
+
806
+ staticRules: function(element) {
807
+ var rules = {};
808
+ var validator = $.data(element.form, 'validator');
809
+ if (validator.settings.rules) {
810
+ rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
811
+ }
812
+ return rules;
813
+ },
814
+
815
+ normalizeRules: function(rules, element) {
816
+ // handle dependency check
817
+ $.each(rules, function(prop, val) {
818
+ // ignore rule when param is explicitly false, eg. required:false
819
+ if (val === false) {
820
+ delete rules[prop];
821
+ return;
822
+ }
823
+ if (val.param || val.depends) {
824
+ var keepRule = true;
825
+ switch (typeof val.depends) {
826
+ case "string":
827
+ keepRule = !!$(val.depends, element.form).length;
828
+ break;
829
+ case "function":
830
+ keepRule = val.depends.call(element, element);
831
+ break;
832
+ }
833
+ if (keepRule) {
834
+ rules[prop] = val.param !== undefined ? val.param : true;
835
+ } else {
836
+ delete rules[prop];
837
+ }
838
+ }
839
+ });
840
+
841
+ // evaluate parameters
842
+ $.each(rules, function(rule, parameter) {
843
+ rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
844
+ });
845
+
846
+ // clean number parameters
847
+ $.each(['minlength', 'maxlength', 'min', 'max'], function() {
848
+ if (rules[this]) {
849
+ rules[this] = Number(rules[this]);
850
+ }
851
+ });
852
+ $.each(['rangelength', 'range'], function() {
853
+ if (rules[this]) {
854
+ rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
855
+ }
856
+ });
857
+
858
+ if ($.validator.autoCreateRanges) {
859
+ // auto-create ranges
860
+ if (rules.min && rules.max) {
861
+ rules.range = [rules.min, rules.max];
862
+ delete rules.min;
863
+ delete rules.max;
864
+ }
865
+ if (rules.minlength && rules.maxlength) {
866
+ rules.rangelength = [rules.minlength, rules.maxlength];
867
+ delete rules.minlength;
868
+ delete rules.maxlength;
869
+ }
870
+ }
871
+
872
+ // To support custom messages in metadata ignore rule methods titled "messages"
873
+ if (rules.messages) {
874
+ delete rules.messages;
875
+ }
876
+
877
+ return rules;
878
+ },
879
+
880
+ // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
881
+ normalizeRule: function(data) {
882
+ if( typeof data == "string" ) {
883
+ var transformed = {};
884
+ $.each(data.split(/\s/), function() {
885
+ transformed[this] = true;
886
+ });
887
+ data = transformed;
888
+ }
889
+ return data;
890
+ },
891
+
892
+ // http://docs.jquery.com/Plugins/Validation/Validator/addMethod
893
+ addMethod: function(name, method, message) {
894
+ $.validator.methods[name] = method;
895
+ $.validator.messages[name] = message != undefined ? message : $.validator.messages[name];
896
+ if (method.length < 3) {
897
+ $.validator.addClassRules(name, $.validator.normalizeRule(name));
898
+ }
899
+ },
900
+
901
+ methods: {
902
+
903
+ // http://docs.jquery.com/Plugins/Validation/Methods/required
904
+ required: function(value, element, param) {
905
+ // check if dependency is met
906
+ if ( !this.depend(param, element) )
907
+ return "dependency-mismatch";
908
+ switch( element.nodeName.toLowerCase() ) {
909
+ case 'select':
910
+ // could be an array for select-multiple or a string, both are fine this way
911
+ var val = $(element).val();
912
+ return val && val.length > 0;
913
+ case 'input':
914
+ if ( this.checkable(element) )
915
+ return this.getLength(value, element) > 0;
916
+ default:
917
+ return $.trim(value).length > 0;
918
+ }
919
+ },
920
+
921
+ // http://docs.jquery.com/Plugins/Validation/Methods/remote
922
+ remote: function(value, element, param) {
923
+ if ( this.optional(element) )
924
+ return "dependency-mismatch";
925
+
926
+ var previous = this.previousValue(element);
927
+ if (!this.settings.messages[element.name] )
928
+ this.settings.messages[element.name] = {};
929
+ previous.originalMessage = this.settings.messages[element.name].remote;
930
+ this.settings.messages[element.name].remote = previous.message;
931
+
932
+ param = typeof param == "string" && {url:param} || param;
933
+
934
+ if ( this.pending[element.name] ) {
935
+ return "pending";
936
+ }
937
+ if ( previous.old === value ) {
938
+ return previous.valid;
939
+ }
940
+
941
+ previous.old = value;
942
+ var validator = this;
943
+ this.startRequest(element);
944
+ var data = {};
945
+ data[element.name] = value;
946
+ $.ajax($.extend(true, {
947
+ url: param,
948
+ mode: "abort",
949
+ port: "validate" + element.name,
950
+ dataType: "json",
951
+ data: data,
952
+ success: function(response) {
953
+ validator.settings.messages[element.name].remote = previous.originalMessage;
954
+ var valid = response === true;
955
+ if ( valid ) {
956
+ var submitted = validator.formSubmitted;
957
+ validator.prepareElement(element);
958
+ validator.formSubmitted = submitted;
959
+ validator.successList.push(element);
960
+ validator.showErrors();
961
+ } else {
962
+ var errors = {};
963
+ var message = response || validator.defaultMessage( element, "remote" );
964
+ errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;
965
+ validator.showErrors(errors);
966
+ }
967
+ previous.valid = valid;
968
+ validator.stopRequest(element, valid);
969
+ }
970
+ }, param));
971
+ return "pending";
972
+ },
973
+
974
+ // http://docs.jquery.com/Plugins/Validation/Methods/minlength
975
+ minlength: function(value, element, param) {
976
+ return this.optional(element) || this.getLength($.trim(value), element) >= param;
977
+ },
978
+
979
+ // http://docs.jquery.com/Plugins/Validation/Methods/maxlength
980
+ maxlength: function(value, element, param) {
981
+ return this.optional(element) || this.getLength($.trim(value), element) <= param;
982
+ },
983
+
984
+ // http://docs.jquery.com/Plugins/Validation/Methods/rangelength
985
+ rangelength: function(value, element, param) {
986
+ var length = this.getLength($.trim(value), element);
987
+ return this.optional(element) || ( length >= param[0] && length <= param[1] );
988
+ },
989
+
990
+ // http://docs.jquery.com/Plugins/Validation/Methods/min
991
+ min: function( value, element, param ) {
992
+ return this.optional(element) || value >= param;
993
+ },
994
+
995
+ // http://docs.jquery.com/Plugins/Validation/Methods/max
996
+ max: function( value, element, param ) {
997
+ return this.optional(element) || value <= param;
998
+ },
999
+
1000
+ // http://docs.jquery.com/Plugins/Validation/Methods/range
1001
+ range: function( value, element, param ) {
1002
+ return this.optional(element) || ( value >= param[0] && value <= param[1] );
1003
+ },
1004
+
1005
+ // http://docs.jquery.com/Plugins/Validation/Methods/email
1006
+ email: function(value, element) {
1007
+ // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
1008
+ return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
1009
+ },
1010
+
1011
+ // http://docs.jquery.com/Plugins/Validation/Methods/url
1012
+ url: function(value, element) {
1013
+ // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
1014
+ return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
1015
+ },
1016
+
1017
+ // http://docs.jquery.com/Plugins/Validation/Methods/date
1018
+ date: function(value, element) {
1019
+ return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
1020
+ },
1021
+
1022
+ // http://docs.jquery.com/Plugins/Validation/Methods/dateISO
1023
+ dateISO: function(value, element) {
1024
+ return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
1025
+ },
1026
+
1027
+ // http://docs.jquery.com/Plugins/Validation/Methods/number
1028
+ number: function(value, element) {
1029
+ return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
1030
+ },
1031
+
1032
+ // http://docs.jquery.com/Plugins/Validation/Methods/digits
1033
+ digits: function(value, element) {
1034
+ return this.optional(element) || /^\d+$/.test(value);
1035
+ },
1036
+
1037
+ // http://docs.jquery.com/Plugins/Validation/Methods/creditcard
1038
+ // based on http://en.wikipedia.org/wiki/Luhn
1039
+ creditcard: function(value, element) {
1040
+ if ( this.optional(element) )
1041
+ return "dependency-mismatch";
1042
+ // accept only digits and dashes
1043
+ if (/[^0-9-]+/.test(value))
1044
+ return false;
1045
+ var nCheck = 0,
1046
+ nDigit = 0,
1047
+ bEven = false;
1048
+
1049
+ value = value.replace(/\D/g, "");
1050
+
1051
+ for (var n = value.length - 1; n >= 0; n--) {
1052
+ var cDigit = value.charAt(n);
1053
+ var nDigit = parseInt(cDigit, 10);
1054
+ if (bEven) {
1055
+ if ((nDigit *= 2) > 9)
1056
+ nDigit -= 9;
1057
+ }
1058
+ nCheck += nDigit;
1059
+ bEven = !bEven;
1060
+ }
1061
+
1062
+ return (nCheck % 10) == 0;
1063
+ },
1064
+
1065
+ // http://docs.jquery.com/Plugins/Validation/Methods/accept
1066
+ accept: function(value, element, param) {
1067
+ param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
1068
+ return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
1069
+ },
1070
+
1071
+ // http://docs.jquery.com/Plugins/Validation/Methods/equalTo
1072
+ equalTo: function(value, element, param) {
1073
+ // bind to the blur event of the target in order to revalidate whenever the target field is updated
1074
+ // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
1075
+ var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
1076
+ $(element).valid();
1077
+ });
1078
+ return value == target.val();
1079
+ }
1080
+
1081
+ }
1049
1082
 
1050
- return (nCheck % 10) == 0;
1051
- },
1052
-
1053
- // http://docs.jquery.com/Plugins/Validation/Methods/accept
1054
- accept: function(value, element, param) {
1055
- param = typeof param == "string" ? param : "png|jpe?g|gif";
1056
- return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
1057
- },
1058
-
1059
- // http://docs.jquery.com/Plugins/Validation/Methods/equalTo
1060
- equalTo: function(value, element, param) {
1061
- return value == $(param).val();
1062
- }
1063
-
1064
- }
1065
-
1066
1083
  });
1067
1084
 
1085
+ // deprecated, use $.validator.format instead
1086
+ $.format = $.validator.format;
1087
+
1068
1088
  })(jQuery);
1069
1089
 
1070
1090
  // ajax mode: abort
1071
1091
  // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
1072
- // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
1092
+ // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
1073
1093
  ;(function($) {
1074
- var ajax = $.ajax;
1075
- var pendingRequests = {};
1076
- $.ajax = function(settings) {
1077
- // create settings for compatibility with ajaxSetup
1078
- settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));
1079
- var port = settings.port;
1080
- if (settings.mode == "abort") {
1081
- if ( pendingRequests[port] ) {
1082
- pendingRequests[port].abort();
1083
- }
1084
- return (pendingRequests[port] = ajax.apply(this, arguments));
1085
- }
1086
- return ajax.apply(this, arguments);
1087
- };
1094
+ var pendingRequests = {};
1095
+ // Use a prefilter if available (1.5+)
1096
+ if ( $.ajaxPrefilter ) {
1097
+ $.ajaxPrefilter(function(settings, _, xhr) {
1098
+ var port = settings.port;
1099
+ if (settings.mode == "abort") {
1100
+ if ( pendingRequests[port] ) {
1101
+ pendingRequests[port].abort();
1102
+ }
1103
+ pendingRequests[port] = xhr;
1104
+ }
1105
+ });
1106
+ } else {
1107
+ // Proxy ajax
1108
+ var ajax = $.ajax;
1109
+ $.ajax = function(settings) {
1110
+ var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
1111
+ port = ( "port" in settings ? settings : $.ajaxSettings ).port;
1112
+ if (mode == "abort") {
1113
+ if ( pendingRequests[port] ) {
1114
+ pendingRequests[port].abort();
1115
+ }
1116
+ return (pendingRequests[port] = ajax.apply(this, arguments));
1117
+ }
1118
+ return ajax.apply(this, arguments);
1119
+ };
1120
+ }
1088
1121
  })(jQuery);
1089
1122
 
1090
1123
  // provides cross-browser focusin and focusout events
1091
1124
  // IE has native support, in other browsers, use event caputuring (neither bubbles)
1092
1125
 
1093
1126
  // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
1094
- // handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target
1095
-
1096
- // provides triggerEvent(type: String, target: Element) to trigger delegated events
1127
+ // handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target
1097
1128
  ;(function($) {
1098
- $.each({
1099
- focus: 'focusin',
1100
- blur: 'focusout'
1101
- }, function( original, fix ){
1102
- $.event.special[fix] = {
1103
- setup:function() {
1104
- if ( $.browser.msie ) return false;
1105
- this.addEventListener( original, $.event.special[fix].handler, true );
1106
- },
1107
- teardown:function() {
1108
- if ( $.browser.msie ) return false;
1109
- this.removeEventListener( original,
1110
- $.event.special[fix].handler, true );
1111
- },
1112
- handler: function(e) {
1113
- arguments[0] = $.event.fix(e);
1114
- arguments[0].type = fix;
1115
- return $.event.handle.apply(this, arguments);
1116
- }
1117
- };
1118
- });
1119
- $.extend($.fn, {
1120
- delegate: function(type, delegate, handler) {
1121
- return this.bind(type, function(event) {
1122
- var target = $(event.target);
1123
- if (target.is(delegate)) {
1124
- return handler.apply(target, arguments);
1125
- }
1126
- });
1127
- },
1128
- triggerEvent: function(type, target) {
1129
- return this.triggerHandler(type, [$.event.fix({ type: type, target: target })]);
1130
- }
1131
- })
1129
+ // only implement if not provided by jQuery core (since 1.4)
1130
+ // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
1131
+ if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
1132
+ $.each({
1133
+ focus: 'focusin',
1134
+ blur: 'focusout'
1135
+ }, function( original, fix ){
1136
+ $.event.special[fix] = {
1137
+ setup:function() {
1138
+ this.addEventListener( original, handler, true );
1139
+ },
1140
+ teardown:function() {
1141
+ this.removeEventListener( original, handler, true );
1142
+ },
1143
+ handler: function(e) {
1144
+ arguments[0] = $.event.fix(e);
1145
+ arguments[0].type = fix;
1146
+ return $.event.handle.apply(this, arguments);
1147
+ }
1148
+ };
1149
+ function handler(e) {
1150
+ e = $.event.fix(e);
1151
+ e.type = fix;
1152
+ return $.event.handle.call(this, e);
1153
+ }
1154
+ });
1155
+ };
1156
+ $.extend($.fn, {
1157
+ validateDelegate: function(delegate, type, handler) {
1158
+ return this.bind(type, function(event) {
1159
+ var target = $(event.target);
1160
+ if (target.is(delegate)) {
1161
+ return handler.apply(target, arguments);
1162
+ }
1163
+ });
1164
+ }
1165
+ });
1132
1166
  })(jQuery);