将jQuery滑块连接到KnockOut模型

时间:2013-09-12 14:54:47

标签: javascript jquery jquery-mobile knockout.js

我正在构建一个购物车风格的应用程序,试图在MVC和KnockOut / jQuery中发展我的技能。

我已经开始工作,您可以选择房间类型,入住等,并更新总价值。

我在这里有一个jsFiddle到目前为止我所到达的地方:http://jsfiddle.net/mtait/cGGvA/1/

我现在要添加3个滑块:

          <label for="slider-1">Extra Towels:</label>
          <input type="range" name="slider-1" id="slider-1" min="0" max="100" value="50" data-popup-enabled="true">
          <label for="slider-2">Morning Papers:</label>
          <input type="range" name="slider-2" id="slider-2" min="0" max="100" value="50" data-show-value="true">
          <label for="slider-3">Packed Lunch:</label>
          <input type="range" name="slider-3" id="slider-3" min="0" max="100" value="50" data-show-value="true" data-popup-enabled="true">

此外,添加一些Javascript,以将每个滑块项的成本与滑块相关联:

<script>
   var slider1cost = 10;
   var slider2cost = 40;
   var slider3cost = 65;    
</script>

因此,例如,如果有人选择2张额外的毛巾,1张早报和0张午餐 - 我希望Total Value计算房间成本,就像现在一样,但也要加60英镑(2 x 10 + 1 x 40)。

下面的KnockOut代码仅用于房间 - 我如何将滑块中的值添加到该代码中:

我到目前为止的整个HTML是:

<div class='liveExample'>
<table width="100%" style="width:99%;" data-role="table" id="movietable2" class="ui-body-c ui-shadow table-stripe ui-responsive ui-table ui-table-columntoggle">
    <thead>
        <tr class="ui-bar-b">
            <th data-priority="1">Room Type</th>
            <th data-priority="2">Occupants</th>
            <th data-priority="4">Number reqd</th>
            <th data-priority="6"></th>
        </tr>
    </thead>
    <tbody data-bind='foreach: lines'>
        <tr>
            <td>
                <select data-bind='jqmOptionsdfd: sampleProductCategories, options: $root.RoomCategories, optionsText: "TypeName", optionsCaption: "Select...", value: category'></select>
            </td>
            <td data-bind="with: category">
                <select id="mine" data-bind='jqmOptionsdfd: sampleProductCategories, options: Occs, optionsText: "occdesc2", optionsCaption: "Select...", value: $parent.occupancy'></select>
            </td>
            <td class='quantity' data-bind="with: category">
                <select data-bind="visible: $parent.occupancy, options: ko.utils.range(0, TypeCount), value: $parent.quantiyt, jqmOptions:sampleProductCategories"></select>
            </td>
            <td> <a href="#" data-bind='click: $parent.removeLine' data-role="button" data-icon="delete">Remove</a>

            </td>
        </tr>
    </tbody>
    <tfoot>
        <tr>
            <td colspan="4" style="text-align:center;">
                 <h4 class='grandTotal'>
                Total value: <span data-bind='text: formatCurrency(grandTotal())'></span>
            </h4> 
                <button data-bind='click: addLine' data-icon="plus">Add another room</button>
            </td>
        </tr>
    </tfoot>
</table>
</div>
<hr />

<h1> Add Extras </h1>

<br />
<script>
  var slider1cost = 10;
  var slider2cost = 40;
  var slider3cost = 65;
</script>
<label for="slider-1">Extra Towels:</label>
<input type="range" name="slider-1" id="slider-1" min="0" max="100" value="50" data-popup-enabled="true">
<label for="slider-2">Morning Papers:</label>
<input type="range" name="slider-2" id="slider-2" min="0" max="100" value="50" data-show-value="true">
<label for="slider-3">Packed Lunch:</label>
<input type="range" name="slider-3" id="slider-3" min="0" max="100" value="50" data-show-value="true" data-popup-enabled="true">

JavaScript是:

var sampleProductCategories = [{
    "RoomName": null,
    "TypeName": "Type 1",
    "TypeID": 1,
    "TypeCount": 2,
    "Occs": [{
            "occdesc": "1 B&B",
            "curr": "£",
            "occdesc2": "1 B&B (£100.00)",
            "ratetocharge": 100.0000,
            "numOfOcc": 1,
            "RatesViewModel": null
    },
    {
            "occdesc": "1 Dinner",
            "curr": "£",
            "occdesc2": "1 Dinner (£100.00)",
            "ratetocharge": 100.0000,
            "numOfOcc": 1,
            "RatesViewModel": null
    }]
    },
    {
    "RoomName": null,
    "TypeName": "Type 2",
    "TypeID": 2,
    "TypeCount": 1,
    "Occs": [{
            "occdesc": "1 B&B",
            "curr": "£",
            "occdesc2": "1 B&B (£100.00)",
            "ratetocharge": 100.0000,
            "numOfOcc": 1,
            "RatesViewModel": null
    },
    {
            "occdesc": "1 Dinner",
            "curr": "£",
            "occdesc2": "1 Dinner (£100.00)",
            "ratetocharge": 100.0000,
            "numOfOcc": 1,
            "RatesViewModel": null
    }]
    }];


