Full Code of NeXTs/Clusterize.js for AI

master 199ff217e491 cached
6 files
16.8 KB
4.3k tokens
4 symbols
1 requests
Download .txt
Repository: NeXTs/Clusterize.js
Branch: master
Commit: 199ff217e491
Files: 6
Total size: 16.8 KB

Directory structure:
gitextract_jzoo8kx6/

├── LICENSE
├── README.md
├── clusterize.css
├── clusterize.js
├── externs.js
└── package.json

================================================
FILE CONTENTS
================================================

================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2015 Denis Lukov

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

================================================
FILE: README.md
================================================
# Clusterize.js
[![Clusterize.js on NPM](https://img.shields.io/npm/v/clusterize.js.svg)](https://www.npmjs.com/package/clusterize.js) 
[![Package Quality](http://npm.packagequality.com/shield/clusterize.js.svg)](http://packagequality.com/#?package=clusterize.js)
[![Gzip Size](http://img.badgesize.io/https://cdn.jsdelivr.net/npm/clusterize.js/clusterize.min.js?compression=gzip)](https://cdn.jsdelivr.net/npm/clusterize.js/clusterize.min.js)
[![Install Size](https://packagephobia.now.sh/badge?p=clusterize.js)](https://packagephobia.now.sh/result?p=clusterize.js)
[![Download Count](https://img.shields.io/npm/dt/clusterize.js.svg)](https://www.npmjs.com/package/clusterize.js)
[![Join the chat at https://gitter.im/NeXTs/Clusterize.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/NeXTs/Clusterize.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

> Tiny vanilla JS plugin to display large data sets easily

[Demo, usage, etc…](https://clusterize.js.org/)

[![example](http://nexts.github.io/Clusterize.js/img/table_example.gif)](https://clusterize.js.org/)


================================================
FILE: clusterize.css
================================================
/* max-height - the only parameter in this file that needs to be edited.
 * Change it to suit your needs. The rest is recommended to leave as is.
 */
.clusterize-scroll{
  max-height: 200px;
  overflow: auto;
}

/**
 * Avoid vertical margins for extra tags
 * Necessary for correct calculations when rows have nonzero vertical margins
 */
.clusterize-extra-row{
  margin-top: 0 !important;
  margin-bottom: 0 !important;
}

/* By default extra tag .clusterize-keep-parity added to keep parity of rows.
 * Useful when used :nth-child(even/odd)
 */
.clusterize-extra-row.clusterize-keep-parity{
  display: none;
}

/* During initialization clusterize adds tabindex to force the browser to keep focus
 * on the scrolling list, see issue #11
 * Outline removes default browser's borders for focused elements.
 */
.clusterize-content{
  outline: 0;
  counter-reset: clusterize-counter;
}

/* Centering message that appears when no data provided
 */
.clusterize-no-data td{
  text-align: center;
}

================================================
FILE: clusterize.js
================================================
/* Clusterize.js - v1.0.0 - 2023-01-22
 http://NeXTs.github.com/Clusterize.js/
 Copyright (c) 2015 Denis Lukov; Licensed MIT */

;(function(name, definition) {
    if (typeof module != 'undefined') module.exports = definition();
    else if (typeof define == 'function' && typeof define.amd == 'object') define(definition);
    else this[name] = definition();
}('Clusterize', function() {
  "use strict"

  // detect ie9 and lower
  // https://gist.github.com/padolsey/527683#comment-786682
  var ie = (function(){
    for( var v = 3,
             el = document.createElement('b'),
             all = el.all || [];
         el.innerHTML = '<!--[if gt IE ' + (++v) + ']><i><![endif]-->',
         all[0];
       ){}
    return v > 4 ? v : document.documentMode;
  }()),
  is_mac = navigator.platform.toLowerCase().indexOf('mac') + 1;
  var Clusterize = function(data) {
    if( ! (this instanceof Clusterize))
      return new Clusterize(data);
    var self = this;

    var defaults = {
      rows_in_block: 50,
      blocks_in_cluster: 4,
      tag: null,
      show_no_data_row: true,
      no_data_class: 'clusterize-no-data',
      no_data_text: 'No data',
      keep_parity: true,
      callbacks: {}
    }

    // public parameters
    self.options = {};
    var options = ['rows_in_block', 'blocks_in_cluster', 'show_no_data_row', 'no_data_class', 'no_data_text', 'keep_parity', 'tag', 'callbacks'];
    for(var i = 0, option; option = options[i]; i++) {
      self.options[option] = typeof data[option] != 'undefined' && data[option] != null
        ? data[option]
        : defaults[option];
    }

    var elems = ['scroll', 'content'];
    for(var i = 0, elem; elem = elems[i]; i++) {
      self[elem + '_elem'] = data[elem + 'Id']
        ? document.getElementById(data[elem + 'Id'])
        : data[elem + 'Elem'];
      if( ! self[elem + '_elem'])
        throw new Error("Error! Could not find " + elem + " element");
    }

    // tabindex forces the browser to keep focus on the scrolling list, fixes #11
    if( ! self.content_elem.hasAttribute('tabindex'))
      self.content_elem.setAttribute('tabindex', 0);

    // private parameters
    var rows = isArray(data.rows)
        ? data.rows
        : self.fetchMarkup(),
      cache = {},
      scroll_top = self.scroll_elem.scrollTop;

    // append initial data
    self.insertToDOM(rows, cache);

    // restore the scroll position
    self.scroll_elem.scrollTop = scroll_top;

    // adding scroll handler
    var last_cluster = false,
    scroll_debounce = 0,
    pointer_events_set = false,
    scrollEv = function() {
      // fixes scrolling issue on Mac #3
      if (is_mac) {
          if( ! pointer_events_set) self.content_elem.style.pointerEvents = 'none';
          pointer_events_set = true;
          clearTimeout(scroll_debounce);
          scroll_debounce = setTimeout(function () {
              self.content_elem.style.pointerEvents = 'auto';
              pointer_events_set = false;
          }, 50);
      }
      if (last_cluster != (last_cluster = self.getClusterNum(rows)))
        self.insertToDOM(rows, cache);
      if (self.options.callbacks.scrollingProgress)
        self.options.callbacks.scrollingProgress(self.getScrollProgress());
    },
    resize_debounce = 0,
    resizeEv = function() {
      clearTimeout(resize_debounce);
      resize_debounce = setTimeout(self.refresh, 100);
    }
    on('scroll', self.scroll_elem, scrollEv);
    on('resize', window, resizeEv);

    // public methods
    self.destroy = function(clean) {
      off('scroll', self.scroll_elem, scrollEv);
      off('resize', window, resizeEv);
      self.html((clean ? self.generateEmptyRow() : rows).join(''));
    }
    self.refresh = function(force) {
      if(self.getRowsHeight(rows) || force) self.update(rows);
    }
    self.update = function(new_rows) {
      rows = isArray(new_rows)
        ? new_rows
        : [];
      var scroll_top = self.scroll_elem.scrollTop;
      // fixes #39
      if(rows.length * self.options.item_height < scroll_top) {
        self.scroll_elem.scrollTop = 0;
        last_cluster = 0;
      }
      self.insertToDOM(rows, cache);
      self.scroll_elem.scrollTop = scroll_top;
    }
    self.clear = function() {
      self.update([]);
    }
    self.getRowsAmount = function() {
      return rows.length;
    }
    self.getScrollProgress = function() {
      return this.options.scroll_top / (rows.length * this.options.item_height) * 100 || 0;
    }

    var add = function(where, _new_rows) {
      var new_rows = isArray(_new_rows)
        ? _new_rows
        : [];
      if( ! new_rows.length) return;
      rows = where == 'append'
        ? rows.concat(new_rows)
        : new_rows.concat(rows);
      self.insertToDOM(rows, cache);
    }
    self.append = function(rows) {
      add('append', rows);
    }
    self.prepend = function(rows) {
      add('prepend', rows);
    }
  }

  Clusterize.prototype = {
    constructor: Clusterize,
    // fetch existing markup
    fetchMarkup: function() {
      var rows = [], rows_nodes = this.getChildNodes(this.content_elem);
      while (rows_nodes.length) {
        rows.push(rows_nodes.shift().outerHTML);
      }
      return rows;
    },
    // get tag name, content tag name, tag height, calc cluster height
    exploreEnvironment: function(rows, cache) {
      var opts = this.options;
      opts.content_tag = this.content_elem.tagName.toLowerCase();
      if( ! rows.length) return;
      if(ie && ie <= 9 && ! opts.tag) opts.tag = rows[0].match(/<([^>\s/]*)/)[1].toLowerCase();
      if(this.content_elem.children.length <= 1) cache.data = this.html(rows[0] + rows[0] + rows[0]);
      if( ! opts.tag) opts.tag = this.content_elem.children[0].tagName.toLowerCase();
      this.getRowsHeight(rows);
    },
    getRowsHeight: function(rows) {
      var opts = this.options,
        prev_item_height = opts.item_height;
      opts.cluster_height = 0;
      if( ! rows.length) return;
      var nodes = this.content_elem.children;
      if( ! nodes.length) return;
      var node = nodes[Math.floor(nodes.length / 2)];
      opts.item_height = node.offsetHeight;
      // consider table's border-spacing
      if(opts.tag == 'tr' && getStyle('borderCollapse', this.content_elem) != 'collapse')
        opts.item_height += parseInt(getStyle('borderSpacing', this.content_elem), 10) || 0;
      // consider margins (and margins collapsing)
      if(opts.tag != 'tr') {
        var marginTop = parseInt(getStyle('marginTop', node), 10) || 0;
        var marginBottom = parseInt(getStyle('marginBottom', node), 10) || 0;
        opts.item_height += Math.max(marginTop, marginBottom);
      }
      opts.block_height = opts.item_height * opts.rows_in_block;
      opts.rows_in_cluster = opts.blocks_in_cluster * opts.rows_in_block;
      opts.cluster_height = opts.blocks_in_cluster * opts.block_height;
      return prev_item_height != opts.item_height;
    },
    // get current cluster number
    getClusterNum: function (rows) {
      var opts = this.options;
      opts.scroll_top = this.scroll_elem.scrollTop;
      var cluster_divider = opts.cluster_height - opts.block_height;
      var current_cluster = Math.floor(opts.scroll_top / cluster_divider);
      var max_cluster = Math.floor((rows.length * opts.item_height) / cluster_divider);
      return Math.min(current_cluster, max_cluster);
    },
    // generate empty row if no data provided
    generateEmptyRow: function() {
      var opts = this.options;
      if( ! opts.tag || ! opts.show_no_data_row) return [];
      var empty_row = document.createElement(opts.tag),
        no_data_content = document.createTextNode(opts.no_data_text), td;
      empty_row.className = opts.no_data_class;
      if(opts.tag == 'tr') {
        td = document.createElement('td');
        // fixes #53
        td.colSpan = 100;
        td.appendChild(no_data_content);
      }
      empty_row.appendChild(td || no_data_content);
      return [empty_row.outerHTML];
    },
    // generate cluster for current scroll position
    generate: function (rows) {
      var opts = this.options,
        rows_len = rows.length;
      if (rows_len < opts.rows_in_block) {
        return {
          top_offset: 0,
          bottom_offset: 0,
          rows_above: 0,
          rows: rows_len ? rows : this.generateEmptyRow()
        }
      }
      var items_start = Math.max((opts.rows_in_cluster - opts.rows_in_block) * this.getClusterNum(rows), 0),
        items_end = items_start + opts.rows_in_cluster,
        top_offset = Math.max(items_start * opts.item_height, 0),
        bottom_offset = Math.max((rows_len - items_end) * opts.item_height, 0),
        this_cluster_rows = [],
        rows_above = items_start;
      if(top_offset < 1) {
        rows_above++;
      }
      for (var i = items_start; i < items_end; i++) {
        rows[i] && this_cluster_rows.push(rows[i]);
      }
      return {
        top_offset: top_offset,
        bottom_offset: bottom_offset,
        rows_above: rows_above,
        rows: this_cluster_rows
      }
    },
    renderExtraTag: function(class_name, height) {
      var tag = document.createElement(this.options.tag),
        clusterize_prefix = 'clusterize-';
      tag.className = [clusterize_prefix + 'extra-row', clusterize_prefix + class_name].join(' ');
      height && (tag.style.height = height + 'px');
      return tag.outerHTML;
    },
    // if necessary verify data changed and insert to DOM
    insertToDOM: function(rows, cache) {
      // explore row's height
      if( ! this.options.cluster_height) {
        this.exploreEnvironment(rows, cache);
      }
      var data = this.generate(rows),
        this_cluster_rows = data.rows.join(''),
        this_cluster_content_changed = this.checkChanges('data', this_cluster_rows, cache),
        top_offset_changed = this.checkChanges('top', data.top_offset, cache),
        only_bottom_offset_changed = this.checkChanges('bottom', data.bottom_offset, cache),
        callbacks = this.options.callbacks,
        layout = [];

      if(this_cluster_content_changed || top_offset_changed) {
        if(data.top_offset) {
          this.options.keep_parity && layout.push(this.renderExtraTag('keep-parity'));
          layout.push(this.renderExtraTag('top-space', data.top_offset));
        }
        layout.push(this_cluster_rows);
        data.bottom_offset && layout.push(this.renderExtraTag('bottom-space', data.bottom_offset));
        callbacks.clusterWillChange && callbacks.clusterWillChange();
        this.html(layout.join(''));
        this.options.content_tag == 'ol' && this.content_elem.setAttribute('start', data.rows_above);
        this.content_elem.style['counter-increment'] = 'clusterize-counter ' + (data.rows_above-1);
        callbacks.clusterChanged && callbacks.clusterChanged();
      } else if(only_bottom_offset_changed) {
        this.content_elem.lastChild.style.height = data.bottom_offset + 'px';
      }
    },
    // unfortunately ie <= 9 does not allow to use innerHTML for table elements, so make a workaround
    html: function(data) {
      var content_elem = this.content_elem;
      if(ie && ie <= 9 && this.options.tag == 'tr') {
        var div = document.createElement('div'), last;
        div.innerHTML = '<table><tbody>' + data + '</tbody></table>';
        while((last = content_elem.lastChild)) {
          content_elem.removeChild(last);
        }
        var rows_nodes = this.getChildNodes(div.firstChild.firstChild);
        while (rows_nodes.length) {
          content_elem.appendChild(rows_nodes.shift());
        }
      } else {
        content_elem.innerHTML = data;
      }
    },
    getChildNodes: function(tag) {
        var child_nodes = tag.children, nodes = [];
        for (var i = 0, ii = child_nodes.length; i < ii; i++) {
            nodes.push(child_nodes[i]);
        }
        return nodes;
    },
    checkChanges: function(type, value, cache) {
      var changed = value != cache[type];
      cache[type] = value;
      return changed;
    }
  }

  // support functions
  function on(evt, element, fnc) {
    return element.addEventListener ? element.addEventListener(evt, fnc, false) : element.attachEvent("on" + evt, fnc);
  }
  function off(evt, element, fnc) {
    return element.removeEventListener ? element.removeEventListener(evt, fnc, false) : element.detachEvent("on" + evt, fnc);
  }
  function isArray(arr) {
    return Object.prototype.toString.call(arr) === '[object Array]';
  }
  function getStyle(prop, elem) {
    return window.getComputedStyle ? window.getComputedStyle(elem)[prop] : elem.currentStyle[prop];
  }

  return Clusterize;
}));

================================================
FILE: externs.js
================================================
/**
 * @fileoverview Closure Compiler externs for Clusterize.js 0.16.0.
 * @see https://developers.google.com/closure/compiler/docs/api-tutorial3
 * @externs
 */

var Clusterize = {
    "scroll_elem": {},
    "content_elem": {},
    "tag": {},
    "rows_in_block": {},
    "blocks_in_cluster": {},
    "show_no_data_row": {},
    "no_data_text": {},
    "no_data_class": {},
    "keep_parity": {},
    "callbacks": {
        "clusterWillChange": function() {},
        "clusterChanged": function() {},
        "scrollingProgress": function() {}
    },
    "update": function() {},
    "append": function() {},
    "prepend": function() {},
    "refresh": function() {},
    "getRowsAmount": function() {},
    "getScrollProgress": function() {},
    "clear": function() {},
    "destroy": function() {}
};


================================================
FILE: package.json
================================================
{
  "name": "clusterize.js",
  "version": "1.0.0",
  "description": "Tiny vanilla JS plugin to display large data sets easily",
  "main": "clusterize.js",
  "style": "clusterize.css",
  "scripts": {
  },
  "repository": {
    "type": "git",
    "url": "git@github.com:NeXTs/Clusterize.js.git"
  },
  "keywords": [
    "large",
    "vanillajs",
    "table",
    "grid",
    "list",
    "scroll",
    "cluster"
  ],
  "author": "Denis Lukov",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/NeXTs/Clusterize.js/issues"
  },
  "homepage": "https://github.com/NeXTs/Clusterize.js"
}
Download .txt
gitextract_jzoo8kx6/

├── LICENSE
├── README.md
├── clusterize.css
├── clusterize.js
├── externs.js
└── package.json
Download .txt
SYMBOL INDEX (4 symbols across 1 files)

FILE: clusterize.js
  function on (line 321) | function on(evt, element, fnc) {
  function off (line 324) | function off(evt, element, fnc) {
  function isArray (line 327) | function isArray(arr) {
  function getStyle (line 330) | function getStyle(prop, elem) {
Condensed preview — 6 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (18K chars).
[
  {
    "path": "LICENSE",
    "chars": 1077,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2015 Denis Lukov\n\nPermission is hereby granted, free of charge, to any person obtai"
  },
  {
    "path": "README.md",
    "chars": 1107,
    "preview": "# Clusterize.js\n[![Clusterize.js on NPM](https://img.shields.io/npm/v/clusterize.js.svg)](https://www.npmjs.com/package/"
  },
  {
    "path": "clusterize.css",
    "chars": 991,
    "preview": "/* max-height - the only parameter in this file that needs to be edited.\n * Change it to suit your needs. The rest is re"
  },
  {
    "path": "clusterize.js",
    "chars": 12650,
    "preview": "/* Clusterize.js - v1.0.0 - 2023-01-22\n http://NeXTs.github.com/Clusterize.js/\n Copyright (c) 2015 Denis Lukov; Licensed"
  },
  {
    "path": "externs.js",
    "chars": 806,
    "preview": "/**\n * @fileoverview Closure Compiler externs for Clusterize.js 0.16.0.\n * @see https://developers.google.com/closure/co"
  },
  {
    "path": "package.json",
    "chars": 593,
    "preview": "{\n  \"name\": \"clusterize.js\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Tiny vanilla JS plugin to display large data sets e"
  }
]

About this extraction

This page contains the full source code of the NeXTs/Clusterize.js GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 6 files (16.8 KB), approximately 4.3k tokens, and a symbol index with 4 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!