1// Example of js-plugin; How to extend the Abou namespace 2; (function (window, document, Abou, $, undefined) { 3 4 /* 5 Overview: 6 7 */ 8 var hasMobilePosition = !$(".filter-options").has("div"); 9 10 Abou.listnewsfilter = (function () { 11 12 13 var filterViewModel = function (filterText, targetGroups, fromDate, toDate) { 14 var self = this; 15 self.filterText = ko.observable(filterText); 16 self.targetGroups = ko.observableArray(targetGroups); 17 self.fromDate = ko.observable(fromDate); 18 self.fromDateAsMoment = ko.computed(function () { 19 return moment(self.fromDate()); 20 }); 21 self.toDate = ko.observable(toDate); 22 self.toDateAsMoment = ko.computed(function () { 23 return moment(self.toDate()); 24 }); 25 }; 26 27 var newsItemModel = function () { 28 var self = this; 29 self.id = 0; 30 self.name = ""; 31 self.intro = ""; 32 self.incident = false; 33 self.imageUrl = ""; 34 self.epiUrl = ""; 35 self.imageUrl = ""; 36 self.date = null; 37 self.targetGroups = []; 38 }; 39 40 var initFilterViewModel = function () { 41 var filterText = $("#NewsListPage [name=query]").val(); 42 var targetGroups = []; 43 $("#NewsListPage [name=tgid]:checked").each(function () { 44 targetGroups.push($(this).val()); 45 }); 46 var fromDateText = $("#NewsListPage [name=fromDate]").val(); 47 var toDateText = $("#NewsListPage [name=toDate]").val(); 48 49 return new filterViewModel(filterText, targetGroups, fromDateText, toDateText); 50 }; 51 52 var NewsListViewModel = function (newsItems) { 53 var self = this; 54 self.newsItems = newsItems; 55 self.newsItems.sort(function (a, b) { 56 if (a.date.isAfter(b.date)) return -1; 57 if (a.date.isBefore(b.date)) return 1; 58 return 0; 59 }); 60 61 self.filters = initFilterViewModel(); 62 63 self.filterOnText = function (newsItemsToFilter) { 64 var filterText = self.filters.filterText(); 65 if (!filterText) { 66 return newsItemsToFilter; 67 } 68 var result = []; 69 70 //Regexp created once for performance reasons. 71 //Note: Js has trouble with word boundaries and 'åäö' the current solution gives false positives for words when 72 // search phrase begins with åäö. Ie: searching for "äga" matches "säga". This seems however to be the least bad solution. 73 var textRegExp = new XRegExp('\\p{Separator}' + filterText, 'i'); 74 $.each(newsItemsToFilter, function (index, newsItem) { 75 var textToTest = ' ' + newsItem.name + ' ' + newsItem.intro; 76 if (textRegExp.test(textToTest)) { 77 result.push(newsItem); 78 } 79 }); 80 return result; 81 }; 82 83 self.filterOnTargetGroups = function (newsItemsToFilter) { 84 var activeTargetGroups = self.filters.targetGroups(); 85 86 self.displayActiveTargetGroups(activeTargetGroups); 87 88 if (!activeTargetGroups || !activeTargetGroups.length) { 89 return newsItemsToFilter; 90 } 91 var result = []; 92 93 $.each(newsItemsToFilter, function (index, newsItem) { 94 var hit = false; 95 $.each(newsItem.targetGroups, function (index, eventTg) { 96 if ($.inArray(eventTg.pageId, activeTargetGroups) > -1) { 97 hit = true; 98 } 99 }); 100 if (hit) { 101 result.push(newsItem); 102 } 103 }); 104 105 return result; 106 };
107 self.displayActiveTargetGroups = function (targetGroups) { 108 var selectedTargetGroupText = $(".current-target-group"); 109 var newSelectedTargetGroups = ""; 110 if (targetGroups.length == 0) { 111 newSelectedTargetGroups = "För vem?"; 112 } 113 else if (targetGroups.length == 1) { 114 newSelectedTargetGroups = $("#NewsListPage [name=tgid]:checked + label .target-group-name").text(); 115 } 116 else { 117 newSelectedTargetGroups = "För vem? (" + targetGroups.length + "st)"; 118 } 119 selectedTargetGroupText.text(newSelectedTargetGroups); 120 } 121 122 self.filterOnDates = function (newsItemsToFilter) { 123 var fromDateAsMoment = self.filters.fromDateAsMoment(); 124 var toDateAsMoment = self.filters.toDateAsMoment(); 125 if (!fromDateAsMoment.isValid() && !toDateAsMoment.isValid()) { 126 return newsItemsToFilter; 127 } 128 var partResult = newsItemsToFilter; 129 if (fromDateAsMoment.isValid()) { 130 partResult = []; 131 $.each(newsItemsToFilter, function (index, newsItem) { 132 if (newsItem.date.isValid() && newsItem.date.isAfter(fromDateAsMoment)) { 133 partResult.push(newsItem); 134 } 135 }); 136 } 137 var result = partResult; 138 if (toDateAsMoment.isValid()) { 139 result = []; 140 toDateAsMoment = toDateAsMoment.add(1, 'days'); //Add one day to achieve 'including' selection 141 $.each(partResult, function (index, newsItem) { 142 //firstly check toDate. Todate can be null, if so check against fromdate instead. 143 if ((newsItem.date.isValid() && newsItem.date.isBefore(toDateAsMoment)) 144 || (newsItem.date.isValid() && newsItem.date.isBefore(toDateAsMoment))) { 145 result.push(newsItem); 146 } 147 }); 148 } 149 return result; 150 }; 151 152 self.resetDateFilters = function () { 153 self.filters.fromDate(""); 154 self.filters.toDate(""); 155 156 updateSelectedDates(); 157 158 $(".chosen-dates").text("Datum"); 159 160 $(".hasDatepicker").datepicker('setDate', null); 161 $(".hasDatepicker").datepicker('setDate', null); 162 163 self.filters.filterText(""); 164 }; 165 166 self.resetTargetGroupsFilters = function () { 167 self.filters.targetGroups.removeAll(); 168 169 self.filters.filterText(""); 170 } 171 172 self.hitNewsItems = ko.computed(function () { 173 var hitNewsItems = self.filterOnText(self.newsItems); 174 hitNewsItems = self.filterOnTargetGroups(hitNewsItems); 175 //hitOccasions = self.filterOnCategories(hitOccasions); 176 hitNewsItems = self.filterOnDates(hitNewsItems); 177 178 return hitNewsItems; 179 }); 180 181 self.pageSize = 5; 182 self.visibleCount = ko.observable(self.pageSize); 183 self.visibleNewsItems = ko.computed(function () { 184 return self.hitNewsItems().slice(0, self.visibleCount()); 185 }); 186 187 var clickCount = 1; 188 var clickCountInQuery = Number(getUrlVars()["view_more"]); 189 if (clickCountInQuery > 1) { 190 clickCount = clickCountInQuery; 191 } 192 $(document).ready(function () { 193 self.visibleCount(clickCount * self.pageSize) 194 }); 195 self.showMore = function () { 196 var currentLoc = window.location.href; 197 clickCount++; 198 window.history.pushState("", "", updateQueryStringParameter(currentLoc, 'view_more', clickCount)); 199 self.visibleCount(clickCount * self.pageSize) 200 } 201 }; 202 203 var toggleDisplay = function (event) { 204 //toggle class on parent element 205 $("#FilteredNewsList").toggleClass("displayFiltersInMobile"); 206 event.preventDefault(); 207 }; 208 209 var closeDisplay = function (e) { 210 e.preventDefault(); 211 $(".option:visible").slideUp(); 212 $(".filter-action-button.active").focus(); 213 $(".filter-action-button.active").attr('aria-expanded', 'false'); 214 $(".filter-action-button.active").removeClass("active"); 215 } 216 217 var setupToggleFunction = function () { 218 var activeOption; 219 $(".filter-action-button").each(function () { 220 var targetId = $(this).attr('aria-controls'); 221 $(this).on("click", function (e) { 222 if ($(this).hasClass("active")) { 223 $(this).toggleClass("active"); 224 $(this).attr('aria-expanded', 'false'); 225 } else { 226 $(".filter-action-button.active").removeClass("active"); 227 $(this).toggleClass("active"); 228 $(this).attr('aria-expanded', 'true'); 229 230 var that = this; 231 setTimeout(function () { 232 if ($(that).attr('data-action-target') == 'date') { 233 $('.from-date-holder').find('.ui-datepicker-next').focus(); 234 } 235 else {
236 $('#' + targetId).find('input:first-of-type').focus(); 237 } 238 }, 200); 239 } 240 e.preventDefault(); 241 activeOption = $(this).data("action-target"); 242 243 if ($(".option:visible").hasClass(activeOption)) { 244 $(".option." + $(this).data("action-target")).slideToggle("fast"); 245 } 246 else if ($(".option:visible").length > 0) { 247 if (!Abou.common.isBelowMobileMode()) { 248 $(".option:visible").toggle(); 249 $(".option." + $(this).data("action-target")).toggle(); 250 } 251 else { 252 $(".option." + $(this).data("action-target")).slideToggle("fast"); 253 } 254 } 255 else { 256 $(".option." + $(this).data("action-target")).slideToggle("fast"); 257 } 258 }); 259 if (targetId === "eventList-filter-date") { 260 $('.from-date-holder').find('.ui-datepicker-next').on("keydown", function(e) { 261 if ((e.key === 'Tab' || e.keyCode === 9) && e.shiftKey) { 262 closeDisplay(e); 263 } 264 }) 265 } 266 else { 267 $('#' + targetId).find('input:first-of-type').on("keydown", function(e) 268 { 269 if ((e.key === 'Tab' || e.keyCode === 9) && e.shiftKey) { 270 closeDisplay(e); 271 } 272 }) 273 } 274 }); 275 }; 276 var updateSelectedDates = function () { 277 278 var fromDate = moment($(".from-date-place-holder").text()); 279 var toDate = moment($(".to-date-place-holder").text()); 280 var selecteDateString = ""; 281 282 if (fromDate.isValid()) { 283 selecteDateString += fromDate.format("DD") + " " + fromDate.format("MMM"); 284 } 285 if (toDate.isValid()) { 286 selecteDateString += " till " + toDate.format("DD") + " " + toDate.format("MMM"); 287 } 288 $(".chosen-dates").text(selecteDateString); 289 }; 290 291 var setToggleOptionsPosition = function () { 292 293 if (Abou.common.isBelowMobileMode() && !hasMobilePosition) { 294 hasMobilePosition = !hasMobilePosition; 295 $("#FilteredNewsList .filter-action-button").each(function () { 296 activeOption = $(this).data("action-target"); 297 $(this).after($(".option." + activeOption).detach()); 298 }); 299 } 300 else if (hasMobilePosition && !Abou.common.isBelowMobileMode()) { 301 hasMobilePosition = !hasMobilePosition; 302 $(".filter-options").append($(".option").detach()); 303 } 304 } 305 306 // Public properties 307 return { 308 init: function () { 309 $(".searchForm [type=text][name=fromDate], .searchForm [type=text][name=toDate]").prop('disabled', false); 310 $(".filterWrapper .filters .dateFilters").show(); 311 312 var datePickerOptionsFrom = { 313 dateFormat: "yy-mm-dd", 314 minDate: "-2y", 315 maxDate: "0", 316 defaultDate: "-1m", 317 onSelect: function (date) { 318 $(".from-date-place-holder").text(date); 319 $(".from-date-place-holder").val(date); 320 $(".from-date-place-holder").change(); 321 updateSelectedDates(); 322 } 323 }; 324 325 var datePickerOptionsTo = { 326 dateFormat: "yy-mm-dd", 327 minDate: "-2y", 328 maxDate: "0", 329 onSelect: function (date) { 330 $(".to-date-place-holder").text(date); 331 $(".to-date-place-holder").val(date); 332 $(".to-date-place-holder").change(); 333 updateSelectedDates();
334 } 335 }; 336 337 var fromDatePicker = $(".from-date-holder").datepicker(datePickerOptionsFrom); 338 var toDatePicker = $(".to-date-holder").datepicker(datePickerOptionsTo); 339 340 //update datepickers depending on others value 341 $(".searchForm [type=text][name=fromDate]").change(function (event) { 342 var currentFromDate = fromDatePicker.datepicker("getDate"); 343 var minDate = !!currentFromDate ? currentFromDate : "-1m"; 344 toDatePicker.datepicker("option", "minDate", minDate); 345 }); 346 $(".searchForm [type=text][name=toDate]").change(function (event) { 347 var currentToDate = toDatePicker.datepicker("getDate"); 348 var maxDate = !!currentToDate ? currentToDate : "0"; 349 fromDatePicker.datepicker("option", "maxDate", maxDate); 350 }); 351 //} 352 353 if ($("input.jsonNewsItems").length) { 354 var newsItemsJson = JSON.parse($("input.jsonNewsItems").val()); 355 var newsItemModels = []; 356 $.each(newsItemsJson, function (index, jsonNewsItem) { 357 var newsModel = new newsItemModel(); 358 newsModel.id = jsonNewsItem.Id; 359 newsModel.name = jsonNewsItem.Name; 360 newsModel.intro = jsonNewsItem.Intro; 361 newsModel.incident = jsonNewsItem.Incident; 362 newsModel.imageUrl = jsonNewsItem.ImageUrl; 363 newsModel.epiUrl = jsonNewsItem.EpiUrl; 364 newsModel.imageUrl = jsonNewsItem.ImageUrl; 365 newsModel.date = moment(jsonNewsItem.Date); 366 newsModel.targetGroups = []; 367 $.each(jsonNewsItem.TargetGroups, function (index, targetGroup) { 368 newsModel.targetGroups.push({ 369 pageId: targetGroup.PageId, 370 iChar: !!targetGroup.Char ? "&#x" + targetGroup.Char + ";" : "", 371 color: targetGroup.Color 372 }); 373 }); 374 375 newsItemModels.push(newsModel); 376 }); 377 378 var newsListViewModel = new NewsListViewModel(newsItemModels); 379 ko.applyBindings(newsListViewModel, document.getElementById("FilteredNewsList")); 380 } 381 382 $(".filterLink").click(toggleDisplay); 383 $(".close-options-button").click(closeDisplay); 384 385 $(".close-options-button").on("keydown", function(e) { 386 387 if (e.key === 'Tab' || e.keyCode === 9) { 388 if (!e.shiftKey) { 389 closeDisplay(e); 390 } 391 } 392 }) 393 394 $("#newsListForm").submit(function (e) { 395 e.preventDefault(); 396 }); 397 398 setupToggleFunction(); 399 400 $(window).on("resize", function () 401 { 402 setToggleOptionsPosition(); 403 }); 404 405 setToggleOptionsPosition(); 406 } 407 }; 408 }()); 409 410}(this, this.document, window.Abou = window.Abou || {}, jQuery));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.