<commit_before>'use strict';

// alphabetSize, charToIndex and indexToChar are hardcoded here to keep the code short, however they
// could easily be be passed as arguments in the Trie constructor.
var alphabetSize = 36; // 0-9 and a-z
var charToIndex = function(char) {
    return parseInt(char, 36);
}
var indexToChar = function(index) {
    return index.toString(36);
}

exports.Trie = function() {
    var root = new Node();

    this.has = function(key) {
        var n = find(root, key);
        return n && n.hasValue();
    };

    this.get = function(key) {
        var n = find(root, key);
        if (n && n.hasValue()) {
            return n.value;
        }
    };

    this.set = function(key, value) {
        set(root, key, value);
    };

    this.del = function(key) {
        del(root, key);
    };

    this.all = function() {
        var a = [];
        preOrder(root, '', function(key, value) {
            a.push({key: key, value: value});
        });
        return a;
    };

    // this.log = function() {
    //     log(root, 0);
    // }
};

function Node() {
    this.children = new Array(alphabetSize);
}

Node.prototype.hasValue = function() {
    return this.hasOwnProperty('value');
};

Node.prototype.delValue = function() {
    delete this.value;
};

function find(n, key) {
    if (!key) {
        return n;
    }
    var i = charToIndex(key[0]);
    var child = n.children[i];
    if (!child) {
        return null;
    }
    return find(child, key.substring(1));
}

function set(n, key, value) {
    if (!key) {
        n.value = value;
        return;
    }
    var i = charToIndex(key[0]);
    var child = n.children[i];
    if (!child) {
        child = new Node();
        n.children[i] = child;
    }
    set(child, key.substring(1), value);
}

function del(n, key) {
    var i = charToIndex(key[0]);
    var child = n.children[i];
    if (!child) {
        return;
    }
    if (key.length > 1) {
        del(child, key.substring(1));
        return;
    }
    // Delete this child.
    if (isEmpty(child.children)) {
        n.children[i] = null;
    } else {
        child.delValue();
    }
}

function preOrder(n, key, callback) {
    if (n.hasValue()) {
        callback(key, n.value);
    }
    for (var i = 0; i < n.children.length; i++) {
        var child = n.children[i];
        if (child) {
            preOrder(child, key + indexToChar(i), callback);
        }
    }
}

function isEmpty(a) {
    return a.every(function(x) {
        return !x;
    });
}

// function log(n, indent) {
//     var spaces = new Array(indent + 1).join(' ');
//     for (var char in n.children) {
//         if (n.children.hasOwnProperty(char)) {
//             var child = n.children[char];
//             var v = child.hasValue() ? '(' + child.value + ')' : '';
//             console.log(spaces + char + ' ' + v);
//             log(child, indent + 2);
//         }
//     }
// }
<commit_msg>[trie/javascript] Add missing semicolons<commit_after>'use strict';

// alphabetSize, charToIndex and indexToChar are hardcoded here to keep the code short, however they
// could easily be be passed as arguments in the Trie constructor.
var alphabetSize = 36; // 0-9 and a-z
var charToIndex = function(char) {
    return parseInt(char, 36);
};
var indexToChar = function(index) {
    return index.toString(36);
};

exports.Trie = function() {
    var root = new Node();

    this.has = function(key) {
        var n = find(root, key);
        return n && n.hasValue();
    };

    this.get = function(key) {
        var n = find(root, key);
        if (n && n.hasValue()) {
            return n.value;
        }
    };

    this.set = function(key, value) {
        set(root, key, value);
    };

    this.del = function(key) {
        del(root, key);
    };

    this.all = function() {
        var a = [];
        preOrder(root, '', function(key, value) {
            a.push({key: key, value: value});
        });
        return a;
    };

    // this.log = function() {
    //     log(root, 0);
    // }
};

function Node() {
    this.children = new Array(alphabetSize);
}

Node.prototype.hasValue = function() {
    return this.hasOwnProperty('value');
};

Node.prototype.delValue = function() {
    delete this.value;
};

function find(n, key) {
    if (!key) {
        return n;
    }
    var i = charToIndex(key[0]);
    var child = n.children[i];
    if (!child) {
        return null;
    }
    return find(child, key.substring(1));
}

function set(n, key, value) {
    if (!key) {
        n.value = value;
        return;
    }
    var i = charToIndex(key[0]);
    var child = n.children[i];
    if (!child) {
        child = new Node();
        n.children[i] = child;
    }
    set(child, key.substring(1), value);
}

function del(n, key) {
    var i = charToIndex(key[0]);
    var child = n.children[i];
    if (!child) {
        return;
    }
    if (key.length > 1) {
        del(child, key.substring(1));
        return;
    }
    // Delete this child.
    if (isEmpty(child.children)) {
        n.children[i] = null;
    } else {
        child.delValue();
    }
}

function preOrder(n, key, callback) {
    if (n.hasValue()) {
        callback(key, n.value);
    }
    for (var i = 0; i < n.children.length; i++) {
        var child = n.children[i];
        if (child) {
            preOrder(child, key + indexToChar(i), callback);
        }
    }
}

function isEmpty(a) {
    return a.every(function(x) {
        return !x;
    });
}

// function log(n, indent) {
//     var spaces = new Array(indent + 1).join(' ');
//     for (var char in n.children) {
//         if (n.children.hasOwnProperty(char)) {
//             var child = n.children[char];
//             var v = child.hasValue() ? '(' + child.value + ')' : '';
//             console.log(spaces + char + ' ' + v);
//             log(child, indent + 2);
//         }
//     }
// }
<|endoftext|>


<commit_before>/** The minplayer namespace. */
var minplayer = minplayer || {};

/** All the media player implementations */
minplayer.players = minplayer.players || {};

/**
 * @constructor
 * @extends minplayer.players.base
 * @class The Dailymotion media player.
 *
 * @param {object} context The jQuery context.
 * @param {object} options This components options.
 * @param {object} queue The event queue to pass events around.
 */
minplayer.players.dailymotion = function(context, options, queue) {

    /** The quality of the Dailymotion stream. */
    this.quality = 'default';

    // Derive from players base.
    minplayer.players.base.call(this, context, options, queue);
};

/** Derive from minplayer.players.base. */
minplayer.players.dailymotion.prototype = new minplayer.players.base();

/** Reset the constructor. */
minplayer.players.dailymotion.prototype.constructor = minplayer.players.dailymotion;

/**
 * @see minplayer.plugin.construct
 * @this minplayer.players.dailymotion
 */
minplayer.players.dailymotion.prototype.construct = function() {

    // Call the players.flash constructor.
    minplayer.players.base.prototype.construct.call(this);

    // Set the plugin name within the options.
    this.options.pluginName = 'dailymotion';
};

/**
 * @see minplayer.players.base#getPriority
 * @param {object} file A {@link minplayer.file} object.
 * @return {number} The priority of this media player.
 */
minplayer.players.dailymotion.getPriority = function(file) {
    return 10;
};

/**
 * @see minplayer.players.base#canPlay
 * @return {boolean} If this player can play this media type.
 */
minplayer.players.dailymotion.canPlay = function(file) {

    // Check for the mimetype for dailymotion.
    if (file.mimetype === 'video/dailymotion') {
        return true;
    }

    // If the path is a Dailymotion path, then return true.
    var regex = /^http(s)?\:\/\/(www\.)?(dailymotion\.com)/i;
    return (file.path.search(regex) === 0);
};

/**
 * Return the ID for a provided media file.
 *
 * @param {object} file A {@link minplayer.file} object.
 * @return {string} The ID for the provided media.
 */
minplayer.players.dailymotion.getMediaId = function(file) {
    var regex = '^http[s]?\\:\\/\\/(www\\.)?';
    regex += '(dailymotion\\.com\\/video/)';
    regex += '([a-z0-9\\-]+)';
    regex += '_*';
    var reg = RegExp(regex, 'i');

    // Locate the media id.
    if (file.path.search(reg) === 0) {
        return file.path.match(reg)[3];
    }
    else {
        return file.path;
    }
};

/**
 * Returns a preview image for this media player.
 *
 * @param {object} file A {@link minplayer.file} object.
 * @param {string} type The type of image.
 * @param {function} callback Called when the image is retrieved.
 */
minplayer.players.dailymotion.getImage = function(file, type, callback) {
    type = (type == 'thumbnail') ? '1' : '0';
    callback('http://www.dailymotion.com/thumbnail/video/' + file.id);
};

/**
 * Parse a single playlist node.
 *
 * @param {object} item The dailymotion item.
 * @return {object} The mediafront node.
 */
minplayer.players.dailymotion.parseNode = function(item) {
     return {
        title: node.title,
        description: node.description,
        mediafiles: {
            image: {
                'thumbnail': {
                    path: node.thumbnail_small_url
                },
                'image': {
                    path: node.thumbnail_url
                }
            },
           media: {
                'media': {
                    player: 'dailymotion',
                    id: node.id
                }
            }
        }
     };
};

/**
 * Returns information about this dailymotion video.
 *
 * @param {object} file The file to load.
 * @param {function} callback Called when the node is loaded.
 */
minplayer.players.dailymotion.getNode = function(file, callback) {

    var url = 'https://api.dailymotion.com/video/' + file.id;
    url += '?fields=title,id,description,thumbnail_small_url,thumbnail_url';
    jQuery.get(url, function(data) {
        callback(minplayer.players.dailymotion.parseNode(data.data));
    },
    "jsonp");
};

/**
 * Called when an API is loaded and ready.
 *
 * @param {string} event The onReady event that was triggered.
 */
