initialization HD Quiz by ajax
-
I’m wanting to initiate the next question after the user clicks next button without reloading the page with ajax. However I only get the a tag back and it only has a page reload function. So is there any way to initialize it? Thank u so much!
-
This topic was modified 3 years, 10 months ago by
khanhfe.
-
This topic was modified 3 years, 10 months ago by
-
Hi khanhfe,
can you provide any information on what it is you are exactly doing and why you want to use ajax for this? The better I understand your goals, the better I can try and point you in the right direction 🙂Hi @harmonic_design,
I want the user to continue taking a new quiz after completing a previous quiz. However, I couldn’t find any solution, so I thought of passing a parameter to the do_shortcode function through the wordpress ajax, so that the server can execute this function. However, on the client side (front-end) I only get 1 a tag and my href attribute is empty, so when I click it it just reloads the page.The code that I write in the theme’s function is as follows:
add_action( 'wp_ajax_nopriv_handle_ajax_shortcode', 'handle_ajax_shortcode' ); add_action( 'wp_ajax_handle_ajax_shortcode', 'handle_ajax_shortcode' ); function handle_ajax_shortcode(){ $content = $_POST['dataShortcode']; $data = do_shortcode( $content ); wp_send_json_success($data); wp_die(); }Hope the above information can be useful to you. Now I have found an alternative solution but I feel it is not optimal so I would still appreciate your help.
Thank you so much!Off the top of my head, here are my first thoughts on the best way to do this.
One thing that comes to mind is that you’ll want to “reset” the quiz settings once you’ve loaded in a new quiz. This way we won’t have any conflicts with quiz settings or timers or anything like that. The easiest way is to this is to call
HDQ_INITwhich will take the initial printed settings and set them to the quiz. Of course, this would only work if your quizzes all use those same settings.To load in a new quiz, you are on the right track, but you have a fatal flaw. HD Quiz does not return data, but instead echos it directly. Strictly speaking, this is actually bad practice, but I do it this way to make enqueuing assets (css, js) far more consistent and compatible, while also ensuring that HD Quiz assets only ever load when a quiz is present.
To get around this, take a look at PHPs
ob_flushfunctions. Usingob_start,ob_get_contentsandob_end_cleanyou can “capture” the printed content and store it into a variable.Example:
ob_start(); echo do_shortcode( $content ); $data = ob_get_contents(); ob_end_clean();and then once your ajax call has finished, you can then run
HDQ_INIT()to reset the quiz settings.Hmm,
After trying to follow your instructions, i actually still only get a tag which is the data returned from the server. Also, I tried to run HDQ_INIT(), however, the browser console only logs one more time the message “HD Quiz Init” without any other changes. I tried to figure out why but still can’t understand the working flow of this plugin so I still need your help!
Thank you very much for your enthusiastic support!Or can I somehow create a link to another quiz? In this case no longer using ajax, however I think it’s the ultimate solution to what I’m having!
Here you go 🙂
This example does the following.
- Adds a new button to the end of a quiz that will load the next quiz. You can add this button anywhere you want. Just take note of…
- Adds the Javascript to the end of a quiz. This means that the code will only load on pages that have quizzes. The only thing to note is that this means that where you place the button needs to be ABOVE where this code executes. You can take this code and add it to your footer if that makes more sense for you instead.
- Send the current Quiz ID via ajax to the server
- On server, accepts the curent quiz ID, and using that, figures out what the “next” quiz to load should be. It then prints that entire quiz and sends back to the client
- Now back on our javascript, we add the new quiz to the site, remove the old quiz, reset the quiz settings, and scroll the site back to the top.
NOTE: You can ignore my “figure out what the next quiz should be” if you want. I just added it in because I thought it was cool haha.
/* HD Quiz - khanhfe */ // Load a new quiz via ajax call // and figure out what the "next" quiz to load is function hdq_khanhfe_after_quiz_content() { // this function allows us to add custom content to the end of a quiz // we are using it to add our custom javascript so that the code // only exists on pages that have a quiz on it ?> <!-- for this example, we are adding in the "next quiz" button here we are using 'div' instead of 'a' so that we do not have to link hijack --> <div id = "hdq_khanhfe_load_new_quiz" title = "Load Next Quiz" aria-role = "button" class = "button">Next Quiz</div> <script> function hdq_khanhfe_load_new_quiz() { document.getElementById("hdq_khanhfe_load_new_quiz").addEventListener("click", function () { /* HDQ.VARS.ajax is preloaded by HD Quiz * in this example, we are automatically grabbing the "next quiz" * so replace 'HDQ.VARS.id' with the quiz id of whatever quiz you want to load * a specific one instead */ const data = HDQ.VARS.id; // the current quiz ID. jQuery.ajax({ type: "POST", data: { action: "hdq_khanhfe_handle_ajax_shortcode", data: data, }, url: HDQ.VARS.ajax, success: async function (res) { // res will contain all of the HTML for the quiz. We can use this to replace the existing quiz const el = document.getElementsByClassName("hdq_quiz_wrapper")[0]; el.insertAdjacentHTML("beforebegin", res); el.remove(); await HDQ.init(); hdq_khanhfe_load_new_quiz(); // run this function again to reset the eventListener document.getElementsByClassName("hdq_before")[0].scrollIntoView({ behavior: "smooth", block: "start", inline: "nearest" }); }, }); }); } hdq_khanhfe_load_new_quiz(); </script> <?php } add_action("hdq_after", "hdq_khanhfe_after_quiz_content"); function hdq_khanhfe_handle_ajax_shortcode() { // this is the function that will be called via the ajax call $current_quiz_id = intval($_POST['data']); // we sent the quiz ID in the ajax call // now we grab as list of ALL quizzes, and loop through them until we find // the quiz whose ID matches current_quiz_id. We can then use this to grab // the next quiz in the list, or reset to the first if we are at the end $term_args = array( 'hide_empty' => true, // no point loading in an empty quiz! 'orderby' => 'name', // feel free to change 'order' => 'ASC', // these to whatever makes sense ); $quizzes = get_terms("quiz", $term_args); $next_quiz_id = 0; for($i = 0; $i < count($quizzes) - 1; $i++){ // since we are using quiz count - 1, if we do not find a match // we can assume that the current quiz was the last in the list if($quizzes[$i]->term_id === $current_quiz_id){ // get the quiz id for the next quiz in the list $next_quiz_id = $quizzes[$i + 1]->term_id; break; } } // if $next_quiz_id is still zero, then the current quiz was probably // the last in the list and we can reset to the first in the list if($next_quiz_id === 0){ $next_quiz_id = $quizzes[0]->term_id; } define('HDQ_REDIRECT', false); // this disalbes the "is_single" check for AMP pages // cool. we now have the quiz id for the next quiz! ob_start(); echo do_shortcode('[HDquiz quiz = "'.$next_quiz_id.'"]'); $data = ob_get_contents(); ob_end_clean(); echo $data; die(); } add_action( 'wp_ajax_nopriv_hdq_khanhfe_handle_ajax_shortcode', 'hdq_khanhfe_handle_ajax_shortcode' ); add_action( 'wp_ajax_hdq_khanhfe_handle_ajax_shortcode', 'hdq_khanhfe_handle_ajax_shortcode' );Yeah!
Thank you very much! I see your enthusiasm and am grateful for it! In the meantime waiting for your solution, I went back to the method I was thinking of as an alternative to ajax and it seems to be acceptable. Thank you again!Oh, I just reviewed your code. And I see I do the same and even shorter, however it fails and doesn’t work.:>
The topic ‘initialization HD Quiz by ajax’ is closed to new replies.