<commit_before>class MahjongTilePicker {
    private tile: Tile;
    private parentElem: HTMLElement;
    private containerElem: HTMLDivElement;
    private previewElem: HTMLImageElement;
    private buttonText: string;
    private lightbox: MahjongTilePickerLightbox;
    
    constructor(elementId: string, buttonText="Pick a tile") {
        this.parentElem = document.getElementById(elementId);
        this.buttonText = buttonText;
        this.init();
    }
    
    pickTile(tile: Tile): void {
        this.tile = tile;
        this.updatePreview();
        this.onTilePicked(tile);
    }
    
    getTile(): Tile {
        return this.tile;
    }
    
    /**
     * This method is meant to be overwritten on instance-by-instance basis
     */
    onTilePicked(tile: Tile): any {
        console.log(Tile[tile] + " got picked.");
    }
    
    private init(): void {
        this.tile = null;
        this.lightbox = MahjongTilePickerLightbox.getInstance();
        this.initDomElements();
        this.initBindings();
    }
    
    private initDomElements(): void {
        this.containerElem = document.createElement("div");
        this.containerElem.className = "mahjong-tile-picker";
        
        this.initPreviewElem();
        
        this.parentElem.appendChild(this.containerElem);
    }
    
    private initPreviewElem(): void {
        this.previewElem = document.createElement("img");
        this.previewElem.setAttribute("src", MahjongTilePickerHelper.getImagePath(null));
        this.containerElem.appendChild(this.previewElem);
    }
    
    private initBindings(): void {
        this.previewElem.onclick = () => {
            this.lightbox.showForPicker(this);
        }
    }
    
    private updatePreview(): void {
        var imagePath = MahjongTilePickerHelper.getImagePath(this.tile);
        this.previewElem.setAttribute("src", imagePath);
    }
}

/**
 * A singleton class that hosts the lightbox part of the picker that is shared
 * across all the pickers on the same page
 */
class MahjongTilePickerLightbox {
    private static instance: MahjongTilePickerLightbox;
    private tileElems: HTMLImageElement[];
    private boxElem: HTMLDivElement;
    private backgroundElem: HTMLDivElement;
    private selectedPicker: MahjongTilePicker;
    
    /**
     * Call this method instead of the constructor.
     */
    static getInstance(): MahjongTilePickerLightbox {
        if (this.instance == undefined) {
            this.instance = new MahjongTilePickerLightbox();
        }
        return this.instance;
    }
    
    showForPicker(picker: MahjongTilePicker): void {
        this.selectedPicker = picker;
        this.show();
    }
    
    /**
     * Do not call this. Use getInstance() instead.
     */
    constructor() {
        this.initBackgroundElem();
        this.initBoxElem();
        this.initBindings();
    }
    
    private initBackgroundElem(): void {
        this.backgroundElem = document.createElement("div");
        this.backgroundElem.className = "mahjong-tile-picker-lightbox-background";
        this.backgroundElem.setAttribute("max-opacity", "0.7");
        document.getElementsByTagName("body")[0].appendChild(this.backgroundElem);
    }
    
    private initBoxElem(): void {
        this.boxElem = document.createElement("div");
        this.boxElem.className = "mahjong-tile-picker-lightbox";
        this.boxElem.setAttribute("max-opacity", "1");
        this.initTileElems();
        document.getElementsByTagName("body")[0].appendChild(this.boxElem);
    }
    
    private initTileElems(): void {
        this.tileElems = [];
        ["W", "T", "S"].forEach((suit, index, suits) => {
            for (var i = 1; i <= 9; i++) {
                this.initTileElem("tile-" + suit, suit + i);
                if (i == 5) {
                    this.initTileElem("tile-" + suit, suit + i + "_red");
                }
            }
        });
        for (var i = Tile.East; i <= Tile.Red; i++) {
            this.initTileElem("tile-Winds", Tile[i]);
        }
    }
    
    private initTileElem(className: string, tileName: string): void {
        var tileElem = document.createElement("img");
        tileElem.className = "mahjong-tile " + className;
        tileElem.id = tileName;
        tileElem.setAttribute("src", MahjongTilePickerHelper.getImagePath(Tile[tileName]));
        this.boxElem.appendChild(tileElem);
        this.tileElems.push(tileElem);
    }
    
    private initBindings(): void {
        this.tileElems.forEach((tileElem, index, elems) => {
            tileElem.onclick = () => {
                this.selectedPicker.pickTile(Tile[tileElem.id]);
                this.selectedPicker = null;
                this.hide();
            }
        });
        this.backgroundElem.onclick = () => {
            this.selectedPicker = null;
            this.hide();
        }
    }
    
    private show(): void {
        fadeIn(this.boxElem);
        fadeIn(this.backgroundElem);
    }
    
