/** * jQuery Data Remote Plugin * http://github.com/codfish/jquery-dataremote * Copyright 2014-2015, Chris O'Donnell * * jQuery plugin that simplifies the common task of making api/remote requests * and injecting the response to the page. Optionally leverages templating * engines (handlebars). Inpired by ruby on rails' unobtrusive scripting adapter * for jQuery (https://github.com/rails/jquery-ujs). */ ;(function ($, window, undefined) { 'use strict'; $.fn.dataRemote = function () { var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; // Default Settings var defaults = { url: null, // request url data: {}, // request data debug: false, eventType: 'load', // js event type to fire data request on (load, click, submit, mouseover, custom, etc.) dataType: 'json', // data type that's expected in response from your request type: 'GET', // type of request (currently only supports GET) target: '', // selector of the element where you want your response injected handlebars: false, // use handlebars to render the response? template: '', // handlebar template selector. by default it will look inside target placement: 'html', // where to inject response relative to target (jquery DOM insertion methods ) loaderImg: null, // target selector for data response oneAndDone: true, // whether to remove the event binding after the first time running debounceEvents: ['keyup', 'keydown', 'keypress', 'scroll', 'resize'], success: successCallback, // gets passed 3 parameters ($target, options, response) error: errorCallback, // gets passed 4 parameters ($target, options, response, error) complete: function complete() {}, // callback fires after the request is made (on success OR error) before: function before() {} // callback fires directly before the request is made }; // Extend our default options with those provided when instantiating options = $.extend({}, defaults, options); /** * Default success callback for ajax requests. * * Handles hiding of loader image, debugging (if option is set), * and handling the ajax requests' response (levering handlebars if option * is set or handlebars template is found inside the target element). * * @param {jQuery} $target jquery object containing the target element for the ajax response * @param {object} options plugin options set during instantiation * @param {object} response data response from the ajax request */ function successCallback($target, options, response) { var source; var template; var html; var $template; $target.find('.loader-image').hide(); if (options.debug) { $.fn.dataRemote.debug($target, response); } // Use handlebars if the option is set to true *or* if a handlebars template is found if (options.handlebars !== false || $target.find('[type="text/x-handlebars-template"]').length) { $template = options.template ? $(options.template) : $target.find('[type="text/x-handlebars-template"]'); source = $template.html(); template = Handlebars.compile(source); html = template(response); } else { html = response; } // use proper jQuery method based on append option // if append == true, append results to target element, // or else replace inner html with results var validPlacements = ['html', 'append', 'prepend', 'after', 'before']; var placementIsValid = validPlacements.indexOf(options.placement) !== -1; if (!placementIsValid) { return; } $target[options.placement](html); } /** * Default error callback for ajax requests * * Hides the loader image, triggers debugging if it's turned on. * * @param {jQuery} $target jquery object containing the target element for the ajax response * @param {object} options plugin options set during instantiation * @param {object} response data response from the ajax request * @param {string} error textual portion of the HTTP status, i.e. "Not Found" or "Internal Server Error." */ function errorCallback($target, options, response, error) { $target.find('.loader-image').hide(); if (options.debug) { $.fn.dataRemote.debug($target, response, error); } } /** * Private helper method for debounce * * @param [function] func function to debounce * @param [integer] wait amount of time to wait between events * @param [boolean] immediate cancels the debounce if True * @return [function] function function with debounce wrapper */ function debounce(func, wait, immediate) { var timeout; return function () { var context = this, args = arguments; var later = function later() { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; } /** * Private helper method for making the ajax request * * @param {object} url request url * @param {object} settings additional settings for the request * { * @param {jQuery} element jQuery object containing the current data remote element * @param {object} options data remote plugin options for current data remote element * @param {jQuery} $target jQuery object containing the target element to inject response * } * @return {void} */ function fetch(url, settings) { var $element = settings.element; var $target = settings.target; var options = settings.options; // display loader image while retrieving content if (options.loaderImg) { $target.prepend('\n