+ adjustHeight: function(elt) {
+ // https://stackoverflow.com/a/48460773
+ let t = document.querySelector("." + elt + "-edit");
+ t.style.height = "";
+ t.style.height = (t.scrollHeight + 3) + "px";
+ },
+ setVname: function(prob) {
+ prob.vname = this.st.variants.find(v => v.id == prob.vid).name;
+ },
+ // Add vname and user names:
+ decorate: function(problems, callback) {
+ if (this.st.variants.length > 0)
+ problems.forEach(p => this.setVname(p));
+ // Retrieve all problems' authors' names
+ let names = {};
+ problems.forEach(p => {
+ if (p.uid != this.st.user.id) names[p.uid] = "";
+ else p.uname = this.st.user.name;
+ });
+ if (Object.keys(names).length > 0) {
+ ajax(
+ "/users",
+ "GET",
+ {
+ data: { ids: Object.keys(names).join(",") },
+ success: (res2) => {
+ res2.users.forEach(u => {
+ names[u.id] = u.name;
+ });
+ problems.forEach(p => {
+ if (!p.uname)
+ p.uname = names[p.uid];
+ });
+ if (!!callback) callback();
+ }
+ }
+ );
+ } else if (!!callback) callback();
+ },
+ firstChars: function(text) {
+ let preparedText = text
+ // Replace line jumps and <br> by spaces
+ .replace(/\n/g, " ")
+ .replace(/<br\/?>/g, " ")
+ .replace(/<[^>]+>/g, "") //remove remaining HTML tags
+ .replace(/[ ]+/g, " ") //remove series of spaces by only one
+ .trim();
+ const maxLength = 32; //arbitrary...
+ if (preparedText.length > maxLength)
+ return preparedText.substr(0, 32) + "...";
+ return preparedText;
+ },
+ copyProblem: function(p1, p2) {
+ for (let key in p1) p2[key] = p1[key];
+ },
+ setHrefPid: function(p) {
+ // Change href => $route changes, watcher notices, call showProblem
+ const curHref = document.location.href;
+ document.location.href = curHref.split("?")[0] + "?id=" + p.id;
+ },
+ backToList: function() {
+ // Change href => $route change, watcher notices, reset showOne to false
+ document.location.href = document.location.href.split("?")[0];
+ },
+ resetCurProb: function() {
+ this.curproblem.id = 0;
+ this.curproblem.uid = 0;
+ this.curproblem.vid = "";
+ this.curproblem.vname = "";
+ this.curproblem.fen = "";
+ this.curproblem.diag = "";
+ this.curproblem.instruction = "";
+ this.curproblem.solution = "";
+ this.curproblem.showSolution = false;
+ },
+ parseHtml: function(txt) {
+ return !txt.match(/<[/a-zA-Z]+>/)
+ ?
+ // No HTML tag
+ txt.replace(/\n\n/g, "<br/><div class='br'></div>")
+ .replace(/\n/g, "<br/>")
+ : txt;
+ },
+ changeVariant: function(prob) {
+ this.setVname(prob);
+ this.loadVariant(prob.vid, () => {
+ // Set FEN if possible (might not be correct yet)
+ if (V.IsGoodFen(prob.fen)) this.setDiagram(prob);
+ else prob.diag = "";
+ });
+ },
+ loadVariant: async function(vid, cb) {
+ // Condition: vid is a valid variant ID
+ this.loadedVar = 0;
+ const variant = this.st.variants.find(v => v.id == vid);
+ await import("@/variants/" + variant.name + ".js")
+ .then((vModule) => {
+ window.V = vModule[variant.name + "Rules"];
+ this.loadedVar = vid;
+ cb();
+ });
+ // (AJAX) Request to get rules content (plain text, HTML)
+ this.rulesContent =
+ require(
+ "raw-loader!@/translations/rules/" +
+ variant.name + "/" +
+ this.st.lang + ".pug"
+ )
+ // Next two lines fix a weird issue after last update (2019-11)
+ .replace(/\\n/g, " ")
+ .replace(/\\"/g, '"')
+ .replace('module.exports = "', "")
+ .replace(/"$/, "")
+ .replace(/(fen:)([^:]*):/g, replaceByDiag);
+ },
+ trySetDiagram: function(prob) {
+ // Problem edit: FEN could be wrong or incomplete,
+ // variant could not be ready, or not defined
+ if (prob.vid > 0 && this.loadedVar == prob.vid && V.IsGoodFen(prob.fen))
+ this.setDiagram(prob);
+ else prob.diag = "";
+ },
+ setDiagram: function(prob) {
+ // Condition: prob.fen is correct and global V is ready
+ const parsedFen = V.ParseFen(prob.fen);
+ const args = {
+ position: parsedFen.position,
+ orientation: parsedFen.turn
+ };
+ prob.diag = getDiagram(args);
+ },
+ showProblem: function(p_id) {
+ const processWhenWeHaveProb = () => {
+ this.loadVariant(p.vid, () => {
+ this.onlyMine = (p.uid == this.st.user.id);
+ // The FEN is already checked at this stage:
+ this.game.vname = p.vname;
+ this.game.mycolor = V.ParseFen(p.fen).turn; //diagram orientation
+ this.game.fenStart = p.fen;
+ this.game.fen = p.fen;
+ this.showOne = true;
+ // $nextTick to be sure $refs["basegame"] exists
+ this.$nextTick(() => {
+ this.$refs["basegame"].re_setVariables(this.game); });
+ this.curproblem.showSolution = false; //in case of
+ this.copyProblem(p, this.curproblem);
+ });
+ };
+ let p = undefined;
+ if (typeof p_id == "object") p = p_id;
+ else {
+ const problems = this.problems["others"].concat(this.problems["mine"]);
+ p = problems.find(prob => prob.id == p_id);
+ }
+ if (!p) {
+ // Bad luck: problem not in list. Get from server
+ ajax(
+ "/problems",
+ "GET",
+ {
+ data: { id: p_id },
+ success: (res) => {
+ this.decorate([res.problem], () => {
+ p = res.problem;
+ const mode = (p.uid == this.st.user.id ? "mine" : "others");
+ this.problems[mode].push(p);
+ processWhenWeHaveProb();
+ });
+ }
+ }
+ );
+ } else processWhenWeHaveProb();
+ },
+ gotoPrevNext: function(prob, dir) {
+ const mode = (this.onlyMine ? "mine" : "others");
+ const problems = this.problems[mode];
+ const startIdx = problems.findIndex(p => p.id == prob.id);
+ const nextIdx = startIdx + dir;
+ if (nextIdx >= 0 && nextIdx < problems.length)
+ this.setHrefPid(problems[nextIdx]);
+ else if (this.hasMore[mode]) {
+ this.loadMore(
+ mode,
+ (nbProbs) => {
+ if (nbProbs > 0) this.gotoPrevNext(prob, dir);
+ else alert(this.st.tr["No more problems"]);
+ }
+ );
+ }
+ else alert(this.st.tr["No more problems"]);
+ },
+ prepareNewProblem: function() {
+ this.resetCurProb();
+ this.adjustHeight("instructions");
+ this.adjustHeight("solution");
+ window.doClick("modalNewprob");
+ },
+ sendProblem: function() {
+ const error = checkProblem(this.curproblem);
+ if (error) {
+ alert(this.st.tr[error]);