another technical blog...technically

Sunday, February 25, 2018

Just another Knockout paginator

I know I know, Knockout JS is something considered obsolete, but I loved it, so I decided right to write two posts about it to share some snippets I developed, maybe someone will find it useful. So the first post is about a simple paginator, the first snippet is the core of the paginator and you can put it in a common javascript (eg Custom.Utility.js), as you can see it behaviors as a plugin for knockout.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Knockout utilities
if (typeof ko !== "undefined") {
 ko.bindingHandlers.fadeVisible = {
  init: function (element, valueAccessor) {
   $(element).fadeIn();
  },
  update: function (element, valueAccessor) {
   // Whenever the value subsequently changes, slowly fade the element in or out
   var value = valueAccessor();
   ko.unwrap(value) ? $(element).fadeIn() : $(element).fadeOut();
  }
 };
 ko.safeObservable = function (initialValue) {
  var result = ko.observable(initialValue);
  result.safe = ko.dependentObservable(function () {
   return result() || {};
  });
  return result;
 };
 ko.Paginator = function (observableValue) {
  var p = new Object();
  p.PageSize = ko.observable(10);
  p.PageIndex = ko.observable(0);
  p.PagesToShowSize = ko.observable(5);
  p.PagedItemsLength = ko.observable(0);
  p.IsVisible = ko.dependentObservable(function () {
   var length = observableValue().length;
   return (length > p.PageSize());
  });
  p.PagedList = ko.dependentObservable(function () {
   var size = p.PageSize();
   var start = p.PageIndex() * size;
   return observableValue().slice(start, start + size);
  });
  p.MaxPageIndex = ko.dependentObservable(function () {
   var l = observableValue().length;
   if (p.PagedItemsLength() !== l) {
    p.PagedItemsLength(l);
    p.PageIndex(0);
   }
   return Math.ceil(p.PagedItemsLength() / p.PageSize()) - 1;
  });
  p.PreviousPage = function () {
   var prev = p.PageIndex() - 1;
   if (p.PageIndex() > 0) {
    p.PageIndex(prev);
    p.MinPageRelativeIndex(prev);
   }
  };
  p.NextPage = function () {
   var next = p.PageIndex() + 1;
 
   if (p.PageIndex() < p.MaxPageIndex()) {
    p.PageIndex(next);
    p.MinPageRelativeIndex(next);
   }
  };
  p.MinPageRelativeIndex = ko.observable(0);
  p.MaxPageRelativeIndex = ko.dependentObservable(function () {
   var relativeMax = p.MinPageRelativeIndex() + p.PagesToShowSize();
 
   if (relativeMax > p.MaxPageIndex()) {
    var min = p.MaxPageIndex() - p.PagesToShowSize();
    p.MinPageRelativeIndex(min < 0 ? 0 : min);
    relativeMax = p.MaxPageIndex() + 1;
   }
   return relativeMax;
  });
  p.PagesToShow = ko.dependentObservable(function () {
   var pages = [];
   var minValue = p.MinPageRelativeIndex();
   var maxValue = p.MaxPageRelativeIndex();
 
   for (i = minValue; i < maxValue; i++) {
    pages.push({ PageNumber: (i + 1) });
   }
   return pages;
  });
  p.MoveToPage = function (index) {
   p.PageIndex(index);
  };
  return p;
 };
}
else {
 console.log("Knockout not imported... cannot decorate with new functions")
}
This second snippet is the declaration of the paginator in the HTML page, as you can see I refer to Custom.ViewModel as the namespace of the javascript. In the DIV class=”items” you are free to implement your preferred view, while in the DIV class=”paginator” you simply have to refer to the correct namespace.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<div data-bind="foreach:
 {
  data: Custom.ViewModel.Paginator.PagedList(),
 }">
<div class="items" data-bind="css: { selected:  Custom.ViewModel.IsSelectedItem($data) },
     click: function() {  Custom.ViewModel.SelectItem($data) }">
...
   
 </div>
</div>
<!-- ko if: Custom.ViewModel.Paginator.IsVisible -->
<div class="paginator">
<ul class="pagination">
<li data-bind="css: { disabled: Custom.ViewModel.Paginator.PageIndex() === 0 }">
   <a data-bind="click: Custom.ViewModel.Paginator.PreviousPage" href="https://www.blogger.com/blogger.g?blogID=8182359208124161774#"><<</a>
  </li>
<!-- ko foreach: Custom.ViewModel.Paginator.PagesToShow -->
<li data-bind="css: { active: $data.PageNumber === (Custom.ViewModel.Paginator.PageIndex() + 1) }">
   <a data-bind="text: $data.PageNumber,
      click: function() { Custom.ViewModel.Paginator.MoveToPage($data.PageNumber-1); }" href="https://www.blogger.com/blogger.g?blogID=8182359208124161774#">
   </a>
  </li>
<!-- /ko -->
<li data-bind="css: { disabled: Custom.ViewModel.Paginator.PageIndex() === Custom.ViewModel.Paginator.MaxPageIndex() }">
   <a data-bind="click: Custom.ViewModel.Paginator.NextPage" href="https://www.blogger.com/blogger.g?blogID=8182359208124161774#">>></a>
  </li>
</ul>
</div>
<!-- /ko -->
Last but not least this is the initialization all the component in the Knockout controller.
1
2
3
4
5
6
7
// View model definition
controller.ViewModel = function ViewModel() {
 var vm = this;
 vm.Paginator = ko.Paginator(vm.Items);
  
 ...
};
Share:
written in: Milano MI, Italia

0 commenti:

Post a Comment

Because of a lot of SPAM about courses, I need to moderate all comments here.
I ensure you that I will answer whenever possible (if you are not a spammer).

Me, myself and I

My Photo
I'm just another IT guy sharing his knowledge with all of you out there.
Wanna know more?