Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VDOM sytleModule feature #2614

Closed
kleiteimc opened this issue Aug 29, 2018 · 1 comment
Closed

VDOM sytleModule feature #2614

kleiteimc opened this issue Aug 29, 2018 · 1 comment

Comments

@kleiteimc
Copy link

kleiteimc commented Aug 29, 2018

The new VDOM feature of F7 was implemented using the snabbdom package. Snabbdom has a Style Module feature that could be used for very impressive animations for Lists. It would be very nice to have that feature in F7.

Describe the solution you'd like

Below are changes to include the Style Module.

An example on how to use the new sytleModule feature in a list:

      {{#each assigned}}
      <li key="{{id}}" data-style= "{'opacity': '1', 'transform': 'translate(-200px)', 'transition': 'opacity 1s, transform 1s', 'delayed': { 'transform': 'translate(0px)' }, 'remove': {'opacity': '0'} }">
        <a href="/order/{{id}}" data-view=".view-main" class="panel-close">
          Order: {{id}}<br/>Ship To: {{name}}
        </a>
      </li>
      {{/each}}

Thanks,
Kris

PS - I tested this by putting the changes in the Framework7.js file. I am guessing as to where it should go in the src directory. The code works very nicely with Framework7.js.

F7/src/core/modules/component/vdom.js

Around line 183 there is this:

    if (attrName === 'id' && !data.key) {
      data.key = attrValue;
    }

After the "if" statement, add this:

    if (attrName === 'data-style') {
        try {
          data.style = JSON.parse(attrValue.replace(/\'/g,'"'));
        } catch(e) {}
    }

F7/src/core/modules/component/patch.js -- add sytleModule

  var patch = init$1([
    attributesModule,
    propsModule,
    styleModule,       //<---------------
    eventListenersModule ]);

Create a new file: style-component.js with the following:

   import $ from 'dom7';

  function updateStyle(oldVnode, vnode) {
  var cur, name, elm = vnode.elm,
      oldStyle = oldVnode.data.style,
      style = vnode.data.style;

  if (!oldStyle && !style) return;
  if (oldStyle === style) return;
  oldStyle = oldStyle || {};
  style = style || {};
  var oldHasDel = 'delayed' in oldStyle;

  var raf = (typeof window !== 'undefined' && window.requestAnimationFrame) || setTimeout;
  var nextFrame = function(fn) { raf(function() { raf(fn); }); };
  var setNextFrame = function(obj, prop, val) {
    nextFrame(function() { obj[prop] = val; });
  }

  for (name in oldStyle) {
    if (!style[name]) {
      if (name[0] === '-' && name[1] === '-') {
        elm.style.removeProperty(name);
      } else {
        elm.style[name] = '';
      }
    }
  }
  for (name in style) {
    cur = style[name];
    if (name === 'delayed' && style.delayed) {
      for (let name2 in style.delayed) {
        cur = style.delayed[name2];
        if (!oldHasDel || cur !== oldStyle.delayed[name2]) {
          setNextFrame(elm.style, name2, cur);
        }
      }
    } else if (name !== 'remove' && cur !== oldStyle[name]) {
      if (name[0] === '-' && name[1] === '-') {
        elm.style.setProperty(name, cur);
      } else {
        elm.style[name] = cur;
      }
    }
  }
}

function applyDestroyStyle(vnode) {
  var style, name, elm = vnode.elm, s = vnode.data.style;
  if (!s || !(style = s.destroy)) return;
  for (name in style) {
    elm.style[name] = style[name];
  }
}

function applyRemoveStyle(vnode, rm) {
  var s = vnode.data.style;
  if (!s || !s.remove) {
    rm();
    return;
  }
  var name, elm = vnode.elm, i = 0, compStyle,
      style = s.remove, amount = 0, applied = [];
  for (name in style) {
    applied.push(name);
    elm.style[name] = style[name];
  }
  compStyle = getComputedStyle(elm);
  var props = compStyle['transition-property'].split(', ');
  for (; i < props.length; ++i) {
    if(applied.indexOf(props[i]) !== -1) amount++;
  }
  elm.addEventListener('transitionend', function (ev) {
    if (ev.target === elm) --amount;
    if (amount === 0) rm();
  });
}

var styleModule = {
  create: updateStyle,
  update: updateStyle,
  destroy: applyDestroyStyle,
  remove: applyRemoveStyle
};



@nolimits4web
Copy link
Member

Ok, added, thanks for tip! 👍

But i made it to read style attribute, so if style attribute contains JSON ({ and }) then we parse and send it to style module, otherwise it renders like usual style attribute

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants