@steinv/filippine
Version:
Filippine - acrostic word puzzle with Angular
278 lines (267 loc) • 13.1 kB
JavaScript
(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