djv tdd

Tutorials of (Djv tdd) by Tomas langkaas

<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>djv tdd</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  
  
      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>

  <div><textarea id="results"></textarea></div>
<div id="test"></div>

<!-- test lists -->

<div id="listTemplate">
  <h1>List view test</h1>
  <ul djv="id: items"><ul>
</div>
    
<script id="itemTemplate" type="text/x-template">
  <li>{{title}}
    <input type="text" djv="bind: title" /><button djv="click: remove">Remove</button
    ><button djv="click: update">Update</button
    ><button djv="click: cancel">Cancel</button>
  </li>
</script>

<script>setTimeout(function(){
listViewConstructor = djv(
  'listTemplate',{
    itemConstructor: djv('itemTemplate',{
      remove: function(){
        this.$parent.removeItem(this.index);
      },
      update: function(){
        this.$parent.updateItem(this.index);
      },
      cancel: function(){
        this(this.$parent('items')[this.index]);
      }
    }),
    removeItem: function(index){
      var items = this('items');
      items.splice(index, 1);
      this('items', items); // notify observers
    },
    updateItem: function(index){
      var items = this('items');
      items[index] = this.itemViews[index]();
      this('items', items); // notify observers
    },
    $mount: function(){ // initialize view
      this.itemViews = [];
    },
    $update: function(prop, val){
      if(prop === 'items'){
        var items = this.itemViews;
        for(var i = items.length - 1; i >= val.length; i--){
          items[i].$destroy();
        }
        items.length = val.length;
        for(i = 0 ; i < val.length; i++){
          if(!items[i]) items[i] = this.itemConstructor(this, 'items');
          items[i](val[i]);
          items[i].index = i;
        }
      }
    }
  },{
    items : [
      {title: 'one'},
      {title: 'two'},
      {title: 'three'}
    ]
  });
listView = listViewConstructor();
})</script>
    
    <h1>Progress bar test</h1>
    <div id="progressBar">
      <div>
        <div djv="bind: message"></div>
        <div class="djv-progress-container">
          <div djv="id: bar" class="djv-progress-bar"></div>
        </div>
        <div djv="bind: progress, format: percentage"></div>
      </div>
    </div>
    
    <script>setTimeout(function(){
    var progressBarInstance = djv('progressBar',{
      $update: function(property, value){
        if(property === 'progress'){
          this.$('bar').style.width = 100 * value + '%';
        }
      },
      percentage: function(value){
        return Math.round(100 * value) + '%'
      }
    },{
      message: 'Any progress yet?'
    })();
    
    setInterval(function(){
      progressBarInstance('progress', (((+new Date) / 100) % 100) / 100);
    }, 50);
    })</script>
  <script src='js/zpvpjb.js'></script>

  

    <script  src="js/index.js"></script>




</body>

</html>
/* Downloaded from https://www.codeseek.co/ */
html, body{
  font-family: sans-serif;
}

#results{
  width: 80%;
  height: 20em;
  margin: auto;
}

/* djv progress bar */

div.djv-progress-bar{
  height: 3px;
  width: 0;
  background: #000;
}

div.djv-progress-container{
  background: #ddd;
}
/* Downloaded from https://www.codeseek.co/ */
/*
  TODO:
  - object arguments {template, public, state}?
  - component updater (onupdate)
  - other hooks? oncreate, ondestroy, ondestroyed, onmount, onmounted, onupdate, onupdated
  - standard prefix: $destroy, $, $id, $children, $parent
  - djv.attribute(elm, attribute)? use case?
  - function mixins
  - <select> ?
  - label for="" ==> djv="for:id"
  - automatic testing
  - clean up & comment code
*/


