Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I just invented PSEUDO Query!

var objects = $.pquery([
    '##pquery##', // Initialize as PSEUDO Query Object
    [document.body, 'css', [{'background-color':'#f00'}], 'append',
        ['##pquery##', // Helps distinguish array needing parsing from array of arguments
        '<div />', 'text', 'LOL!']
    ],
    ['textarea', 'css', ['background-color', '#0f0']]
]);

...Is equivalent to:

var objects = [
    $(document.body).css({background-color: '#f00'}).append($('<div />').text('LOL!')),
    $('textarea').css('background-color', '#0f0')
];

Example image (got spam blocked for too low of reputation):
http://i.stack.imgur.com/IoSgi.png

The point?
The point of this is in no way for added readability, but rather to provide a means to execute jQuery via PHP outputted JSON through Ajax. I believe this is going to make possible a nicely structured, and well defined output class for PHP, with very little code.

Ultimately, my goal is to have all clients long polling the server, to accept new Javascript and commands at any given moment. I plan to use jQuery for exactly what it is, as a framework, and extend any common commands/routines directly to it as extensions. Eventually I'll revise the structure to support $.method() calls, without having to have a selector. I might need some ideas for the best way to go about that, without causing problems.

What are the advantages? added 2/21/2012 2:00pm
- Easy PHP output
- Strictly governed remote script execution

What are some concerns with this? updated 2/21/2012 2:00pm
I wanted to avoid it, but I think I'm going to have to eval the Ajax array, for setting callback functions. Or I'll just pass it to a new <script /> element, and delete it after parse. Another option is to add some method to detect function structures, and pass the quoted code through new Function. The last option I can think of, is to only allow predefined functions, which I've already extended to jQuery. I've heard it is bad to pass Javascript through through JSON, however I feel it is necessary if I'm going to be constructing new objects with bound events. I also feel that maybe this whole thing may be a little redundant if I'm going to just eval the code, but there's still the factor of easy output with PHP, which makes me want to continue with this extension. Basically, I'm not sure what the best way to handle my JSON would be. Should I accept text only, or allow Javascript in the mix and evaluate the array into a variable?
This is the area that I could really use the most advice and opinions about.

Another concern I realized is the need for a PHP compatible way to output unquoted Javascript variables, from PHP arrays to json_encode($array);. This likely isn't very easily possible, and would demean the value of this extension, which is supposed to define a simple protocol to make PHP output much easier and very efficient.

Can you help me?
Any structural/general ideas or concerns about this? Or possibly some suggestions to just scrap the whole thing, and start with a different approach to the madness?

The code added 2/21/12 2:00pm
I'm not a big fan of comments, and since this post is more a question on what the best possible structure would be, to avoid issues and maintain functionality, I didn't think it would be necessary to post the code to the actual extension. Due to popular demand(lol?), here is the code for the actual pQuery extension:

