SpontaneousCMS/spontaneous

View on GitHub
application/js/ajax.js

Summary

Maintainability
D
1 day
Test Coverage
// console.log("Loading Ajax...");

Spontaneous.Ajax = (function($, S) {
    'use strict';

    $.ajaxSetup({
        'async': true,
        'cache': false,
        'dataType': 'json',
        'ifModified': false
    });

    var csrfToken = S.csrf_token;
    var requestCache = {};

    var __authenticate = function(request) {
        request.setRequestHeader(S.csrf_header, csrfToken);
    };
    // wraps jQuery.ajax with a auth aware error catcher
    var __request = function(params) {
        // console.log("AJAX", params)
        var requestSuccessHandler = params.success;
        var successHandler = function(data, textStatus, xhr) {
            if (textStatus === 'success') {
                if (params.ifModified) {
                    requestCache[params.url] = data;
                }
            } else if (!data && (textStatus === 'notmodified')) {
                data = requestCache[params.url];
            }
            requestSuccessHandler(data, textStatus, xhr);
        };
        var requestErrorHandler = params.error;
        var errorHandler = function(xhr, textStatus, error_thrown) {
            if (xhr.status === 401) {
                S.Ajax.unauthorized();
            } else if (requestErrorHandler) {
                requestErrorHandler(xhr, textStatus, error_thrown);
            }
        };
        params.error = errorHandler;
        params.success = successHandler;
        params.beforeSend = function(request) {
            __authenticate(request);
        };
        $.ajax(params);
    };
    return {
        namespace: '/@spontaneous',
        // returns a modified xmlhttprequest that adds csrf headers
        // after #open is called.
        authenticatedRequest: function(request) {
            var xhr = new XMLHttpRequest();
            xhr.__open = xhr.open;
            xhr.open = function() {
                this.__open.apply(this, arguments);
                __authenticate(this);
            };
            return xhr;
        },
        authenticateRequest: function(request) {
            __authenticate(request);
        },
        get: function(url, data, callback, options) {
            if (typeof data === 'function') {
                callback = data;
                data = {};
            }
            this.makeRequest('GET', url, data, callback, options);
        },
        put: function(url, data, callback) {
            this.makeRequest('PUT', url, data, callback);
        },
        del: function(url, data, callback) {
            this.makeRequest('DELETE', url, data, callback);
        },
        post: function(url, data, callback) {
            this.makeRequest('POST', url, data, callback);
        },
        patch: function(url, data, callback) {
            this.makeRequest('PATCH', url, data, callback);
        },
        makeRequest: function(method, url, data, callback, options) {
            var success = function(data, textStatus, xhr) {
                if (typeof callback === 'function') {
                    callback(data, textStatus, xhr);
                }
            };
            var error = function(xhr, textStatus, error_thrown) {
                var result = false;
                try {
                    result = $.parseJSON(xhr.responseText);
                } catch (e) { }
                if (typeof callback === 'function') {
                    callback(result, textStatus, xhr);
                }
            };
            data = data || {};
            var ajaxOptions = $.extend({}, options, {
                'url': this.request_url(url),
                'type': method,
                'data': data,
                'success': success,
                'error': error
            });
            __request(ajaxOptions);
        },
        unauthorized: function() {
            window.location.href = '/';
        },
        test_field_versions: function(target, fields, success, failure) {
            var version_data = {}, modified = 0;
            for (var i = 0, ii = fields.length; i < ii; i++) {
                var field = fields[i], key = '[fields]['+field.schema_id()+']';
                if (field.is_modified()) {
                    version_data[key] = field.version();
                    modified++;
                }
            }
            if (modified === 0) { success(); }

            this.post(['/field/conflicts', target.id()].join('/'), version_data, function(data, textStatus, xhr) {
                if (textStatus === 'success') {
                    success();
                } else {
                    if (xhr.status === 409) {
                        var field_map = {};
                        for (var i = 0, ii = fields.length; i < ii; i++) {
                            var f = fields[i];
                            field_map[f.schema_id()] = f;
                        }
                        var conflicted_fields = [];
                        for (var sid in data) {
                            if (data.hasOwnProperty(sid)) {
                                var values = data[sid], field = field_map[sid];
                                conflicted_fields.push({
                                    field:field,
                                    version: values[0],
                                    values: {
                                        server_original: values[1],
                                        local_edited: field.edited_value(),
                                        local_original: field.original_value()
                                    }
                                });
                            }
                        }
                        failure(conflicted_fields);
                    }
                }
            });
        },
        csrf_token: function() {
            return {'__token':csrfToken };
        },
        request_url: function(url, needs_key) {
            var path = this.namespace + url;
            if (needs_key) {
                path += '?'+$.param(this.csrf_token());
            }
            return path;
        }
    };
}(jQuery, Spontaneous));