1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Scratchpad - Demonstration AJAX Add-on

Discussion in 'Official Development Tutorials and Resources' started by Kier, Nov 23, 2010.

  1. Kier

    Kier XenForo Developer Staff Member

    This add-on is intended to be a demonstration of how to work with AJAX form submission data and return HTML that can be inserted into your page without a refresh.

    It takes the form of a very simple textbox into which notes can be entered, then when submitted, they appear in a list of recent notes below.

    The add-on makes use of XenForo.AutoValidator to facilitate the form submission, then uses custom code in the controller and the view layer to return template HTML and additional data.

    This video accompanies the add-on, and explains what is going on:


    Or view on Vimeo

    To install the add-on, decompress the zip then upload the contents of the upload directory (which should contain js/scratchpad and library/Scratchpad) and finally install the addon_Scratchpad.xml via the XenForo Add-on Installer system.
     

    Attached Files:

    wang, Adam K M, tranduybien and 15 others like this.
  2. Jaxel

    Jaxel Well-Known Member

    Would you look at that... it worked! Wonderful as always Kier... I tell ya, its really nice to get this kind of interaction with the developers. I can tell that XenForo is going to have a burgeoning mod community because of it...

    This is my new code: only the relevant bits of course...
    Code:
    public function actionMediaPost()
    {
    	$this->_assertPostOnly();
    
    	$mediaParts = explode('.', $this->slugs[0]);
    	$mediaID = end($mediaParts);
    
    	if (!$media = $this->getModelFromCache('EWRmedio_Model_Media')->getMediaByID($mediaID))
    	{
    		return $this->responseRedirect(XenForo_ControllerResponse_Redirect::SUCCESS, 'media');
    	}
    
    	$input['username'] = $this->_input->filterSingle('username', XenForo_Input::STRING);
    	$input['message'] = $this->getHelper('Editor')->getMessageText('message', $this->_input);
    	$this->getModelFromCache('EWRmedio_Model_Comments')->postComment($input, $media);
    
    	if ($this->_noRedirect())
    	{
    		return $this->actionMediaComments();
    	}
    
    	return $this->responseRedirect(XenForo_ControllerResponse_Redirect::SUCCESS,XenForo_Link::buildPublicLink('full:media', $media));
    }
    
    Code:
    <?php
    
    class EWRmedio_ViewPublic_MediaComments extends XenForo_ViewPublic_Base
    {
    	public function renderJson()
    	{
    		$output = $this->_renderer->getDefaultOutputArray(get_class($this), $this->_params, $this->_templateName);
    		$output['status'] = new XenForo_Phrase('your_comment_has_been_posted');
    		return XenForo_ViewRenderer_Json::jsonEncodeForOutput($output);
    	}
    }
    Code:
    XenForo.CommentPoster = function($form)
    {
    	$form.bind('AutoValidationBeforeSubmit', function(e)
    	{
    		XenForo.MultiSubmitFix($form);
    	});
    
    	$form.bind('AutoValidationComplete', function(e)
    	{
    		if (e.ajaxData.status)
    		{
    			$form.find('textarea[name=message]').val('').blur();
    
    			$('#CommentStatus').text(e.ajaxData.status);
    			setTimeout(function() { $('#CommentStatus').text(''); }, 4000);
    		}
    
    		if (e.ajaxData.templateHtml)
    		{
    			e.preventDefault();
    
    			new XenForo.ExtLoader(e.ajaxData, function()
    			{
    				$(e.ajaxData.templateHtml).xfInsert('replaceAll', '#mediaComments', 'xfShow');
    			});
    		}
    	});
    }
    
     
    HydraulicJack likes this.
  3. Jaxel

    Jaxel Well-Known Member

    Couple of notes...

    You have the following line in your scratchpad.js
    Code:
    	// re-enable the submit button if it's been disabled
    	$form.find('input:submit').removeAttr('disabled').removeClass('disabled');
    I don't see the use for this. Instead of manually disabling the submit button, I am using your built in
    "XenForo.MultiSubmitFix()" function, as it looks like it does all this automatically. It disables the submit button for 4 seconds the moment its clicked. I like this because it prevents double/triple posting.

    The next thing is that I decided NOT to use the "e.preventDefault()" function in my newest code. You say in your code that it prevents the Redirect Processing... but I don't think it does that. Even when I remove this function, it still prevents the redirect processing, probably because I am now returning a ResponseView, instead of a ResponseRedirect. So in essence this function's purpose should have nothing to do with that when it comes to FORMS. I understand it does work like this when you're replacing simple <A> tags, but for forms, it seems useless.

    Instead, it looks like the only thing it does for forms is disable the popdown error/success messages that show up when you make a post. I rather like these messages and I wish to keep them in. So I have taken the preventDefault function out. Are there any other negatives to doing this that I should be aware of? (yes, I ended my sentence with a preposition... but I'm American, its what we do!)

    Also, right now the popdown message is saying "Unspecified Error"... how do I edit this?
     
  4. Kier

    Kier XenForo Developer Staff Member

    Looks good. Only one comment:
    PHP:
    if ($this->_noRedirect())
    {
        return 
    $this->actionMediaComments(); 
    }
    Should probably be
    PHP:
    if ($this->_noRedirect())
    {
        return 
    $this->responseReroute(__CLASS__'media-comments');
    }
    As this will allow your own code to be extended in due course :)
     
  5. Allan

    Allan Well-Known Member

    When install xml file:
     
  6. Jaxel

    Jaxel Well-Known Member

    Don't you mean?
    Code:
    return $this->responseReroute(__CLASS__, 'MediaComments');
    Also... I just edited my last post with a question:
     
  7. Shadab

    Shadab Well-Known Member

    The addon's install file seems to have an unnecessary event listener. Removing that, I was able to install and test the addon successfully. Also, in /Scratchpad/Model/Node.php (Line 45); you should call the max() function:
    PHP:
            // ensure we have a meaningful value for $maxNotes
            
    if ($maxNotes max($maxNotes0))
            {

    Thanks for the demo! :)
     
  8. Kier

    Kier XenForo Developer Staff Member

    I manually re-enable the button because it's done after the textarea is cleared, and after the AJAX request has returned - so it's fine to allow things to resume immediately.
     
  9. Kier

    Kier XenForo Developer Staff Member

    Yes, you're right - I'll update the zip in a moment.
     
  10. Kier

    Kier XenForo Developer Staff Member

    No, it doesn't affect the PHP at all. It simply prevents the XenForo.AutoValidator Javascript function from continuing and posting the normal success message. See xenforo.js line 5199:
    Code:
    if (eComplete.isDefaultPrevented())
    {
    	return false;
    }
     
  11. Kier

    Kier XenForo Developer Staff Member

    Send a '_redirectMessage' phrase back along with your other AJAX data.
     
  12. Jaxel

    Jaxel Well-Known Member

    I'm getting an odd inspector response...

    Code:
        <form action="{xen:link 'full:media/post', $media}" method="post" style="margin: 0px;" class="messageSimple primaryContent AutoValidator" id="CommentPoster">
            <xen:avatar user="$visitor" size="s" />
            <div class="messageInfo">
                <xen:if is="!{$visitor.user_id}"><input type="text" name="username" class="textCtrl" placeholder="{xen:phrase guest}..." /></xen:if>
                <textarea name="message" class="textCtrl Elastic" placeholder="{xen:phrase post_comment}..." rows="3" cols="50"></textarea>
                <div style="margin-top: 8px; float: left;" id="CommentStatus"></div>
                <div class="submitUnit">
                    <input type="hidden" name="_xfToken" value="{$visitor.csrf_token_page}" />
                    <input type="submit" class="button primary" value="{xen:phrase post}" accesskey="s" />
                </div>
            </div>
        </form>
     
  13. Kier

    Kier XenForo Developer Staff Member

    It's an expected notice - you only need to be concerned if you to do want before-submission validation, like we have on the homepage field when you edit your personal details.
     
  14. Jaxel

    Jaxel Well-Known Member

    Is there any way to fix it? I dont like errors and warnings...
     
  15. Sir nick

    Sir nick Well-Known Member

    Easter Egg: Navigation has "Nudes" :eek:! Care to explain?
     
    Mikey likes this.
  16. Kier

    Kier XenForo Developer Staff Member

    Just hit up-up, down-down, left-right, left-right, q-r-y-i-p, delete, delete backspace enter.
     
  17. Kier

    Kier XenForo Developer Staff Member

    Code updated to resolve the oopsies spotted by Shadab.

    Now at version 0.2.
     
  18. Kier

    Kier XenForo Developer Staff Member

    You could give it a field validator I suppose, or alternatively just add a class of 'OptOut' to your textarea.
     
  19. Jaxel

    Jaxel Well-Known Member

    What will doing this do exactly?
     
  20. Kier

    Kier XenForo Developer Staff Member

    This was to be the subject of another video, but I'll lay out the basics here.

    XenForo.AutoValidator is a multi-purpose class. It does the following:
    1. Submits the form data via AJAX
    2. Receives back the AJAX response and determines if it is valid, and shows an appropriate set of errors if it's not
    3. Submits individual fields for validation before form submission, and displays inline errors if they do not validate.
    The first two parts are automatic, and happen simply by identifying a form as class="AutoValidator".

    The third part requires the use of a field validator action. This can be identified using data-fieldValidatorUrl="{xen:link prefix/validator-action}" in the form tag.

    An example field validator controller action might look like this:
    PHP:
    public function actionValidateField()
    {
        
    $this->_assertPostOnly();

        
    $field $this->_getFieldValidationInputParams();

        return 
    $this->_validateField('XenForo_DataWriter_User', array(
            
    'name' => $field['name'],
            
    'existingDataKey' => $this->_input->filterSingle('user_id'XenForo_Input::UINT)
        ));
    }
    It is possible to have the form act as an opt-in field validator, in which all fields are ignored unless they specifically include class="OptIn", or to have it as an opt-out system, in which all fields are included in the validation unless they include class="OptOut".

    Hope that goes some of the way to answering your question :)
     

Share This Page