$(document).ready(function () {
    cart.RoomCategories(sampleProductCategories)


});

function formatCurrency(value) {
    return "£" + value.toFixed(2);
}

ko.bindingHandlers.jqmOptionsdfd = {
    update: function (element, valueAccessor, allBindingsAccessor, context) {
            ko.bindingHandlers.options.update(element, valueAccessor, allBindingsAccessor, context);
            $(element).selectmenu();

            $(element).selectmenu("refresh", true);
            //    alert("triggered");
    }
};

 ko.bindingHandlers.jqmOptions = {
    init: function (element, valueAccessor, allBindingsAccessor, context) {
            ko.applyBindingsToNode(element, {
                    options: valueAccessor()
            }, context);
            $(element).selectmenu();
    },
    update: function (element, valueAccessor, allBindingsAccessor, context) {
            $(element).selectmenu("refresh", true);
    }
};

var CartLine = function () {
    var self = this;
    self.category = ko.observable();
    self.categoryID = ko.observable();
    self.occupancy = ko.observable();
    self.quantity = ko.observable(1);
    $('.liveExample').trigger('create');
    self.subtotal = ko.computed(function () {
            return self.occupancy() ? self.occupancy().ratetocharge * parseInt("0" + self.quantity(), 10) : 0;
    });

    // Whenever the category changes, reset the occupancy selection
    self.category.subscribe(function () {
            self.occupancy(undefined);
    });
};

var Cart = function () {
    // Stores an array of lines, and from these, can work out the grandTotal
    var self = this;
    self.RoomCategories = ko.observableArray([]);
    self.lines = ko.observableArray([new CartLine()]); // Put one line in by default
    self.grandTotal = ko.computed(function () {
            var total = 0;
            $.each(self.lines(), function () {
                    total += this.subtotal()
            })
            return total;
    });

    // Operations
    self.addLine = function () {
            self.lines.push(new CartLine());
            $('.liveExample').trigger('create');
    };
    self.removeLine = function (line) {
            self.lines.remove(line)
    };

};


var cart = new Cart();
ko.applyBindings(cart);

function mtMob() {
    $('.liveExample').trigger('create');
};

function mtMob2() {
    $('.liveExample').trigger('create');
};


function groupByTypeID(arr) {
    var groupBy = {};
    $.each(arr, function () {
            var currentCount = groupBy[this.TypeName] || 0;
            groupBy[this.TypeName] = currentCount + parseInt(this.TypeCount);
    });
    return groupBy;
}

function dump(arr, level) {
    var dumped_text = "";
    if (!level) level = 0;

    //The padding given at the beginning of the line.
    var level_padding = "";
    for (var j = 0; j < level + 1; j++) level_padding += "    ";
    if (typeof(arr) == 'object') { //Array/Hashes/Objects
            for (var item in arr) {
                    var value = arr[item];
                    if (typeof(value) == 'object') { //If it is an array,
                            dumped_text += level_padding + "'" + item + "' ...\n";
                            dumped_text += dump(value, level + 1);
                    } else {
                            dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
                    }
            }
    } else { //Stings/Chars/Numbers etc.
            dumped_text = "===>" + arr + "<===(" + typeof(arr) + ")";
    }
    return dumped_text;
}

感谢您的帮助,

标记

1 个答案:

答案 0 :(得分:1)

您必须考虑编写自己的自定义绑定。会有类似的东西:

<div id="your-slider"data-bind="slider: TheValueSliderIsFor, max: 10, step: 1, min: 1">

然后您的自定义操作会在移动滑块时更新您的observable。

类似的东西:

ko.bindingHandlers.slider = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
  var max, min, observable, sValue, step;

  min = 0;
  max = 100;
  sValue = 50;
  step = 1;
  observable = valueAccessor();
  if (allBindingsAccessor().min != null) {
    min = allBindingsAccessor().min;
  }
  if (allBindingsAccessor().max != null) {
    max = allBindingsAccessor().max;
  }
  if (allBindingsAccessor().slider() != null) {
    sValue = allBindingsAccessor().slider();
  }
  if (allBindingsAccessor().step != null) {
    step = allBindingsAccessor().step;
  }
  $(element).slider({
    value: sValue,
    min: min,
    max: max,
    step: step
  }).on('slide', function(ev, ui) {
    var slideValue;

    slideValue = ui.value;
    if (slideValue < min) {
      $(element).slider('value', min);
      return observable(min);
    } else if (slideValue > max) {
      $(element).slider('value', max);
      return observable(max);
    } else {
      return observable(slideValue);
    }
  }).on('stop', function(event, ui) {
    if (ui.value < min) {
      $(element).slider('value', min);
      return observable(min);
    } else if (ui.value > max) {
      $(element).slider('value', max);
      return observable(max);
    }
  });
  return ko.bindingHandlers.validationCore.init(element, valueAccessor, allBindingsAccessor);
},
update: function(element, valueAccessor, allBindingsAccessor, viewModel) {}
};