<commit_before>const pg = require("pg");

module.exports = client => {
    var devconfig = JSON.parse(JSON.stringify(client.config.pgconfig));
    devconfig.database = "listendev";
    var dev = new pg.Client(devconfig);
    dev.connect((err) => {
        if (err) console.log(err);
        console.log("dev pg connected.");
        dev.query({
            "text": "SELECT * FROM public.users;"
        }).then(res => {
            for (row in res.rows) {
                client.pg.query({
                    "text": "SELECT * FROM public.users WHERE id = $1;",
                    "values": [res.rows[row].id]
                }).then((newres) => {
                    if (newres.rowCount == 0) {
                        client.pg.query({
                            "text": "INSERT INTO public.users (id, steamid, dotaid) VALUES ($1, $2, $3);",
                            "values": [discord_id, parseInt(steam_id), parseInt(dota_id)]
                        }).then(() => {
                            util.log(`  inserted dota id ${dota_id}`);
                        }).catch(err => {
                            util.log("  something went wrong inserting a user");
                            util.log(err);
                        });
                    } else {
                        client.pg.query({
                            "text": "UPDATE public.users SET id = $1, steamid = $2, dotaid = $3 WHERE id = $1;",
                            "values": [discord_id, parseInt(steam_id), parseInt(dota_id)]
                        }).then(() => {
                            util.log(`  updated dota id ${newres.rows[0].dotaid} -> ${dota_id}`);
                        }).catch(err => {
                            util.log("  something went wrong updating a user");
                            util.log(err);
                        });
                    }
                })
            }
        }).catch(err => {
            util.log("  something went wrong selecting a user");
            util.log(err);
        });
    })
};<commit_msg>(╯°□°）╯︵ ┻━┻<commit_after>const pg = require("pg");

module.exports = client => {
    var devconfig = JSON.parse(JSON.stringify(client.config.pgconfig));
    devconfig.database = "listendev";
    var dev = new pg.Client(devconfig);
    dev.connect((err) => {
        if (err) console.log(err);
        console.log("dev pg connected.");
        dev.query({
            "text": "SELECT * FROM public.users;"
        }).then(res => {
            for (row in res.rows) {
                client.pg.query({
                    "text": "SELECT * FROM public.users WHERE id = $1;",
                    "values": [res.rows[row].id]
                }).then((newres) => {
                    if (newres.rowCount == 0) {
                        client.pg.query({
                            "text": "INSERT INTO public.users (id, steamid, dotaid) VALUES ($1, $2, $3);",
                            "values": [res.rows[row].id, res.rows[row].steamid, res.rows[row].dotaid]
                        }).then(() => {
                            util.log(`  inserted dota id ${res.rows[row].id}`);
                        }).catch(err => {
                            util.log("  something went wrong inserting a user");
                            util.log(err);
                        });
                    } else {
                        client.pg.query({
                            "text": "UPDATE public.users SET id = $1, steamid = $2, dotaid = $3 WHERE id = $1;",
                            "values": [res.rows[row].id, res.rows[row].steamid, res.rows[row].dotaid]
                        }).then(() => {
                            util.log(`  updated dota id ${newres.rows[0].dotaid} -> ${res.rows[row].id}`);
                        }).catch(err => {
                            util.log("  something went wrong updating a user");
                            util.log(err);
                        });
                    }
                })
            }
        }).catch(err => {
            util.log("  something went wrong selecting a user");
            util.log(err);
        });
    })
};<|endoftext|>


<commit_before>export const isVirtual = authorize => authorize.is_virtual === '1';
<commit_msg>Compare to number not char<commit_after>export const isVirtual = authorize => authorize.is_virtual === 1;
<|endoftext|>


<commit_before>define(function(require, exports, module) {
    main.consumes = [
        "Plugin", "ui", "tabManager"
    ];
    main.provides = ["terminal.monitor.message_view"];
    return main;

    function main(options, imports, register) {
        var ui = imports.ui;
        var Plugin = imports.Plugin;
        var tabManager = imports.tabManager;

        /***** Initialization *****/

        var plugin = new Plugin("Ajax.org", main.consumes);
        var css = require("text!./message_view.css");

        tabManager.on("tabDestroy", function() {
            hide();
        });

        tabManager.on("tabBeforeReparent", function() {
            hide();
        });

        var containerNode, contentNode, isVisible = false;

        var loaded = false;
        function load(){
            if (loaded) return false;
            loaded = true;

            // Load CSS
            ui.insertCss(css, plugin);
            draw();
        }

        function draw(){
            // Create HTML elements
            var html = require("text!./message_view.html");
            containerNode = ui.insertHtml(null, html, plugin)[0];
            contentNode = containerNode.querySelector(".message");
            contentNode.addEventListener("click", handleClick);
        }

        function handleClick(e) {
            switch (e.target.getAttribute("data-type")) {
                case "preview":
                    handlePreview(e);
                default:
                    hide();
            }
        }

        function handlePreview(e) {
            e.preventDefault();
            tabManager.open({
                editorType : "preview",
                active     : true,
                document   : {
                    preview : {
                        path: e.target.innerText
                    }
                }
            }, function(err, tab) {});
        }

        function show(message, referenceNode) {
            if (!containerNode)
                return;

            var referenceBoundingRect = referenceNode.getBoundingClientRect();
            var offset = { top: 8, left: 8, right: 8 };
            var top = referenceBoundingRect.top + offset.top;
            var left = referenceBoundingRect.left + offset.left;
            var width = referenceBoundingRect.width - offset.right - offset.left;

            contentNode.innerHTML = message;
            containerNode.style.display = 'block';
            containerNode.style.top = top + 'px';
            containerNode.style.left = left + 'px';
            containerNode.style.width = width + 'px';

            setTimeout(function() {
                containerNode.style.opacity = 1;
            });

            document.addEventListener("mousedown", hide, true);
            document.addEventListener("keydown", hide, true);
            tabManager.once("focusSync", hide);

            isVisible = true;
        }

        function hide() {
            if (!containerNode || !isVisible)
                return;

            containerNode.style.display = 'none';
            containerNode.style.opacity = 0;
            contentNode.innerHTML = '';

            document.removeEventListener("mousedown", hide);
            document.removeEventListener("keydown", hide);

            isVisible = false;
        }

        plugin.on("load", function(){
            load();
        });

        plugin.freezePublicAPI({
            show: show,
            hide: hide
        });

        register(null, {
            "terminal.monitor.message_view": plugin
        });
    }
});
<commit_msg>Properly handle events<commit_after>define(function(require, exports, module) {
    main.consumes = [
        "Plugin", "ui", "tabManager"
    ];
    main.provides = ["terminal.monitor.message_view"];
    return main;

    function main(options, imports, register) {
        var ui = imports.ui;
        var Plugin = imports.Plugin;
        var tabManager = imports.tabManager;

        /***** Initialization *****/

        var plugin = new Plugin("Ajax.org", main.consumes);
        var css = require("text!./message_view.css");

        var containerNode, contentNode, isVisible = false;

        var loaded = false;
        function load(){
            if (loaded) return false;
            loaded = true;

            // Load CSS
            ui.insertCss(css, plugin);
            draw();
        }

        function draw(){
            // Create HTML elements
            var html = require("text!./message_view.html");
            containerNode = ui.insertHtml(null, html, plugin)[0];
            contentNode = containerNode.querySelector(".message");
            contentNode.addEventListener("click", handleClick);
        }

        function handleClick(e) {
            switch (e.target.getAttribute("data-type")) {
                case "preview":
                    handlePreview(e);
                default:
                    hide();
            }
        }

        function handlePreview(e) {
            e.preventDefault();
            tabManager.open({
                editorType : "preview",
                active     : true,
                document   : {
                    preview : {
                        path: e.target.innerText
                    }
                }
            }, function(err, tab) {});
        }

        function show(message, referenceNode) {
            if (!containerNode)
                return;

            var referenceBoundingRect = referenceNode.getBoundingClientRect();
            var offset = { top: 8, left: 8, right: 8 };
            var top = referenceBoundingRect.top + offset.top;
            var left = referenceBoundingRect.left + offset.left;
            var width = referenceBoundingRect.width - offset.right - offset.left;

            contentNode.innerHTML = message;
            containerNode.style.display = 'block';
            containerNode.style.top = top + 'px';
            containerNode.style.left = left + 'px';
            containerNode.style.width = width + 'px';

            setTimeout(function() {
                containerNode.style.opacity = 1;
            });

            document.addEventListener("click", handleClick);
            document.addEventListener("keydown", hide, true);
            tabManager.once("focusSync", hide);
            tabManager.once("tabBeforeReparent", hide);

            isVisible = true;
        }

        function hide() {
            if (!containerNode || !isVisible)
                return;

            containerNode.style.display = 'none';
            containerNode.style.opacity = 0;
            contentNode.innerHTML = '';

            document.removeEventListener("click", handleClick);
            document.removeEventListener("keydown", hide, true);
            tabManager.off("focusSync", hide);
            tabManager.off("tabBeforeReparent", hide);

            isVisible = false;
        }

        plugin.on("load", function(){
            load();
        });

        plugin.freezePublicAPI({
            show: show,
            hide: hide
        });

        register(null, {
            "terminal.monitor.message_view": plugin
        });
    }
});
<|endoftext|>


<commit_before>/*
 * Fluster2 0.1.1
 * Copyright (C) 2009 Fusonic GmbH
 *
 * This file is part of Fluster2.
 *
 * Fluster2 is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * Fluster2 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Creates a new Fluster to manage masses of markers in a Google Maps v3.
 *
 * @constructor
 * @param {google.maps.Map} the Google Map v3
 * @param {bool} run in debug mode or not
 */
function Fluster2(_map, _debug)
{
	// Private variables
	var map = _map;
	var projection = new Fluster2ProjectionOverlay(map);
	var me = this;
	var clusters = new Object();
	var markersLeft = new Object();

	// Properties
	this.debugEnabled = _debug;
	this.gridSize = 60;
	this.markers = new Array();
	this.currentZoomLevel = -1;
	this.styles = {
		0: {
			image: 'http://gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/1.0/images/m1.png',
			textColor: '#FFFFFF',
			width: 53,
			height: 52
		},
		10: {
			image: 'http://gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/1.0/images/m2.png',
			textColor: '#FFFFFF',
			width: 56,
			height: 55
		},
		20: {
			image: 'http://gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/1.0/images/m3.png',
			textColor: '#FFFFFF',
			width: 66,
			height: 65
		}
	};

	// Timeouts
	var zoomChangedTimeout = null;

	/**
	 * Create clusters for the current zoom level and assign markers.
	 */
	function createClusters()
	{
		var zoom = map.getZoom();

		if(clusters[zoom])
		{
			me.debug('Clusters for zoom level ' + zoom + ' already initialized.');
		}
		else
		{
			// Create clusters array
			var clustersThisZoomLevel = new Array();

			// Set cluster count
			var clusterCount = 0;

			// Get marker count
			var markerCount = me.markers.length;

			// Walk all markers
			for(var i = 0; i < markerCount; i++)
			{
				var marker = me.markers[i];
				var markerPosition = marker.getPosition();
				var done = false;

				// Find a cluster which contains the marker
				for(var j = clusterCount - 1; j >= 0; j--)
				{
					var cluster = clustersThisZoomLevel[j];
					if(cluster.contains(markerPosition))
					{
						cluster.addMarker(marker);
						done = true;
						break;
					}
				}

				if(!done)
				{
					// No cluster found, create a new one
					var cluster = new Fluster2Cluster(me, marker);
					clustersThisZoomLevel.push(cluster);

					// Increase cluster count
					clusterCount++;
				}
			}

			clusters[zoom] = clustersThisZoomLevel;

			me.debug('Initialized ' + clusters[zoom].length + ' clusters for zoom level ' + zoom + '.');
		}

		// Hide markers of previous zoom level
		if(clusters[me.currentZoomLevel])
		{
			for(var i = 0; i < clusters[me.currentZoomLevel].length; i++)
			{
				clusters[me.currentZoomLevel][i].hide();
			}
		}

		// Set current zoom level
		me.currentZoomLevel = zoom;

		// Show clusters
		showClustersInBounds();
	}

	/**
	 * Displays all clusters inside the current map bounds.
	 */
	function showClustersInBounds()
	{
		var mapBounds = map.getBounds();

		for(var i = 0; i < clusters[me.currentZoomLevel].length; i++)
		{
			var cluster = clusters[me.currentZoomLevel][i];
			if(mapBounds.contains(cluster.getPosition()))
			{
				cluster.show();
			}
		}
	}

	/**
	 * Callback which is executed 500ms after the map's zoom level has changed.
	 */
	this.zoomChanged = function()
	{
		window.clearInterval(zoomChangedTimeout);
		zoomChangedTimeout = window.setTimeout(createClusters, 500);
	};

	/**
	 * Returns the map assigned to this Fluster.
	 */
	this.getMap = function()
	{
		return map;
	};

	/**
	 * Returns the map projection.
	 */
	this.getProjection = function()
	{
		return projection.getP();
	};

	/**
	 * Prints debug messages to console if debugging is enabled.
	 */
	this.debug = function(message)
	{
		if(me.debugEnabled)
		{
			console.log('Fluster2: ' + message);
		}
	};

	/**
	 * Adds a marker to the Fluster.
	 */
	this.addMarker = function(_marker)
	{
		me.markers.push(_marker);
	};

	/**
	 * Returns the currently assigned styles.
	 */
	this.getStyles = function()
	{
		return me.styles;
	};

	/**
	 * Sets map event handlers and setup's the markers for the current
	 * map state.
	 */
	this.initialize = function()
	{
		// Add event listeners
		google.maps.event.addListener(map, 'zoom_changed', this.zoomChanged);
		google.maps.event.addListener(map, 'dragend', showClustersInBounds);

		// Setup markers for the current state
		window.setTimeout(createClusters, 1000);
	};
}<commit_msg>FIX: Use protocol agnostic URL so that both http and https function with error warnings or just fail completely<commit_after>/*
 * Fluster2 0.1.1
 * Copyright (C) 2009 Fusonic GmbH
 *
 * This file is part of Fluster2.
 *
 * Fluster2 is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * Fluster2 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Creates a new Fluster to manage masses of markers in a Google Maps v3.
 *
 * @constructor
 * @param {google.maps.Map} the Google Map v3
 * @param {bool} run in debug mode or not
 */
function Fluster2(_map, _debug)
{
	// Private variables
	var map = _map;
	var projection = new Fluster2ProjectionOverlay(map);
	var me = this;
	var clusters = new Object();
	var markersLeft = new Object();

	// Properties
	this.debugEnabled = _debug;
	this.gridSize = 60;
	this.markers = new Array();
	this.currentZoomLevel = -1;
	this.styles = {
		0: {
			image: '//gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/1.0/images/m1.png',
			textColor: '#FFFFFF',
			width: 53,
			height: 52
		},
		10: {
			image: '//gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/1.0/images/m2.png',
			textColor: '#FFFFFF',
			width: 56,
			height: 55
		},
		20: {
			image: '//gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/1.0/images/m3.png',
			textColor: '#FFFFFF',
			width: 66,
			height: 65
		}
	};

	// Timeouts
	var zoomChangedTimeout = null;

	/**
	 * Create clusters for the current zoom level and assign markers.
	 */
	function createClusters()
	{
		var zoom = map.getZoom();

		if(clusters[zoom])
		{
			me.debug('Clusters for zoom level ' + zoom + ' already initialized.');
		}
		else
		{
			// Create clusters array
			var clustersThisZoomLevel = new Array();

			// Set cluster count
			var clusterCount = 0;

			// Get marker count
			var markerCount = me.markers.length;

			// Walk all markers
			for(var i = 0; i < markerCount; i++)
			{
				var marker = me.markers[i];
				var markerPosition = marker.getPosition();
				var done = false;

				// Find a cluster which contains the marker
				for(var j = clusterCount - 1; j >= 0; j--)
				{
					var cluster = clustersThisZoomLevel[j];
					if(cluster.contains(markerPosition))
					{
						cluster.addMarker(marker);
						done = true;
						break;
					}
				}

				if(!done)
				{
					// No cluster found, create a new one
					var cluster = new Fluster2Cluster(me, marker);
					clustersThisZoomLevel.push(cluster);

					// Increase cluster count
					clusterCount++;
				}
			}

			clusters[zoom] = clustersThisZoomLevel;

			me.debug('Initialized ' + clusters[zoom].length + ' clusters for zoom level ' + zoom + '.');
		}

		// Hide markers of previous zoom level
		if(clusters[me.currentZoomLevel])
		{
			for(var i = 0; i < clusters[me.currentZoomLevel].length; i++)
			{
				clusters[me.currentZoomLevel][i].hide();
			}
		}

		// Set current zoom level
		me.currentZoomLevel = zoom;

		// Show clusters
		showClustersInBounds();
	}

	/**
	 * Displays all clusters inside the current map bounds.
	 */
	function showClustersInBounds()
	{
		var mapBounds = map.getBounds();

		for(var i = 0; i < clusters[me.currentZoomLevel].length; i++)
		{
			var cluster = clusters[me.currentZoomLevel][i];
			if(mapBounds.contains(cluster.getPosition()))
			{
				cluster.show();
			}
		}
	}

	/**
	 * Callback which is executed 500ms after the map's zoom level has changed.
	 */
	this.zoomChanged = function()
	{
		window.clearInterval(zoomChangedTimeout);
		zoomChangedTimeout = window.setTimeout(createClusters, 500);
	};

	/**
	 * Returns the map assigned to this Fluster.
	 */
	this.getMap = function()
	{
		return map;
	};

	/**
	 * Returns the map projection.
	 */
	this.getProjection = function()
	{
		return projection.getP();
	};

	/**
	 * Prints debug messages to console if debugging is enabled.
	 */
	this.debug = function(message)
	{
		if(me.debugEnabled)
		{
			console.log('Fluster2: ' + message);
		}
	};

	/**
	 * Adds a marker to the Fluster.
	 */
	this.addMarker = function(_marker)
	{
		me.markers.push(_marker);
	};

	/**
	 * Returns the currently assigned styles.
	 */
	this.getStyles = function()
	{
		return me.styles;
	};

	/**
	 * Sets map event handlers and setup's the markers for the current
	 * map state.
	 */
	this.initialize = function()
	{
		// Add event listeners
		google.maps.event.addListener(map, 'zoom_changed', this.zoomChanged);
		google.maps.event.addListener(map, 'dragend', showClustersInBounds);

		// Setup markers for the current state
		window.setTimeout(createClusters, 1000);
	};
}<|endoftext|>


<commit_before>/* eslint max-nested-callbacks: 0  */

// ヘッダーのキーの小文字化
// JSONのパース
// ショートハンド

import { __util } from '../sources/ffetch';

describe('__createFullUrl()', () => {
  describe('should generating a full url using base, param and query', () => {
    [
      {
        base: '/path/to/api/page/:page',
        param: { page: 1 },
        query: { order: ['published_at', 'id'], filter: 'open' },
        joined: '/path/to/api/page/1?order=published_at&order=id&filter=open',
      },
      {
        base: '/path/to/api/article/:articleId/comment/:commentId',
        param: { articleId: 23, commentId: 1045 },
        query: { for_admin: 'true' },
        joined: '/path/to/api/article/23/comment/1045?for_admin=true',
      },
      {
        base: '/path/to/api/article/:articleId/comment/:commentId',
        param: { articleId: 23, commentId: 1045 },
        query: {},
        joined: '/path/to/api/article/23/comment/1045',
      },
      {
        base: '/path/to/api',
        param: {},
        query: { order: ['published_at', 'id'], filter: 'open' },
        joined: '/path/to/api?order=published_at&order=id&filter=open',
      },
      {
        base: '/path/to/api',
        param: {},
        query: {},
        joined: '/path/to/api',
      },
      {
        base: '/path/to/api',
        /* eslint-disable no-undefined */
        param: undefined,
        query: undefined,
        /* eslint-enable no-undefined */
        joined: '/path/to/api',
      },
    ].forEach(({ base, param, query, joined }, i) => {
      it(`case ${i}`, () => {
        expect(__util.__createFullUrl(base, param, query)).to.be(joined);
      });
    });
  });
});
<commit_msg>Add a test<commit_after>/* eslint max-nested-callbacks: 0  */

// ヘッダーのキーの小文字化
// JSONのパース
// ショートハンド

import { __util, ffetch } from '../sources/ffetch';

describe('__createFullUrl()', () => {
  describe('should generating a full url using base, param and query', () => {
    [
      {
        base: '/path/to/api/page/:page',
        param: { page: 1 },
        query: { order: ['published_at', 'id'], filter: 'open' },
        joined: '/path/to/api/page/1?order=published_at&order=id&filter=open',
      },
      {
        base: '/path/to/api/article/:articleId/comment/:commentId',
        param: { articleId: 23, commentId: 1045 },
        query: { for_admin: 'true' },
        joined: '/path/to/api/article/23/comment/1045?for_admin=true',
      },
      {
        base: '/path/to/api/article/:articleId/comment/:commentId',
        param: { articleId: 23, commentId: 1045 },
        query: {},
        joined: '/path/to/api/article/23/comment/1045',
      },
      {
        base: '/path/to/api',
        param: {},
        query: { order: ['published_at', 'id'], filter: 'open' },
        joined: '/path/to/api?order=published_at&order=id&filter=open',
      },
      {
        base: '/path/to/api',
        param: {},
        query: {},
        joined: '/path/to/api',
      },
      {
        base: '/path/to/api',
        /* eslint-disable no-undefined */
        param: undefined,
        query: undefined,
        /* eslint-enable no-undefined */
        joined: '/path/to/api',
      },
    ].forEach(({ base, param, query, joined }, i) => {
      it(`case ${i}`, () => {
        expect(__util.__createFullUrl(base, param, query)).to.be(joined);
      });
    });
  });
});

describe('ffetch()', () => {
  it('__createFullUrl() is called when call ffetch()', () => {
    const cached = __util.__createFullUrl;
    const mock = (...args) => {
      expect(args[0]).to.be('/path/to/api/article/:articleId');
      expect(args[1]).to.eql({ articleId: 23 });
      expect(args[2]).to.eql({ for_admin: 'true' });
    };

    __util.__createFullUrl = mock;

    ffetch('/path/to/api/article/:articleId', {
      method: 'GET',
      param: { articleId: 23 },
      query: { for_admin: 'true' },
    });

    __util.__createFullUrl = cached;
  });
});
<|endoftext|>


<commit_before>function elemIsCodeBlock(elem) {
    return elem.tagName.toLowerCase() === 'code-block';
}

/**
 * @param {Editor} editor
 * @param {String} code
 * @param {String} language
 * @param {function(string, string)} callback (Receives (code: string,language: string)
 */
function showPopup(editor, code, language, callback) {
    window.components.first('code-editor').open(code, language, (newCode, newLang) => {
        callback(newCode, newLang)
        editor.focus()
    });
}

/**
 * @param {Editor} editor
 * @param {CodeBlockElement} codeBlock
 */
function showPopupForCodeBlock(editor, codeBlock) {
    showPopup(editor, codeBlock.getContent(), codeBlock.getLanguage(), (newCode, newLang) => {
        codeBlock.setContent(newCode, newLang);
    });
}

/**
 * Define our custom code-block HTML element that we use.
 * Needs to be delayed since it needs to be defined within the context of the
 * child editor window and document, hence its definition within a callback.
 * @param {Editor} editor
 */
function defineCodeBlockCustomElement(editor) {
    const doc = editor.getDoc();
    const win = doc.defaultView;

    class CodeBlockElement extends win.HTMLElement {
        constructor() {
            super();
            this.attachShadow({mode: 'open'});
            const linkElem = document.createElement('link');
            linkElem.setAttribute('rel', 'stylesheet');
            linkElem.setAttribute('href', window.baseUrl('/dist/styles.css'));

            const cmContainer = document.createElement('div');
            cmContainer.style.pointerEvents = 'none';
            cmContainer.contentEditable = 'false';
            cmContainer.classList.add('CodeMirrorContainer');

            this.shadowRoot.append(linkElem, cmContainer);
        }

        getLanguage() {
            const getLanguageFromClassList = (classes) => {
                const langClasses = classes.split(' ').filter(cssClass => cssClass.startsWith('language-'));
                return (langClasses[0] || '').replace('language-', '');
            };

            const code = this.querySelector('code');
            const pre = this.querySelector('pre');
            return getLanguageFromClassList(pre.className) || (code && getLanguageFromClassList(code.className)) || '';
        }

        setContent(content, language) {
            if (this.cm) {
                importVersioned('code').then(Code => {
                    Code.setContent(this.cm, content);
                    Code.setMode(this.cm, language, content);
                });
            }

            let pre = this.querySelector('pre');
            if (!pre) {
                pre = doc.createElement('pre');
                this.append(pre);
            }
            pre.innerHTML = '';

            const code = doc.createElement('code');
            pre.append(code);
            code.innerText = content;
            code.className = `language-${language}`;
        }

        getContent() {
            const code = this.querySelector('code') || this.querySelector('pre');
            const tempEl = document.createElement('pre');
            tempEl.innerHTML = code.innerHTML.replace(/\ufeff/g, '');

            const brs = tempEl.querySelectorAll('br');
            for (const br of brs) {
                br.replaceWith('\n');
            }

            return tempEl.textContent;
        }

        connectedCallback() {
            const connectedTime = Date.now();
            if (this.cm) {
                return;
            }

            this.cleanChildContent();
            const content = this.getContent();
            const lines = content.split('\n').length;
            const height = (lines * 19.2) + 18 + 24;
            this.style.height = `${height}px`;

            const container = this.shadowRoot.querySelector('.CodeMirrorContainer');
            const renderCodeMirror = (Code) => {
                this.cm = Code.wysiwygView(container, content, this.getLanguage());
                setTimeout(() => Code.updateLayout(this.cm), 10);
                setTimeout(() => this.style.height = null, 12);
            };

            window.importVersioned('code').then((Code) => {
                const timeout = (Date.now() - connectedTime < 20) ? 20 : 0;
                setTimeout(() => renderCodeMirror(Code), timeout);
            });
        }

        cleanChildContent() {
            const pre = this.querySelector('pre');
            if (!pre) return;

            for (const preChild of pre.childNodes) {
                if (preChild.nodeName === '#text' && preChild.textContent === '') {
                    preChild.remove();
                }
            }
        }
    }

    win.customElements.define('code-block', CodeBlockElement);
}

/**
 * @param {Editor} editor
 * @param {String} url
 */
function register(editor, url) {

    editor.ui.registry.addIcon('codeblock', '<svg width="24" height="24"><path d="M4 3h16c.6 0 1 .4 1 1v16c0 .6-.4 1-1 1H4a1 1 0 0 1-1-1V4c0-.6.4-1 1-1Zm1 2v14h14V5Z"/><path d="M11.103 15.423c.277.277.277.738 0 .922a.692.692 0 0 1-1.106 0l-4.057-3.78a.738.738 0 0 1 0-1.107l4.057-3.872c.276-.277.83-.277 1.106 0a.724.724 0 0 1 0 1.014L7.6 12.012ZM12.897 8.577c-.245-.312-.2-.675.08-.955.28-.281.727-.27 1.027.033l4.057 3.78a.738.738 0 0 1 0 1.107l-4.057 3.872c-.277.277-.83.277-1.107 0a.724.724 0 0 1 0-1.014l3.504-3.412z"/></svg>')

    editor.ui.registry.addButton('codeeditor', {
        tooltip: 'Insert code block',
        icon: 'codeblock',
        onAction() {
            editor.execCommand('codeeditor');
        }
    });

    editor.addCommand('codeeditor', () => {
        const selectedNode = editor.selection.getNode();
        const doc = selectedNode.ownerDocument;
        if (elemIsCodeBlock(selectedNode)) {
            showPopupForCodeBlock(editor, selectedNode);
        } else {
            const textContent = editor.selection.getContent({format: 'text'});
            showPopup(editor, textContent, '', (newCode, newLang) => {
                const pre = doc.createElement('pre');
                const code = doc.createElement('code');
                code.classList.add(`language-${newLang}`);
                code.innerText = newCode;
                pre.append(code);

                editor.insertContent(pre.outerHTML);
            });
        }
    });

    editor.on('dblclick', event => {
        let selectedNode = editor.selection.getNode();
        if (elemIsCodeBlock(selectedNode)) {
            showPopupForCodeBlock(editor, selectedNode);
        }
    });

    editor.on('PreInit', () => {
        editor.parser.addNodeFilter('pre', function(elms) {
            for (const el of elms) {
                const wrapper = tinymce.html.Node.create('code-block', {
                    contenteditable: 'false',
                });

                const spans = el.getAll('span');
                for (const span of spans) {
                    span.unwrap();
                }
                el.attr('style', null);
                el.wrap(wrapper);
            }
        });

        editor.parser.addNodeFilter('code-block', function(elms) {
            for (const el of elms) {
                el.attr('contenteditable', 'false');
            }
        });

        editor.serializer.addNodeFilter('code-block', function(elms) {
            for (const el of elms) {
                el.unwrap();
            }
        });
    });

    editor.on('PreInit', () => {
        defineCodeBlockCustomElement(editor);
    });
}

/**
 * @param {WysiwygConfigOptions} options
 * @return {register}
 */
export function getPlugin(options) {
    return register;
}<commit_msg>Fixed custom code theme not showing in WYSIWYG<commit_after>function elemIsCodeBlock(elem) {
    return elem.tagName.toLowerCase() === 'code-block';
}

/**
 * @param {Editor} editor
 * @param {String} code
 * @param {String} language
 * @param {function(string, string)} callback (Receives (code: string,language: string)
 */
function showPopup(editor, code, language, callback) {
    window.components.first('code-editor').open(code, language, (newCode, newLang) => {
        callback(newCode, newLang)
        editor.focus()
    });
}

/**
 * @param {Editor} editor
 * @param {CodeBlockElement} codeBlock
 */
function showPopupForCodeBlock(editor, codeBlock) {
    showPopup(editor, codeBlock.getContent(), codeBlock.getLanguage(), (newCode, newLang) => {
        codeBlock.setContent(newCode, newLang);
    });
}

/**
 * Define our custom code-block HTML element that we use.
 * Needs to be delayed since it needs to be defined within the context of the
 * child editor window and document, hence its definition within a callback.
 * @param {Editor} editor
 */
function defineCodeBlockCustomElement(editor) {
    const doc = editor.getDoc();
    const win = doc.defaultView;

    class CodeBlockElement extends win.HTMLElement {
        constructor() {
            super();
            this.attachShadow({mode: 'open'});

            const stylesToCopy = document.querySelectorAll('link[rel="stylesheet"]:not([media="print"])');
            const copiedStyles = Array.from(stylesToCopy).map(styleEl => styleEl.cloneNode(false));

            const cmContainer = document.createElement('div');
            cmContainer.style.pointerEvents = 'none';
            cmContainer.contentEditable = 'false';
            cmContainer.classList.add('CodeMirrorContainer');

            this.shadowRoot.append(...copiedStyles, cmContainer);
        }

        getLanguage() {
            const getLanguageFromClassList = (classes) => {
                const langClasses = classes.split(' ').filter(cssClass => cssClass.startsWith('language-'));
                return (langClasses[0] || '').replace('language-', '');
            };

            const code = this.querySelector('code');
            const pre = this.querySelector('pre');
            return getLanguageFromClassList(pre.className) || (code && getLanguageFromClassList(code.className)) || '';
        }

        setContent(content, language) {
            if (this.cm) {
                importVersioned('code').then(Code => {
                    Code.setContent(this.cm, content);
                    Code.setMode(this.cm, language, content);
                });
            }

            let pre = this.querySelector('pre');
            if (!pre) {
                pre = doc.createElement('pre');
                this.append(pre);
            }
            pre.innerHTML = '';

            const code = doc.createElement('code');
            pre.append(code);
            code.innerText = content;
            code.className = `language-${language}`;
        }

        getContent() {
            const code = this.querySelector('code') || this.querySelector('pre');
            const tempEl = document.createElement('pre');
            tempEl.innerHTML = code.innerHTML.replace(/\ufeff/g, '');

            const brs = tempEl.querySelectorAll('br');
            for (const br of brs) {
                br.replaceWith('\n');
            }

            return tempEl.textContent;
        }

        connectedCallback() {
            const connectedTime = Date.now();
            if (this.cm) {
                return;
            }

            this.cleanChildContent();
            const content = this.getContent();
            const lines = content.split('\n').length;
            const height = (lines * 19.2) + 18 + 24;
            this.style.height = `${height}px`;

            const container = this.shadowRoot.querySelector('.CodeMirrorContainer');
            const renderCodeMirror = (Code) => {
                this.cm = Code.wysiwygView(container, content, this.getLanguage());
                setTimeout(() => Code.updateLayout(this.cm), 10);
                setTimeout(() => this.style.height = null, 12);
            };

            window.importVersioned('code').then((Code) => {
                const timeout = (Date.now() - connectedTime < 20) ? 20 : 0;
                setTimeout(() => renderCodeMirror(Code), timeout);
            });
        }

        cleanChildContent() {
            const pre = this.querySelector('pre');
            if (!pre) return;

            for (const preChild of pre.childNodes) {
                if (preChild.nodeName === '#text' && preChild.textContent === '') {
                    preChild.remove();
                }
            }
        }
    }

    win.customElements.define('code-block', CodeBlockElement);
}

/**
 * @param {Editor} editor
 * @param {String} url
 */
function register(editor, url) {

    editor.ui.registry.addIcon('codeblock', '<svg width="24" height="24"><path d="M4 3h16c.6 0 1 .4 1 1v16c0 .6-.4 1-1 1H4a1 1 0 0 1-1-1V4c0-.6.4-1 1-1Zm1 2v14h14V5Z"/><path d="M11.103 15.423c.277.277.277.738 0 .922a.692.692 0 0 1-1.106 0l-4.057-3.78a.738.738 0 0 1 0-1.107l4.057-3.872c.276-.277.83-.277 1.106 0a.724.724 0 0 1 0 1.014L7.6 12.012ZM12.897 8.577c-.245-.312-.2-.675.08-.955.28-.281.727-.27 1.027.033l4.057 3.78a.738.738 0 0 1 0 1.107l-4.057 3.872c-.277.277-.83.277-1.107 0a.724.724 0 0 1 0-1.014l3.504-3.412z"/></svg>')

    editor.ui.registry.addButton('codeeditor', {
        tooltip: 'Insert code block',
        icon: 'codeblock',
        onAction() {
            editor.execCommand('codeeditor');
        }
    });

    editor.addCommand('codeeditor', () => {
        const selectedNode = editor.selection.getNode();
        const doc = selectedNode.ownerDocument;
        if (elemIsCodeBlock(selectedNode)) {
            showPopupForCodeBlock(editor, selectedNode);
        } else {
            const textContent = editor.selection.getContent({format: 'text'});
            showPopup(editor, textContent, '', (newCode, newLang) => {
                const pre = doc.createElement('pre');
                const code = doc.createElement('code');
                code.classList.add(`language-${newLang}`);
                code.innerText = newCode;
                pre.append(code);

                editor.insertContent(pre.outerHTML);
            });
        }
    });

    editor.on('dblclick', event => {
        let selectedNode = editor.selection.getNode();
        if (elemIsCodeBlock(selectedNode)) {
            showPopupForCodeBlock(editor, selectedNode);
        }
    });

    editor.on('PreInit', () => {
        editor.parser.addNodeFilter('pre', function(elms) {
            for (const el of elms) {
                const wrapper = tinymce.html.Node.create('code-block', {
                    contenteditable: 'false',
                });

                const spans = el.getAll('span');
                for (const span of spans) {
                    span.unwrap();
                }
                el.attr('style', null);
                el.wrap(wrapper);
            }
        });

        editor.parser.addNodeFilter('code-block', function(elms) {
            for (const el of elms) {
                el.attr('contenteditable', 'false');
            }
        });

        editor.serializer.addNodeFilter('code-block', function(elms) {
            for (const el of elms) {
                el.unwrap();
            }
        });
    });

    editor.on('PreInit', () => {
        defineCodeBlockCustomElement(editor);
    });
}

/**
 * @param {WysiwygConfigOptions} options
 * @return {register}
 */
export function getPlugin(options) {
    return register;
}<|endoftext|>


<commit_before>(function (global) {

	var cdn = 'https://unpkg.com/';
	var versionPlaceholder = '@{{VERSION}}/';

	var mcgLayerSupportPathPrefix = cdn + 'leaflet.markercluster.layersupport' + versionPlaceholder + 'dist/';

	var libs = [
		global.libLeafletVersions, // Assumes that "leaflet-versions.js" file has already been executed, so that libLeafletVersions is globally available.
	];

	// In case libLeafletMarkerClusterVersions is also globally available.
	if (global.libLeafletMarkerClusterVersions) {
		libs.push(global.libLeafletMarkerClusterVersions);
	}

	// In case extra libraries must be loaded as well.
	if (global.extraLibs) {
		libs = libs.concat(global.extraLibs);
	}

	// Plugin library.
	libs.push({
		name: 'leaflet.markercluster.layersupport',
		mandatory: true,
		versions: [
			// You can use https://www.srihash.org/ to generate the SRI hash.
			_makeMcgLayerSupportVersionAssets({
				name: '2.0.0',
				sriSrcJs: ''
			}),
			_makeMcgLayerSupportVersionAssets({
				name: '1.0.5',
				sriSrcJs: ''
			}),
			_makeMcgLayerSupportVersionAssets({
				name: '1.0.4',
				sriSrcJs: ''
			}),
			_makeMcgLayerSupportVersionAssets({
				name: '1.0.3',
				sriSrcJs: ''
			}),
			_makeMcgLayerSupportVersionAssets({
				name: '1.0.2',
				sriSrcJs: ''
			}),
			// Versions 1.0.1, 1.0.0 and 0.1.0 are not published on npm, hence not available on CDN.
			{
				name: 'local',
				defaultVersion: true,
				disabled: true, // Will be enabled if assets are found to be available at runtime (use `checkAssetsAvailability`).
				assets: [{
					type: 'script',
					path: '../../dist/leaflet.markercluster.layersupport-src.js'
				}]
			}
		]
	});

	// To be executed after manage-libs-versions is ready.
	// https://github.com/ghybs/manage-libs-versions
	// https://www.npmjs.com/package/manage-libs-versions
	global.bundle1 = new manageLibsVersions.Bundle({
		name: 'bundle1',
		libs: libs
	});

	function _makeMcgLayerSupportVersionAssets(options) {
		var versionName = options.name;

		return {
			name: versionName,
			defaultVersion: options.defaultVersion,
			disabled: options.disabled,
			assets: [
				manageLibsVersions.makeScript(mcgLayerSupportPathPrefix + 'leaflet.markercluster.layersupport-src.js', versionName, options.sriSrcJs)
			]
		};
	}

})(this);
<commit_msg>Feat(libs-setup): add versions 1.0.1, 1.0.0, 0.1.0 through jsDelivr CDN<commit_after>(function (global) {

	var cdn = 'https://unpkg.com/';
	var versionPlaceholder = '@{{VERSION}}/';
	var libName = 'leaflet.markercluster.layersupport';

	var mcgLayerSupportPathPrefix = cdn + libName + versionPlaceholder + 'dist/';

	var cdn2 = 'https://cdn.jsdelivr.net/';
	// https://www.jsdelivr.com/features
	// Template: https://cdn.jsdelivr.net/gh/user/repo@version/file
	// Note: versions not published on npm (1.0.1, 1.0.0, 0.1.0) were not built, therefore the src file is not in a `dist/` folder.
	var mcgLayerSupportPathPrefix2 = cdn2 + 'gh/ghybs/' + libName + versionPlaceholder;

	var libs = [
		global.libLeafletVersions, // Assumes that "leaflet-versions.js" file has already been executed, so that libLeafletVersions is globally available.
	];

	// In case libLeafletMarkerClusterVersions is also globally available.
	if (global.libLeafletMarkerClusterVersions) {
		libs.push(global.libLeafletMarkerClusterVersions);
	}

	// In case extra libraries must be loaded as well.
	if (global.extraLibs) {
		libs = libs.concat(global.extraLibs);
	}

	// Plugin library.
	libs.push({
		name: libName,
		mandatory: true,
		versions: [
			// You can use https://www.srihash.org/ to generate the SRI hash.
			_makeMcgLayerSupportVersionAssets({
				name: '2.0.0',
				sriSrcJs: ''
			}),
			_makeMcgLayerSupportVersionAssets({
				name: '1.0.5',
				sriSrcJs: ''
			}),
			_makeMcgLayerSupportVersionAssets({
				name: '1.0.4',
				sriSrcJs: ''
			}),
			_makeMcgLayerSupportVersionAssets({
				name: '1.0.3',
				sriSrcJs: ''
			}),
			_makeMcgLayerSupportVersionAssets({
				name: '1.0.2',
				sriSrcJs: ''
			}),
			// Versions 1.0.1, 1.0.0 and 0.1.0 are not published on npm, hence not available on unpkg CDN.
			// Use jsDelivr instead.
			_makeMcgLayerSupportVersionAssets({
				name: '1.0.1',
				cdnPrefix: mcgLayerSupportPathPrefix2,
				sriSrcJs: ''
			}),
			_makeMcgLayerSupportVersionAssets({
				name: '1.0.0',
				cdnPrefix: mcgLayerSupportPathPrefix2,
				sriSrcJs: ''
			}),
			_makeMcgLayerSupportVersionAssets({
				name: '0.1.0',
				cdnPrefix: mcgLayerSupportPathPrefix2,
				sriSrcJs: ''
			}),
			{
				name: 'local',
				defaultVersion: true,
				disabled: true, // Will be enabled if assets are found to be available at runtime (use `checkAssetsAvailability`).
				assets: [{
					type: 'script',
					path: '../../dist/leaflet.markercluster.layersupport-src.js'
				}]
			}
		]
	});

	// To be executed after manage-libs-versions is ready.
	// https://github.com/ghybs/manage-libs-versions
	// https://www.npmjs.com/package/manage-libs-versions
	global.bundle1 = new manageLibsVersions.Bundle({
		name: 'bundle1',
		libs: libs
	});

	function _makeMcgLayerSupportVersionAssets(options) {
		var versionName = options.name;
		var cdnPrefix = options.cdnPrefix || mcgLayerSupportPathPrefix;

		return {
			name: versionName,
			defaultVersion: options.defaultVersion,
			disabled: options.disabled,
			assets: [
				manageLibsVersions.makeScript(cdnPrefix + 'leaflet.markercluster.layersupport-src.js', versionName, options.sriSrcJs)
			]
		};
	}

})(this);
<|endoftext|>


<commit_before>define('app/i18n/ru',{
    "postbox-text": "Оставить комментарий (минимум 3 символа)",
    "postbox-author": "Имя (необязательно)",
    "postbox-email": "Email (необязательно)",
    "postbox-website": "Сайт (необязательно)",
    "postbox-submit": "Отправить",
    "num-comments": "1 комментарий\n{{ n }} комментария\n{{ n }} комментариев",
    "no-comments": "Оставить комментарий",
    "comment-reply": "Ответить",
    "comment-edit": "Правка",
    "comment-save": "Сохранить",
    "comment-delete": "Удалить",
    "comment-confirm": "Подтвердить удаление",
    "comment-close": "Закрыть",
    "comment-cancel": "Отменить",
    "comment-deleted": "Комментарий удалён",
    "comment-queued": "Комментарий будет проверен модератором",
    "comment-anonymous": "Анонимус",
    "comment-hidden": "Показать ещё 1 комментарий\nПоказать ещё {{ n }} комментария\nПоказать ещё {{ n }} комментариев",
    "date-now": "Только что",
    "date-minute": "{{ n }} минуту назад\n{{ n }} минуты назад\n{{ n }} минут назад",
    "date-hour": "{{ n }} час назад\n{{ n }} часа назад\n{{ n }} часов назад",
    "date-day": "{{ n }} день назад\n{{ n }} дня назад\n{{ n }} дней назад",
    "date-week": "{{ n }} неделю назад\n{{ n }} недели назад\n{{ n }} недель назад",
    "date-month": "{{ n }} месяц назад\n{{ n }} месяца назад\n{{ n }} месяцев назад",
    "date-year": "{{ n }} год назад\n{{ n }} года назад\n{{ n }} лет назад"
});
<commit_msg>Update ru.js<commit_after>define('app/i18n/ru',{
    "postbox-text": "Оставить комментарий (минимум 3 символа)",
    "postbox-author": "Имя (необязательно)",
    "postbox-email": "Email (необязательно)",
    "postbox-website": "Сайт (необязательно)",
    "postbox-submit": "Отправить",
    "num-comments": "1 комментарий\n{{ n }} комментария\n{{ n }} комментариев",
    "no-comments": "Оставить комментарий",
    "comment-reply": "Ответить",
    "comment-edit": "Правка",
    "comment-save": "Сохранить",
    "comment-delete": "Удалить",
    "comment-confirm": "Подтвердить удаление",
    "comment-close": "Закрыть",
    "comment-cancel": "Отменить",
    "comment-deleted": "Комментарий удалён",
    "comment-queued": "Комментарий будет проверен модератором",
    "comment-anonymous": "Аноним",
    "comment-hidden": "Показать ещё 1 комментарий\nПоказать ещё {{ n }} комментария\nПоказать ещё {{ n }} комментариев",
    "date-now": "Только что",
    "date-minute": "{{ n }} минуту назад\n{{ n }} минуты назад\n{{ n }} минут назад",
    "date-hour": "{{ n }} час назад\n{{ n }} часа назад\n{{ n }} часов назад",
    "date-day": "{{ n }} день назад\n{{ n }} дня назад\n{{ n }} дней назад",
    "date-week": "{{ n }} неделю назад\n{{ n }} недели назад\n{{ n }} недель назад",
    "date-month": "{{ n }} месяц назад\n{{ n }} месяца назад\n{{ n }} месяцев назад",
    "date-year": "{{ n }} год назад\n{{ n }} года назад\n{{ n }} лет назад"
});
<|endoftext|>


<commit_before>Z.wrap('github/ionicabizau/list/v0.0.1/client/pagination.js', function (require, module, exports) {

    module.exports = function (self) {
        var config = self._conf;
        var pagination = this;

        pagination._cache = {
            skip: 0,
            limit: config.options.options.limit,
            active: 1
        };

        pagination.ui =  {
            initialHTML: $(self.view.page.dom)[0].outerHTML,
            selector: self.view.page.dom,
            $: $(self.view.page.dom),
            classes: config.pagination.classes
        }

        // Handlers
        // TODO Move in ui.js
        pagination.ui.$.on("click", "." + pagination.ui.classes.item, function (ev) {
            pagination.select.call(self, ev, $(this));
            return false;
        });

        pagination.ui.$.on("click", "." + pagination.ui.classes.next, function (ev) {
            pagination.selectNext(self, ev, $(this));
            return false;
        });

        pagination.ui.$.on("click", "." + pagination.ui.classes.prev, function (ev) {
            pagination.selectPrev(self, ev, $(this));
            return false;
        });

        pagination.update = function (ev, data) {
            self.model.req({
                m: "count",
                q: self.filters._query
            }, function (err, count) {
                if (err) { return self._errorHandler(err); }

                // Create data array
                var pagesNumber = Math.ceil(count / pagination._cache.limit);
                var data = [];
                for (var i = 0; i < pagesNumber; ++i) {
                    data.push({
                        pageNr: i + 1
                    });
                }

                // Modify HTML before updating innerHTML
                self.view.page.on.html = function (html) {
                    var $allPages = $(pagination.ui.initialHTML.replace(
                        "[pages]",
                        html
                    ));

                    var max = config.pagination.numbers.max;
                    if (max < 3) {
                        switch (max) {
                            // « | »
                            case 0:
                                $allPages = $(pagination.ui.initialHTML.replace(
                                    "[pages]",
                                    ""
                                ));
                                break;
                            // « | <pgNr> | »
                            case 1:
                                // TODO
                                break;
                            case 2:
                                // TODO
                                break;
                        }
                    } else {
                        var active = pagination._cache.active;
                        var pag = config.pagination;
                        var $liElms = $allPages.find("li:not(." + pag.classes.next + ",." + pag.classes.prev + ")");
                        var $active = $liElms.eq(active + -1 ).addClass(pag.classes.active);

                        // TODO Clean up code
                        // Go to right
                        var $c = null;
                        var $next = $active.next();
                        var i = 0;
                        while (true) {
                            $c = $next;
                            var br = $c.hasClass(pag.classes.next) ||
                                     ($c.next().hasClass(pag.classes.next) &&
                                     pag.numbers.aLast) ||
                                     !$c.length;
                            if (br) { break; }
                            $next = $c.next();
                            if (++i <= pag.numbers.max) { continue; }
                            $c.remove();
                        }

                        // Go to left
                        var $c = null;
                        var $prev = $active.prev();
                        var i = 0;
                        while (true) {
                            $c = $prev;
                            var br = $c.hasClass(pag.classes.prev) ||
                                     ($c.prev().hasClass(pag.classes.prev) &&
                                     pag.numbers.aLast) ||
                                     !$c.length;
                            if (br) { break; }
                            $prev = $c.prev();
                            if (++i <= pag.numbers.max) { continue; }
                            $c.remove();
                        }

                        // Append dots
                        var $last = $liElms.last();
                        var $first = $liElms.first();
                        if (pag.numbers.aLast) {
                            var lastPageValue1 = parseInt($last.find("a").html())
                            var lastPageValue2 = parseInt($last.prev().find("a").html())
                            if (lastPageValue1 >= lastPageValue2 + 2) {
                                var $clone = $last.clone();
                                $clone.addClass(pag.classes.disabled);
                                $clone.find(":contains(" + pagesNumber + ")").text("…");
                                $last.before($clone);
                            }
                        }

                        if (pag.numbers.aFirst) {
                            var firstPageValue1 = parseInt($first.find("a").html())
                            var firstPageValue2 = parseInt($first.next().find("a").html())
                            if (firstPageValue1 <= firstPageValue2 - 2) {
                                var $clone = $first.clone();
                                $clone.addClass(pag.classes.disabled);
                                $clone.find(":contains(1)").text("…");
                                $first.after($clone);
                            }
                        }
                    }

                    $allPages.children().each(function () {
                        var $c = $(this);
                        var nr = parseInt($c.text());
                        if (isNaN(nr)) { return; }
                        $c.attr("data-page", nr);
                    });

                    return $allPages[0].outerHTML;
                };

                // Render view
                self.view.page.render(data);
            });
        };

        pagination.select = function (ev, data) {
            var $page = null;
            var pageNr = -1;
            if (data instanceof $) {
                $page = data;
            } else if (typeof data === "number") {
                $page = $("[data-page='" + data + "']", pagination.ui.$);
            }

            pageNr = parseInt($page.attr("data-page"));

            // pagination.ui.$.find("." + pagination.ui.classes.item).removeClass(pagination.ui.classes.active);
            // $page.addClass(pagination.ui.classes.active);

            // TODO Cache somehow to prevent count requests to Mongo
            pagination.update();

            // Update cache and filter options
            pagination._cache.active = pageNr;
            pagination._cache.skip = (pageNr - 1) * config.pagination.size;
            self.filters.set(null, {
                options: { skip: pagination._cache.skip }
            });

            // Emit page changed event
            self.emit("pageChanged", ev, {
                pageNr: pageNr,
                $: $page
            });
        };

        pagination.selectNext = function (ev, data) {
            pagination.select(ev, pagination._cache.active + 1);
        };

        pagination.selectPrev = function (ev, data) {
            pagination.select(ev, pagination._cache.active - 1);
        };

        this.disableItem = function (ev, data) {

        };
    };

    return module;
});
<commit_msg>Removed disable item function<commit_after>Z.wrap('github/ionicabizau/list/v0.0.1/client/pagination.js', function (require, module, exports) {

    module.exports = function (self) {
        var config = self._conf;
        var pagination = this;

        pagination._cache = {
            skip: 0,
            limit: config.options.options.limit,
            active: 1
        };

        pagination.ui =  {
            initialHTML: $(self.view.page.dom)[0].outerHTML,
            selector: self.view.page.dom,
            $: $(self.view.page.dom),
            classes: config.pagination.classes
        }

        // Handlers
        // TODO Move in ui.js
        pagination.ui.$.on("click", "." + pagination.ui.classes.item, function (ev) {
            pagination.select.call(self, ev, $(this));
            return false;
        });

        pagination.ui.$.on("click", "." + pagination.ui.classes.next, function (ev) {
            pagination.selectNext(self, ev, $(this));
            return false;
        });

        pagination.ui.$.on("click", "." + pagination.ui.classes.prev, function (ev) {
            pagination.selectPrev(self, ev, $(this));
            return false;
        });

        pagination.update = function (ev, data) {
            self.model.req({
                m: "count",
                q: self.filters._query
            }, function (err, count) {
                if (err) { return self._errorHandler(err); }

                // Create data array
                var pagesNumber = Math.ceil(count / pagination._cache.limit);
                var data = [];
                for (var i = 0; i < pagesNumber; ++i) {
                    data.push({
                        pageNr: i + 1
                    });
                }

                // Modify HTML before updating innerHTML
                self.view.page.on.html = function (html) {
                    var $allPages = $(pagination.ui.initialHTML.replace(
                        "[pages]",
                        html
                    ));

                    var max = config.pagination.numbers.max;
                    if (max < 3) {
                        switch (max) {
                            // « | »
                            case 0:
                                $allPages = $(pagination.ui.initialHTML.replace(
                                    "[pages]",
                                    ""
                                ));
                                break;
                            // « | <pgNr> | »
                            case 1:
                                // TODO
                                break;
                            case 2:
                                // TODO
                                break;
                        }
                    } else {
                        var active = pagination._cache.active;
                        var pag = config.pagination;
                        var $liElms = $allPages.find("li:not(." + pag.classes.next + ",." + pag.classes.prev + ")");
                        var $active = $liElms.eq(active + -1 ).addClass(pag.classes.active);

                        // TODO Clean up code
                        // Go to right
                        var $c = null;
                        var $next = $active.next();
                        var i = 0;
                        while (true) {
                            $c = $next;
                            var br = $c.hasClass(pag.classes.next) ||
                                     ($c.next().hasClass(pag.classes.next) &&
                                     pag.numbers.aLast) ||
                                     !$c.length;
                            if (br) { break; }
                            $next = $c.next();
                            if (++i <= pag.numbers.max) { continue; }
                            $c.remove();
                        }

                        // Go to left
                        var $c = null;
                        var $prev = $active.prev();
                        var i = 0;
                        while (true) {
                            $c = $prev;
                            var br = $c.hasClass(pag.classes.prev) ||
                                     ($c.prev().hasClass(pag.classes.prev) &&
                                     pag.numbers.aLast) ||
                                     !$c.length;
                            if (br) { break; }
                            $prev = $c.prev();
                            if (++i <= pag.numbers.max) { continue; }
                            $c.remove();
                        }

                        // Append dots
                        var $last = $liElms.last();
                        var $first = $liElms.first();
                        if (pag.numbers.aLast) {
                            var lastPageValue1 = parseInt($last.find("a").html())
                            var lastPageValue2 = parseInt($last.prev().find("a").html())
                            if (lastPageValue1 >= lastPageValue2 + 2) {
                                var $clone = $last.clone();
                                $clone.addClass(pag.classes.disabled);
                                $clone.find(":contains(" + pagesNumber + ")").text("…");
                                $last.before($clone);
                            }
                        }

                        if (pag.numbers.aFirst) {
                            var firstPageValue1 = parseInt($first.find("a").html())
                            var firstPageValue2 = parseInt($first.next().find("a").html())
                            if (firstPageValue1 <= firstPageValue2 - 2) {
                                var $clone = $first.clone();
                                $clone.addClass(pag.classes.disabled);
                                $clone.find(":contains(1)").text("…");
                                $first.after($clone);
                            }
                        }
                    }

                    $allPages.children().each(function () {
                        var $c = $(this);
                        var nr = parseInt($c.text());
                        if (isNaN(nr)) { return; }
                        $c.attr("data-page", nr);
                    });

                    return $allPages[0].outerHTML;
                };

                // Render view
                self.view.page.render(data);
            });
        };

        pagination.select = function (ev, data) {
            var $page = null;
            var pageNr = -1;
            if (data instanceof $) {
                $page = data;
            } else if (typeof data === "number") {
                $page = $("[data-page='" + data + "']", pagination.ui.$);
            }

            pageNr = parseInt($page.attr("data-page"));

            // pagination.ui.$.find("." + pagination.ui.classes.item).removeClass(pagination.ui.classes.active);
            // $page.addClass(pagination.ui.classes.active);

            // TODO Cache somehow to prevent count requests to Mongo
            pagination.update();

            // Update cache and filter options
            pagination._cache.active = pageNr;
            pagination._cache.skip = (pageNr - 1) * config.pagination.size;
            self.filters.set(null, {
                options: { skip: pagination._cache.skip }
            });

            // Emit page changed event
            self.emit("pageChanged", ev, {
                pageNr: pageNr,
                $: $page
            });
        };

        pagination.selectNext = function (ev, data) {
            pagination.select(ev, pagination._cache.active + 1);
        };

        pagination.selectPrev = function (ev, data) {
            pagination.select(ev, pagination._cache.active - 1);
        };
    };

    return module;
});
<|endoftext|>


<commit_before>let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader);
loader.loadSubScript("chrome://sendtocategory/content/category_tools.js");

