// Initialize the Drupal JSON object and run the bootstrap, if necessary.
var Drupal = {}; drupal_init();
var jDrupal = Drupal; // @TODO deprecate Drupal in favor of jDrupal object.
/**
* Initializes the Drupal JSON object.
*/
function drupal_init() {
try {
if (!Drupal) { Drupal = {}; }
// General properties.
Drupal.csrf_token = false;
Drupal.sessid = null;
Drupal.user = drupal_user_defaults();
// Settings.
Drupal.settings = {
app_directory: 'app',
base_path: '/',
cache: {
entity: {
enabled: false,
expiration: 3600
},
views: {
enabled: false,
expiration: 3600
}
},
debug: false,
endpoint: '',
file_public_path: 'sites/default/files',
language_default: 'und',
site_path: ''
};
// Includes. Although we no longer dynamically load the includes, we want
// to place them each in their own JSON object, so we have an easy way to
// access them.
Drupal.includes = {};
Drupal.includes['module'] = {};
// Modules. Although we no longer dynamically load the core modules, we want
// to place them each in their own JSON object, so we have an easy way to
// access them.
Drupal.modules = {
core: {},
contrib: {},
custom: {}
};
// Build a JSON object to house the entity service request queues. This is
// used to prevent async calls to the same resource from piling up and
// making duplicate requests.
// @TODO - this needs to be dynamic, what about custom entity types?
Drupal.services_queue = {
comment: {
retrieve: {}
},
file: {
retrieve: {}
},
node: {
retrieve: {}
},
taxonomy_term: {
retrieve: {}
},
taxonomy_vocabulary: {
retrieve: {}
},
user: {
retrieve: {}
}
};
// Build a JSON object to house cache expiration indices.
Drupal.cache_expiration = window.localStorage.getItem('cache_expiration');
if (!Drupal.cache_expiration) {
Drupal.cache_expiration = {
// Entities will expire by a key value (key timestamp) pair
entities: {}
};
}
else { Drupal.cache_expiration = JSON.parse(Drupal.cache_expiration); }
}
catch (error) { console.log('drupal_init - ' + error); }
}
/**
* Equivalent to PHP's date function. You may optionally pass in a second int
* timestamp argument (number of milliseconds since epoch, not the number of
* seconds since the epoch) to format that particular time, otherwise it'll
* default to the current time.
* @param {String} format The format of the outputted date string.
* @return {String}
* @see http://php.net/manual/en/function.date.php
*/
function date(format) {
try {
// @TODO - create a github repo for this function.
// Let's figure out the timestamp and date.
var d = null;
var timestamp = null;
if (arguments[1]) {
timestamp = arguments[1];
if (typeof timestamp === 'string') { timestamp = parseInt(timestamp); }
d = new Date(timestamp);
}
else {
d = new Date();
timestamp = d.getTime();
}
var result = '';
var grab_next = false;
for (var i = 0; i < format.length; i++) {
var character = format.charAt(i);
if (grab_next) {
result += character;
grab_next = false;
continue;
}
switch (character) {
// Escape character.
case '\\':
grab_next = true;
break;
/* DAY */
// Day of the month, 2 digits with leading zeros: 01 to 31
case 'd':
var day = '' + d.getDate();
if (day.length == 1) { day = '0' + day; }
result += day;
break;
// A textual representation of a day, three letters: Mon through Sun
case 'D':
var day = d.getDay();
switch (day) {
case 0: result += 'Sun'; break;
case 1: result += 'Mon'; break;
case 2: result += 'Tue'; break;
case 3: result += 'Wed'; break;
case 4: result += 'Thu'; break;
case 5: result += 'Fri'; break;
case 6: result += 'Sat'; break;
}
break;
// Day of the month without leading zeros: 1 to 31
case 'j': result += d.getDate(); break;
// A full textual representation of the day of the week: Sunday through
// Saturday
case 'l':
var day = d.getDay();
switch (day) {
case 0: result += 'Sunday'; break;
case 1: result += 'Monday'; break;
case 2: result += 'Tuesday'; break;
case 3: result += 'Wednesday'; break;
case 4: result += 'Thursday'; break;
case 5: result += 'Friday'; break;
case 6: result += 'Saturday'; break;
}
break;
// 1 (for Monday) through 7 (for Sunday)
case 'N':
result += d.getDay() + 1;
break;
// 0 (for Sunday) through 6 (for Saturday)
case 'w':
result += d.getDay();
break;
/* WEEK */
/* MONTH */
// A full textual representation of a month, such as January or March:
// January through December
case 'F':
switch (d.getMonth()) {
case 0: result += 'January'; break;
case 1: result += 'February'; break;
case 2: result += 'March'; break;
case 3: result += 'April'; break;
case 4: result += 'May'; break;
case 5: result += 'June'; break;
case 6: result += 'July'; break;
case 7: result += 'August'; break;
case 8: result += 'September'; break;
case 9: result += 'October'; break;
case 10: result += 'November'; break;
case 11: result += 'December'; break;
}
break;
// Numeric representation of a month, with leading zeros: 01 through 12
case 'm':
var month = '' + (d.getMonth() + 1);
if (month.length == 1) { month = '0' + month; }
result += month;
break;
// A short textual representation of a month, three letters
case 'M':
switch (d.getMonth()) {
case 0: result += 'Jan'; break;
case 1: result += 'Feb'; break;
case 2: result += 'Mar'; break;
case 3: result += 'Apr'; break;
case 4: result += 'May'; break;
case 5: result += 'Jun'; break;
case 6: result += 'Jul'; break;
case 7: result += 'Aug'; break;
case 8: result += 'Sep'; break;
case 9: result += 'Oct'; break;
case 10: result += 'Nov'; break;
case 11: result += 'Dec'; break;
}
break;
/* YEAR */
// A full numeric representation of a year, 4 digits.
// Examples: 1999 or 2003
case 'Y':
result += d.getFullYear();
break;
/* TIME */
// Lowercase Ante meridiem and Post meridiem: am or pm
case 'a':
// Uppercase Ante meridiem and Post meridiem: AM or PM
case 'A':
var hours = d.getHours();
if (hours < 12) { result += 'am'; }
else { result += 'pm'; }
if (character == 'A') { result = result.toUpperCase(); }
break;
// 12-hour format of an hour without leading zeros: 1 through 12
case 'g':
var hours = d.getHours();
if (hours == 0 || hours == 23) { hours = 12; }
else { hours = hours % 12; }
result += '' + hours;
break;
// 24-hour format of an hour without leading zeros: 0 through 23
case 'G':
var hours = '' + d.getHours();
result += hours;
break;
// 12-hour format of an hour with leading zeros: 01 through 12
case 'h':
var hours = '' + (d.getHours() % 12);
if (hours == '0') { hours = '12'; }
else if (hours.length == 1) { hours = '0' + hours; }
result += hours;
break;
// 24-hour format of an hour with leading zeros: 00 through 23
case 'H':
var hours = '' + d.getHours();
if (hours.length == 1) { hours = '0' + hours; }
result += hours;
break;
// Minutes with leading zeros: 00 to 59
case 'i':
var minutes = '' + d.getMinutes();
if (minutes.length == 1) { minutes = '0' + minutes; }
result += minutes;
break;
// Seconds with leading zeros: 00 to 59
case 's':
var seconds = '' + d.getSeconds();
if (seconds.length == 1) { seconds = '0' + seconds; }
result += seconds;
break;
default:
// Any characters that we don't know how to process, just place them
// onto the result.
result += character;
break;
}
}
return result;
}
catch (error) { console.log('date - ' + error); }
}
/**
* Given a JSON object or string, this will print it to the console. It accepts
* an optional boolean as second argument, if it is false the output sent to the
* console will not use pretty printing in a Chrome/Ripple environment.
* @param {Object} data
*/
function dpm(data) {
try {
if (typeof data !== 'undefined') {
if (typeof parent.window.ripple === 'function') {
if (typeof arguments[1] !== 'undefined' && arguments[1] == false) {
console.log(JSON.stringify(data));
}
else {
console.log(data);
}
}
else if (typeof data === 'object') { console.log(JSON.stringify(data)); }
if (data == '') { console.log('<empty-string>'); }
else { console.log(data); }
}
else { console.log('<undefined>'); }
// Show the caller name.
//var caller = arguments.callee.caller.name + '()';
//console.log(caller);
}
catch (error) { console.log('dpm - ' + error); }
}
/**
* Returns a default JSON object representing an anonymous Drupal user account.
* @return {Object}
*/
function drupal_user_defaults() {
try {
return {
uid: '0',
roles: {'1': 'anonymous user'},
permissions: []
};
}
catch (error) { console.log('drupal_user_defaults - ' + error); }
}
/**
* Returns true if given value is empty. A generic way to test for emptiness.
* @param {*} value
* @return {Boolean}
*/
function empty(value) {
try {
if (value === null) { return true; }
if (typeof value === 'object') { return Object.keys(value).length === 0; }
return (typeof value === 'undefined' || value == '');
}
catch (error) { console.log('empty - ' + error); }
}
/**
* Given a JS function name, this returns true if the function exists in the
* scope, false otherwise.
* @param {String} name
* @return {Boolean}
*/
function function_exists(name) {
try {
return (eval('typeof ' + name) == 'function');
}
catch (error) {
alert('function_exists - ' + error);
}
}
/**
* Given an integer http status code, this will return the title of it.
* @param {Number} status
* @return {String} title
*/
function http_status_code_title(status) {
try {
// @todo - this can be replaced by using the statusText property on the XHR
// object.
//https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#Properties
var title = '';
switch (status) {
case 200: title = 'OK'; break;
case 401: title = 'Unauthorized'; break;
case 404: title = 'Not Found'; break;
case 406: title = 'Not Acceptable'; break;
case 500: title = 'Internal Server Error'; break;
}
return title;
}
catch (error) {
console.log('http_status_code_title - ' + error);
}
}
/**
* Checks if the needle string, is in the haystack array. Returns true if it is
* found, false otherwise. Credit: http://stackoverflow.com/a/15276975/763010
* @param {String|Number} needle
* @param {Array} haystack
* @return {Boolean}
*/
function in_array(needle, haystack) {
try {
if (typeof haystack === 'undefined') { return false; }
if (typeof needle === 'string') { return (haystack.indexOf(needle) > -1); }
else {
var found = false;
for (var i = 0; i < haystack.length; i++) {
if (haystack[i] == needle) {
found = true;
break;
}
}
return found;
}
}
catch (error) { console.log('in_array - ' + error); }
}
/**
* Given something, this will return true if it's an array, false otherwise.
* @param {*} obj
* @returns {boolean}
* @see http://stackoverflow.com/a/1058753/763010
*/
function is_array(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}
/**
* Given an argument, this will return true if it is an int, false otherwise.
* @param {Number} n
* @return {Boolean}
*/
function is_int(n) {
// Credit: http://stackoverflow.com/a/3886106/763010
if (typeof n === 'string') { n = parseInt(n); }
return typeof n === 'number' && n % 1 == 0;
}
/**
* Get the default language from Drupal.settings.
* @return {String}
*/
function language_default() {
try {
if (Drupal.settings.language_default &&
Drupal.settings.language_default != '') {
return Drupal.settings.language_default;
}
return 'und';
}
catch (error) { console.log('language_default - ' + error); }
}
/**
* Given a module name, this returns true if the module is enabled, false
* otherwise.
* @param {String} name The name of the module
* @return {Boolean}
*/
function module_exists(name) {
try {
var exists = false;
if (typeof Drupal.modules.core[name] !== 'undefined') {
exists = true;
}
else if (typeof Drupal.modules.contrib[name] !== 'undefined') {
exists = true;
}
else if (typeof Drupal.modules.custom[name] !== 'undefined') {
exists = true;
}
return exists;
}
catch (error) { console.log('module_exists - ' + error); }
}
/**
* Shuffle an array.
* @see http://stackoverflow.com/a/12646864/763010
* @param {Array} array
* @return {Array}
*/
function shuffle(array) {
try {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
catch (error) { console.log('shuffle - ' + error); }
}
/**
* Javascript equivalent of php's time() function.
* @return {Number}
*/
function time() {
var d = new Date();
return Math.floor(d / 1000);
}
/**
* Given a string, this will change the first character to upper case and return
* the new string.
* @param {String} str
* @return {String}
*/
function ucfirst(str) {
// @see http://kevin.vanzonneveld.net
// + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + bugfixed by: Onno Marsman
// + improved by: Brett Zamir (http://brett-zamir.me)
str += '';
var f = str.charAt(0).toUpperCase();
return f + str.substr(1);
}