(function(window, document) {
  window["djv"] = djv;
  djv.version = "0.2";

  // active views

  var views = {};

  // view instance id generator

  var IDPrefix = "djv",
    IDCounter = 1;

  function generateID() {
    return IDPrefix + IDCounter++;
  }

  // utils
  
  var defer = setTimeout;

  function attr(elm, prop) {
    return elm.getAttribute("djv-" + prop) || "";
  }

  function runFn(obj, fn, arg1, arg2, arg3) {
    fn && typeof obj[fn] === "function" && obj[fn](arg1, arg2, arg3);
  }

  function setHandler(elm, remove) {
    elm.onkeydown = elm.onkeypress = elm.onkeyup = elm.onclick = elm.oninput = elm.onfocusout = remove
      ? null
      : handler;

    elm[(remove = (remove ? "remove" : "add") + "EventListener")] &&
      elm[remove]("blur", handler, true);
  }
  
  function getHTML(elm){
    return elm.innerHTML;
  }
  
  function setHTML(elm, html){
    elm.innerHTML = html;
  }

  djv["keydown"] = function(evt, keycode, prevent) {
    if (evt.type === "keydown" && keycode === (evt.keyCode || evt.charCode)) {
      if (prevent) {
        evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
      }
      return true;
    }
    return false;
  };

  djv["focus"] = function(viewInstance, localID) {
    defer(function() {
      viewInstance.$(localID).focus();
    });
  };

  // view constructor: djv(templateStringOrId [, methods][, defaultState])

  function djv(templateStringOrID, methods, defaultState) {

    methods = methods || {};
    defaultState = defaultState || {};

    var bindings = {},
      localIDs = {},
      template = elm(templateStringOrID);
    template = parseTemplate(
      template ? getHTML(template) : templateStringOrID,
      bindings,
      localIDs
    );

    viewConstructor["_params"] = [
      template,
      bindings,
      localIDs,
      methods,
      defaultState
    ];
    //var viewInstance = viewClass(parentViewInstance, parentLocalID)
    //                   OR viewClass([parentElementOrId]) // root container
    function viewConstructor(parent, parentID, clear, viewID) {
      var viewInstance = obs(),
        children,
        prop;
      
      if(!parent){ // mount to template container
        parent = elm(templateStringOrID);
        clear = true;
      }
      
      // update when attached to DOM
      
      defer(function(){
        viewInstance(viewInstance(null));
        runFn(viewInstance, '$mounted');
      })

      // public interface

      for (prop in methods) {
        viewInstance[prop] = methods[prop];
      }

      viewID = viewInstance["_"] = viewID || generateID();
      children = viewInstance["$children"] = {};
      viewInstance["$"] = function(localID) {
        if (localID = localIDs[localID]) {
          return elm(this["_"] + "_" + localID);
        }
      };
      viewInstance["$destroy"] = function() {
        // TODO: transform to mixin
        var viewInstance = this,
            viewID = viewInstance["_"],
          domElm = elm(viewID + "_1"),
          parent = domElm.parentNode,
          childrenID;
        domElm && parent.removeChild(domElm);
        if (!viewInstance.$parent) {
          // is root view
          setHandler(parent, true);
        } else {
          for (childrenID in children) {
            children[childrenID] && children[childrenID].$destroy();
          }
          viewInstance.$parent.$children[viewID] = void 0;
        }
        views[viewID] = null;
      };

      // root or child view?

      if (parentID && parent.$) {
        // child view
        viewInstance["$parent"] = parent;
        parent.$children[viewID] = viewInstance;
        parent = parent.$(parentID);
      } else if (parent = elm(parent)) {
        // root view
        setHandler(parent);
      }
      
      // $mount hook
      runFn(viewInstance, '$mount');
      
      //parent.innerHTML = (clear ? "" : parent.innerHTML) + template(viewID);
      setHTML(parent, (clear ? "" : getHTML(parent)) + template(viewID));
      views[viewID] = viewInstance;

      // view updater
      viewInstance(defaultState);
      viewInstance(updateViewInstance);
      
      return viewInstance;
    }

    // view updater

    function updateViewInstance(prop, val, avoidID) {
      var a = bindings[prop] || [],
        l = a.length,
        i = 0,
        domElm,
        fun,
        formatted,
        tagName,
        viewID = this._;
      runFn(this, '$update', prop, val);
      for (i; i < l; i++) {
        if (avoidID !== viewID + "_" + a[i] && (domElm = elm(viewID + "_" + a[i]))) {
          //domElm = elm(viewID + "_" + a[i]);
          tagName = domElm.tagName.toLowerCase();
          formatted =
            "" + [(fun = this[attr(domElm, "format")]) ? fun(val) : val]; // run in context => apply to this?
          if (domElm.type === "radio" || domElm.type === "checkbox") {
            domElm.checked = domElm.value === val;
          } else if (tagName === "input" || tagName === "button") {
            domElm.value = formatted;
          } else if (tagName === "textarea") {
            setHTML(domElm, formatted);
            domElm.setAttribute("value", formatted); // old IE
          } else {
            setHTML(domElm, formatted.replace(/[<>"'&]/g, function(match) {
              return "&#" + match.charCodeAt(0) + ";";
            }));
          }
        }
      }
      runFn(this, '$updated', prop, val);
    }
    
    return viewConstructor;
  }

  // djv.elm(idOrElement); get element by id

  function elm(id) {
    return typeof id.innerHTML === "string" ? id : document.getElementById(id);
  }

  djv["elm"] = elm;

  // parseTemplate(templateString, bindings, localIDs); internal template parser

  // compile regexes only once
  var ptRegEx1 = /\{\{(\w+)(?:[\s\|]+(\w+))?\}\}| djv\=(\"([^\"]*)\"|\'([^\']*)\')|[\x00-\x1f\"\\]/gi,
    ptRegEx2 = /\s*(\w+)\s*\:\s*(\w+)\s*/g,
    ptRegEx3 = /^(\s*<[a-z1-6]+)([^>]*>)/i;

  function parseTemplate(str, bindings, localIDs) {
    var IDcounter = 1,
      regex1 = ptRegEx1, // /\{\{(\w+)(?:[\s\|]+(\w+))?\}\}| djv\=(\"([^\"]*)\"|\'([^\']*)\')|[\x00-\x1f\"\\]/gi,
      regex2 = ptRegEx2, // /\s*(\w+)\s*\:\s*(\w+)\s*/g;
      regex3 = ptRegEx3,
      temp;
    if ((temp = str.match(regex3))) {
      if (!/\sdjv\=[\"\']/.test(temp)) {
        str = str.replace(regex3, '$1 djv=""$2');
      }
    } else {
      str = '<div djv="">' + str + "</div>";
    }
    function replacer2(arr, prop, value) {
      if (prop === "id") {
        localIDs[value] = IDcounter - 1;
      } else if (prop === "bind") {
        (arr = bindings[value] = bindings[value] || [])[arr.length] =
          IDcounter - 1;
      }
      return prop === "radio"
        ? " name=\"'+c+'_" + value + '"'
        : " djv-" + prop + '="' + value + '"';
    }

    return new Function(
      "c",
      "return'" +
        str.replace(regex1, function(m, prop, format, params, p1, p2) {
          return params
            ? " id=\"'+c+'_" +
                IDcounter++ +
                '"' +
                ((p1 || p2 || "").match(regex2) || [])
                  .join(" ")
                  .replace(regex2, replacer2)
            : prop
              ? (((prop = bindings[prop] = bindings[prop] || [])[
                  prop.length
                ] = IDcounter),
                "<span id=\"'+c+'_" +
                  IDcounter++ +
                  '"' +
                  (format ? ' djv-format="' + format + '"' : "") +
                  "></span>")
              : "\\x" + encodeURI(m).slice(-2);
        }) +
        "'"
    );
  }

  djv["_pt"] = parseTemplate;

  // root view event capture handler

  function handler(
    evt,
    elm,
    id,
    key,
    view,
    bind,
    type,
    inputType,
    val,
    fun,
    isBlur
  ) {
    evt = evt || window.event;
    elm = evt.target || evt.srcElement;
    elm = elm.nodeType === 3 ? elm.parentNode : elm;
    id = elm.id || ""; //).split("_");
    view = views[id.split("_")[0]];
    if (view) {
      type = evt.type;
      inputType = "" + elm.type;
      if (type === "keydown" || type === "keypress") {
        runFn(view, "onkey", evt, evt.keyCode || evt.charCode, elm);
      } else if ((bind = attr(elm, "bind"))) {
        if (inputType === "radio" || inputType === "checkbox") {
          if (type === "click") {
            view(bind, elm.checked ? elm.value : "", 0, 1);
          }
        } else if (
          ~"text tel url datetime-local search month week file password number email".indexOf(
            inputType
          ) ||
          elm.tagName.toLowerCase() === "textarea"
        ) {
          isBlur = type === "blur" || type === "focusout";
          val = elm.value;
          //protect id if not blur/focusout
          view(
            bind,
            typeof (fun = view[attr(elm, "parse")]) === "function"
              ? fun(val)
              : val, // what if fn not defined?
            isBlur ? null : id,
            1
          );
          if (isBlur) {
            val = view(bind);
            elm.value =
              typeof (fun = view[attr(elm, "format")]) === "function"
                ? fun(val)
                : val;
          }
        }
      }
      runFn(view, attr(elm, type), evt, evt.keyCode || evt.charCode, elm);
    }
  }

  // obs: observable objects

  obs["ver"] = "0.2";
  djv["obs"] = obs;

  function obs(init) {
    var data = {},
      observers = {},
      iter = 1;

    function notify(prop, msg, val, i) {
      val = getPropVal(data, prop); //CONSIDER: drop computable/callable props, except on object copy
      for (i in observers) {
        observers[i] && observers[i].call(obs, prop, val, msg);
      }
    }

    function getPropVal(obj, prop, preserve) {
      return obj.hasOwnProperty(prop)
        ? typeof obj[prop] === "function" && !preserve
          ? obj[prop].call(obs)
          : obj[prop]
        : void 0;
    }

    function obs(arg1, arg2, arg3, arg4) {
      // obs() => return computed copy
      // obs(null) => return equivalent copy
      // obs(object) => overwrite with object data
      // obs(prop) => get property
      // obs(prop, val [, msg][, onlyIfDifferent])=> set property
      var preserve = arg1 === null,
        args = arguments,
        i,
        target,
        source,
        copy = !args.length || preserve;
      if (copy || typeof arg1 === "object") {
        if (!copy) {
          for (i in arg1) {
            data[i] = arg1[i];
          }
        }
        target = copy ? {} : data;
        source = copy ? data : arg1;
        for (i in data) {
          arg2 = getPropVal(source, i, preserve);
          if (copy ^ (arg2 === void 0)) {
            target[i] = arg2;
          }
          !copy && notify(i, arg3);
        }
        return copy ? target : obs;
      } else if (typeof arg1 === "function") {
        return (function(index) {
          observers[index] = arg1;
          return function() {
            observers[index] = 0;
          };
        })(iter++);
      } else {
        if (1 in args && (!arg4 || data[arg1] !== arg2)) {
          data[arg1] = arg2;
          notify(arg1, arg3);
        }
        return getPropVal(data, arg1); //CONSIDER: drop computable/callable props, except on object copy
      }
    }
    if (init) {
      obs(init);
    }
    return obs;
  }
})(window, document);

// djv tests

if (window["check"] && djv) {
  (function() {
    var tests = check.suite("djv tests", "results");

    // djv.version

    tests("djv version", function(done, eq) {
      done(typeof djv.version === "string");
    });

    // djv.elm()

    function randomString() {
      return "test" + ((Math.random() * 0x1000000) | 0);
    }

    tests("djv.elm(nonExistingId)", function(done, eq) {
      done(eq(djv.elm(randomString()), null));
    });

    tests("djv.elm(DOMElement)", function(done, eq) {
      var mockElm = { innerHTML: randomString() };
      done(mockElm.innerHTML === djv.elm(mockElm).innerHTML);
    });

    tests("djv.elm(id)", function(done, eq) {
      var testDiv = document.body.appendChild(document.createElement("div"));
      testDiv.id = randomString();
      var result = djv.elm(testDiv.id).id === testDiv.id;
      document.body.removeChild(testDiv);
      done(result);
    });

    // internal parseTemplate function

    tests("parseTemplate(/* double bracket syntax */)", function(done, eq) {
      var bindings = {},
        template = "<p>{{varName}} {{varName2}} {{varName | formatter}}</p>";
      done(
        djv._pt(template, bindings, {})("PF") ===
          '<p id="PF_1"><span id="PF_2"></span> <span id="PF_3"></span> <span id="PF_4" djv-format="formatter"></span></p>' &&
          eq(bindings, { varName: [2, 4], varName2: [3] })
      );
    });

    tests('parseTemplate(/* djv="" syntax */)', function(done, eq) {
      var bindings = {},
        localIDs = {},
        template =
          '<input djv="id: id1, bind: varName, attr1: value1 not any value attr2: value2">';
      done(
        djv._pt(template, bindings, localIDs)("PF") ===
          '<input id="PF_1" djv-id="id1" djv-bind="varName" djv-attr1="value1" djv-attr2="value2">' &&
          eq(bindings, { varName: [1] }) &&
          eq(localIDs, { id1: 1 })
      );
    });

    tests("parseTemplate(/* radio groups */)", function(done, eq) {
      var bindings = {},
        template =
          '<input djv="bind: varName, radio: group1">' +
          '<input djv="bind: varName2, radio: group2">' +
          '<input djv="bind: varName, radio: group1">';
      done(
        djv._pt(template, bindings, {})("PF") ===
          '<input id="PF_1" djv-bind="varName" name="PF_group1">' +
            '<input id="PF_2" djv-bind="varName2" name="PF_group2">' +
            '<input id="PF_3" djv-bind="varName" name="PF_group1">' &&
          eq(bindings, { varName: [1, 3], varName2: [2] })
      );
    });

    tests("parseTemplate('\b\t\n\u000b\f\r\u000e\u000f')", function(done, eq) {
      var template = "\b\t\n\u000b\f\r\u000e\u000f";
      done(
        djv._pt(template, {}, {})("PF") ===
          '<div id="PF_1">' + template + "</div>"
      );
    });

    tests("parseTemplate('<p djv=\"x\">')", function(done, eq) {
      var template = '<p djv="x">';
      done(djv._pt(template, {}, {})("PF") === '<p id="PF_1">');
    });

    tests("parseTemplate('<p></p>')", function(done, eq) {
      var template = "<p></p>";
      done(djv._pt(template, {}, {})("PF") === '<p id="PF_1"></p>');
    });

    // view constructors: djv(templateStringOrId [, methods][, defaultState])

    tests("djv is a function and returns a function", function(done, eq) {
      var viewConstructor = djv("Hello World!");
      done(typeof viewConstructor === "function");
    });

    tests("viewConstructor template function and bindings", function(done, eq) {
      var viewConstructor = djv("Hello {{World}}!");
      done(
        viewConstructor._params[0]("PF") ===
          '<div id="PF_1">Hello <span id="PF_2"></span>!</div>' &&
          eq(viewConstructor._params[1], { World: [2] })
      );
    });

    // view instances

    tests("viewInstance interface", function(done, eq) {
      var viewConstructor = djv("Hello {{World}}!");
      var viewInstanceID = "PF1";
      var viewInstanceParent = document.createElement("div");
      var viewInstance = viewConstructor(
        viewInstanceParent,
        null,
        false,
        viewInstanceID
      );
      done(
        viewInstance._ === viewInstanceID &&
          typeof viewInstance === "function" &&
          typeof viewInstance.$ === "function" &&
          typeof viewInstance.$destroy === "function" &&
          typeof viewInstance.$children === "object"
      );
    });

    tests("basic view instance", function(done, eq) {
      var viewConstructor = djv("Hello {{World}}");
      var viewInstanceID = "PF1";
      var viewInstanceParent = document.body.appendChild(
        document.createElement("div")
      );
      var viewInstance = viewConstructor(
        viewInstanceParent,
        null,
        viewInstanceID
      );
      var testString = randomString();
      //console.log(viewInstanceParent.innerText);
      viewInstance("World", testString);
      //console.log(viewInstanceParent.innerText);
      var result =
        (viewInstanceParent.innerText || viewInstanceParent.textContent) ===
        "Hello " + testString;
      document.body.removeChild(viewInstanceParent);
      done(result);
    });

    /*
    tests("", function(done, eq){
      done();
    });
    */

    /*
    
    rootView ?
    viewClass/Component
    viewInstance
    
    var viewClass = djv(templateStringOrId [, methods][, defaultState])
    
    var viewInstance = viewClass(parentViewInstance, parentLocalID)
                       OR viewClass(parentElementOrId) // root container
        viewInstance.destroy()
    
    TODO: parseTemplate => find and mark view container if not opening tag contains djv="
    
    */
  })();
}

/* test */

/*
var vclass = djv(
  'Hello {{world | caps}} <input type="text" djv="bind: world, format: caps">', 
  {
    caps: function(str){return (''+str).toUpperCase()}
  }
);
var vinst = vclass('test')({world:'world'});
*/


//djv('abc')('abc', false, true)({World: 'WORLD!'});

This awesome code ( djv tdd ) is write by Tomas Langkaas, you can se more from this user in the personal repository

You can find the original code on Codepen.io

2018 © Tomas Langkaas