//###################################################
// overriding a core thunderbird function
//###################################################

// The function 'GenerateAddressFromCard' is defined at: https://dxr.mozilla.org/comm-central/source/mail/components/addrbook/content/abCommon.js#596
// Overiding this function to fix bugs:
// 1: Also check for secondary email, if primary not present.
// 2: Do not return anything (not even the name), if no email present, so that addSelectedAddresses (https://dxr.mozilla.org/comm-central/source/mail/components/addrbook/content/abContactsPanel.js#56) does not add contacts without email.
function GenerateAddressFromCard(card)
{
  if (!card)
    return "";

  var email;

  if (card.isMailList)
  {
    var directory = GetDirectoryFromURI(card.mailListURI);
    email = directory.description || card.displayName;
  } else {
    email = card.primaryEmail
    if (email == "") try {email = card.getPropertyAsAString("SecondEmail");} catch (ex) {}
  }

  if (email) {
    return MailServices.headerParser.makeMimeAddress(card.displayName, email);
  } else {
    return ""
  }
}

//###################################################
//adding additional functions to the local jbCatMan Object
//###################################################

/*
  We might want some event listeners as in addressbook_overlay.js to
  catch category modifications (via EditDialog) and update Categories
  and members.
*/

jbCatMan.contactPanelCategoryMenuInit = function () {
  jbCatMan.dump("Begin with contactPanelCategoryMenuInit()",1);

  //contactPanelCategoryMenuInit is called onSelect, which is triggered once without a book selected
  let currentlySelectedAddressbook = document.getElementById('addressbookList').value;
  if (currentlySelectedAddressbook != "") {

    jbCatMan.scanCategories(GetSelectedDirectory());

    let menulist = document.getElementById("CatManCategoryFilterList");
    menulist.selectedItem = null;
    let itemCount = menulist.itemCount;
    for(let i = (itemCount-1); i >= 0; i-- ) menulist.removeItemAt(i);

    let menupopup = document.getElementById("CatManCategoryFilterListPopup");
    let newItem = document.createElement("menuitem");
    newItem.setAttribute("label", jbCatMan.locale.placeholderText);
    newItem.setAttribute("value", "");
    menupopup.appendChild( newItem );

    for (let i = 0; i < jbCatMan.data.categoryList.length; i++) {
      let newItem = document.createElement("menuitem");
      newItem.setAttribute("label", "- " + jbCatMan.data.categoryList[i]);
      newItem.setAttribute("value", jbCatMan.data.categoryList[i]);
      menupopup.appendChild( newItem );
    }
    menulist.selectedItem = menulist.getItemAtIndex(0);

    if (jbCatMan.data.categoryList.length == 0) {
      menulist.disabled = true;
    } else {
      menulist.disabled = false;
    }
  }
  jbCatMan.dump("Done with contactPanelCategoryMenuInit()",-1);
}

