Jump To …

can.view.modifiers.js

/*!
* CanJS - 1.1.4 (2013-02-05)
* http://canjs.us/
* Copyright (c) 2013 Bitovi
* Licensed MIT
*/
(function (window, $, can, undefined) {

can/view/modifiers/modifiers.js

---- ADD jQUERY HELPERS ----- converts jquery functions to use views

  var convert, modify, isTemplate, isHTML, isDOM, getCallback,

text and val cannot produce an element, so don't run hookups on them

  noHookup = {
    'val': true,
    'text': true
  };

  convert = function (func_name) {

save the old jQuery helper

    var old = $.fn[func_name];

replace it with our new helper

    $.fn[func_name] = function () {

      var args = can.makeArray(arguments),
        callbackNum, callback, self = this,
        result;

if the first arg is a deferred wait until it finishes, and call modify with the result

      if (can.isDeferred(args[0])) {
        args[0].done(function (res) {
          modify.call(self, [res], old);
        })
        return this;
      }

check if a template

      else if (isTemplate(args)) {

if we should operate async

        if ((callbackNum = getCallback(args))) {
          callback = args[callbackNum];
          args[callbackNum] = function (result) {
            modify.call(self, [result], old);
            callback.call(self, result);
          };
          can.view.apply(can.view, args);
          return this;
        }

call view with args (there might be deferreds)

        result = can.view.apply(can.view, args);

if we got a string back

        if (!can.isDeferred(result)) {

we are going to call the old method with that string

          args = [result];
        } else {

if there is a deferred, wait until it is done before calling modify

          result.done(function (res) {
            modify.call(self, [res], old);
          })
          return this;
        }
      }
      return noHookup[func_name] ? old.apply(this, args) : modify.call(this, args, old);
    };
  };

modifies the content of the element but also will run any hookup

  modify = function (args, old) {
    var res, stub, hooks;

check if there are new hookups

    for (var hasHookups in can.view.hookups) {
      break;
    }

if there are hookups, turn into a frag and insert that by using a frag, the element can be recursively hooked up before insterion

    if (hasHookups && args[0] && isHTML(args[0])) {
      args[0] = can.view.frag(args[0]).childNodes;
    }

then insert into DOM

    res = old.apply(this, args);

    return res;
  };

returns true or false if the args indicate a template is being used $('#foo').html('/path/to/template.ejs',{data}) in general, we want to make sure the first arg is a string and the second arg is data

  isTemplate = function (args) {

save the second arg type

    var secArgType = typeof args[1];

the first arg is a string

    return typeof args[0] == "string" &&

the second arg is an object or function

    (secArgType == 'object' || secArgType == 'function') &&

but it is not a dom element

    !isDOM(args[1]);
  };

returns true if the arg is a jQuery object or HTMLElement

  isDOM = function (arg) {
    return arg.nodeType || (arg[0] && arg[0].nodeType)
  };

returns whether the argument is some sort of HTML data

  isHTML = function (arg) {
    if (isDOM(arg)) {

if jQuery object or DOM node we're good

      return true;
    } else if (typeof arg === "string") {

if string, do a quick sanity check that we're HTML

      arg = can.trim(arg);
      return arg.substr(0, 1) === "<" && arg.substr(arg.length - 1, 1) === ">" && arg.length >= 3;
    } else {

don't know what you are

      return false;
    }
  };

returns the callback arg number if there is one (for async view use)

  getCallback = function (args) {
    return typeof args[3] === 'function' ? 3 : typeof args[2] === 'function' && 2;
  };


  $.fn.hookup = function () {
    can.view.frag(this);
    return this;
  };


  can.each([

  "prepend",

  "append",

  "after",

  "before",

  "text",

  "html",

  "replaceWith", "val"], function (func) {
    convert(func);
  });


})(this, jQuery, can);