minplayer.players.dailymotion.prototype.onReady = function(event) {
    minplayer.players.base.prototype.onReady.call(this);
    if (!this.options.autoplay) {
        this.pause();
    }
    this.onLoaded();
};

/**
 * Checks to see if this player can be found.
 * @return {bool} TRUE - Player is found, FALSE - otherwise.
 */
minplayer.players.dailymotion.prototype.playerFound = function() {
    return (this.display.find(this.mediaFile.type).length > 0);
};

/**
 * Called when the player quality changes.
 *
 * @param {string} newQuality The new quality for the change.
 */
minplayer.players.dailymotion.prototype.onQualityChange = function(newQuality) {
    this.quality = newQuality.data;
};

/**
 * Determines if the player should show the playloader.
 *
 * @param {string} preview The preview image.
 * @return {bool} If this player implements its own playLoader.
 */
minplayer.players.dailymotion.prototype.hasPlayLoader = function(preview) {
    return minplayer.hasTouch || !preview;
};

/**
 * Determines if the player should show the controller.
 *
 * @return {bool} If this player implements its own playLoader.
 */
minplayer.players.dailymotion.prototype.hasController = function() {
    return minplayer.isIDevice;
};

/**
 * @see minplayer.players.base#create
 * @return {object} The media player entity.
 */
minplayer.players.dailymotion.prototype.createPlayer = function() {
    minplayer.players.base.prototype.createPlayer.call(this);

    // Insert the Dailymotion iframe API player.
    var dailymotion_script = document.location.protocol + '//api.dmcdn.net/all.js';
    if (jQuery('script[src="' + dailymotion_script + '"]').length == 0) {
        var tag = document.createElement('script');
        tag.src = dailymotion_script;
        var firstScriptTag = document.getElementsByTagName('script')[0];
        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    }

    // Get the player ID.
    this.playerId = this.options.id + '-player';

    // Poll until the Dailymotion API is ready.
    this.poll(this.options.id + '_dailymotion', (function(player) {
        return function() {
            var ready = jQuery('#' + player.playerId).length > 0;
            ready = ready && ('DM' in window);
            ready = ready && (typeof DM.player == 'function');
            if (ready) {
                // Determine the origin of this script.
                jQuery('#' + player.playerId).addClass('dailymotion-player');

                var params = {};
                params = {
                    id: player.playerId,
                    api: minplayer.isIDevice ? 0 : 1,
                    wmode: 'opaque',
                    controls: minplayer.isAndroid ? 1 : 0,
                    related: 0,
                    info: 0,
                    logo: 0
                };

                // Create the player.
                player.player = new DM.player(player.playerId, {
                    video: player.mediaFile.id,
                    height: '100%',
                    width: '100%',
                    frameborder: 0,
                    params: params
                });

                player.player.addEventListener('apiready', function() { player.onReady(player) } );
                player.player.addEventListener('ended', function() { player.onComplete(player) });
                player.player.addEventListener('playing', function() { player.onPlaying(player) });
                player.player.addEventListener('progress', function() { player.onWaiting(player) });
                player.player.addEventListener('pause', function() { player.onPaused(player) });
                player.player.addEventListener('error', function() { player.onError(player) });
            }
            return !ready;
        };
    })(this), 200);

    // Return the player.
    return jQuery(document.createElement('div')).attr({
        id: this.playerId
    });
};

/**
 * @see minplayer.players.base#load
 */
minplayer.players.dailymotion.prototype.load = function(file, callback) {
    minplayer.players.base.prototype.load.call(this, file, function() {
        this.player.load(file.id);
        if (callback) {
            callback.call(this);
        }
    });
};

/**
 * @see minplayer.players.base#play
 */
minplayer.players.dailymotion.prototype.play = function(callback) {
    minplayer.players.base.prototype.play.call(this, function() {
        //this.onWaiting();
        this.player.play();
        if (callback) {
            callback.call(this);
        }
    });
};

/**
 * @see minplayer.players.base#pause
 */
minplayer.players.dailymotion.prototype.pause = function(callback) {
    minplayer.players.base.prototype.pause.call(this, function() {
        this.player.pause();
        if (callback) {
            callback.call(this);
        }
    });
};

/**
 * @see minplayer.players.base#stop
 */
minplayer.players.dailymotion.prototype.stop = function(callback) {
    minplayer.players.base.prototype.stop.call(this, function() {
        this.player.pause();
        if (callback) {
            callback.call(this);
        }
    });
};

/**
 * @see minplayer.players.base#seek
 */
minplayer.players.dailymotion.prototype.seek = function(pos, callback) {
    minplayer.players.base.prototype.seek.call(this, pos, function() {
        this.onWaiting();
        this.player.seek(pos);
        if (callback) {
            callback.call(this);
        }
    });
};

/**
 * @see minplayer.players.base#setVolume
 */
minplayer.players.dailymotion.prototype.setVolume = function(vol, callback) {
    minplayer.players.base.prototype.setVolume.call(this, vol, function() {
        this.player.setVolume(vol);
        if (callback != undefined) {
            callback.call(this);
        }
    });
};

/**
 * @see minplayer.players.base#getValue
 */
minplayer.players.dailymotion.prototype.getValue = function(getter, callback) {
  if (this.isReady()) {
    var value = this.player[getter];
    if ((value !== undefined) && (value !== null) && callback) {
      callback(value);
    }
  }
};

/**
 * @see minplayer.players.base#getVolume
 */
minplayer.players.dailymotion.prototype.getVolume = function(callback) {
    this.getValue('volume', callback);
};

/**
 * @see minplayer.players.base#getDuration.
 */
minplayer.players.dailymotion.prototype.getDuration = function(callback) {
    if (this.options.duration && callback != undefined) {
        callback(this.options.duration);
    }
    else {
        this.getValue('duration', callback);
    }
};

/**
 * @see minplayer.players.base#getCurrentTime
 */
minplayer.players.dailymotion.prototype.getCurrentTime = function(callback) {
    this.getValue('currentTime', callback);
};<commit_msg>Fix console errors (Player was not ready) / Fix double space tab<commit_after>/** The minplayer namespace. */
var minplayer = minplayer || {};

/** All the media player implementations */
minplayer.players = minplayer.players || {};

/**
 * @constructor
 * @extends minplayer.players.base
 * @class The Dailymotion media player.
 *
 * @param {object} context The jQuery context.
 * @param {object} options This components options.
 * @param {object} queue The event queue to pass events around.
 */
minplayer.players.dailymotion = function(context, options, queue) {

  /** The quality of the Dailymotion stream. */
  this.quality = 'default';

  // Derive from players base.
  minplayer.players.base.call(this, context, options, queue);
};

/** Derive from minplayer.players.base. */
minplayer.players.dailymotion.prototype = new minplayer.players.base();

/** Reset the constructor. */
minplayer.players.dailymotion.prototype.constructor = minplayer.players.dailymotion;

/**
 * @see minplayer.plugin.construct
 * @this minplayer.players.dailymotion
 */
minplayer.players.dailymotion.prototype.construct = function() {

  // Call the players.flash constructor.
  minplayer.players.base.prototype.construct.call(this);

  // Set the plugin name within the options.
  this.options.pluginName = 'dailymotion';
};

/**
 * @see minplayer.players.base#getPriority
 * @param {object} file A {@link minplayer.file} object.
 * @return {number} The priority of this media player.
 */
minplayer.players.dailymotion.getPriority = function(file) {
  return 10;
};

/**
 * @see minplayer.players.base#canPlay
 *
 * @param {object} file A {@link minplayer.file} object.
 * @return {boolean} If this player can play this media type.
 */
minplayer.players.dailymotion.canPlay = function(file) {

  // Check for the mimetype for dailymotion.
  if (file.mimetype === 'video/dailymotion') {
    return true;
  }

  // If the path is a Dailymotion path, then return true.
  var regex = /^http(s)?\:\/\/(www\.)?(dailymotion\.com)/i;
  return (file.path.search(regex) === 0);
};

/**
 * Return the ID for a provided media file.
 *
 * @param {object} file A {@link minplayer.file} object.
 * @return {string} The ID for the provided media.
 */
minplayer.players.dailymotion.getMediaId = function(file) {
  var regex = '^http[s]?\\:\\/\\/(www\\.)?';
  regex += '(dailymotion\\.com\\/video/)';
  regex += '([a-z0-9\\-]+)';
  regex += '_*';
  var reg = RegExp(regex, 'i');

  // Locate the media id.
  if (file.path.search(reg) === 0) {
    return file.path.match(reg)[3];
  }
  else {
    return file.path;
  }
};

/**
 * Returns a preview image for this media player.
 *
 * @param {object} file A {@link minplayer.file} object.
 * @param {string} type The type of image.
 * @param {function} callback Called when the image is retrieved.
 */
minplayer.players.dailymotion.getImage = function(file, type, callback) {
  callback('http://www.dailymotion.com/thumbnail/video/' + file.id);
};

/**
 * Parse a single playlist node.
 *
 * @param {object} item The dailymotion item.
 * @return {object} The mediafront node.
 */
minplayer.players.dailymotion.parseNode = function(item) {
  return {
    title: node.title,
    description: node.description,
    mediafiles: {
      image: {
        'thumbnail': {
          path: node.thumbnail_small_url
        },
        'image': {
          path: node.thumbnail_url
        }
      },
      media: {
        'media': {
          player: 'dailymotion',
          id: node.id
        }
      }
    }
  };
};

