Helper functions
Qbix provides a few helper functions to generate URLs for making requests:
var url1 = Q.url("img/foo.png"); var url2 = Q.action("First/welcome");
Qbix uses these internally to generate absolute URLs, but they are also available for you to make use of in your own apps. Read the PHP guide to learn more about modules and actions.
Scripts and stylesheets
As we learn in the PHP output guide, a page can already include references to .js and .css files when it is sent to the browser. However, Qbix provides a way to load things at runtime as well:
// Add one or more scripts: Q.addScript(urls, onload, options); // Add one or more stylesheets: Q.addStylesheet(urls, onload, options);
Of course, Qbix applies Q.url( ) beforehand to anything that isn't an absolute URL.
Q.addScript is built to be as efficient as possible on all the browsers. It tries to fetch all the resources at once, but then appends them to the document and inserts them in the order they were passed. If a script already exists, however, it does not try to append and execute another copy, unless the we pass the option {duplicate: true}.
You can also use Q.findScript and Q.findStylesheet to quickly search for scripts and stylesheets already included into the document.
Require and Exports
Q provides a mechanism similar to Node.js for loading scripts, which you may want to use instead of Q.addScript(). In your script files, you can export certain variables, like this:
Q.exports(a, b, c); // called synchronously in file
Then you can simply load these scripts and get the exported variables:
Q.require(src, function (a, b, c) { // use the variables however you want });
If a javascript file has already been loaded, then the arguments to Q.export() are saved, and passed to the Q.require() callback for that src every time it's called. Otherwise, the script is fetched and executed first.
This may be useful for implementing patterns such as the following:
if (js = handlers[name]) { if (typeof js === 'string') { Q.require(js, function (js) { Q.handle(js, context, args); }); } else { Q.handle(js, context, args); } }
And then your handlers simply look like this:
"use strict"; (function(Q, $, undefined) { var _private = 2; Q.exports(function () { // do stuff }); })(Q, jQuery);
Dynamic Requests
You can use several methods in Q to make dynamic requests to servers. They include:
Q.request(url, slotNames, callback, options);
Check out all the different options in the client JS reference. They include "post", "method", "fields", "duplicate" and "timeout". You can learn more about the slotNames when reading about PHP requests and output. Until then, you can just pass null there.
If the url is on the same domain, XMLHttpRequest is used. For remote domains, Qbix issues a GET request by adding a script tag to the document temporarily. The suggested best practice is to avoid querying remote domains, and instead make use of client-side Cross-Domain Messaging with a library like EasyXDM.
Qbix also includes a shorthand method for issuing requests for a specific action. Once you learn about modules and actions, you will understand how to use this shorthand method:
Q.req("Module/action", slotNames, callback, opt);
More methods
Internally, Qbix uses the following methods for requests:
- Q.loadUrl to actually load the urls
- Q.ajaxExtend to extend URLs with extra information
- Q.serializeFields to prepare data to be sent via HTTP
You can also use Q.formPost to make dynamic requests via form post (the drawback is that you can't access the output).
Q.handle is an all-purpose function to "handle" whatever you give it, whether an event, a function, a URL, or some string to eval.
Response
When a Qbix server processes a dynamic request, the generated output is typically a JSON structure that looks like this on success:
{ "slots": { ... }, "timestamp": ... }
And like this if there were errors:
{ "errors": { ... }, "timestamp": ... }
When making requests in your code, you should typically use the function Q.firstErrorMessage to process the errors and see if there are any messages to display. You can also use Q.ajaxErrors for displaying form validation errors.
When you learn about the Streams API, you'll drastically reduce the amount of code you write for issuing and handling requests yourself.
This topic is developed further when we discuss loading pages with Qbix
Visual feedback
Among the options you can pass to Q.handle, Q.loadUrl, Q.request and Q.req is "quiet". By default, Q.request and Q.req have "quiet" set to false, whereas Q.handle and Q.loadUrl have it set to true.
When "quiet" is not false, Qbix fires "onLoadStart" and "onLoadEnd" events that can be used to do things like darken the screen and show a "cancel" button on a mobile device. In fact, Qbix provides default handlers that do exactly this.
Cookies
Qbix provides a function to work with cookies:
// Read a cookie var value = Q.cookie(name); // Set a cookie Q.cookie(name, value, options); // Remove a cookie Q.cookie(name, null);
The cookies are tied to your domain, which presents additional issues for Cordova apps.
Nonce
Web apps are often vulnerable to Cross-Site Request Forgery attacks, which occur when a different website initiates a request to your web app server while the user is logged in. Because your app receives the right cookies, it executes the request and returns some output. To prevent this, Qbix saves a nonce in the session and encourages your request handlers to make sure it's valid before proceeding.
If a page is generated dynamically by PHP, the nonce is usually already generated and rendered as part of the page, so no additional request to the server is made to obtain it.