XenForo AJAX Tutorial

Okay, that's what I thought you were doing. How about not doing that separate AJAX call at all, and having the necessary templates etc. to refresh your comment list (or just the latest comments) be returned from the same request that submits the form data? Having that extra XenForo.ajax() call is rather wasteful of resources. I've got to take the kids to nursery now, but I'll embellish some details when I return unless you've already worked it out. :)
I'm not exactly sure how I would do that...

Why is it a waste of resources? The queries will be going either way, wont they?

Below is the code for my comment switcher, and the comment poster
Code:
	public function actionMediaComments()
	{
		$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');
		}

		$options = XenForo_Application::get('options');
		$start = $this->_input->filterSingle('page', XenForo_Input::UINT) < 1 ? 1 : $this->_input->filterSingle('page', XenForo_Input::UINT);
		$stop = $options->EWRmedio_commentcount;

		$viewParams = array(
			'perms' => $this->perms,
			'start' => $start,
			'stop' => $stop,
			'media' => $media,
			'count' => $this->getModelFromCache('EWRmedio_Model_Comments')->getCommentCount($media),
			'comments' => $this->getModelFromCache('EWRmedio_Model_Comments')->getComments($media, $start, $stop),
		);

		return $this->responseView('EWRmedio_ViewPublic_MediaComments', 'EWRmedio_MediaComments', $viewParams);
	}

	public function actionMediaPost()
	{
		$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');
		}

		if ($this->_request->isPost())
		{
			$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);
		}

		return $this->responseRedirect(
			XenForo_ControllerResponse_Redirect::SUCCESS,
			XenForo_Link::buildPublicLink('full:media', $media),
			null,
			array(
				'newurl' => XenForo_Link::buildPublicLink('full:media/comments', $media),
				'status' => new XenForo_Phrase('your_comment_has_been_posted')
				)
		);
	}
 
Okay, let's take a look here Jason...

First thing to do is to update your Javascript. We don't want that second AJAX call, it's a big waste of resources to make that second connection, so let's alter the Javascript to expect the templateHtml to be returned by the first AJAX request:
Code:
// updates comment list after validation
$form.bind('AutoValidationComplete', function(e)
{
    // blurs focus away from submit button, dont see purpose of this line
    $form.find('input:submit').blur();

    // sets contents of a "status" DIV in template, removes status notice after 4 seconds
    if (e.ajaxData.status)
    {
        $('#CommentStatus').text(e.ajaxData.status);
        setTimeout(function() { $('#CommentStatus').text(''); }, 4000);
    }

    // gets information about the contents of text area
    var StatusEditor,
        $textarea = $form.find('textarea[name="message"]')
        .val('')
        .blur();

    // clears contents of text area
    if (StatusEditor = $textarea.data('XenForo.StatusEditor'))
    {
        StatusEditor.update();
    }

    // now replace the existing comments with the templateHtml that was returned
    $(ajaxData.templateHtml).xfInsert('replaceAll', '#mediaComments', 'xfShow');
});
Next, we need to alter your PHP to return the template.

I don't know the exact code you're running obviously, so this will be a basic guide that should be able to decipher.

Where you currently have this (or something similar) in your public controller:
PHP:
public function actionSaveComment()
{
	$data = $this->_input->filter(array(
		// some stuff
	));

	$writer = XenForo_DataWriter::create('JxCommentFeed_DataWriter_Comment');
	$writer->bulkSet($data);
	$writer->save();

	return $this->responseRedirect(
		XenForo_ControllerResponse_Redirect::SUCCESS,
		XenForo_Link::buildPublicLink('comment-feed')
	);
}
Try changing it to something like this:
PHP:
public function actionSaveComment()
{
	$data = $this->_input->filter(array(
		// some stuff
	));

	$writer = XenForo_DataWriter::create('JxCommentFeed_DataWriter_Comment');
	$writer->bulkSet($data);
	$writer->save();

	// XenForo AJAX calls always send an _xfNoRedirect parameter,
	// which allows us to detect if the request came from AJAX
	if ($this->_noRedirect())
	{
		$commentModel = $this->getModelFromCache('JxCommentFeed_Comment');

		$viewParams = array(
			'comments' => $commentModel->getLatestComments()
		);

		return $this->responseView(
			'JxCommentFeed_ViewPublic_LatestComments',
			'jxcommentfeed_latest_comments',
			$viewParams
		);
	}

	return $this->responseRedirect(
		XenForo_ControllerResponse_Redirect::SUCCESS,
		XenForo_Link::buildPublicLink('comment-feed')
	);
}
I hope that was reasonably clear... If not, take a look at actionComment() in XenForo_ControllerPublic_ProfilePost and see how it does a very similar thing around line 365.

Good luck!
 
I hope that was reasonably clear...

Good luck!
I do see one complication... You are replacing the ResponseRedirect with a ResponseView to get templateHtml. The problem is that my ResponseView was sending additional JSON parameters
Code:
		return $this->responseRedirect(
			XenForo_ControllerResponse_Redirect::SUCCESS,
			XenForo_Link::buildPublicLink('full:media', $media),
			null,
			array(
				'newurl' => XenForo_Link::buildPublicLink('full:media/comments', $media),
				'status' => new XenForo_Phrase('your_comment_has_been_posted')
				)
		);
How would I send those extra parameters 'newurl' and 'status' in ResponseView?
 
I do see one complication... You are replacing the ResponseRedirect with a ResponseView to get templateHtml. The problem is that my ResponseView was sending additional JSON parameters. How would I send those extra parameters 'newurl' and 'status' in ResponseView?
Video and demo code now uploading... all will become clear :)
 
Okay... here is an odd one for you...

OverlayTrigger is awesome, it does a popup overlay on click...

Is there any way I can get the overlay to popup on page load?
 
This thread, or just the videos should be added to the help section so they can be found easily in the future.

Thanks, Jeff
 
Hey Kier, can I ask you exactly what "data-optInOut" does?
Let's say you have a form with four text boxes. The default XenForo.AutoValidator behaviour is to validate all those fields on blur, and individual fields have to expressly opt-out of the validation to prevent it from firing.

Sometimes, you have more fields that should not be inline-validated than those that should be, so you switch the behaviour from opt-out to opt-in, meaning that fields have to expressly opt-in to the validation process or they will be ignored and only validated on form submission.

Does that answer your question?
 
data-optInOut prevents some fields from autovalidation.
You could check my invite add-on, there i'm using this;)

Edit: oh, kier was faster
 
Kier is there a way to say "add <div class="secondaryContent"> " if only used in a overlay?
Am trying to get the register_form to work but as it has no background (in a overlay).
Or should I just make a new template and call that?

Cheers awesome video btw thanks alot
 
Kier is there a way to say "add <div class="secondaryContent"> " if only used in a overlay?
Am trying to get the register_form to work but as it has no background (in a overlay).
Or should I just make a new template and call that?

Cheers awesome video btw thanks alot
Try adding 'formOverlay' as a class to the register form.
 
Top Bottom