/**
 * Returns information about this dailymotion video.
 *
 * @param {object} file The file to load.
 * @param {function} callback Called when the node is loaded.
 */
minplayer.players.dailymotion.getNode = function(file, callback) {

  var url = 'https://api.dailymotion.com/video/' + file.id;
  url += '?fields=title,id,description,thumbnail_small_url,thumbnail_url';
  jQuery.get(url, function(data) {
    callback(minplayer.players.dailymotion.parseNode(data.data));
  },
          "jsonp");
};

/**
 * Called when an API is loaded and ready.
 *
 * @param {string} event The onReady event that was triggered.
 */
minplayer.players.dailymotion.prototype.onReady = function(event) {
  minplayer.players.base.prototype.onReady.call(this);
  if (!this.options.autoplay) {
    this.pause();
  }
  this.onLoaded();
};

/**
 * Checks to see if this player can be found.
 * @return {bool} TRUE - Player is found, FALSE - otherwise.
 */
minplayer.players.dailymotion.prototype.playerFound = function() {
  return (this.display.find(this.mediaFile.type).length > 0);
};

/**
 * Called when the player quality changes.
 *
 * @param {string} newQuality The new quality for the change.
 */
minplayer.players.dailymotion.prototype.onQualityChange = function(newQuality) {
  this.quality = newQuality.data;
};

/**
 * Determines if the player should show the playloader.
 *
 * @param {string} preview The preview image.
 * @return {bool} If this player implements its own playLoader.
 */
minplayer.players.dailymotion.prototype.hasPlayLoader = function(preview) {
  return minplayer.hasTouch || !preview;
};

/**
 * Determines if the player should show the controller.
 *
 * @return {bool} If this player implements its own playLoader.
 */
minplayer.players.dailymotion.prototype.hasController = function() {
  return minplayer.isIDevice;
};

/**
 * @see minplayer.players.base#create
 * @return {object} The media player entity.
 */
minplayer.players.dailymotion.prototype.createPlayer = function() {
  minplayer.players.base.prototype.createPlayer.call(this);

  // Insert the Dailymotion iframe API player.
  var dailymotion_script = document.location.protocol + '//api.dmcdn.net/all.js';
  if (jQuery('script[src="' + dailymotion_script + '"]').length === 0) {
    var tag = document.createElement('script');
    tag.src = dailymotion_script;
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  }

  // Get the player ID.
  this.playerId = this.options.id + '-player';

  // Poll until the Dailymotion API is ready.
  this.poll(this.options.id + '_dailymotion', (function(player) {
    return function() {
      var ready = jQuery('#' + player.playerId).length > 0;
      ready = ready && ('DM' in window);
      ready = ready && (typeof DM.player === 'function');
      if (ready) {
        // Determine the origin of this script.
        jQuery('#' + player.playerId).addClass('dailymotion-player');

        var params = {};
        params = {
          id: player.playerId,
          api: minplayer.isIDevice ? 0 : 1,
          wmode: 'opaque',
          controls: minplayer.isAndroid ? 1 : 0,
          related: 0,
          info: 0,
          logo: 0
        };

        // Create the player.
        player.player = new DM.player(player.playerId, {
          video: player.mediaFile.id,
          height: '100%',
          width: '100%',
          frameborder: 0,
          params: params
        });

        player.player.addEventListener('apiready', function() {
          player.onReady(player);
        });
        player.player.addEventListener('ended', function() {
          player.onComplete(player);
        });
        player.player.addEventListener('playing', function() {
          player.onPlaying(player);
        });
        player.player.addEventListener('progress', function() {
          player.onWaiting(player);
        });
        player.player.addEventListener('pause', function() {
          player.onPaused(player);
        });
        player.player.addEventListener('error', function() {
          player.onError(player);
        });
      }
      return !ready;
    };
  })(this), 200);

  // Return the player.
  return jQuery(document.createElement('div')).attr({
    id: this.playerId
  });
};

/**
 * @see minplayer.players.base#load
 */
minplayer.players.dailymotion.prototype.load = function(file, callback) {
  minplayer.players.base.prototype.load.call(this, file, function() {
    this.player.load(file.id);
    if (callback) {
      callback.call(this);
    }
  });
};

/**
 * @see minplayer.players.base#play
 */
minplayer.players.dailymotion.prototype.play = function(callback) {
  minplayer.players.base.prototype.play.call(this, function() {
    this.onWaiting();
    this.player.play();
    if (callback) {
      callback.call(this);
    }
  });
};

/**
 * @see minplayer.players.base#pause
 */
minplayer.players.dailymotion.prototype.pause = function(callback) {
  minplayer.players.base.prototype.pause.call(this, function() {
    if (this.loaded) {
      this.player.pause();
      if (callback) {
        callback.call(this);
      }
    }
  });
};

/**
 * @see minplayer.players.base#stop
 */
minplayer.players.dailymotion.prototype.stop = function(callback) {
  minplayer.players.base.prototype.stop.call(this, function() {
    this.player.pause();
    if (callback) {
      callback.call(this);
    }
  });
};

/**
 * @see minplayer.players.base#seek
 */
minplayer.players.dailymotion.prototype.seek = function(pos, callback) {
  minplayer.players.base.prototype.seek.call(this, pos, function() {
    this.onWaiting();
    this.player.seek(pos);
    if (callback) {
      callback.call(this);
    }
  });
};

/**
 * @see minplayer.players.base#setVolume
 */
minplayer.players.dailymotion.prototype.setVolume = function(vol, callback) {
  minplayer.players.base.prototype.setVolume.call(this, vol, function() {
    if (this.loaded) {
      this.player.setVolume(vol);
      if (callback !== undefined) {
        callback.call(this);
      }
    }
  });

};

/**
 * @see minplayer.players.base#getValue
 */
minplayer.players.dailymotion.prototype.getValue = function(getter, callback) {
  if (this.isReady()) {
    var value = this.player[getter];
    if ((value !== undefined) && (value !== null) && callback) {
      callback(value);
    }
  }
};

/**
 * @see minplayer.players.base#getVolume
 */
minplayer.players.dailymotion.prototype.getVolume = function(callback) {
  this.getValue('volume', callback);
};

/**
 * @see minplayer.players.base#getDuration.
 */
minplayer.players.dailymotion.prototype.getDuration = function(callback) {
  if (this.options.duration && callback !== undefined) {
    callback(this.options.duration);
  }
  else {
    this.getValue('duration', callback);
  }
};

/**
 * @see minplayer.players.base#getCurrentTime
 */
minplayer.players.dailymotion.prototype.getCurrentTime = function(callback) {
  this.getValue('currentTime', callback);
};<|endoftext|>


<commit_before>import $ from '../../shared/dom.js';
import {
  extend,
  bindModuleMethods,
  classesToSelector,
  createElementIfNotDefined,
} from '../../shared/utils.js';

