PageSourceSearch

https://flatleyheating.com/wp-content/plugins/cherry-projects/public/assets/js/salvattore.min.js?ver=1.0.9

js flatleyheating.com collected 2026-10-06 19:37:13 UTC 12,020 bytes, 415 lines download raw bytes

vendor: 12,020 bytes, lines 1-415
1/* jshint laxcomma: true */
2var salvattore = (function (global, document, undefined) {
3"use strict";
4
5var self = {},
6    grids = [],
7    mediaRules = [],
8    mediaQueries = [],
9    add_to_dataset = function(element, key, value) {
10      // uses dataset function or a fallback for <ie10
11      if (element.dataset) {
12        element.dataset[key] = value;
13      } else {
14        element.setAttribute("data-" + key, value);
15      }
16      return;
17    };
18
19self.obtainGridSettings = function obtainGridSettings(element) {
20  // returns the number of columns and the classes a column should have,
21  // from computing the style of the ::before pseudo-element of the grid.
22
23  var computedStyle = global.getComputedStyle(element, ":before")
24    , content = computedStyle.getPropertyValue("content").slice(1, -1)
25    , matchResult = content.match(/^\s*(\d+)(?:\s?\.(.+))?\s*$/)
26    , numberOfColumns = 1
27    , columnClasses = []
28  ;
29
30  if (matchResult) {
31    numberOfColumns = matchResult[1];
32    columnClasses = matchResult[2];
33    columnClasses = columnClasses? columnClasses.split(".") : ["column"];
34  } else {
35    matchResult = content.match(/^\s*\.(.+)\s+(\d+)\s*$/);
36    if (matchResult) {
37      columnClasses = matchResult[1];
38      numberOfColumns = matchResult[2];
39      if (numberOfColumns) {
40            numberOfColumns = numberOfColumns.split(".");
41      }
42    }
43  }
44
45  return {
46    numberOfColumns: numberOfColumns,
47    columnClasses: columnClasses
48  };
49};
50
51
52self.addColumns = function addColumns(grid, items) {
53  // from the settings obtained, it creates columns with
54  // the configured classes and adds to them a list of items.
55
56  var settings = self.obtainGridSettings(grid)
57    , numberOfColumns = settings.numberOfColumns
58    , columnClasses = settings.columnClasses
59    , columnsItems = new Array(+numberOfColumns)
60    , columnsFragment = document.createDocumentFragment()
61    , i = numberOfColumns
62    , selector
63  ;
64
65  while (i-- !== 0) {
66    selector = "[data-columns] > *:nth-child(" + numberOfColumns + "n-" + i + ")";
67    columnsItems.push(items.querySelectorAll(selector));
68  }
69
70  columnsItems.forEach(function append_to_grid_fragment(rows) {
71    var column = document.createElement("div")
72      , rowsFragment = document.createDocumentFragment()
73    ;
74
75    column.className = columnClasses.join(" ");
76
77    Array.prototype.forEach.call(rows, function append_to_column(row) {
78      rowsFragment.appendChild(row);
79    });
80    column.appendChild(rowsFragment);
81    columnsFragment.appendChild(column);
82  });
83
84  grid.appendChild(columnsFragment);
85  add_to_dataset(grid, 'columns', numberOfColumns);
86};
87
88
89self.removeColumns = function removeColumns(grid) {
90  // removes all the columns from a grid, and returns a list
91  // of items sorted by the ordering of columns.
92
93  var range = document.createRange();
94  range.selectNodeContents(grid);
95
96  var columns = Array.prototype.filter.call(range.extractContents().childNodes, function filter_elements(node) {
97    return node instanceof global.HTMLElement;
98  });
99
100  var numberOfColumns = columns.length
101    , numberOfRowsInFirstColumn = columns[0].childNodes.length
102    , sortedRows = new Array(numberOfRowsInFirstColumn * numberOfColumns)
103  ;
104
105  Array.prototype.forEach.call(columns, function iterate_columns(column, columnIndex) {
106    Array.prototype.forEach.call(column.children, function iterate_rows(row, rowIndex) {
107      sortedRows[rowIndex * numberOfColumns + columnIndex] = row;
108    });
109  });
110
111  var container = document.createElement("div");
112  add_to_dataset(container, 'columns', 0);
113
114  sortedRows.filter(function filter_non_null(child) {
115    return !!child;
116  }).forEach(function append_row(child) {
117    container.appendChild(child);
118  });
119
120  return container;
121};
122
123
124self.recreateColumns = function recreateColumns(grid) {
125  // removes all the columns from the grid, and adds them again,
126  // it is used when the number of columns change.
127
128  global.requestAnimationFrame(function render_after_css_mediaQueryChange() {
129    self.addColumns(grid, self.removeColumns(grid));
130    var columnsChange = new CustomEvent("columnsChange");
131    grid.dispatchEvent(columnsChange);
132  });
133};
134
135
136self.mediaQueryChange = function mediaQueryChange(mql) {
137  // recreates the columns when a media query matches the current state
138  // of the browser.
139
140  if (mql.matches) {
141    Array.prototype.forEach.call(grids, self.recreateColumns);
142  }
143};
144
145
146self.getCSSRules = function getCSSRules(stylesheet) {
147  // returns a list of css rules from a stylesheet
148
149  var cssRules;
150  try {
151    cssRules = stylesheet.sheet.cssRules || stylesheet.sheet.rules;
152  } catch (e) {
153    return [];
154  }
155
156  return cssRules || [];
157};
158
159
160self.getStylesheets = function getStylesheets() {
161  // returns a list of all the styles in the document (that are accessible).
162
163  var inlineStyleBlocks = Array.prototype.slice.call(document.querySelectorAll("style"));
164  inlineStyleBlocks.forEach(function(stylesheet, idx) {
165    if (stylesheet.type !== 'text/css' && stylesheet.type !== '') {
166      inlineStyleBlocks.splice(idx, 1);
167    }
168  });
169
170  return Array.prototype.concat.call(
171    inlineStyleBlocks,
172    Array.prototype.slice.call(document.querySelectorAll("link[rel='stylesheet']"))
173  );
174};
175
176
177self.mediaRuleHasColumnsSelector = function mediaRuleHasColumnsSelector(rules) {
178  // checks if a media query css rule has in its contents a selector that
179  // styles the grid.
180
181  var i, rule;
182
183  try {
184    i = rules.length;
185  }
186  catch (e) {
187    i = 0;
188  }
189
190  while (i--) {
191    rule = rules[i];
192    if (rule.selectorText && rule.selectorText.match(/\[data-columns\](.*)::?before$/)) {
193      return true;
194    }
195  }
196
197  return false;
198};
199
200
201self.scanMediaQueries = function scanMediaQueries() {
202  // scans all the stylesheets for selectors that style grids,
203  // if the matchMedia API is supported.
204
205  var newMediaRules = [];
206
207  if (!global.matchMedia) {
208    return;
209  }
210
211  self.getStylesheets().forEach(function extract_rules(stylesheet) {
212    Array.prototype.forEach.call(self.getCSSRules(stylesheet), function filter_by_column_selector(rule) {
213      // rule.media throws an 'not implemented error' in ie9 for import rules occasionally
214      try {
215        if (rule.media && rule.cssRules && self.mediaRuleHasColumnsSelector(rule.cssRules)) {
216          newMediaRules.push(rule);
217        }
218      } catch (e) {}
219    });
220  });
221
222  // remove matchMedia listeners from the old rules
223  var oldRules = mediaRules.filter(function (el) {
224      return newMediaRules.indexOf(el) === -1;
225  });
226  mediaQueries.filter(function (el) {
227    return oldRules.indexOf(el.rule) !== -1;
228  }).forEach(function (el) {
229      el.mql.removeListener(self.mediaQueryChange);
230  });
231  mediaQueries = mediaQueries.filter(function (el) {
232    return oldRules.indexOf(el.rule) === -1;
233  });
234
235  // add matchMedia listeners to the new rules
236  newMediaRules.filter(function (el) {
237    return mediaRules.indexOf(el) == -1;
238  }).forEach(function (rule) {
239      var mql = global.matchMedia(rule.media.mediaText);
240      mql.addListener(self.mediaQueryChange);
241      mediaQueries.push({rule: rule, mql:mql});
242  });
243
244  // swap mediaRules with the new set
245  mediaRules.length = 0;
246  mediaRules = newMediaRules;
247};
248
249
250self.rescanMediaQueries = function rescanMediaQueries() {
251    self.scanMediaQueries();
252    Array.prototype.forEach.call(grids, self.recreateColumns);
253};
254
255
256self.nextElementColumnIndex = function nextElementColumnIndex(grid, fragments) {
257  // returns the index of the column where the given element must be added.
258
259  var children = grid.children
260    , m = children.length
261    , lowestRowCount = 0
262    , child
263    , currentRowCount
264    , i
265    , index = 0
266  ;
267  for (i = 0; i < m; i++) {
268    child = children[i];
269    currentRowCount = child.children.length + (fragments[i].children || fragments[i].childNodes).length;
270  if(lowestRowCount === 0) {
271    lowestRowCount = currentRowCount;
272  }
273    if(currentRowCount < lowestRowCount) {
274      index = i;
275      lowestRowCount = currentRowCount;
276    }
277  }
278
279  return index;
280};
281
282
283self.createFragmentsList = function createFragmentsList(quantity) {
284  // returns a list of fragments
285
286  var fragments = new Array(quantity)
287    , i = 0
288  ;
289
290  while (i !== quantity) {
291    fragments[i] = document.createDocumentFragment();
292    i++;
293  }
294
295  return fragments;
296};
297
298
299self.appendElements = function appendElements(grid, elements) {
300  // adds a list of elements to the end of a grid
301
302  var columns = grid.children
303    , numberOfColumns = columns.length
304    , fragments = self.createFragmentsList(numberOfColumns)
305  ;
306
307  Array.prototype.forEach.call(elements, function append_to_next_fragment(element) {
308    var columnIndex = self.nextElementColumnIndex(grid, fragments);
309    fragments[columnIndex].appendChild(element);
310  });
311
312  Array.prototype.forEach.call(columns, function insert_column(column, index) {
313    column.appendChild(fragments[index]);
314  });
315};
316
317
318self.prependElements = function prependElements(grid, elements) {
319  // adds a list of elements to the start of a grid
320
321  var columns = grid.children
322    , numberOfColumns = columns.length
323    , fragments = self.createFragmentsList(numberOfColumns)
324    , columnIndex = numberOfColumns - 1
325  ;
326
327  elements.forEach(function append_to_next_fragment(element) {
328    var fragment = fragments[columnIndex];
329    fragment.insertBefore(element, fragment.firstChild);
330    if (columnIndex === 0) {
331      columnIndex = numberOfColumns - 1;
332    } else {
333      columnIndex--;
334    }
335  });
336
337  Array.prototype.forEach.call(columns, function insert_column(column, index) {
338    column.insertBefore(fragments[index], column.firstChild);
339  });
340
341  // populates a fragment with n columns till the right
342  var fragment = document.createDocumentFragment()
343    , numberOfColumnsToExtract = elements.length % numberOfColumns
344  ;
345
346  while (numberOfColumnsToExtract-- !== 0) {
347    fragment.appendChild(grid.lastChild);
348  }
349
350  // adds the fragment to the left
351  grid.insertBefore(fragment, grid.firstChild);
352};
353
354
355self.registerGrid = function registerGrid (grid) {
356  if (global.getComputedStyle(grid).display === "none") {
357    return;
358  }
359
360  if ( 'true' === grid.getAttribute('data-inited') ) {
361    return;
362  }
363
364  grid.setAttribute( 'data-inited', 'true' );
365
366  // retrieve the list of items from the grid itself
367  var range = document.createRange();
368  range.selectNodeContents(grid);
369
370  var items = document.createElement("div");
371  items.appendChild(range.extractContents());
372
373
374  add_to_dataset(items, 'columns', 0);
375  self.addColumns(grid, items);
376  grids.push(grid);
377};
378
379
380self.init = function init() {
381  // adds required CSS rule to hide 'content' based
382  // configuration.
383
384  var css = document.createElement("style");
385  css.innerHTML = "[data-columns]::before{display:block;visibility:hidden;position:absolute;font-size:1px;}";
386  document.head.appendChild(css);
387
388  // scans all the grids in the document and generates
389  // columns from their configuration.
390
391  var gridElements = document.querySelectorAll("[data-columns]");
392
393  Array.prototype.forEach.call(gridElements, self.registerGrid);
394  self.scanMediaQueries();
395};
396
397self.init();
398
399return {
400  appendElements: self.appendElements,
401  prependElements: self.prependElements,
402  registerGrid: self.registerGrid,
403  recreateColumns: self.recreateColumns,
404  rescanMediaQueries: self.rescanMediaQueries,
405  init: self.init,
406
407  // maintains backwards compatibility with underscore style method names
408  append_elements: self.appendElements,
409  prepend_elements: self.prependElements,
410  register_grid: self.registerGrid,
411  recreate_columns: self.recreateColumns,
412  rescan_media_queries: self.rescanMediaQueries
413};
414
415})(window, window.document);

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.