    private hide(): void {
        fadeOut(this.boxElem);
        fadeOut(this.backgroundElem);
    }
}<commit_msg>Add the null tile for selection<commit_after>class MahjongTilePicker {
    private tile: Tile;
    private parentElem: HTMLElement;
    private containerElem: HTMLDivElement;
    private previewElem: HTMLImageElement;
    private buttonText: string;
    private lightbox: MahjongTilePickerLightbox;
    
    constructor(elementId: string, buttonText="Pick a tile") {
        this.parentElem = document.getElementById(elementId);
        this.buttonText = buttonText;
        this.init();
    }
    
    pickTile(tile: Tile): void {
        this.tile = tile;
        this.updatePreview();
        this.onTilePicked(tile);
    }
    
    getTile(): Tile {
        return this.tile;
    }
    
    /**
     * This method is meant to be overwritten on instance-by-instance basis
     */
    onTilePicked(tile: Tile): any {
        console.log(Tile[tile] + " got picked.");
    }
    
    private init(): void {
        this.tile = null;
        this.lightbox = MahjongTilePickerLightbox.getInstance();
        this.initDomElements();
        this.initBindings();
    }
    
    private initDomElements(): void {
        this.containerElem = document.createElement("div");
        this.containerElem.className = "mahjong-tile-picker";
        
        this.initPreviewElem();
        
        this.parentElem.appendChild(this.containerElem);
    }
    
    private initPreviewElem(): void {
        this.previewElem = document.createElement("img");
        this.previewElem.className = "mahjong-tile-picker-preview";
        this.previewElem.setAttribute("src", MahjongTilePickerHelper.getImagePath(null));
        this.containerElem.appendChild(this.previewElem);
    }
    
    private initBindings(): void {
        this.previewElem.onclick = () => {
            this.lightbox.showForPicker(this);
        }
    }
    
    private updatePreview(): void {
        var imagePath = MahjongTilePickerHelper.getImagePath(this.tile);
        this.previewElem.setAttribute("src", imagePath);
    }
}

/**
 * A singleton class that hosts the lightbox part of the picker that is shared
 * across all the pickers on the same page
 */
class MahjongTilePickerLightbox {
    private static instance: MahjongTilePickerLightbox;
    private tileElems: HTMLImageElement[];
    private boxElem: HTMLDivElement;
    private backgroundElem: HTMLDivElement;
    private selectedPicker: MahjongTilePicker;
    
    /**
     * Call this method instead of the constructor.
     */
    static getInstance(): MahjongTilePickerLightbox {
        if (this.instance == undefined) {
            this.instance = new MahjongTilePickerLightbox();
        }
        return this.instance;
    }
    
    showForPicker(picker: MahjongTilePicker): void {
        this.selectedPicker = picker;
        this.show();
    }
    
    /**
     * Do not call this. Use getInstance() instead.
     */
    constructor() {
        this.initBackgroundElem();
        this.initBoxElem();
        this.initBindings();
    }
    
    private initBackgroundElem(): void {
        this.backgroundElem = document.createElement("div");
        this.backgroundElem.className = "mahjong-tile-picker-lightbox-background";
        this.backgroundElem.setAttribute("max-opacity", "0.7");
        document.getElementsByTagName("body")[0].appendChild(this.backgroundElem);
    }
    
    private initBoxElem(): void {
        this.boxElem = document.createElement("div");
        this.boxElem.className = "mahjong-tile-picker-lightbox";
        this.boxElem.setAttribute("max-opacity", "1");
        this.initTileElems();
        document.getElementsByTagName("body")[0].appendChild(this.boxElem);
    }
    
    private initTileElems(): void {
        this.tileElems = [];
        ["W", "T", "S"].forEach((suit, index, suits) => {
            for (var i = 1; i <= 9; i++) {
                this.initTileElem("tile-" + suit, suit + i);
                if (i == 5) {
                    this.initTileElem("tile-" + suit, suit + i + "_red");
                }
            }
        });
        for (var i = Tile.East; i <= Tile.Red; i++) {
            this.initTileElem("tile-Winds", Tile[i]);
        }
        this.initTileElem("tile-Back", "Back");
    }
    
    private initTileElem(className: string, tileName: string): void {
        var tileElem = document.createElement("img");
        tileElem.className = "mahjong-tile " + className;
        tileElem.id = tileName;
        tileElem.setAttribute("src", MahjongTilePickerHelper.getImagePath(Tile[tileName]));
        this.boxElem.appendChild(tileElem);
        this.tileElems.push(tileElem);
    }
    
    private initBindings(): void {
        this.tileElems.forEach((tileElem, index, elems) => {
            tileElem.onclick = () => {
                if (tileElem.id == "Back") {
                    var tile = null;
                } else {
                    var tile = Tile[tileElem.id];
                }
                this.selectedPicker.pickTile(tile);
                this.selectedPicker = null;
                this.hide();
            }
        });
        this.backgroundElem.onclick = () => {
            this.selectedPicker = null;
            this.hide();
        }
    }
    
    private show(): void {
        fadeIn(this.boxElem);
        fadeIn(this.backgroundElem);
    }
    
    private hide(): void {
        fadeOut(this.boxElem);
        fadeOut(this.backgroundElem);
    }
}
{'fraction_non_alphanumeric': 0.1203580270424681, 'fraction_numerical': 0.001523519329651495, 'mean_word_length': 2.2021341463414634, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2094148', 'n_tokens_mistral': 2995, 'n_tokens_neox': 2958, 'n_words': 563}