const Pagination = {
  update() {
    // Render || Update Pagination bullets/items
    const swiper = this;
    const rtl = swiper.rtl;
    const params = swiper.params.pagination;
    if (
      !params.el ||
      !swiper.pagination.el ||
      !swiper.pagination.$el ||
      swiper.pagination.$el.length === 0
    )
      return;
    const slidesLength =
      swiper.virtual && swiper.params.virtual.enabled
        ? swiper.virtual.slides.length
        : swiper.slides.length;
    const $el = swiper.pagination.$el;
    // Current/Total
    let current;
    const total = swiper.params.loop
      ? Math.ceil((slidesLength - swiper.loopedSlides * 2) / swiper.params.slidesPerGroup)
      : swiper.snapGrid.length;
    if (swiper.params.loop) {
      current = Math.ceil(
        (swiper.activeIndex - swiper.loopedSlides) / swiper.params.slidesPerGroup,
      );
      if (current > slidesLength - 1 - swiper.loopedSlides * 2) {
        current -= slidesLength - swiper.loopedSlides * 2;
      }
      if (current > total - 1) current -= total;
      if (current < 0 && swiper.params.paginationType !== 'bullets') current = total + current;
    } else if (typeof swiper.snapIndex !== 'undefined') {
      current = swiper.snapIndex;
    } else {
      current = swiper.activeIndex || 0;
    }
    // Types
    if (
      params.type === 'bullets' &&
      swiper.pagination.bullets &&
      swiper.pagination.bullets.length > 0
    ) {
      const bullets = swiper.pagination.bullets;
      let firstIndex;
      let lastIndex;
      let midIndex;
      if (params.dynamicBullets) {
        swiper.pagination.bulletSize = bullets
          .eq(0)
          [swiper.isHorizontal() ? 'outerWidth' : 'outerHeight'](true);
        $el.css(
          swiper.isHorizontal() ? 'width' : 'height',
          `${swiper.pagination.bulletSize * (params.dynamicMainBullets + 4)}px`,
        );
        if (params.dynamicMainBullets > 1 && swiper.previousIndex !== undefined) {
          swiper.pagination.dynamicBulletIndex += current - swiper.previousIndex;
          if (swiper.pagination.dynamicBulletIndex > params.dynamicMainBullets - 1) {
            swiper.pagination.dynamicBulletIndex = params.dynamicMainBullets - 1;
          } else if (swiper.pagination.dynamicBulletIndex < 0) {
            swiper.pagination.dynamicBulletIndex = 0;
          }
        }
        firstIndex = current - swiper.pagination.dynamicBulletIndex;
        lastIndex = firstIndex + (Math.min(bullets.length, params.dynamicMainBullets) - 1);
        midIndex = (lastIndex + firstIndex) / 2;
      }
      bullets.removeClass(
        `${params.bulletActiveClass} ${params.bulletActiveClass}-next ${params.bulletActiveClass}-next-next ${params.bulletActiveClass}-prev ${params.bulletActiveClass}-prev-prev ${params.bulletActiveClass}-main`,
      );
      if ($el.length > 1) {
        bullets.each((bullet) => {
          const $bullet = $(bullet);
          const bulletIndex = $bullet.index();
          if (bulletIndex === current) {
            $bullet.addClass(params.bulletActiveClass);
          }
          if (params.dynamicBullets) {
            if (bulletIndex >= firstIndex && bulletIndex <= lastIndex) {
              $bullet.addClass(`${params.bulletActiveClass}-main`);
            }
            if (bulletIndex === firstIndex) {
              $bullet
                .prev()
                .addClass(`${params.bulletActiveClass}-prev`)
                .prev()
                .addClass(`${params.bulletActiveClass}-prev-prev`);
            }
            if (bulletIndex === lastIndex) {
              $bullet
                .next()
                .addClass(`${params.bulletActiveClass}-next`)
                .next()
                .addClass(`${params.bulletActiveClass}-next-next`);
            }
          }
        });
      } else {
        const $bullet = bullets.eq(current);
        const bulletIndex = $bullet.index();
        $bullet.addClass(params.bulletActiveClass);
        if (params.dynamicBullets) {
          const $firstDisplayedBullet = bullets.eq(firstIndex);
          const $lastDisplayedBullet = bullets.eq(lastIndex);
          for (let i = firstIndex; i <= lastIndex; i += 1) {
            bullets.eq(i).addClass(`${params.bulletActiveClass}-main`);
          }
          if (swiper.params.loop) {
            if (bulletIndex >= bullets.length - params.dynamicMainBullets) {
              for (let i = params.dynamicMainBullets; i >= 0; i -= 1) {
                bullets.eq(bullets.length - i).addClass(`${params.bulletActiveClass}-main`);
              }
              bullets
                .eq(bullets.length - params.dynamicMainBullets - 1)
                .addClass(`${params.bulletActiveClass}-prev`);
            } else {
              $firstDisplayedBullet
                .prev()
                .addClass(`${params.bulletActiveClass}-prev`)
                .prev()
                .addClass(`${params.bulletActiveClass}-prev-prev`);
              $lastDisplayedBullet
                .next()
                .addClass(`${params.bulletActiveClass}-next`)
                .next()
                .addClass(`${params.bulletActiveClass}-next-next`);
            }
          } else {
            $firstDisplayedBullet
              .prev()
              .addClass(`${params.bulletActiveClass}-prev`)
              .prev()
              .addClass(`${params.bulletActiveClass}-prev-prev`);
            $lastDisplayedBullet
              .next()
              .addClass(`${params.bulletActiveClass}-next`)
              .next()
              .addClass(`${params.bulletActiveClass}-next-next`);
          }
        }
      }
      if (params.dynamicBullets) {
        const dynamicBulletsLength = Math.min(bullets.length, params.dynamicMainBullets + 4);
        const bulletsOffset =
          (swiper.pagination.bulletSize * dynamicBulletsLength - swiper.pagination.bulletSize) / 2 -
          midIndex * swiper.pagination.bulletSize;
        const offsetProp = rtl ? 'right' : 'left';
        bullets.css(swiper.isHorizontal() ? offsetProp : 'top', `${bulletsOffset}px`);
      }
    }
    if (params.type === 'fraction') {
      $el
        .find(classesToSelector(params.currentClass))
        .text(params.formatFractionCurrent(current + 1));
      $el.find(classesToSelector(params.totalClass)).text(params.formatFractionTotal(total));
    }
    if (params.type === 'progressbar') {
      let progressbarDirection;
      if (params.progressbarOpposite) {
        progressbarDirection = swiper.isHorizontal() ? 'vertical' : 'horizontal';
      } else {
        progressbarDirection = swiper.isHorizontal() ? 'horizontal' : 'vertical';
      }
      const scale = (current + 1) / total;
      let scaleX = 1;
      let scaleY = 1;
      if (progressbarDirection === 'horizontal') {
        scaleX = scale;
      } else {
        scaleY = scale;
      }
      $el
        .find(classesToSelector(params.progressbarFillClass))
        .transform(`translate3d(0,0,0) scaleX(${scaleX}) scaleY(${scaleY})`)
        .transition(swiper.params.speed);
    }
    if (params.type === 'custom' && params.renderCustom) {
      $el.html(params.renderCustom(swiper, current + 1, total));
      swiper.emit('paginationRender', $el[0]);
    } else {
      swiper.emit('paginationUpdate', $el[0]);
    }
    if (swiper.params.watchOverflow && swiper.enabled) {
      $el[swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);
    }
  },
  render() {
    // Render Container
    const swiper = this;
    const params = swiper.params.pagination;
    if (
      !params.el ||
      !swiper.pagination.el ||
      !swiper.pagination.$el ||
      swiper.pagination.$el.length === 0
    )
      return;
    const slidesLength =
      swiper.virtual && swiper.params.virtual.enabled
        ? swiper.virtual.slides.length
        : swiper.slides.length;

    const $el = swiper.pagination.$el;
    let paginationHTML = '';
    if (params.type === 'bullets') {
      let numberOfBullets = swiper.params.loop
        ? Math.ceil((slidesLength - swiper.loopedSlides * 2) / swiper.params.slidesPerGroup)
        : swiper.snapGrid.length;
      if (
        swiper.params.freeMode &&
        swiper.params.freeMode.enabled &&
        !swiper.params.loop &&
        numberOfBullets > slidesLength
      ) {
        numberOfBullets = slidesLength;
      }
      for (let i = 0; i < numberOfBullets; i += 1) {
        if (params.renderBullet) {
          paginationHTML += params.renderBullet.call(swiper, i, params.bulletClass);
        } else {
          paginationHTML += `<${params.bulletElement} class="${params.bulletClass}"></${params.bulletElement}>`;
        }
      }
      $el.html(paginationHTML);

      swiper.pagination.bullets = $el.find(classesToSelector(params.bulletClass));
    }
    if (params.type === 'fraction') {
      if (params.renderFraction) {
        paginationHTML = params.renderFraction.call(swiper, params.currentClass, params.totalClass);
      } else {
        paginationHTML =
          `<span class="${params.currentClass}"></span>` +
          ' / ' +
          `<span class="${params.totalClass}"></span>`;
      }
      $el.html(paginationHTML);
    }
    if (params.type === 'progressbar') {
      if (params.renderProgressbar) {
        paginationHTML = params.renderProgressbar.call(swiper, params.progressbarFillClass);
      } else {
        paginationHTML = `<span class="${params.progressbarFillClass}"></span>`;
      }
      $el.html(paginationHTML);
    }
    if (params.type !== 'custom') {
      swiper.emit('paginationRender', swiper.pagination.$el[0]);
    }
  },
  init() {
    const swiper = this;
    swiper.params.pagination = createElementIfNotDefined(
      swiper.$el,
      swiper.params.pagination,
      swiper.params.createElements,
      { el: 'swiper-pagination' },
    );
    const params = swiper.params.pagination;
    if (!params.el) return;

    let $el = $(params.el);
    if ($el.length === 0) return;

    if (swiper.params.uniqueNavElements && typeof params.el === 'string' && $el.length > 1) {
      $el = swiper.$el.find(params.el);
    }

    if (params.type === 'bullets' && params.clickable) {
      $el.addClass(params.clickableClass);
    }

    $el.addClass(params.modifierClass + params.type);

    if (params.type === 'bullets' && params.dynamicBullets) {
      $el.addClass(`${params.modifierClass}${params.type}-dynamic`);
      swiper.pagination.dynamicBulletIndex = 0;
      if (params.dynamicMainBullets < 1) {
        params.dynamicMainBullets = 1;
      }
    }
    if (params.type === 'progressbar' && params.progressbarOpposite) {
      $el.addClass(params.progressbarOppositeClass);
    }

    if (params.clickable) {
      $el.on('click', classesToSelector(params.bulletClass), function onClick(e) {
        e.preventDefault();
        let index = $(this).index() * swiper.params.slidesPerGroup;
        if (swiper.params.loop) index += swiper.loopedSlides;
        swiper.slideTo(index);
      });
    }

    extend(swiper.pagination, {
      $el,
      el: $el[0],
    });

    if (!swiper.enabled) {
      $el.addClass(params.lockClass);
    }
  },
  destroy() {
    const swiper = this;
    const params = swiper.params.pagination;
    if (
      !params.el ||
      !swiper.pagination.el ||
      !swiper.pagination.$el ||
      swiper.pagination.$el.length === 0
    )
      return;
    const $el = swiper.pagination.$el;

    $el.removeClass(params.hiddenClass);
    $el.removeClass(params.modifierClass + params.type);
    if (swiper.pagination.bullets) swiper.pagination.bullets.removeClass(params.bulletActiveClass);
    if (params.clickable) {
      $el.off('click', classesToSelector(params.bulletClass));
    }
  },
};