jbCatMan.contactPanelCategoryMenuChanged = function () {
  jbCatMan.dump("Begin with contactPanelCategoryMenuChanged()",1);
  if (document.getElementById("CatManCategoryFilterList").value != "") {
    //get selected category
    jbCatMan.data.selectedCategory = document.getElementById("CatManCategoryFilterList").value;

    //revert selection to placeholdertext (topmost entry)
    let menulist = document.getElementById("CatManCategoryFilterList");
    menulist.selectedItem = menulist.getItemAtIndex(0);

    //apply filter
    jbCatMan.doCategorySearch(document.getElementById('addressbookList').value);

    //select all members of the selected category to save mouse clicks (if only
    //one member is to be selected, the user still has to click once as before)
    let abResultsTree = document.getElementById("abResultsTree");
    abResultsTree.treeBoxObject.view.selection.selectAll();
  }
  jbCatMan.dump("Done with contactPanelCategoryMenuChanged()",-1);
}
<commit_msg>doCategorySearch does not need parameter<commit_after>let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader);
loader.loadSubScript("chrome://sendtocategory/content/category_tools.js");

//###################################################
// overriding a core thunderbird function
//###################################################

// The function 'GenerateAddressFromCard' is defined at: https://dxr.mozilla.org/comm-central/source/mail/components/addrbook/content/abCommon.js#596
// Overiding this function to fix bugs:
// 1: Also check for secondary email, if primary not present.
// 2: Do not return anything (not even the name), if no email present, so that addSelectedAddresses (https://dxr.mozilla.org/comm-central/source/mail/components/addrbook/content/abContactsPanel.js#56) does not add contacts without email.
function GenerateAddressFromCard(card)
{
  if (!card)
    return "";

  var email;

  if (card.isMailList)
  {
    var directory = GetDirectoryFromURI(card.mailListURI);
    email = directory.description || card.displayName;
  } else {
    email = card.primaryEmail
    if (email == "") try {email = card.getPropertyAsAString("SecondEmail");} catch (ex) {}
  }

  if (email) {
    return MailServices.headerParser.makeMimeAddress(card.displayName, email);
  } else {
    return ""
  }
}

