Asked  2 Years ago    Answers:  5   Viewed   65 times

I've built an online community in Drupal with a homepage that is kind of like the Facebook wall. You see the 25 most recent posts, with the two most recent comments below those posts. There is also a textarea right below those comments so that you can quickly post a new comment on a particular post.

These Facebook-style posts have a lot of functionality built into them via JavaScript. Clicking a "view all comments" link directly below a post makes an AJAX call that grabs all the comments for that post and displays them right below it. You can also mark posts as helpful, as the solution to your question, edit comments inline, etc. All of these actions require AJAX requests, which means that the JavaScript making the request needs to know essential information such as the Node ID (the unique identifier of the post), the comment ID (unique identifier of the comment), etc.

My initial implementation had these pieces of essential data sprinkled all over the posts, making it more complicated to write the JS that needed to find it. So my second implementation simply output all this data into a JSON-compatible string in the main wrapping element of each post. While this made it much easier for the JS to find the data it needed, writing JSON as a string is a pain (escaping quotes, no line breaks).

So now I have a third idea, and I'm looking for feedback on it prior to implementation. The idea is to create a single global JS Array for all these posts that contains within it objects that hold the data for each post. Each element in that array would hold the necessary data needed for the AJAX calls. So it would look something like this:

Facebook-style post template

<div class="post" data-postindex="<?php echo $post->index; ?>">
    <!-- lots of other HTML for the post -->
</div>
<script type="text/javascript">
    globalPostArray.push({
        nid: <?php echo $post->nid; ?>,
        authorID: <?php $post->authorID; ?>,
        //etc. etc. etc.
    });
</script>

The result of the above code is that when a link gets clicked that requires an AJAX request, the JS would simply traverse the DOM upwards from that link until it finds the main .post element. It would then grab the value of data-postindex in order to know which element in globalPostArray holds the data it needs.

Thoughts? I feel like there must be some standard, accepted way of accomplishing something like this.

 Answers

5

I've never heard of a standard way to "pass" information between PHP and Javascript, as they are a server-side and client-side language, respectively. I would personally use a hybrid of your second and third solutions.

Store the post id in a data-postindex attribute (data attributes are newish, and the "right" way to store small amounts of data). But I would still just use a JSON array for the rest, as storing lots of data in data-attributes (and escaping them!) is potentially problematic. PHP has a json_encode function that takes care of all the escaping and such for you - just build a PHP array (say, $postdata) like you normally would, and then throw this in your post template:

<script type="text/javascript">
    globalPostArray.push(<?php echo json_encode($postdata) ?>);
</script>

Where $postdata is something like the following:

$postdata = array(
    'nid' => 5,
    'authorId' => 45
    ...etc...
);

It should be easy enough to generate such an array from your existing code.

I wrote a blog post a while back about my implementation of this kind of thing, but it sounds like all you need is a pointer at json_encode.

Monday, August 8, 2022
2
<script>
   $.ajax({
      type: "POST",
      url: "index.php",
      data: {var:'value'},
      dataType: 'text',
      success:function(data){
       // Test what is returned from the server
         alert(data);
      }
    });
 </script>
Thursday, August 25, 2022
1

Your quick solution would be:

$("#select_coffee_talk_year").button().click(function() {
    var form = $('#coffee_talk_year');  
    var data = form.serialize();

    $.ajax({
        url: "include/scripts/select_event.php",
        type: "POST",
        data: data,
        dataType: 'json',
        success: function (select) {
            var coffee_talk = $("#coffee_talk");
            coffee_talk.fadeOut('fast', function() {
                for(i in select) {
                    row = select[i];
                    div = coffee_talk.append('<div id="row_'+i+'" />');
                    for(column in row) {
                       div.append('<span class="column_'+column+'">'+row[column]+'</span>');
                    }
                }
                coffee_talk.fadeIn();
            });
        }   
    });
    return false;
});

For a nicer approach you should lookup Moustache.js which is a client side JavaScript templating engine (which has equivalents in PHP/Java/Ruby/Python/Go and other languages and is based on Google CTemplates).

It will allow you to create HTML templates and populate them with the data you have in a variable such as the JSON variable an AJAX request might receive.

Friday, November 4, 2022
 
abhinav
 
5

You can also use Prototype's function toJSON() to convert an array into a JSON object. After passing it to server via Ajax call, simply use PHP's function json_decode() to decode the object.

Thursday, November 10, 2022
3

In my MVC URLs look like: index.php?c=Controller&m=ControllerMethod&d=slash/sepparated/list/of/stuff

Data (d=) is exploded on the slashes and passed as an array to every controller method. Autoloading (via spl_autoload_register()) is used to call the class (c=) and then the method in that class (m=).

Also, it sounds like you're either not setting the ACTION on your form or you're deliberately setting the ACTION to GET. As a general rule, ACTION should be POST to keep the URLs sane. Except search forms. Those can be GET with various advantages.

Re-directing to prevent a resubmitted form on refresh is your best option (probably only option). But in my MVC index.php?c=user&m=login handles both the login page and the login action.

Example

class login extends Controller {

    public function login($data) {

        if(empty($_POST)) {

            $this->view = "login.tpl";

            return TRUE;

        }


        $res = $this->model->auth();

        if($res !== TRUE) {

            $_POST = NULL;

            $this->errorState = 1;
            $this->errorMsg = "Invalid login details";

            $this->login();

            return FALSE;

        }

        Core::setMessage('success', 'user', 'login', '2', 'Logged in successfully');

        $home = new home(); //whatever the main controller is
        $home->index($data);

        //alternatively you can redirect

        header("Location: index.php?c=home&m=index);

        return TRUE;

    }

}

Does this make sense or have I completely missed the mark?

Sunday, August 7, 2022
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 

Browse Other Code Languages