export default {
  name: 'pagination',
  params: {
    pagination: {
      el: null,
      bulletElement: 'span',
      clickable: false,
      hideOnClick: false,
      renderBullet: null,
      renderProgressbar: null,
      renderFraction: null,
      renderCustom: null,
      progressbarOpposite: false,
      type: 'bullets', // 'bullets' or 'progressbar' or 'fraction' or 'custom'
      dynamicBullets: false,
      dynamicMainBullets: 1,
      formatFractionCurrent: (number) => number,
      formatFractionTotal: (number) => number,
      bulletClass: 'swiper-pagination-bullet',
      bulletActiveClass: 'swiper-pagination-bullet-active',
      modifierClass: 'swiper-pagination-', // NEW
      currentClass: 'swiper-pagination-current',
      totalClass: 'swiper-pagination-total',
      hiddenClass: 'swiper-pagination-hidden',
      progressbarFillClass: 'swiper-pagination-progressbar-fill',
      progressbarOppositeClass: 'swiper-pagination-progressbar-opposite',
      clickableClass: 'swiper-pagination-clickable', // NEW
      lockClass: 'swiper-pagination-lock',
    },
  },
  create() {
    const swiper = this;
    bindModuleMethods(swiper, {
      pagination: {
        dynamicBulletIndex: 0,
        ...Pagination,
      },
    });
  },
  on: {
    init(swiper) {
      swiper.pagination.init();
      swiper.pagination.render();
      swiper.pagination.update();
    },
    activeIndexChange(swiper) {
      if (swiper.params.loop) {
        swiper.pagination.update();
      } else if (typeof swiper.snapIndex === 'undefined') {
        swiper.pagination.update();
      }
    },
    snapIndexChange(swiper) {
      if (!swiper.params.loop) {
        swiper.pagination.update();
      }
    },
    slidesLengthChange(swiper) {
      if (swiper.params.loop) {
        swiper.pagination.render();
        swiper.pagination.update();
      }
    },
    snapGridLengthChange(swiper) {
      if (!swiper.params.loop) {
        swiper.pagination.render();
        swiper.pagination.update();
      }
    },
    destroy(swiper) {
      swiper.pagination.destroy();
    },
    'enable disable': (swiper) => {
      const { $el } = swiper.pagination;
      if ($el) {
        $el[swiper.enabled ? 'removeClass' : 'addClass'](swiper.params.pagination.lockClass);
      }
    },
    click(swiper, e) {
      const targetEl = e.target;
      if (
        swiper.params.pagination.el &&
        swiper.params.pagination.hideOnClick &&
        swiper.pagination.$el.length > 0 &&
        !$(targetEl).hasClass(swiper.params.pagination.bulletClass)
      ) {
        if (
          swiper.navigation &&
          ((swiper.navigation.nextEl && targetEl === swiper.navigation.nextEl) ||
            (swiper.navigation.prevEl && targetEl === swiper.navigation.prevEl))
        )
          return;
        const isHidden = swiper.pagination.$el.hasClass(swiper.params.pagination.hiddenClass);
        if (isHidden === true) {
          swiper.emit('paginationShow');
        } else {
          swiper.emit('paginationHide');
        }
        swiper.pagination.$el.toggleClass(swiper.params.pagination.hiddenClass);
      }
    },
  },
};
<commit_msg>feat(core): convert Pagination to functional module<commit_after>import $ from '../../shared/dom.js';
import { extend, classesToSelector, createElementIfNotDefined } from '../../shared/utils.js';