//###################################################
//adding additional functions to the local jbCatMan Object
//###################################################

/*
  We might want some event listeners as in addressbook_overlay.js to
  catch category modifications (via EditDialog) and update Categories
  and members.
*/

jbCatMan.contactPanelCategoryMenuInit = function () {
  jbCatMan.dump("Begin with contactPanelCategoryMenuInit()",1);

  //contactPanelCategoryMenuInit is called onSelect, which is triggered once without a book selected
  let currentlySelectedAddressbook = document.getElementById('addressbookList').value;
  if (currentlySelectedAddressbook != "") {

    jbCatMan.scanCategories(GetSelectedDirectory());

    let menulist = document.getElementById("CatManCategoryFilterList");
    menulist.selectedItem = null;
    let itemCount = menulist.itemCount;
    for(let i = (itemCount-1); i >= 0; i-- ) menulist.removeItemAt(i);

    let menupopup = document.getElementById("CatManCategoryFilterListPopup");
    let newItem = document.createElement("menuitem");
    newItem.setAttribute("label", jbCatMan.locale.placeholderText);
    newItem.setAttribute("value", "");
    menupopup.appendChild( newItem );

    for (let i = 0; i < jbCatMan.data.categoryList.length; i++) {
      let newItem = document.createElement("menuitem");
      newItem.setAttribute("label", "- " + jbCatMan.data.categoryList[i]);
      newItem.setAttribute("value", jbCatMan.data.categoryList[i]);
      menupopup.appendChild( newItem );
    }
    menulist.selectedItem = menulist.getItemAtIndex(0);

    if (jbCatMan.data.categoryList.length == 0) {
      menulist.disabled = true;
    } else {
      menulist.disabled = false;
    }
  }
  jbCatMan.dump("Done with contactPanelCategoryMenuInit()",-1);
}

