UNPKG

@steinv/filippine

Version:

Filippine - acrostic word puzzle with Angular

278 lines (267 loc) 13.1 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/forms'), require('@angular/common')) : typeof define === 'function' && define.amd ? define('@steinv/filippine', ['exports', '@angular/core', '@angular/forms', '@angular/common'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.steinv = global.steinv || {}, global.steinv.filippine = {}), global.ng.core, global.ng.forms, global.ng.common)); }(this, (function (exports, core, forms, common) { 'use strict'; var FilippineComponent = /** @class */ (function () { function FilippineComponent(_changeDetectorRef) { this._changeDetectorRef = _changeDetectorRef; this.answer = new core.EventEmitter(); /** * Emits when the form has been completed * returns false when answered wrongly, true when correctly answered */ this.completed = new core.EventEmitter(); this.filippineForm = new forms.FormGroup({}); this.columns = 1; this.tiles = []; } FilippineComponent.prototype.ngOnInit = function () { var _this = this; /** * Calculate how big the grid should be */ var left = this.configuration.questions.reduce(function (acc, q) { return acc = acc > q.answerPosition ? acc : q.answerPosition; }, 0); var right = this.configuration.questions.reduce(function (acc, q) { return acc = acc > q.answerLength - q.answerPosition ? acc : q.answerLength - q.answerPosition; }, 0); this.columns = left + right; /** * map the configuration to the tiles on the grid * Creates a filippineForm that can validate each question */ var inputFieldCounter = 0; this.configuration.questions.map(function (m, i) { var blankCellsLeft = left - m.answerPosition; var blankCellsRight = _this.columns - (m.answerLength + blankCellsLeft); var inputCells = m.answerLength; _this.tiles.push(new Array()); if (blankCellsLeft > 0) { _this.tiles[i].push({ colspan: blankCellsLeft, question: false, highlight: false }); } var formQuestion = new forms.FormGroup({}, _this.rightAnswer(m)); for (var index = 0; index < inputCells; index++) { _this.tiles[i].push({ index: inputFieldCounter, highlight: (index === m.answerPosition), colspan: 1, question: true, name: index, coordinates: i.toString() + ',' + (index + blankCellsLeft).toString() // coorindates row, column }); inputFieldCounter++; formQuestion.addControl(index.toString(), new forms.FormControl('')); // m.answer.charAt(index) } _this.filippineForm.addControl(i.toString(), formQuestion); if (blankCellsRight > 0) { _this.tiles[i].push({ colspan: blankCellsRight, question: false, highlight: false }); } _this.filippineForm.valueChanges.subscribe(function () { for (var group in _this.filippineForm.controls) { var controlGroup = _this.filippineForm.get(group); for (var field in controlGroup.controls) { var inputField = controlGroup.get(field); if (!inputField || !inputField.value) { return; } } } _this.completed.emit(_this.filippineForm.valid); }); }); }; FilippineComponent.prototype.rightAnswer = function (question) { var _this = this; return function (c) { var formGroup = c; var invalid = false; var reply = ''; for (var field in formGroup.controls) { var control = formGroup.get(field); // only validate answer when entire group is filled if (!control || !control.value) { return null; } // concat control value upon reply string reply += control.value; // validate response if (question.answer && question.answer.length >= +field && control.value.toUpperCase() !== question.answer.charAt(+field).toUpperCase()) { invalid = true; } } // emit answer that client entered if (reply) { _this.answer.emit({ question: question, answer: reply, }); } return invalid ? { invalid: true } : null; }; }; FilippineComponent.prototype.ngAfterViewInit = function () { this._changeDetectorRef.detectChanges(); }; return FilippineComponent; }()); FilippineComponent.decorators = [ { type: core.Component, args: [{ selector: 'filippine', template: "\n<form [formGroup]=\"filippineForm\">\n <grid-list \n *ngFor=\"let row of tiles; let i = index\" \n [cols]=\"columns\" \n gutterSize=\"0\"\n [formGroupName]=\"i\"\n >\n <grid-tile \n *ngFor=\"let tile of row\"\n [colspan]=\"tile.colspan\"\n [ngClass]=\"{'input': tile.question, 'spacer': !tile.question, '': true, 'highlight': tile.highlight}\">\n <input \n *ngIf=\"tile.question === true\" \n AutoTab \n [id]=\"tile.coordinates\" \n [name]=\"tile.index\" \n type=\"text\" \n maxlength=\"1\" \n [formControlName]=\"tile.name\" \n />\n </grid-tile>\n </grid-list>\n</form>", changeDetection: core.ChangeDetectionStrategy.OnPush, styles: ["grid-tile{border:1px solid #000;box-shadow:0 0 0 1px #000;display:flex;position:relative}grid-tile input{background:transparent;border:none;height:0;margin:0;outline:none;padding:50% 0;text-align:center;text-transform:uppercase;width:100%}.spacer{background-color:#000}.input{background-color:#fff;border:1px solid #000;box-shadow:0 0 0 1px #000}.highlight{background-color:#ff0}grid-list.ng-invalid .input{border-color:red;box-shadow:0 0 0 1px red;z-index:1}"] },] } ]; FilippineComponent.ctorParameters = function () { return [ { type: core.ChangeDetectorRef } ]; }; FilippineComponent.propDecorators = { configuration: [{ type: core.Input }], answer: [{ type: core.Output }], completed: [{ type: core.Output }] }; var GridTileComponent = /** @class */ (function () { function GridTileComponent(_elementRef) { this._elementRef = _elementRef; this.colspan = 1; this._width = '100%'; } Object.defineProperty(GridTileComponent.prototype, "width", { set: function (width) { this._width = width; }, enumerable: false, configurable: true }); GridTileComponent.prototype.ngAfterContentInit = function () { var element = this._elementRef.nativeElement; }; return GridTileComponent; }()); GridTileComponent.decorators = [ { type: core.Component, args: [{ selector: 'grid-tile', template: "<ng-content></ng-content>", changeDetection: core.ChangeDetectionStrategy.OnPush, styles: [":host{box-sizing:border-box}"] },] } ]; GridTileComponent.ctorParameters = function () { return [ { type: core.ElementRef } ]; }; GridTileComponent.propDecorators = { colspan: [{ type: core.Input }], _width: [{ type: core.HostBinding, args: ['style.width',] }] }; var GridListComponent = /** @class */ (function () { function GridListComponent() { } GridListComponent.prototype.ngAfterContentInit = function () { var _this = this; this.tiles.map(function (tile) { tile.width = ((tile.colspan * 100) / _this.cols).toString() + '%'; }); }; return GridListComponent; }()); GridListComponent.decorators = [ { type: core.Component, args: [{ selector: 'grid-list', template: "<ng-content [select]=\"tiles\"></ng-content>\n", changeDetection: core.ChangeDetectionStrategy.OnPush, styles: [":host{display:flex;width:100%}"] },] } ]; GridListComponent.ctorParameters = function () { return []; }; GridListComponent.propDecorators = { cols: [{ type: core.Input }], tiles: [{ type: core.ContentChildren, args: [GridTileComponent,] }] }; var AutoTabDirective = /** @class */ (function () { function AutoTabDirective() { } AutoTabDirective.prototype.onKeyUp = function (event) { var input = event.target; if (!input.id || event.key === 'Tab' || event.key === 'Shift') { return; } var length = input.value.length; var index = +input.name; var position = input.id.split(','); var elementByCoordinates = position; var elementByName = index; if ((length === 1 || event.key === 'ArrowRight') && input.id) { elementByCoordinates = position[0] + ',' + (+position[1] + 1); elementByName = index + 1; } if ((event.key === 'Backspace' || event.key === 'ArrowLeft') && input.id) { elementByCoordinates = position[0] + ',' + (+position[1] - 1); elementByName = index - 1; } if ((event.key === 'ArrowUp') && input.id) { elementByCoordinates = (+position[0] - 1) + ',' + position[1]; elementByName = index - 1; } if ((event.key === 'ArrowDown') && input.id) { elementByCoordinates = (+position[0] + 1) + ',' + position[1]; elementByName = index + 1; } var field = document.getElementById(elementByCoordinates); if (field) { field.focus(); field.setSelectionRange(0, 1); return; } else { var fields = document.getElementsByName(elementByName.toString()); if (fields && fields.item(0)) { var inputField = fields.item(0); inputField.focus(); inputField.setSelectionRange(0, 1); } } }; return AutoTabDirective; }()); AutoTabDirective.decorators = [ { type: core.Directive, args: [{ selector: '[AutoTab]', },] } ]; AutoTabDirective.ctorParameters = function () { return []; }; AutoTabDirective.propDecorators = { onKeyUp: [{ type: core.HostListener, args: ['keyup', ['$event'],] }] }; var FilippineModule = /** @class */ (function () { function FilippineModule() { } return FilippineModule; }()); FilippineModule.decorators = [ { type: core.NgModule, args: [{ declarations: [ AutoTabDirective, FilippineComponent, GridListComponent, GridTileComponent ], imports: [ common.CommonModule, forms.FormsModule, forms.ReactiveFormsModule, ], exports: [FilippineComponent] },] } ]; /* * Public API Surface of filippine */ /** * Generated bundle index. Do not edit. */ exports.FilippineComponent = FilippineComponent; exports.FilippineModule = FilippineModule; exports.ɵa = AutoTabDirective; exports.ɵb = GridListComponent; exports.ɵc = GridTileComponent; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=steinv-filippine.umd.js.map