export default function Pagination({ swiper, extendParams, on, emit }) {
  extendParams({
    pagination: {
      el: null,
      bulletElement: 'span',
      clickable: false,
      hideOnClick: false,
      renderBullet: null,
      renderProgressbar: null,
      renderFraction: null,
      renderCustom: null,
      progressbarOpposite: false,
      type: 'bullets', // 'bullets' or 'progressbar' or 'fraction' or 'custom'
      dynamicBullets: false,
      dynamicMainBullets: 1,
      formatFractionCurrent: (number) => number,
      formatFractionTotal: (number) => number,
      bulletClass: 'swiper-pagination-bullet',
      bulletActiveClass: 'swiper-pagination-bullet-active',
      modifierClass: 'swiper-pagination-',
      currentClass: 'swiper-pagination-current',
      totalClass: 'swiper-pagination-total',
      hiddenClass: 'swiper-pagination-hidden',
      progressbarFillClass: 'swiper-pagination-progressbar-fill',
      progressbarOppositeClass: 'swiper-pagination-progressbar-opposite',
      clickableClass: 'swiper-pagination-clickable',
      lockClass: 'swiper-pagination-lock',
    },
  });

  swiper.pagination = {
    el: null,
    $el: null,
    bullets: [],
  };

  let bulletSize;
  let dynamicBulletIndex = 0;

  function isPaginationDisabled() {
    return (
      !swiper.params.pagination.el ||
      !swiper.pagination.el ||
      !swiper.pagination.$el ||
      swiper.pagination.$el.length === 0
    );
  }

  function setSideBullets($bulletEl, position) {
    const { bulletActiveClass } = swiper.params.pagination;
    $bulletEl[position]()
      .addClass(`${bulletActiveClass}-${position}`)
      [position]()
      .addClass(`${bulletActiveClass}-${position}-${position}`);
  }

  function update() {
    // Render || Update Pagination bullets/items
    const rtl = swiper.rtl;
    const params = swiper.params.pagination;
    if (isPaginationDisabled()) return;
    const slidesLength =
      swiper.virtual && swiper.params.virtual.enabled
        ? swiper.virtual.slides.length
        : swiper.slides.length;
    const $el = swiper.pagination.$el;
    // Current/Total
    let current;
    const total = swiper.params.loop
      ? Math.ceil((slidesLength - swiper.loopedSlides * 2) / swiper.params.slidesPerGroup)
      : swiper.snapGrid.length;
    if (swiper.params.loop) {
      current = Math.ceil(
        (swiper.activeIndex - swiper.loopedSlides) / swiper.params.slidesPerGroup,
      );
      if (current > slidesLength - 1 - swiper.loopedSlides * 2) {
        current -= slidesLength - swiper.loopedSlides * 2;
      }
      if (current > total - 1) current -= total;
      if (current < 0 && swiper.params.paginationType !== 'bullets') current = total + current;
    } else if (typeof swiper.snapIndex !== 'undefined') {
      current = swiper.snapIndex;
    } else {
      current = swiper.activeIndex || 0;
    }
    // Types
    if (
      params.type === 'bullets' &&
      swiper.pagination.bullets &&
      swiper.pagination.bullets.length > 0
    ) {
      const bullets = swiper.pagination.bullets;
      let firstIndex;
      let lastIndex;
      let midIndex;
      if (params.dynamicBullets) {
        bulletSize = bullets.eq(0)[swiper.isHorizontal() ? 'outerWidth' : 'outerHeight'](true);
        $el.css(
          swiper.isHorizontal() ? 'width' : 'height',
          `${bulletSize * (params.dynamicMainBullets + 4)}px`,
        );
        if (params.dynamicMainBullets > 1 && swiper.previousIndex !== undefined) {
          dynamicBulletIndex += current - swiper.previousIndex;
          if (dynamicBulletIndex > params.dynamicMainBullets - 1) {
            dynamicBulletIndex = params.dynamicMainBullets - 1;
          } else if (dynamicBulletIndex < 0) {
            dynamicBulletIndex = 0;
          }
        }
        firstIndex = current - dynamicBulletIndex;
        lastIndex = firstIndex + (Math.min(bullets.length, params.dynamicMainBullets) - 1);
        midIndex = (lastIndex + firstIndex) / 2;
      }
      bullets.removeClass(
        ['', '-next', '-next-next', '-prev', '-prev-prev', '-main']
          .map((suffix) => `${params.bulletActiveClass}${suffix}`)
          .join(' '),
      );
      if ($el.length > 1) {
        bullets.each((bullet) => {
          const $bullet = $(bullet);
          const bulletIndex = $bullet.index();
          if (bulletIndex === current) {
            $bullet.addClass(params.bulletActiveClass);
          }
          if (params.dynamicBullets) {
            if (bulletIndex >= firstIndex && bulletIndex <= lastIndex) {
              $bullet.addClass(`${params.bulletActiveClass}-main`);
            }
            if (bulletIndex === firstIndex) {
              setSideBullets($bullet, 'prev');
            }
            if (bulletIndex === lastIndex) {
              setSideBullets($bullet, 'next');
            }
          }
        });
      } else {
        const $bullet = bullets.eq(current);
        const bulletIndex = $bullet.index();
        $bullet.addClass(params.bulletActiveClass);
        if (params.dynamicBullets) {
          const $firstDisplayedBullet = bullets.eq(firstIndex);
          const $lastDisplayedBullet = bullets.eq(lastIndex);
          for (let i = firstIndex; i <= lastIndex; i += 1) {
            bullets.eq(i).addClass(`${params.bulletActiveClass}-main`);
          }
          if (swiper.params.loop) {
            if (bulletIndex >= bullets.length - params.dynamicMainBullets) {
              for (let i = params.dynamicMainBullets; i >= 0; i -= 1) {
                bullets.eq(bullets.length - i).addClass(`${params.bulletActiveClass}-main`);
              }
              bullets
                .eq(bullets.length - params.dynamicMainBullets - 1)
                .addClass(`${params.bulletActiveClass}-prev`);
            } else {
              setSideBullets($firstDisplayedBullet, 'prev');
              setSideBullets($lastDisplayedBullet, 'next');
            }
          } else {
            setSideBullets($firstDisplayedBullet, 'prev');
            setSideBullets($lastDisplayedBullet, 'next');
          }
        }
      }
      if (params.dynamicBullets) {
        const dynamicBulletsLength = Math.min(bullets.length, params.dynamicMainBullets + 4);
        const bulletsOffset =
          (bulletSize * dynamicBulletsLength - bulletSize) / 2 - midIndex * bulletSize;
        const offsetProp = rtl ? 'right' : 'left';
        bullets.css(swiper.isHorizontal() ? offsetProp : 'top', `${bulletsOffset}px`);
      }
    }
    if (params.type === 'fraction') {
      $el
        .find(classesToSelector(params.currentClass))
        .text(params.formatFractionCurrent(current + 1));
      $el.find(classesToSelector(params.totalClass)).text(params.formatFractionTotal(total));
    }
    if (params.type === 'progressbar') {
      let progressbarDirection;
      if (params.progressbarOpposite) {
        progressbarDirection = swiper.isHorizontal() ? 'vertical' : 'horizontal';
      } else {
        progressbarDirection = swiper.isHorizontal() ? 'horizontal' : 'vertical';
      }
      const scale = (current + 1) / total;
      let scaleX = 1;
      let scaleY = 1;
      if (progressbarDirection === 'horizontal') {
        scaleX = scale;
      } else {
        scaleY = scale;
      }
      $el
        .find(classesToSelector(params.progressbarFillClass))
        .transform(`translate3d(0,0,0) scaleX(${scaleX}) scaleY(${scaleY})`)
        .transition(swiper.params.speed);
    }
    if (params.type === 'custom' && params.renderCustom) {
      $el.html(params.renderCustom(swiper, current + 1, total));
      emit('paginationRender', $el[0]);
    } else {
      emit('paginationUpdate', $el[0]);
    }
    if (swiper.params.watchOverflow && swiper.enabled) {
      $el[swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);
    }
  }
  function render() {
    // Render Container
    const params = swiper.params.pagination;
    if (isPaginationDisabled()) return;
    const slidesLength =
      swiper.virtual && swiper.params.virtual.enabled
        ? swiper.virtual.slides.length
        : swiper.slides.length;

    const $el = swiper.pagination.$el;
    let paginationHTML = '';
    if (params.type === 'bullets') {
      let numberOfBullets = swiper.params.loop
        ? Math.ceil((slidesLength - swiper.loopedSlides * 2) / swiper.params.slidesPerGroup)
        : swiper.snapGrid.length;
      if (
        swiper.params.freeMode &&
        swiper.params.freeMode.enabled &&
        !swiper.params.loop &&
        numberOfBullets > slidesLength
      ) {
        numberOfBullets = slidesLength;
      }
      for (let i = 0; i < numberOfBullets; i += 1) {
        if (params.renderBullet) {
          paginationHTML += params.renderBullet.call(swiper, i, params.bulletClass);
        } else {
          paginationHTML += `<${params.bulletElement} class="${params.bulletClass}"></${params.bulletElement}>`;
        }
      }
      $el.html(paginationHTML);

      swiper.pagination.bullets = $el.find(classesToSelector(params.bulletClass));
    }
    if (params.type === 'fraction') {
      if (params.renderFraction) {
        paginationHTML = params.renderFraction.call(swiper, params.currentClass, params.totalClass);
      } else {
        paginationHTML =
          `<span class="${params.currentClass}"></span>` +
          ' / ' +
          `<span class="${params.totalClass}"></span>`;
      }
      $el.html(paginationHTML);
    }
    if (params.type === 'progressbar') {
      if (params.renderProgressbar) {
        paginationHTML = params.renderProgressbar.call(swiper, params.progressbarFillClass);
      } else {
        paginationHTML = `<span class="${params.progressbarFillClass}"></span>`;
      }
      $el.html(paginationHTML);
    }
    if (params.type !== 'custom') {
      emit('paginationRender', swiper.pagination.$el[0]);
    }
  }
  function init() {
    swiper.params.pagination = createElementIfNotDefined(
      swiper.$el,
      swiper.params.pagination,
      swiper.params.createElements,
      { el: 'swiper-pagination' },
    );
    const params = swiper.params.pagination;
    if (!params.el) return;

    let $el = $(params.el);
    if ($el.length === 0) return;

    if (swiper.params.uniqueNavElements && typeof params.el === 'string' && $el.length > 1) {
      $el = swiper.$el.find(params.el);
    }

    if (params.type === 'bullets' && params.clickable) {
      $el.addClass(params.clickableClass);
    }

    $el.addClass(params.modifierClass + params.type);

    if (params.type === 'bullets' && params.dynamicBullets) {
      $el.addClass(`${params.modifierClass}${params.type}-dynamic`);
      dynamicBulletIndex = 0;
      if (params.dynamicMainBullets < 1) {
        params.dynamicMainBullets = 1;
      }
    }
    if (params.type === 'progressbar' && params.progressbarOpposite) {
      $el.addClass(params.progressbarOppositeClass);
    }

    if (params.clickable) {
      $el.on('click', classesToSelector(params.bulletClass), function onClick(e) {
        e.preventDefault();
        let index = $(this).index() * swiper.params.slidesPerGroup;
        if (swiper.params.loop) index += swiper.loopedSlides;
        swiper.slideTo(index);
      });
    }

    extend(swiper.pagination, {
      $el,
      el: $el[0],
    });

    if (!swiper.enabled) {
      $el.addClass(params.lockClass);
    }
  }
  function destroy() {
    const params = swiper.params.pagination;
    if (isPaginationDisabled()) return;
    const $el = swiper.pagination.$el;

    $el.removeClass(params.hiddenClass);
    $el.removeClass(params.modifierClass + params.type);
    if (swiper.pagination.bullets) swiper.pagination.bullets.removeClass(params.bulletActiveClass);
    if (params.clickable) {
      $el.off('click', classesToSelector(params.bulletClass));
    }
  }

  on('init', () => {
    init();
    render();
    update();
  });
  on('activeIndexChange', () => {
    if (swiper.params.loop) {
      update();
    } else if (typeof swiper.snapIndex === 'undefined') {
      update();
    }
  });
  on('snapIndexChange', () => {
    if (!swiper.params.loop) {
      update();
    }
  });
  on('slidesLengthChange', () => {
    if (swiper.params.loop) {
      render();
      update();
    }
  });
  on('snapGridLengthChange', () => {
    if (!swiper.params.loop) {
      render();
      update();
    }
  });
  on('destroy', () => {
    destroy();
  });
  on('enable disable', () => {
    const { $el } = swiper.pagination;
    if ($el) {
      $el[swiper.enabled ? 'removeClass' : 'addClass'](swiper.params.pagination.lockClass);
    }
  });
  on('click', (_s, e) => {
    const targetEl = e.target;
    const { $el } = swiper.pagination;
    if (
      swiper.params.pagination.el &&
      swiper.params.pagination.hideOnClick &&
      $el.length > 0 &&
      !$(targetEl).hasClass(swiper.params.pagination.bulletClass)
    ) {
      if (
        swiper.navigation &&
        ((swiper.navigation.nextEl && targetEl === swiper.navigation.nextEl) ||
          (swiper.navigation.prevEl && targetEl === swiper.navigation.prevEl))
      )
        return;
      const isHidden = $el.hasClass(swiper.params.pagination.hiddenClass);
      if (isHidden === true) {
        emit('paginationShow');
      } else {
        emit('paginationHide');
      }
      $el.toggleClass(swiper.params.pagination.hiddenClass);
    }
  });
}
<|endoftext|>


<commit_before>require('enyo/options').accessibility = true;

var
	kind = require('enyo/kind'),
	ready = require('enyo/ready');

var
	MoonstoneExtra = require('moonstone-extra');

var
	oldSampler = require('../moonstone-samples/src/All');

// Define all of the extras samples
var samples = {
	ActivityPanelsWithVideoSample        : require('./ActivityPanelsWithVideoSample'),
	AlwaysViewingPanelsWithVideoSample   : require('./AlwaysViewingPanelsWithVideoSample'),
	HistorySample                        : require('./HistorySample'),
	PanelsVideoPlayerSample              : require('./PanelsVideoPlayerSample'),
	VideoPlayerInlineSample              : require('./VideoPlayerInlineSample'),
	VideoPlayerSample                    : require('./VideoPlayerSample')
};