jbCatMan.contactPanelCategoryMenuChanged = function () {
  jbCatMan.dump("Begin with contactPanelCategoryMenuChanged()",1);
  if (document.getElementById("CatManCategoryFilterList").value != "") {
    //get selected category
    jbCatMan.data.selectedCategory = document.getElementById("CatManCategoryFilterList").value;

    //revert selection to placeholdertext (topmost entry)
    let menulist = document.getElementById("CatManCategoryFilterList");
    menulist.selectedItem = menulist.getItemAtIndex(0);

    //apply filter
    jbCatMan.doCategorySearch();

    //select all members of the selected category to save mouse clicks (if only
    //one member is to be selected, the user still has to click once as before)
    let abResultsTree = document.getElementById("abResultsTree");
    abResultsTree.treeBoxObject.view.selection.selectAll();
  }
  jbCatMan.dump("Done with contactPanelCategoryMenuChanged()",-1);
}
<|endoftext|>


<commit_before>import matchesType from '../utils/matchesType';
import invariant from 'invariant';
import isArray from 'lodash/isArray';
import isObject from 'lodash/isObject';

export const BEGIN_DRAG = 'dnd-core/BEGIN_DRAG';
export const PUBLISH_DRAG_SOURCE = 'dnd-core/PUBLISH_DRAG_SOURCE';
export const HOVER = 'dnd-core/HOVER';
export const DROP = 'dnd-core/DROP';
export const END_DRAG = 'dnd-core/END_DRAG';

