Last Updated: February 25, 2016
·
4.873K
· ocodo

Kendo CSS Binding extensions

I've put together a couple of extensions for Kendo Mobile MVVM, which
allow you to simplify the task of representing model states using CSS
classes.

cssToggle

Switch between two css classes based on the truthiness
of the model value

Usage:

<div data-bind="cssToggle: truthyProperty" 
     data-enabled-css="on-class" 
     data-disabled-css="off-class"></div>

Code:

kendo.data.binders.cssToggle = kendo.data.Binder.extend({

  init: function(element, bindings, options) {

    kendo.data.Binder.fn.
                init.call(
                 this, element, bindings, options
               );

    var target = $(element);
    this.enabledCss = target.data("enabledCss");
    this.disabledCss = target.data("disabledCss");
  },

  refresh: function() {
    if ( this.bindings.cssToggle.get() ) {
      $( this.element ).addClass( this.enabledCss );
      $( this.element ).removeClass( this.disabledCss );
    } else{
      $( this.element ).addClass( this.disabledCss );
      $( this.element ).removeClass( this.enabledCss );
    }
  }

});

cssState

Select a css class based on the state value bound. You provide a list
of states with corresponding css class names, see the usage below.

This Preferable to using the built in data-bind="style: property",
as this method allows the states/css association to be declared in the
view.

Usage:

<div data-bind="cssState: switch"
     data-css-states="stop:red, go:green, slowdown:amber">

You can format whitespace in the css-state list how you like,
whitespace will be fixed up by the pre-parser, e.g.

<div data-bind="cssState: switch"
     data-css-states="
                       stop : red, 
                         go : green, 
                   slowdown : amber     ">

Numeric state keys are also valid:

<div data-bind="cssState: switch"
     data-css-states="0:red, 1:green, 2:go">

Code:

kendo.data.binders.cssState = kendo.data.Binder.extend({

  init: function(element, bindings, options) {

    kendo.data.Binder.fn.
                init.call(
                 this, element, bindings, options
               );

    var target = $(element);

    // convert the data-css-states 
    // string to JSON and parse it for use
    // when refresh happens.

    statePairs = target.data.cssStates.split(",");
    ar = [];
    for(var e in statePairs){
      var pair = statePairs[a].split(":");
      ar.push(
        kendo.format("\"{0}\":\"{1}\"",
                     pair[0].trim(),
                     pair[1].trim()
                    )
      );
    }
    this.states = JSON.parse(
                    kendo.format("{{0}}", ar.join(",")
                  )
    );
  },

  refresh: function () {
    var target = $(this.element);
    for(var removeCss in this.states) {
      target.removeClass(this.states[removeCss]);
    }
    var setCss = this.states
                 [
                   this.bindings.cssState.get()
                 ];
    target.addClass(setCss);
  }    
});

5 Responses
Add your response

How to bind two or more css classes to one div, something like: data-bind="css: { answered: answered, answer-accepted: answerAccepted }"

over 1 year ago ·

@dean-yang - sorry for the late reply,

As above, you'd use data-bind="cssState: stateContainer" and data-css-states to map the css classes to the predicted values of stateContainer.

For example stateContainer can contain the strings "answered", or "answerAccepted"... your data-css-states would be:

data-css-states="answered:answered, answerAccepted:answer-accepted"

(Assuming the css classes for these states are "answered" or "answer-accepted")

over 1 year ago ·

Just what I needed -- thanks!

over 1 year ago ·

Thanks Jason for sharing... base on your code, I create this one that I had used in many occasions... the ideas is basically apply a css based on an operation like value equals to 1 or greater than 2... etc...

kendo.data.binders.cssIf = kendo.data.Binder.extend({
init: function (element, bindings, options) {
kendo.data.Binder.fn.
init.call(
this, element, bindings, options
);

    var target = $(element);
    this.class = target.data("class");
    this.operator = target.data("operator");
    this.value = target.data("value");
},

refresh: function(){
    var v = this.bindings.cssIf.get();
    var apply = false;
    if (this.operator === "=" && v === this.value) {
        apply = true;
    } else if (this.operator === ">" && v > this.value) {
        apply = true;
    } else if (this.operator === "<" && v < this.value) {
        apply = true;
    } else if (this.operator === ">=" && v >= this.value) {
        apply = true;
    } else if (this.operator === "<=" && v <= this.value) {
        apply = true;
    } else if (this.operator === "!=" && v !== this.value) {
        apply = true;
    }
    if (apply) {
        $(this.element).addClass(this.class);
    } else {
        $(this.element).removeClass(this.class);
    }
}

});

over 1 year ago ·

Nice work, thanks!

over 1 year ago ·