(function ($, undefined) {
    function object_type (o) { // To replace typeof
        var type = Object.prototype.toString.call(o); // Returns [object "instanceof"], etc
        return type.substring(8, --type.length); // Removes [object ...] and returns value
    }

    var header; // Scope-global header var set in $.pquery

    function pquery (query) { // Parse a single array
        var selector = query.shift(), // Expects selector to be in front at this point
            _selector_type = object_type(selector),
            $selector = ( // Set as a jQuery options
                _selector_type == 'Array'
                    ? $.apply(window, selector) // Multiple values for jQuery() is valid
                    : $.call(window, selector) // Single selector value
            );

        // Consider adding a statement to return if $selector.length is less than one

        while (query.length > 0) { // Loop through rest of  query
            var method = query.shift() || '', // Expects a method to be in front at this point
                _method_type = object_type(method),
                args = query.shift() || [], // Expects arguments to be in front at this point
                _args_type = object_type(args);

            if (_method_type != 'String') { // Name of method should always be a string
                console.log("Method: %o\nArguments: %o\nError: %s", method, args, "pQuery expects all methods to be a string");
                /* Dump is a seperate information class of mine
                dump.log('Uncaught exception', ["Method: %o\nArguments: %o\nError: %s", method, args, "pQuery expects all methods to be a string"]);
                dump.out('Uncaught exception', true);
                */
                return; // Array is out of sync
            }

            if (object_type($selector[method]) == 'Function') { // Check to make sure requested method exists
                if (_args_type != 'Array') { // Arguments should always be an array
                    console.warn('Argument type "%s" should be an array for method "%s"', _args_type, method);
                    args = new Array(args); // Convert to array expected by apply
                }
                else if (args[0] === header) // Header helps us distinguish pQuery arrays from argument arrays
                    args = $.pquery(args); // If first argument matches the header, we parse it as pQuery

                try {
                    $selector[method].apply($selector, args); // Call the methods
                }
                catch (e) {
                    console.log("Method: %s\nArguments: %o\nError: %s", method, args, e.message); //Show the errors
                    /*
                    dump.log('Caught exception', ["Method: %s\nArguments: %o\nError: %s", method, args, e.message]);
                    dump.out('Caught exception', true);
                    */
                }
            }
            else console.warn('Method "%s" does not exist', method); // Allows moving to next method, instead of returning
        }

        return $selector; // Return a single jQuery object
    }

    $.pquery = function (subject, pheader) { // Accept array and a custom header
        var _subject_type = object_type(subject),
            buffer = []; // Output array

        header = (
            object_type(pheader) == 'String'
                ? pheader // Custome header string
                : '##pquery##' // Default header string
        );

        if (_subject_type == 'Array') { // Query structure is defined by array
            if (subject.shift() !== header) { // Not a valide pQuery array
                console.log("Header: %o\nError: %s", header, "The first value of a valid pQuery array should be a header value");
                /*
                dump.log('Uncaught exception', ["Header: %o\nError: %s", header, "The first value of a valid pQuery array should be a header value"]);
                dump.out('Uncaught exception', true);
                */
                return;
            }

            var _form_type = object_type(subject[0]),
                __form_type = object_type(subject[1]);

            // The follow statements trys to distinguish an array of arrays from an array of values
            if (_form_type == 'Array' && (__form_type == 'Array' || __form_type == 'Undefined')) { // Array or arrays, probably multiple queries
                $.each(subject, function (i, query) {
                    buffer.push(pquery(query)); // Push single jQuery object onto return array
                });
            }
            else if ((_form_type == 'String' || _form_type == 'Array') && __form_type != 'Array') // Array of values, probably a single query
                buffer = pquery(subject); // Sets return array to a single jQuery object
            else {
                console.log("Method: %o\nArguments: %o\nError: %s", method, args, "pQuery expects an array of arrays, or an array beginning with a selector");
                /*
                dump.log('Uncaught exception', ["Method: %o\nArguments: %o\nError: %s", method, args, "pQuery expects an array of arrays, or an array beginning with a selector"]);
                dump.out('Uncaught exception', true);
                */
            };
        }
        else throw "pQuery expects an array";

        console.log(buffer);
        return buffer;
    }
})(jQuery);
share|improve this question

1 Answer

(Not sure if this is a comment or an answer...)

First off this seems to be off topic, since there isn't really any code to review, but I'll just ignore that for now :-)

I'm not sure if there is a real use for this. Web apps normally don't need to execute arbitrary JavaScript, but instead just have a static library which gets data via AJAX on what they want to do. Can you give a more concrete use case?

Also I don't really understand what you are saying in the "concerns" section. Are you asking how to execute the "generated" JavaScript? In that case I'd use apply and/or call.

Finally I'm not really fond of the marker string ('##pquery##'). I'm sure it's possible to use a different data structure that doesn't require it.

share|improve this answer
I've added the code, and revised some of my explanations a little bit. For my concerns section, I'm basically trying to decide if I should allow raw Javascript to be passed or not. If you have some ideas for an easily identifiable structure, that would not require the header (##pquery##), please share. I'm mainly trying to get feedback about the structure of the "protocol". Feel free to revise your answer, I'm constantly rereading for things I may have missed. – Shea Feb 21 '12 at 22:03
Basically, I need a structure that is capable of behaving exactly like jQuery, with full functionality. – Shea Feb 21 '12 at 22:08

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.