export function beginDrag(sourceIds, {
  publishSource = true,
  clientOffset = null,
  getSourceClientOffset
}: options = {}) {
  invariant(isArray(sourceIds), 'Expected sourceIds to be an array.');

  const monitor = this.getMonitor();
  const registry = this.getRegistry();
  invariant(
    !monitor.isDragging(),
    'Cannot call beginDrag while dragging.'
  );

  for (let i = 0; i < sourceIds.length; i++) {
    invariant(
      registry.getSource(sourceIds[i]),
      'Expected sourceIds to be registered.'
    );
  }

  let sourceId = null;
  for (let i = sourceIds.length - 1; i >= 0; i--) {
    if (monitor.canDragSource(sourceIds[i])) {
      sourceId = sourceIds[i];
      break;
    }
  }
  if (sourceId === null) {
    return;
  }

  let sourceClientOffset = null;
  if (clientOffset) {
    invariant(
      typeof getSourceClientOffset === 'function',
      'When clientOffset is provided, getSourceClientOffset must be a function.'
    );
    sourceClientOffset = getSourceClientOffset(sourceId);
  }

  const source = registry.getSource(sourceId);
  const item = source.beginDrag(monitor, sourceId);
  invariant(isObject(item), 'Item must be an object.');

  registry.pinSource(sourceId);

  const itemType = registry.getSourceType(sourceId);
  return {
    type: BEGIN_DRAG,
    itemType,
    item,
    sourceId,
    clientOffset,
    sourceClientOffset,
    isSourcePublic: publishSource
  };
}

