diff --git a/lib/WebGUI/Auth/WebGUI.pm b/lib/WebGUI/Auth/WebGUI.pm index b3631337c..d6bac0c22 100644 --- a/lib/WebGUI/Auth/WebGUI.pm +++ b/lib/WebGUI/Auth/WebGUI.pm @@ -165,7 +165,7 @@ sub createAccount { unless($setting->get('webguiUseEmailAsUsername')){ my $username = $form->process("authWebGUI.username"); $vars->{'create.form.username'} - = WebGUI::Form::text($self->session, { + = WebGUI::Form::username($self->session, { name => "authWebGUI.username", value => $username, extras => $self->getExtrasStyle($username) @@ -326,6 +326,32 @@ sub deactivateAccountConfirm { return $self->displayLogin(sprintf( $i18n->get("deactivateAccount success"), $username )); } +#------------------------------------------------------------------- + +=head2 checkField ( ) + +Performs AJAX checks on form field input. For example, can check whether a user +name is free for registration. + +Returns the JSON {"error":"errorString"} where errorString is an error message +or an empty string if the check was successful. + +=cut + +sub checkField { + my $self = shift; + my $session = $self->session; + $session->http->setMimeType( 'application/json' ); + + my $input = $session->form->param('input'); + my $fieldName = $session->form->param('fieldName'); + my $fieldType = $session->form->param('fieldType'); + + my $checkClass = 'WebGUI::Form::'. ucfirst $fieldType; + my (%checkResults) = "$checkClass"->check($session, $input); + return JSON::encode_json(\%checkResults); +} + #------------------------------------------------------------------- sub displayAccount { my $self = shift; @@ -774,7 +800,7 @@ sub new { my $session = shift; my $authMethod = $_[0]; my $userId = $_[1]; - my @callable = ('validateEmail','createAccount','deactivateAccount','displayAccount','displayLogin','login','logout','recoverPassword','resetExpiredPassword','recoverPasswordFinish','createAccountSave','deactivateAccountConfirm','resetExpiredPasswordSave','updateAccount', 'emailResetPassword', 'emailResetPasswordFinish'); + my @callable = ('validateEmail','createAccount','deactivateAccount','displayAccount','displayLogin','login','logout','recoverPassword','resetExpiredPassword','recoverPasswordFinish','createAccountSave','deactivateAccountConfirm','resetExpiredPasswordSave','updateAccount', 'emailResetPassword', 'emailResetPasswordFinish','checkField'); my $self = WebGUI::Auth->new($session,$authMethod,$userId,\@callable); bless $self, $class; } diff --git a/lib/WebGUI/Form/Username.pm b/lib/WebGUI/Form/Username.pm new file mode 100644 index 000000000..d423df332 --- /dev/null +++ b/lib/WebGUI/Form/Username.pm @@ -0,0 +1,124 @@ +package WebGUI::Form::Username; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2009 Plain Black Corporation. + ------------------------------------------------------------------- + Please read the legal notices (docs/legal.txt) and the license + (docs/license.txt) that came with this distribution before using + this software. + ------------------------------------------------------------------- + http://www.plainblack.com info@plainblack.com + ------------------------------------------------------------------- + +=cut + +use strict; +use base 'WebGUI::Form::Text'; +use WebGUI::International; + +=head1 NAME + +Package WebGUI::Form::Username + +=head1 DESCRIPTION + +Creates a text input box form field specifically for a user name. + +=head1 SEE ALSO + +This is a subclass of WebGUI::Form::Text. + +=head1 METHODS + +The following methods are specifically available from this class. Check the superclass for additional methods. + +=cut + +#------------------------------------------------------------------- + +=head2 definition ( [ additionalTerms ] ) + +See the super class for additional details. + +=head3 additionalTerms + +The following additional parameters have been added via this sub class. + +=head4 maxlength + +Defaults to 255. Determines the maximum number of characters allowed in this field. + +=head4 size + +Defaults to the setting textBoxSize or 30 if that's not set. Specifies how big of a text box to display. + +=cut + +#------------------------------------------------------------------- + +=head2 getValue ( [ value ] ) + +Retrieves a value from a form GET or POST and returns it. If the value comes back as undef, this method will return the defaultValue instead. Strip newlines/carriage returns from the value. + +=head3 value + +An optional value to process, instead of POST input. + +=cut + +sub getValue { + my $self = shift; + my $value = $self->SUPER::getValue(@_); + $value =~ tr/\r\n//d; + return $value; +} + +#------------------------------------------------------------------- + +=head2 toHtml ( ) + +Renders a user name field. + +=cut + +sub toHtml { + my $self = shift; + $self->session->style->setScript($self->session->url->extras('form/fieldCheck.js'),{ type=>'text/javascript' }); + $self->session->style->setScript($self->session->url->extras('yui/build/yahoo-dom-event/yahoo-dom-event.js'), {type=>'text/javascript'}); + $self->session->style->setScript($self->session->url->extras('yui/build/connection/connection-min.js'), {type => 'text/javascript'}); + $self->session->style->setScript($self->session->url->extras('yui/build/json/json-min.js'), {type=>'text/javascript'}); + $self->session->style->setScript($self->session->url->extras('yui/build/datasource/datasource-min.js'), {type=>'text/javascript'}); + $self->session->style->setScript($self->session->url->extras('yui-webgui/build/i18n/i18n.js'), {type=>'text/javascript'}); + my $value = $self->fixMacros($self->fixQuotes($self->fixSpecialCharacters(scalar $self->getOriginalValue))); + $self->set("extras", $self->get('extras') . ' onblur="new WebGUI.FieldCheck(\''. $self->get("id").'\',\'username\',1);"'); + return 'get("extras").' />'; +} + +#------------------------------------------------------------------- + +=head2 check ( $session, $input ) + +check() is called as a class method. + +It checks whether a user name is free for registration. Returns a hash +(error => $error) +if the username is not free. + +=cut + +sub check { + my ($class, $session, $input) = @_; + my $i18n = WebGUI::International->new($session, 'Form_Username'); + + my $error = ''; + my ($existingUserId) = $session->db->quickArray("select userId from users where username=".$session->db->quote($input)); + $error = $i18n->get('username in use') if $existingUserId; + + my %checkInfo = (error => $error); + return %checkInfo; +} + +1; + diff --git a/lib/WebGUI/i18n/English/Form.pm b/lib/WebGUI/i18n/English/Form.pm new file mode 100644 index 000000000..292320515 --- /dev/null +++ b/lib/WebGUI/i18n/English/Form.pm @@ -0,0 +1,11 @@ +package WebGUI::i18n::English::Form; +use strict; + +our $I18N = { + 'field required' => { + message => q|This field is required.|, + lastUpdated => 1217216725 + }, +}; + +1; diff --git a/lib/WebGUI/i18n/English/Form_Username.pm b/lib/WebGUI/i18n/English/Form_Username.pm new file mode 100644 index 000000000..ba5fdf373 --- /dev/null +++ b/lib/WebGUI/i18n/English/Form_Username.pm @@ -0,0 +1,11 @@ +package WebGUI::i18n::English::Form_Username; +use strict; + +our $I18N = { + 'username in use' => { + message => q|Sorry, that account name is already in use by another member of this site.|, + lastUpdated => 1217216725 + }, +}; + +1; diff --git a/www/extras/form/cross.png b/www/extras/form/cross.png new file mode 100644 index 000000000..33a383748 Binary files /dev/null and b/www/extras/form/cross.png differ diff --git a/www/extras/form/fieldCheck.js b/www/extras/form/fieldCheck.js new file mode 100644 index 000000000..db18c3778 --- /dev/null +++ b/www/extras/form/fieldCheck.js @@ -0,0 +1,100 @@ +if (typeof WebGUI == "undefined" || !WebGUI) { + var WebGUI = {}; +} + +WebGUI.FieldCheck = function (fieldId,fieldType,required) { + this.fieldId=fieldId; + this.fieldType=fieldType; + this.required=required; + var obj = this; + + this.i18nObj = new WebGUI.i18n( { + namespaces : { + 'Form' : ['field required'] + }, + onpreload : { + fn : this.initialize, + obj : this, + override : true + } + } ); + this.i18n = function (key) { + return this.i18nObj.get('Form',key) + }; + + return this; +} + +WebGUI.FieldCheck.prototype.initialize = function() { + var fieldId=this.fieldId; + var fieldType=this.fieldType; + var required=this.required; + var field=document.getElementById(fieldId); + var fieldName=field.name; + var input=field.value; + + var myAjaxEvent = new WebGUI.FieldCheck.AjaxEvent(); + myAjaxEvent.startThrobber(fieldId); + + if (required && !input) { + var imgEltId=fieldId+"_Img"; + var imgElt=document.getElementById(imgEltId); + imgElt.setAttribute('src','/extras/form/cross.png'); + alert(this.i18n('field required')); + return false; + } + + myAjaxEvent.connect(fieldId,'/?op=auth;method=checkField;fieldName='+fieldName+';fieldType='+fieldType+';input='+input); +} + +WebGUI.FieldCheck.AjaxEvent = function() { + return this; +} + +WebGUI.FieldCheck.AjaxEvent.prototype = { + startThrobber: function(fieldId) { + this.field = document.getElementById(fieldId); + var imgEltId=fieldId+"_Img"; + var imgElt; + if(document.getElementById(imgEltId)==undefined){ + var formElt=this.field.parentNode; + var imgElt=document.createElement('img'); + imgElt.setAttribute('id',imgEltId); + WebGUI.FieldCheck.insertAfter(imgElt,this.field); + }else{ + var imgElt=document.getElementById(imgEltId); + } + imgElt.setAttribute('src','/extras/form/throbber.gif'); + }, + connect: function(fieldId,sUri) { + if (!sUri && !this.sUri) { + return false; + } else { + this.sUri = (!sUri) ? this.sUri : sUri; + YAHOO.util.Connect.asyncRequest('GET', this.sUri, { + success: function (o) { + var oJSON = eval("(" + o.responseText + ")"); + var imgEltId=fieldId+"_Img"; + var imgElt=document.getElementById(imgEltId); + document.getElementById(imgEltId); + if(oJSON.error == ""){ + imgElt.setAttribute('src','/extras/form/tick.png'); + }else{ + imgElt.setAttribute('src','/extras/form/cross.png'); + alert(oJSON.error); + } + }, + scope: this + }); + } + } +}; + +WebGUI.FieldCheck.insertAfter = function(newElement,targetElement) { + var parent = targetElement.parentNode; + if(parent.lastchild == targetElement) { + parent.appendChild(newElement); + }else{ + parent.insertBefore(newElement, targetElement.nextSibling); + } +}; diff --git a/www/extras/form/throbber.gif b/www/extras/form/throbber.gif new file mode 100644 index 000000000..078b55faf Binary files /dev/null and b/www/extras/form/throbber.gif differ diff --git a/www/extras/form/tick.png b/www/extras/form/tick.png new file mode 100644 index 000000000..c277e6b40 Binary files /dev/null and b/www/extras/form/tick.png differ