// Add in all of the moonstone samples
var moonstoneSamples = {
	AccessibilitySample                  : require('../moonstone-samples/src/AccessibilitySample'),
	AccordionSample                      : require('../moonstone-samples/src/AccordionSample'),
	ActivityPanelsSample                 : require('../moonstone-samples/src/ActivityPanelsSample'),
	// ActivityPanelsWithVideoSample        : require('../moonstone-samples/src/ActivityPanelsWithVideoSample'),
	AlwaysViewingPanelsSample            : require('../moonstone-samples/src/AlwaysViewingPanelsSample'),
	// AlwaysViewingPanelsWithVideoSample   : require('../moonstone-samples/src/AlwaysViewingPanelsWithVideoSample'),
	AnimatedButtonSample                 : require('../moonstone-samples/src/AnimatedButtonSample'),
	AudioPlaybackSample                  : require('../moonstone-samples/src/AudioPlaybackSample'),
	AudioPlaybackPlaylistSupportSample   : require('../moonstone-samples/src/AudioPlaybackPlaylistSupportSample'),
	BodyTextSample                       : require('../moonstone-samples/src/BodyTextSample'),
	ButtonSample                         : require('../moonstone-samples/src/ButtonSample'),
	CalendarSample                       : require('../moonstone-samples/src/CalendarSample'),
	CheckboxItemSample                   : require('../moonstone-samples/src/CheckboxItemSample'),
	ClockSample                          : require('../moonstone-samples/src/ClockSample'),
	ContextualPopupSample                : require('../moonstone-samples/src/ContextualPopupSample'),
	DataGridListSample                   : require('../moonstone-samples/src/DataGridListSample'),
	DataListSample                       : require('../moonstone-samples/src/DataListSample'),
	DatePickerSample                     : require('../moonstone-samples/src/DatePickerSample'),
	DialogSample                         : require('../moonstone-samples/src/DialogSample'),
	DividerSample                        : require('../moonstone-samples/src/DividerSample'),
	DrawerSample                         : require('../moonstone-samples/src/DrawerSample'),
	DynamicPanelsSample                  : require('../moonstone-samples/src/DynamicPanelsSample'),
	ExpandableDataPickerSample           : require('../moonstone-samples/src/ExpandableDataPickerSample'),
	ExpandableInputSample                : require('../moonstone-samples/src/ExpandableInputSample'),
	ExpandableListItemSample             : require('../moonstone-samples/src/ExpandableListItemSample'),
	ExpandablePickerSample               : require('../moonstone-samples/src/ExpandablePickerSample'),
	ExpandableTextSample                 : require('../moonstone-samples/src/ExpandableTextSample'),
	FontSample                           : require('../moonstone-samples/src/FontSample'),
	FormCheckboxSample                   : require('../moonstone-samples/src/FormCheckboxSample'),
	HeaderSample                         : require('../moonstone-samples/src/HeaderSample'),
	HighlightTextSample                  : require('../moonstone-samples/src/HighlightTextSample'),
	// HistorySample                        : require('../moonstone-samples/src/HistorySample'),
	IconButtonSample                     : require('../moonstone-samples/src/IconButtonSample'),
	IconSample                           : require('../moonstone-samples/src/IconSample'),
	ImageBadgeSample                     : require('../moonstone-samples/src/ImageBadgeSample'),
	ImageItemSample                      : require('../moonstone-samples/src/ImageItemSample'),
	ImageSample                          : require('../moonstone-samples/src/ImageSample'),
	InputHeaderSample                    : require('../moonstone-samples/src/InputHeaderSample'),
	InputSample                          : require('../moonstone-samples/src/InputSample'),
	IntegerPickerSample                  : require('../moonstone-samples/src/IntegerPickerSample'),
	ItemSample                           : require('../moonstone-samples/src/ItemSample'),
	ItemOverlaySample                    : require('../moonstone-samples/src/ItemOverlaySample'),
	LabeledTextItemSample                : require('../moonstone-samples/src/LabeledTextItemSample'),
	LightPanelsSample                    : require('../moonstone-samples/src/LightPanelsSample'),
	ListActionsSample                    : require('../moonstone-samples/src/ListActionsSample'),
	MarqueeSample                        : require('../moonstone-samples/src/MarqueeSample'),
	NewDataListSample                    : require('../moonstone-samples/src/NewDataListSample'),
	ObjectActionHorizontalTypeSample     : require('../moonstone-samples/src/ObjectActionHorizontalTypeSample'),
	ObjectActionVerticalTypeSample       : require('../moonstone-samples/src/ObjectActionVerticalTypeSample'),
	OverlaySample                        : require('../moonstone-samples/src/OverlaySample'),
	// PanelsVideoPlayerSample              : require('../moonstone-samples/src/PanelsVideoPlayerSample'),
	PanelsWithCardArrangerSample         : require('../moonstone-samples/src/PanelsWithCardArrangerSample'),
	PanelsWithCarouselArrangerSample     : require('../moonstone-samples/src/PanelsWithCarouselArrangerSample'),
	PopupSample                          : require('../moonstone-samples/src/PopupSample'),
	ProgressButtonSample                 : require('../moonstone-samples/src/ProgressButtonSample'),
	ProgressSample                       : require('../moonstone-samples/src/ProgressSample'),
	RadioItemSample                      : require('../moonstone-samples/src/RadioItemSample'),
	Scroller2dSample                     : require('../moonstone-samples/src/Scroller2dSample'),
	ScrollerHorizontalSample             : require('../moonstone-samples/src/ScrollerHorizontalSample'),
	ScrollerTextSample                   : require('../moonstone-samples/src/ScrollerTextSample'),
	ScrollerVerticalSample               : require('../moonstone-samples/src/ScrollerVerticalSample'),
	SelectableItemSample                 : require('../moonstone-samples/src/SelectableItemSample'),
	SimpleIntegerPickerSample            : require('../moonstone-samples/src/SimpleIntegerPickerSample'),
	SimplePickerSample                   : require('../moonstone-samples/src/SimplePickerSample'),
	SliderSample                         : require('../moonstone-samples/src/SliderSample'),
	SpinnerSample                        : require('../moonstone-samples/src/SpinnerSample'),
	TableSample                          : require('../moonstone-samples/src/TableSample'),
	TimePickerSample                     : require('../moonstone-samples/src/TimePickerSample'),
	ToggleButtonSample                   : require('../moonstone-samples/src/ToggleButtonSample'),
	ToggleItemSample                     : require('../moonstone-samples/src/ToggleItemSample'),
	TooltipSample                        : require('../moonstone-samples/src/TooltipSample')
	// VideoPlayerInlineSample              : require('../moonstone-samples/src/VideoPlayerInlineSample'),
	// VideoPlayerSample                    : require('../moonstone-samples/src/VideoPlayerSample')
};

// Merge old samples with new samples
for (var s in moonstoneSamples) {
	if (!samples[s]) {
		samples[s] = moonstoneSamples[s];
	}
}

var NewSampler = kind({
	kind: oldSampler,
	title: 'Moonstone Extra Samples',
	samples: samples,
	create: kind.inherit(function (sup) {
		return function () {
			sup.apply(this, arguments);
			console.log('%cMoonstone-Extra: %s', 'color:blue', MoonstoneExtra.version);
		};
	})
});

ready(function() {
	new NewSampler().renderInto(document.body);
});
<commit_msg>ENYO-3154: enyo-strawman: moonstone-extra incorrect sample paths<commit_after>require('enyo/options').accessibility = true;

var
	kind = require('enyo/kind'),
	ready = require('enyo/ready');

var
	MoonstoneExtra = require('moonstone-extra');

var
	oldSampler = require('../moonstone-samples/src/All');

// Define all of the extras samples
var samples = {
	ActivityPanelsWithVideoSample        : require('./src/ActivityPanelsWithVideoSample'),
	AlwaysViewingPanelsWithVideoSample   : require('./src/AlwaysViewingPanelsWithVideoSample'),
	HistorySample                        : require('./src/HistorySample'),
	PanelsVideoPlayerSample              : require('./src/PanelsVideoPlayerSample'),
	VideoPlayerInlineSample              : require('./src/VideoPlayerInlineSample'),
	VideoPlayerSample                    : require('./src/VideoPlayerSample')
};