export function publishDragSource(manager) {
  const monitor = this.getMonitor();
  if (!monitor.isDragging()) {
    return;
  }

  return {
    type: PUBLISH_DRAG_SOURCE
  };
}

export function hover(targetIds, { clientOffset = null } = {}) {
  invariant(isArray(targetIds), 'Expected targetIds to be an array.');
  targetIds = targetIds.slice(0);

  const monitor = this.getMonitor();
  const registry = this.getRegistry();
  invariant(
    monitor.isDragging(),
    'Cannot call hover while not dragging.'
  );
  invariant(
    !monitor.didDrop(),
    'Cannot call hover after drop.'
  );

  const draggedItemType = monitor.getItemType();
  for (let i = 0; i < targetIds.length; i++) {
    const targetId = targetIds[i];
    invariant(
      targetIds.lastIndexOf(targetId) === i,
      'Expected targetIds to be unique in the passed array.'
    );

    const target = registry.getTarget(targetId);
    invariant(
      target,
      'Expected targetIds to be registered.'
    );

    const targetType = registry.getTargetType(targetId);
    if (matchesType(targetType, draggedItemType)) {
      target.hover(monitor, targetId);
    }
  }

  return {
    type: HOVER,
    targetIds,
    clientOffset
  };
}

export function drop() {
  const monitor = this.getMonitor();
  const registry = this.getRegistry();
  invariant(
    monitor.isDragging(),
    'Cannot call drop while not dragging.'
  );
  invariant(
    !monitor.didDrop(),
    'Cannot call drop twice during one drag operation.'
  );

  const targetIds = monitor
    .getTargetIds()
    .filter(monitor.canDropOnTarget, monitor);

  targetIds.reverse();
  targetIds.forEach((targetId, index) => {
    const target = registry.getTarget(targetId);

    let dropResult = target.drop(monitor, targetId);
    invariant(
      typeof dropResult === 'undefined' || isObject(dropResult),
      'Drop result must either be an object or undefined.'
    );
    if (typeof dropResult === 'undefined') {
      dropResult = index === 0 ?
        {} :
        monitor.getDropResult();
    }

    this.store.dispatch({
      type: DROP,
      dropResult
    });
  });
}

export function endDrag() {
  const monitor = this.getMonitor();
  const registry = this.getRegistry();
  invariant(
    monitor.isDragging(),
    'Cannot call endDrag while not dragging.'
  );

  const sourceId = monitor.getSourceId();
  const source = registry.getSource(sourceId, true);
  source.endDrag(monitor, sourceId);

  registry.unpinSource();

  return {
    type: END_DRAG
  };
}
<commit_msg>Delete non-matching types from targetIds.<commit_after>import matchesType from '../utils/matchesType';
import invariant from 'invariant';
import isArray from 'lodash/isArray';
import isObject from 'lodash/isObject';

export const BEGIN_DRAG = 'dnd-core/BEGIN_DRAG';
export const PUBLISH_DRAG_SOURCE = 'dnd-core/PUBLISH_DRAG_SOURCE';
export const HOVER = 'dnd-core/HOVER';
export const DROP = 'dnd-core/DROP';
export const END_DRAG = 'dnd-core/END_DRAG';

export function beginDrag(sourceIds, {
  publishSource = true,
  clientOffset = null,
  getSourceClientOffset
}: options = {}) {
  invariant(isArray(sourceIds), 'Expected sourceIds to be an array.');

  const monitor = this.getMonitor();
  const registry = this.getRegistry();
  invariant(
    !monitor.isDragging(),
    'Cannot call beginDrag while dragging.'
  );

  for (let i = 0; i < sourceIds.length; i++) {
    invariant(
      registry.getSource(sourceIds[i]),
      'Expected sourceIds to be registered.'
    );
  }

  let sourceId = null;
  for (let i = sourceIds.length - 1; i >= 0; i--) {
    if (monitor.canDragSource(sourceIds[i])) {
      sourceId = sourceIds[i];
      break;
    }
  }
  if (sourceId === null) {
    return;
  }

  let sourceClientOffset = null;
  if (clientOffset) {
    invariant(
      typeof getSourceClientOffset === 'function',
      'When clientOffset is provided, getSourceClientOffset must be a function.'
    );
    sourceClientOffset = getSourceClientOffset(sourceId);
  }

  const source = registry.getSource(sourceId);
  const item = source.beginDrag(monitor, sourceId);
  invariant(isObject(item), 'Item must be an object.');

  registry.pinSource(sourceId);

  const itemType = registry.getSourceType(sourceId);
  return {
    type: BEGIN_DRAG,
    itemType,
    item,
    sourceId,
    clientOffset,
    sourceClientOffset,
    isSourcePublic: publishSource
  };
}

export function publishDragSource(manager) {
  const monitor = this.getMonitor();
  if (!monitor.isDragging()) {
    return;
  }

  return {
    type: PUBLISH_DRAG_SOURCE
  };
}

export function hover(targetIds, { clientOffset = null } = {}) {
  invariant(isArray(targetIds), 'Expected targetIds to be an array.');
  targetIds = targetIds.slice(0);

  const monitor = this.getMonitor();
  const registry = this.getRegistry();
  invariant(
    monitor.isDragging(),
    'Cannot call hover while not dragging.'
  );
  invariant(
    !monitor.didDrop(),
    'Cannot call hover after drop.'
  );

  const draggedItemType = monitor.getItemType();

  // Remove those targetIds that don't match the targetType.  This
  // fixes shallow isOver which would only be non-shallow because of
  // non-matching targets.
  for (let i = targetIds.length - 1; i >= 0; i--) {
    const targetId = targetIds[i];
    const targetType = registry.getTargetType(targetId);
    if (!matchesType(targetType, draggedItemType)) {
      targetIds.splice(i, 1);
    }
  }

  for (let i = 0; i < targetIds.length; i++) {
    const targetId = targetIds[i];
    invariant(
      targetIds.lastIndexOf(targetId) === i,
      'Expected targetIds to be unique in the passed array.'
    );

    const target = registry.getTarget(targetId);
    invariant(
      target,
      'Expected targetIds to be registered.'
    );

    target.hover(monitor, targetId);
  }

  return {
    type: HOVER,
    targetIds,
    clientOffset
  };
}

export function drop() {
  const monitor = this.getMonitor();
  const registry = this.getRegistry();
  invariant(
    monitor.isDragging(),
    'Cannot call drop while not dragging.'
  );
  invariant(
    !monitor.didDrop(),
    'Cannot call drop twice during one drag operation.'
  );

  const targetIds = monitor
    .getTargetIds()
    .filter(monitor.canDropOnTarget, monitor);

  targetIds.reverse();
  targetIds.forEach((targetId, index) => {
    const target = registry.getTarget(targetId);

    let dropResult = target.drop(monitor, targetId);
    invariant(
      typeof dropResult === 'undefined' || isObject(dropResult),
      'Drop result must either be an object or undefined.'
    );
    if (typeof dropResult === 'undefined') {
      dropResult = index === 0 ?
        {} :
        monitor.getDropResult();
    }

    this.store.dispatch({
      type: DROP,
      dropResult
    });
  });
}

export function endDrag() {
  const monitor = this.getMonitor();
  const registry = this.getRegistry();
  invariant(
    monitor.isDragging(),
    'Cannot call endDrag while not dragging.'
  );

  const sourceId = monitor.getSourceId();
  const source = registry.getSource(sourceId, true);
  source.endDrag(monitor, sourceId);

  registry.unpinSource();

  return {
    type: END_DRAG
  };
}
<|endoftext|>


<commit_before>// import queryTreoDatabase from 'path/to/queryTreoDatabase'
// let db = treo('databaseName', schema)
//   .use(queryTreoDatabase)

function plugin(db, treo) {
	let {Store, Index} = treo

	Store.prototype.query = queryStore
	Index.prototype.query = queryIndex
}

export default plugin

import {
	any,
	contains,
	curry,
	filter,
	findIndex,
	first,
	isEqual,
	isString,
	keys,
	last,
	map,
	reject,
	size,
	uniq,
	flatten,
	startsWith} from 'lodash'

import Promise from 'bluebird'
import idbRange from 'idb-range'
import {cmp as idbComparison} from 'treo'
import {checkCourseAgainstQuery as checkAgainstQuery} from 'sto-helpers'

function canAdd({query, value, primaryKey, results}={}) {
	// Check if we want to add the current value to the results array.
	// Essentially, make sure that the current value passes the query,
	// and then that it's not already in the array.
	// Note that because JS checks against identity, we use isEqual to
	// do an equality check against the two objects.
	return checkAgainstQuery(query, value) && !contains(results, primaryKey)
}

function queryStore(query) {
	return new Promise((resolvePromise, rejectPromise) => {
		// Take a query object.
		// Grab a key out of it to operate on an index.
		// Set up a range from the low and high value from the values for that key.
		// Iterate over that range and index, checking each value against the query
		//     and making sure not to add duplicates.
		// Return the results.

		let results = []
		// Prevent invalid logic from not having a query.
		if (!size(query))
			return results

		// Grab a key from the query to use as an index.
		// TODO: Write a function to sort keys by priority.
		let indexKeys = keys(query)
		// // <this is a very hacky way of prioritizing the deptnum>
		// if (contains(keysWithIndices, 'deptnum')) {
		// 	keysWithIndices.splice(findIndex('deptnum'), 1)
		// 	keysWithIndices.unshift('deptnum')
		// }

		// Filter down to just the requested keys that also have indices
		let keysWithIndices = filter(indexKeys, (key) => this.index(key))

		// If the current store has at least one index for a requested key,
		// just run over that index.
		if (size(keysWithIndices)) {
			let indices = filter(this.indexes, index => contains(keysWithIndices, index.name))

			let resultPromises = map(indices,
				index => index.query(query, true))

			let allFoundKeys = Promise.all(resultPromises)

			let allValues = allFoundKeys
				.then(keys => flatten(keys))
				.then(keys => this.batchGet(keys))

			Promise.all(allValues).then(resolvePromise)
		}

		// Otherwise, if the current store doesn't have an index for any of
		// the requested keys, iterate over the entire store.
		else {
			this.cursor({iterator: iterateStore}, done)
		}

		function done(err) {
			if (err)
				rejectPromise(err)
			Promise.all(this.batchGet(results)).then(resolvePromise)
		}

		function iterateStore(cursor) {
			let {value, primaryKey} = cursor
			if (canAdd({query, value, primaryKey, results})) {
				resultIds.push(primaryKey)
			}
			cursor.continue()
		}
	})
}

function queryIndex(query, primaryKeysOnly=false) {
	return new Promise((resolvePromise, rejectPromise) => {
		// - takes a query object
		// - filters down the props to just the current index's name
		// - if there aren't any keys to look for under the current index, return []
		// - otherwise, execute the query

		let results = []

		// Prevent invalid logic from not having a query.
		if (!query || !size(query) || !size(query[this.name]))
			return results

		// The index of our current key
		let current = 0

		// The keys to look for; the list of permissible values for that range from the query
		let keys = query[this.name]
		keys = reject(keys, key => startsWith(key, '$'))

		if (!keys.length) {
			return results
		}

		// If we have any keys, sort them according to the IDB spec
		keys = keys.sort(idbComparison)

		let firstKey = first(keys)
		let lastKey = last(keys)

		// A range to limit ourselves to
		let range = idbRange({
			gte: firstKey,
			// If it's a string, append `uffff` because that's the highest
			// value in Unicode, which lets us make sure and iterate over all
			// values that we need.
			// hacks.mozilla.org/2014/06/breaking-the-borders-of-indexeddb
			lte: isString(lastKey) ? lastKey + 'uffff' : lastKey,
		})

		let done = (err) => {
			if (err) {
				rejectPromise(err)
			}
			else if (primaryKeysOnly) {
				resolvePromise(results)
			}
			else {
				this.objectStore
					.batchGet(results)
					.then(resolvePromise)
			}
		}

		function iterateIndex(cursor) {
			// console.log('cursor', cursor, arguments)
			console.log('key', keys[current], 'idx', current)
			console.log(keys)

			if (current > keys.length) {
				// console.log('done')
				// If we're out of keys, quit.
				done()
			}

			else if (cursor.key > keys[current]) {
				// console.log('greater')
				// If the cursor's key is "past" the current one, we need to skip
				// ahead to the next one key in the list of keys.
				let {value, primaryKey} = cursor
				if (canAdd({query, value, primaryKey, results})) {
					// console.log('adding', value)
					results.push(primaryKey)
				}
				current += 1

				// If we attempt to continue to a key that is before or equal
				// to the current cursor.key, IDB throws an error.
				// Therefore, if the current key equals the current key, we
				// just go forward by one.
				let nextKey = (keys[current] === cursor.key) ? undefined : keys[current]
				cursor.continue(nextKey)
			}

			else if (cursor.key === keys[current]) {
				// console.log('equals')
				// If we've found what we're looking for, add it, and go to
				// the next result.
				let {value, primaryKey} = cursor
				if (canAdd({query, value, primaryKey, results})) {
					// console.log('adding', value)
					results.push(primaryKey)
				}
				cursor.continue()
			}

			else {
				// console.log('other')
				// Otherwise, we're not there yet, and need to skip ahead to the
				// first occurrence of our current key.
				cursor.continue(keys[current])
			}
		}

		this.cursor({range, iterator: iterateIndex}, done)
	})
}
<commit_msg>resolve results, don't return them from a promise<commit_after>// import queryTreoDatabase from 'path/to/queryTreoDatabase'
// let db = treo('databaseName', schema)
//   .use(queryTreoDatabase)

function plugin(db, treo) {
	let {Store, Index} = treo

	Store.prototype.query = queryStore
	Index.prototype.query = queryIndex
}

export default plugin

import {
	any,
	contains,
	curry,
	filter,
	findIndex,
	first,
	isEqual,
	isString,
	keys,
	last,
	map,
	reject,
	size,
	uniq,
	flatten,
	startsWith} from 'lodash'

import Promise from 'bluebird'
import idbRange from 'idb-range'
import {cmp as idbComparison} from 'treo'
import {checkCourseAgainstQuery as checkAgainstQuery} from 'sto-helpers'

function canAdd({query, value, primaryKey, results}={}) {
	// Check if we want to add the current value to the results array.
	// Essentially, make sure that the current value passes the query,
	// and then that it's not already in the array.
	// Note that because JS checks against identity, we use isEqual to
	// do an equality check against the two objects.
	return checkAgainstQuery(query, value) && !contains(results, primaryKey)
}

function queryStore(query) {
	return new Promise((resolvePromise, rejectPromise) => {
		// Take a query object.
		// Grab a key out of it to operate on an index.
		// Set up a range from the low and high value from the values for that key.
		// Iterate over that range and index, checking each value against the query
		//     and making sure not to add duplicates.
		// Return the results.

		let results = []
		// Prevent invalid logic from not having a query.
		if (!size(query))
			return results

		// Grab a key from the query to use as an index.
		// TODO: Write a function to sort keys by priority.
		let indexKeys = keys(query)
		// // <this is a very hacky way of prioritizing the deptnum>
		// if (contains(keysWithIndices, 'deptnum')) {
		// 	keysWithIndices.splice(findIndex('deptnum'), 1)
		// 	keysWithIndices.unshift('deptnum')
		// }

		// Filter down to just the requested keys that also have indices
		let keysWithIndices = filter(indexKeys, (key) => this.index(key))

		// If the current store has at least one index for a requested key,
		// just run over that index.
		if (size(keysWithIndices)) {
			let indices = filter(this.indexes, index => contains(keysWithIndices, index.name))

			let resultPromises = map(indices,
				index => index.query(query, true))

			let allFoundKeys = Promise.all(resultPromises)

			let allValues = allFoundKeys
				.then(keys => flatten(keys))
				.then(keys => this.batchGet(keys))

			Promise.all(allValues).then(resolvePromise)
		}

		// Otherwise, if the current store doesn't have an index for any of
		// the requested keys, iterate over the entire store.
		else {
			this.cursor({iterator: iterateStore}, done)
		}

		function done(err) {
			if (err)
				rejectPromise(err)
			Promise.all(this.batchGet(results)).then(resolvePromise)
		}

		function iterateStore(cursor) {
			let {value, primaryKey} = cursor
			if (canAdd({query, value, primaryKey, results})) {
				resultIds.push(primaryKey)
			}
			cursor.continue()
		}
	})
}

function queryIndex(query, primaryKeysOnly=false) {
	return new Promise((resolvePromise, rejectPromise) => {
		// - takes a query object
		// - filters down the props to just the current index's name
		// - if there aren't any keys to look for under the current index, return []
		// - otherwise, execute the query

		let results = []

		// Prevent invalid logic from not having a query.
		if (!query || !size(query) || !size(query[this.name]))
			resolvePromise(results)

		// The index of our current key
		let current = 0

		// The keys to look for; the list of permissible values for that range from the query
		let keys = query[this.name]
		keys = reject(keys, key => startsWith(key, '$'))

		if (!keys.length) {
			resolvePromise(results)
		}

		// If we have any keys, sort them according to the IDB spec
		keys = keys.sort(idbComparison)

		let firstKey = first(keys)
		let lastKey = last(keys)

		// A range to limit ourselves to
		let range = idbRange({
			gte: firstKey,
			// If it's a string, append `uffff` because that's the highest
			// value in Unicode, which lets us make sure and iterate over all
			// values that we need.
			// hacks.mozilla.org/2014/06/breaking-the-borders-of-indexeddb
			lte: isString(lastKey) ? lastKey + 'uffff' : lastKey,
		})

		let done = (err) => {
			if (err) {
				rejectPromise(err)
			}
			else if (primaryKeysOnly) {
				resolvePromise(results)
			}
			else {
				this.objectStore
					.batchGet(results)
					.then(resolvePromise)
			}
		}

		function iterateIndex(cursor) {
			// console.log('cursor', cursor, arguments)
			console.log('key', keys[current], 'idx', current)
			console.log(keys)

			if (current > keys.length) {
				// console.log('done')
				// If we're out of keys, quit.
				done()
			}

			else if (cursor.key > keys[current]) {
				// console.log('greater')
				// If the cursor's key is "past" the current one, we need to skip
				// ahead to the next one key in the list of keys.
				let {value, primaryKey} = cursor
				if (canAdd({query, value, primaryKey, results})) {
					// console.log('adding', value)
					results.push(primaryKey)
				}
				current += 1

				// If we attempt to continue to a key that is before or equal
				// to the current cursor.key, IDB throws an error.
				// Therefore, if the current key equals the current key, we
				// just go forward by one.
				let nextKey = (keys[current] === cursor.key) ? undefined : keys[current]
				cursor.continue(nextKey)
			}

			else if (cursor.key === keys[current]) {
				// console.log('equals')
				// If we've found what we're looking for, add it, and go to
				// the next result.
				let {value, primaryKey} = cursor
				if (canAdd({query, value, primaryKey, results})) {
					// console.log('adding', value)
					results.push(primaryKey)
				}
				cursor.continue()
			}

			else {
				// console.log('other')
				// Otherwise, we're not there yet, and need to skip ahead to the
				// first occurrence of our current key.
				cursor.continue(keys[current])
			}
		}

		this.cursor({range, iterator: iterateIndex}, done)
	})
}
<|endoftext|>