// Add in all of the moonstone samples
var moonstoneSamples = {
	AccessibilitySample                  : require('../moonstone-samples/src/AccessibilitySample'),
	AccordionSample                      : require('../moonstone-samples/src/AccordionSample'),
	ActivityPanelsSample                 : require('../moonstone-samples/src/ActivityPanelsSample'),
	// ActivityPanelsWithVideoSample        : require('../moonstone-samples/src/ActivityPanelsWithVideoSample'),
	AlwaysViewingPanelsSample            : require('../moonstone-samples/src/AlwaysViewingPanelsSample'),
	// AlwaysViewingPanelsWithVideoSample   : require('../moonstone-samples/src/AlwaysViewingPanelsWithVideoSample'),
	AnimatedButtonSample                 : require('../moonstone-samples/src/AnimatedButtonSample'),
	AudioPlaybackSample                  : require('../moonstone-samples/src/AudioPlaybackSample'),
	AudioPlaybackPlaylistSupportSample   : require('../moonstone-samples/src/AudioPlaybackPlaylistSupportSample'),
	BodyTextSample                       : require('../moonstone-samples/src/BodyTextSample'),
	ButtonSample                         : require('../moonstone-samples/src/ButtonSample'),
	CalendarSample                       : require('../moonstone-samples/src/CalendarSample'),
	CheckboxItemSample                   : require('../moonstone-samples/src/CheckboxItemSample'),
	ClockSample                          : require('../moonstone-samples/src/ClockSample'),
	ContextualPopupSample                : require('../moonstone-samples/src/ContextualPopupSample'),
	DataGridListSample                   : require('../moonstone-samples/src/DataGridListSample'),
	DataListSample                       : require('../moonstone-samples/src/DataListSample'),
	DatePickerSample                     : require('../moonstone-samples/src/DatePickerSample'),
	DialogSample                         : require('../moonstone-samples/src/DialogSample'),
	DividerSample                        : require('../moonstone-samples/src/DividerSample'),
	DrawerSample                         : require('../moonstone-samples/src/DrawerSample'),
	DynamicPanelsSample                  : require('../moonstone-samples/src/DynamicPanelsSample'),
	ExpandableDataPickerSample           : require('../moonstone-samples/src/ExpandableDataPickerSample'),
	ExpandableInputSample                : require('../moonstone-samples/src/ExpandableInputSample'),
	ExpandableListItemSample             : require('../moonstone-samples/src/ExpandableListItemSample'),
	ExpandablePickerSample               : require('../moonstone-samples/src/ExpandablePickerSample'),
	ExpandableTextSample                 : require('../moonstone-samples/src/ExpandableTextSample'),
	FontSample                           : require('../moonstone-samples/src/FontSample'),
	FormCheckboxSample                   : require('../moonstone-samples/src/FormCheckboxSample'),
	HeaderSample                         : require('../moonstone-samples/src/HeaderSample'),
	HighlightTextSample                  : require('../moonstone-samples/src/HighlightTextSample'),
	// HistorySample                        : require('../moonstone-samples/src/HistorySample'),
	IconButtonSample                     : require('../moonstone-samples/src/IconButtonSample'),
	IconSample                           : require('../moonstone-samples/src/IconSample'),
	ImageBadgeSample                     : require('../moonstone-samples/src/ImageBadgeSample'),
	ImageItemSample                      : require('../moonstone-samples/src/ImageItemSample'),
	ImageSample                          : require('../moonstone-samples/src/ImageSample'),
	InputHeaderSample                    : require('../moonstone-samples/src/InputHeaderSample'),
	InputSample                          : require('../moonstone-samples/src/InputSample'),
	IntegerPickerSample                  : require('../moonstone-samples/src/IntegerPickerSample'),
	ItemSample                           : require('../moonstone-samples/src/ItemSample'),
	ItemOverlaySample                    : require('../moonstone-samples/src/ItemOverlaySample'),
	LabeledTextItemSample                : require('../moonstone-samples/src/LabeledTextItemSample'),
	LightPanelsSample                    : require('../moonstone-samples/src/LightPanelsSample'),
	ListActionsSample                    : require('../moonstone-samples/src/ListActionsSample'),
	MarqueeSample                        : require('../moonstone-samples/src/MarqueeSample'),
	NewDataListSample                    : require('../moonstone-samples/src/NewDataListSample'),
	ObjectActionHorizontalTypeSample     : require('../moonstone-samples/src/ObjectActionHorizontalTypeSample'),
	ObjectActionVerticalTypeSample       : require('../moonstone-samples/src/ObjectActionVerticalTypeSample'),
	OverlaySample                        : require('../moonstone-samples/src/OverlaySample'),
	// PanelsVideoPlayerSample              : require('../moonstone-samples/src/PanelsVideoPlayerSample'),
	PanelsWithCardArrangerSample         : require('../moonstone-samples/src/PanelsWithCardArrangerSample'),
	PanelsWithCarouselArrangerSample     : require('../moonstone-samples/src/PanelsWithCarouselArrangerSample'),
	PopupSample                          : require('../moonstone-samples/src/PopupSample'),
	ProgressButtonSample                 : require('../moonstone-samples/src/ProgressButtonSample'),
	ProgressSample                       : require('../moonstone-samples/src/ProgressSample'),
	RadioItemSample                      : require('../moonstone-samples/src/RadioItemSample'),
	Scroller2dSample                     : require('../moonstone-samples/src/Scroller2dSample'),
	ScrollerHorizontalSample             : require('../moonstone-samples/src/ScrollerHorizontalSample'),
	ScrollerTextSample                   : require('../moonstone-samples/src/ScrollerTextSample'),
	ScrollerVerticalSample               : require('../moonstone-samples/src/ScrollerVerticalSample'),
	SelectableItemSample                 : require('../moonstone-samples/src/SelectableItemSample'),
	SimpleIntegerPickerSample            : require('../moonstone-samples/src/SimpleIntegerPickerSample'),
	SimplePickerSample                   : require('../moonstone-samples/src/SimplePickerSample'),
	SliderSample                         : require('../moonstone-samples/src/SliderSample'),
	SpinnerSample                        : require('../moonstone-samples/src/SpinnerSample'),
	TableSample                          : require('../moonstone-samples/src/TableSample'),
	TimePickerSample                     : require('../moonstone-samples/src/TimePickerSample'),
	ToggleButtonSample                   : require('../moonstone-samples/src/ToggleButtonSample'),
	ToggleItemSample                     : require('../moonstone-samples/src/ToggleItemSample'),
	TooltipSample                        : require('../moonstone-samples/src/TooltipSample')
	// VideoPlayerInlineSample              : require('../moonstone-samples/src/VideoPlayerInlineSample'),
	// VideoPlayerSample                    : require('../moonstone-samples/src/VideoPlayerSample')
};

// Merge old samples with new samples
for (var s in moonstoneSamples) {
	if (!samples[s]) {
		samples[s] = moonstoneSamples[s];
	}
}

var NewSampler = kind({
	kind: oldSampler,
	title: 'Moonstone Extra Samples',
	samples: samples,
	create: kind.inherit(function (sup) {
		return function () {
			sup.apply(this, arguments);
			console.log('%cMoonstone-Extra: %s', 'color:blue', MoonstoneExtra.version);
		};
	})
});

ready(function() {
	new NewSampler().renderInto(document.body);
});
<|endoftext|>


<commit_before>var assert = require('assert');

exports.run_replica = function(conf) {
  return exports.init_replica(conf).go('warming');
}

exports.init_replica = function(conf) {
  var log_db = null;

  var time_start = new Date();
  var data_dir  = conf.get('data_dir');
  var seeds     = conf.get('seeds');
  var name      = conf.get('name');

  console.info('replicake...')
  console.info('  time_start: ' + time_start.toJSON());
  console.info('  data_dir: ' + data_dir);
  console.info('  seeds: ' + seeds);
  console.info('  name: ' + name);

  var state = { curr: 'initial' };

  on_transition(state, 'initial', 'warming',
                function() {
                  log_db_load(data_dir, name, conf.get('log_db'),
                              function(err, log_db_in) {
                                assert(log_db == null, 'log_db should be null')
                                  log_db = log_db_in;
                                go(state, 'running');
                              });
                });

  on_transition(state, 'warming', 'running',
                function() {
                  assert(log_db);
                  // Concurrently...
                  // -- find and/or help choose leader
                  // -- start paxos participation / log replica
                  // -- continually catchup on log holes
                  // -- help others catchup on log holes
                  // -- take local snapshots
                  // -- garbage collect old log entries
                  // -- handle configuration changes
                });

  on_transition(state, 'warming', 'cooling', cool);
  on_transition(state, 'running', 'cooling', cool);
  on_transition(state, 'cooling', 'stopped', function() {});

  function cool() {
    log_db_save(log_db, function() {
                  go(state, 'stopped');
                });
  }

  var self = {
    'go': function(to_state) { go(state, to_state); return self; }
  };

  return self;
};

// Log DB helpers.

function log_db_load(data_dir, name, log_db, cb) {
  cb(false, {});
}

function log_db_save(log_db, cb) {
  cb();
}

// State machine helpers.

function on_transition(state, from_state, to_state, cb) {
  state.transitions = state.transitions || {};
  assert(state.transitions[from_state + ' => ' + to_state] == null);
  state.transitions[from_state + ' => ' + to_state] = cb;
}

function go(state, to_state) {
  state.hist = state.hist || [];
  assert(state.curr);
  var transition = state.curr + ' => ' + to_state;
  console.info('transition: ' + transition);
  assert(state.transitions[transition]);
  state.hist[state.hist.length] = (new Date().toJSON()) + ': ' + transition;
  state.curr = to_state;
  state.transitions[transition]();
}
<commit_msg>Check replicake name config.<commit_after>var assert = require('assert');

exports.run_replica = function(conf) {
  return exports.init_replica(conf).go('warming');
}

exports.init_replica = function(conf) {
  var log_db = null;

  var time_start = new Date();
  var data_dir  = conf.get('data_dir');
  var seeds     = conf.get('seeds');
  var name      = conf.get('name');

  console.info('replicake...')
  console.info('  time_start: ' + time_start.toJSON());
  console.info('  data_dir: ' + data_dir);
  console.info('  seeds: ' + seeds);
  console.info('  name: ' + name);

  if (name == null || name.toString().length <= 0) {
    console.error("ERROR: missing name for replicake configuration.");
    return null;
  }

  var state = { curr: 'initial' };

  on_transition(state, 'initial', 'warming',
                function() {
                  log_db_load(data_dir, name, conf.get('log_db'),
                              function(err, log_db_in) {
                                assert(log_db == null, 'log_db should be null')
                                  log_db = log_db_in;
                                go(state, 'running');
                              });
                });

  on_transition(state, 'warming', 'running',
                function() {
                  assert(log_db);
                  // Concurrently...
                  // -- find and/or help choose leader
                  // -- start paxos participation / log replica
                  // -- continually catchup on log holes
                  // -- help others catchup on log holes
                  // -- take local snapshots
                  // -- garbage collect old log entries
                  // -- handle configuration changes
                });

  on_transition(state, 'warming', 'cooling', cool);
  on_transition(state, 'running', 'cooling', cool);
  on_transition(state, 'cooling', 'stopped', function() {});

  function cool() {
    log_db_save(log_db, function() {
                  go(state, 'stopped');
                });
  }

  var self = {
    'go': function(to_state) { go(state, to_state); return self; }
  };

  return self;
};

// Log DB helpers.

function log_db_load(data_dir, name, log_db_conf, cb) {
  var log_db = { data_dir: data_dir,
                 name: name }
  cb(false, log_db);
}

function log_db_save(log_db, cb) {
  cb();
}

// State machine helpers.

function on_transition(state, from_state, to_state, cb) {
  state.transitions = state.transitions || {};
  assert(state.transitions[from_state + ' => ' + to_state] == null);
  state.transitions[from_state + ' => ' + to_state] = cb;
}

function go(state, to_state) {
  state.hist = state.hist || [];
  assert(state.curr);
  var transition = state.curr + ' => ' + to_state;
  console.info('transition: ' + transition);
  assert(state.transitions[transition]);
  state.hist[state.hist.length] = (new Date().toJSON()) + ': ' + transition;
  state.curr = to_state;
  state.transitions[transition]();
}
<|endoftext|>