PageSourceSearch

https://j.gamersky.com/web2015/v2/common/version-switch.js

js gamersky.com collected 2026-09-24 18:32:59 UTC 25,242 bytes, 618 lines download raw bytes

1(function () {
2    "use strict";
3
4    var COOKIE = {
5        preference: "gamersky_pc_home_version",
6        oldInviteSeen: "gamersky_pc_old_invite_seen",
7        newReturnTipSeen: "gamersky_pc_new_return_tip_seen",
8        surveySeen: "gamersky_pc_new_return_survey_seen"
9    };
10    var COOKIE_MAX_AGE = 60 * 60 * 24 * 365 * 10;
11    var STATISTICS = {
12        oldInviteShown: 2185951,
13        oldInviteExperience: 2185953,
14        newReturnSurveyShown: 2185954
15    };
16    var SURVEY = {
17        id: 738,
18        serviceUrl: "//router3.gamersky.com/@wenJuan"
19    };
20    var reportedStatistics = {};
21    var statisticSequence = 0;
22    var isNewHome = document.documentElement.getAttribute("data-home-version") === "new";
23
24    function getCookie(name) {
25        var match = document.cookie.match(new RegExp("(?:^|;\\s*)" + name.replace(/[.*+?^${}()|[\]\\\\]/g, "\\$&") + "=([^;]*)"));
26        return match ? decodeURIComponent(match[1]) : "";
27    }
28
29    function setCookie(name, value) {
30        document.cookie = name + "=" + encodeURIComponent(value) + "; path=/; max-age=" + COOKIE_MAX_AGE + "; samesite=lax";
31    }
32
33    function getRoute(version) {
34        if (window.location.hostname === "www.gamersky.com") {
35            return version === "new" ? "https://www.gamersky.com/indexbeta/" : "https://www.gamersky.com/";
36        }
37        return version === "new" ? "../新版首页/" : "../旧版首页/";
38    }
39
40    // 旧首页以同步脚本加载时,先于页面主体解析完成版本跳转,避免旧首页闪现。
41    if (!isNewHome && getCookie(COOKIE.preference) === "new") {
42        window.location.replace(getRoute("new"));
43        return;
44    }
45
46    function chooseVersion(version) {
47        setCookie(COOKIE.preference, version);
48        window.location.assign(getRoute(version));
49    }
50
51    // 使用站点统一 JSONP 统计接口,避免跨域限制;同一页面内同一事件只上报一次。
52    function reportStatistic(id, callback) {
53        var callbackName;
54        var script;
55        var timeout;
56        var completed = false;
57
58        function complete() {
59            if (completed) {
60                return;
61            }
62            completed = true;
63            if (timeout) {
64                window.clearTimeout(timeout);
65            }
66            if (script && script.parentNode) {
67                script.parentNode.removeChild(script);
68            }
69            try {
70                delete window[callbackName];
71            } catch (error) {
72                window[callbackName] = undefined;
73            }
74            if (typeof callback === "function") {
75                callback();
76            }
77        }
78
79        if (!id || reportedStatistics[id]) {
80            if (typeof callback === "function") {
81                callback();
82            }
83            return;
84        }
85
86        reportedStatistics[id] = true;
87        callbackName = "gsVersionStatistic_" + new Date().getTime() + "_" + statisticSequence;
88        statisticSequence += 1;
89        script = document.createElement("script");
90        script.async = true;
91        window[callbackName] = complete;
92        script.onload = complete;
93        script.onerror = complete;
94        script.src = "//click.gamersky.com/Common/GetHits.aspx?callback=" + encodeURIComponent(callbackName) + "&id=" + encodeURIComponent(id) + "&script=3&_=" + new Date().getTime();
95        timeout = window.setTimeout(complete, 800);
96        (document.head || document.body).appendChild(script);
97    }
98
99    function closeOverlay(overlay) {
100        overlay.hidden = true;
101        document.body.classList.remove("gs-version-overlay-open");
102        document.documentElement.classList.remove("gs-version-overlay-open");
103        var trigger = overlay._trigger;
104        if (trigger && typeof trigger.focus === "function") {
105            trigger.focus();
106        }
107    }
108
109    function openOverlay(overlay, trigger) {
110        overlay._trigger = trigger || null;
111        overlay.hidden = false;
112        document.body.classList.add("gs-version-overlay-open");
113        document.documentElement.classList.add("gs-version-overlay-open");
114        var dialog = overlay.querySelector(".gs-version-dialog");
115        if (dialog) {
116            window.setTimeout(function () { dialog.focus(); }, 0);
117        }
118    }
119
120    function createOverlay(className, label, content) {
121        var overlay = document.createElement("div");
122        overlay.className = "gs-version-overlay";
123        overlay.hidden = true;
124        overlay.setAttribute("role", "presentation");
125        overlay.innerHTML = '<section class="gs-version-dialog ' + className + '" role="dialog" aria-modal="true" aria-label="' + label + '" tabindex="-1">' + content + "</section>";
126        overlay.addEventListener("click", function (event) {
127            if (event.target === overlay) {
128                closeOverlay(overlay);
129            }
130        });
131        document.body.appendChild(overlay);
132        return overlay;
133    }
134
135    function closeButton() {
136        return '<button class="gs-version-dialog__close" type="button" data-version-close aria-label="关闭"><img src="https://image.gamersky.com/webimg13/test/nativeIndex/survey-close.svg" alt="" /></button>';
137    }
138
139    function initOldHome() {
140        var preference = getCookie(COOKIE.preference);
141        if (preference === "new") {
142            window.location.replace(getRoute("new"));
143            return;
144        }
145
146        if (getCookie(COOKIE.surveySeen) === "pending") {
147            setCookie(COOKIE.surveySeen, "shown");
148            setCookie(COOKIE.oldInviteSeen, "1");
149            openReturnSurveyOnOldHome();
150            return;
151        }
152
153        var invite = createOverlay(
154            "gs-version-invite",
155            "体验新版首页",
156            closeButton() +
157            '<div class="gs-version-invite__art"><img src="https://image.gamersky.com/webimg13/test/nativeIndex/invite-header.png" alt="新版首页体验插画" /></div>' +
158            '<div class="gs-version-invite__body"><h2>游民首页上新啦</h2><p>邀请您来体验并提出宝贵建议</p><button class="gs-version-primary-button" type="button" data-version-experience>体验新版</button></div>'
159        );
160        var experienceButton = invite.querySelector("[data-version-experience]");
161        var close = invite.querySelector("[data-version-close]");
162
163        experienceButton.addEventListener("click", function () {
164            if (experienceButton.disabled) {
165                return;
166            }
167            experienceButton.disabled = true;
168            reportStatistic(STATISTICS.oldInviteExperience, function () {
169                chooseVersion("new");
170            });
171        });
172        close.addEventListener("click", function () {
173            setCookie(COOKIE.preference, "old");
174            closeOverlay(invite);
175        });
176
177        if (!getCookie(COOKIE.oldInviteSeen)) {
178            setCookie(COOKIE.oldInviteSeen, "1");
179            window.setTimeout(function () {
180                openOverlay(invite);
181                reportStatistic(STATISTICS.oldInviteShown);
182            }, 0);
183        }
184    }
185
186    function escapeHtml(value) {
187        return String(value === undefined || value === null ? "" : value).replace(/[&<>"']/g, function (character) {
188            return {
189                "&": "&amp;",
190                "<": "&lt;",
191                ">": "&gt;",
192                '"': "&quot;",
193                "'": "&#39;"
194            }[character];
195        });
196    }
197
198    function trimText(value) {
199        return String(value === undefined || value === null ? "" : value).replace(/^\s+|\s+$/g, "");
200    }
201
202    function parseSurveyId(value) {
203        var numberValue = Number(value);
204        return isNaN(numberValue) ? value : numberValue;
205    }
206
207    function getSurveyUserId() {
208        try {
209            if (window.GSAppJsApi && window.GSAppJsApi.User && typeof window.GSAppJsApi.User.getCurrentUserId === "function") {
210                return window.GSAppJsApi.User.getCurrentUserId() || "";
211            }
212        } catch (error) {
213            return "";
214        }
215        return "";
216    }
217
218    // 问卷页同源实现使用的服务:所有请求均为 JSON POST,并携带浏览器凭据。
219    function requestSurvey(path, data, callback) {
220        var request = new XMLHttpRequest();
221        var completed = false;
222
223        function complete(error, response) {
224            if (completed) {
225                return;
226            }
227            completed = true;
228            callback(error, response);
229        }
230
231        request.open("POST", SURVEY.serviceUrl + path, true);
232        request.withCredentials = true;
233        request.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
234        request.onreadystatechange = function () {
235            var response;
236            if (request.readyState !== 4) {
237                return;
238            }
239            if (request.status < 200 || request.status >= 300) {
240                complete(new Error("问卷服务请求失败"));
241                return;
242            }
243            try {
244                response = JSON.parse(request.responseText || "{}");
245            } catch (error) {
246                complete(error);
247                return;
248            }
249            complete(null, response);
250        };
251        request.onerror = function () {
252            complete(new Error("问卷服务请求失败"));
253        };
254        request.send(JSON.stringify(data || {}));
255    }
256
257    function getSurveyVisibleQuestions(questionArray) {
258        var questions = [];
259        var index;
260        var question;
261        var answerType;
262
263        for (index = 0; index < questionArray.length; index += 1) {
264            question = questionArray[index];
265            answerType = Number(question.answerType);
266            if (Number(question.isOpen) === 1 && Number(question.isPagination) === 0 && (answerType === 1 || answerType === 2 || answerType === 3)) {
267                questions.push(question);
268            }
269        }
270        return questions;
271    }
272
273    function renderSurveyQuestion(question, index) {
274        var answerType = Number(question.answerType);
275        var questionId = escapeHtml(question.id);
276        var answerName = "survey-answer-" + questionId;
277        var number = index + 1 < 10 ? "0" + (index + 1) : String(index + 1);
278        var required = Number(question.isMustAnswer) === 1;
279        var title = '<legend class="gs-version-question__title"><span class="gs-version-question__number">' + number + '</span>' +
280            (required ? '<span class="gs-version-question__required">*</span>' : "") +
281            '<span>' + escapeHtml(question.title) + "</span>" +
282            (answerType === 2 ? '<span class="gs-version-question__optional">[多选题]</span>' : "") +
283            "</legend>";
284        var options = question.answerModelArray || [];
285        var optionHtml = "";
286        var optionIndex;
287        var option;
288        var optionId;
289        var isOther;
290        var inputType;
291
292        if (answerType === 3) {
293            return '<fieldset class="gs-version-question" data-survey-question-id="' + questionId + '" data-survey-answer-type="3" data-survey-required="' + (required ? "1" : "0") + '">' +
294                title +
295                '<textarea class="gs-version-textarea" data-survey-text-answer="' + questionId + '" placeholder="请输入内容"></textarea></fieldset>';
296        }
297
298        inputType = answerType === 2 ? "checkbox" : "radio";
299        for (optionIndex = 0; optionIndex < options.length; optionIndex += 1) {
300            option = options[optionIndex];
301            optionId = escapeHtml(option.id);
302            isOther = option.answerType === "user_input_answer";
303            optionHtml += '<label><input type="' + inputType + '" name="' + answerName + '" value="' + optionId + '" data-survey-option-answer="1" />' +
304                (answerType === 2 ? '<i class="gs-version-checkbox-icon" aria-hidden="true"></i>' : "") +
305                '<span>' + escapeHtml(option.answerText) + "</span></label>";
306            if (isOther) {
307                optionHtml += '<input class="gs-version-other-input" type="text" data-survey-other-for="' + optionId + '" placeholder="请输入内容" hidden />';
308            }
309        }
310
311        return '<fieldset class="gs-version-question" data-survey-question-id="' + questionId + '" data-survey-answer-type="' + answerType + '" data-survey-required="' + (required ? "1" : "0") + '">' +
312            title +
313            '<div class="' + (answerType === 2 ? "gs-version-options" : "gs-version-scale") + '">' + optionHtml + "</div></fieldset>";
314    }
315
316    function setSurveyNotice(survey, message, isError) {
317        var notice = survey.querySelector("[data-version-survey-notice]");
318        if (!notice) {
319            return;
320        }
321        notice.textContent = message || "";
322        notice.hidden = !message;
323        notice.className = "gs-version-survey__notice" + (isError ? " gs-version-survey__notice--error" : "");
324    }
325
326    function setSurveySubmitState(survey, disabled, text) {
327        var button = survey.querySelector("[data-version-survey-submit]");
328        if (!button) {
329            return;
330        }
331        button.disabled = disabled;
332        if (text) {
333            button.textContent = text;
334        }
335    }
336
337    function renderSurveyQuestions(survey, questions) {
338        var content = survey.querySelector("[data-version-survey-content]");
339        var html = '<p class="gs-version-survey__notice" data-version-survey-notice hidden></p>';
340        var index;
341
342        if (!questions.length) {
343            content.innerHTML = '<p class="gs-version-survey__loading">当前问卷暂无可展示题目,请稍后再试。</p>';
344            setSurveySubmitState(survey, true, "提交问卷");
345            return;
346        }
347        for (index = 0; index < questions.length; index += 1) {
348            html += renderSurveyQuestion(questions[index], index);
349        }
350        content.innerHTML = html;
351    }
352
353    function syncSurveyOtherInputs(form) {
354        var otherInputs = form.querySelectorAll("[data-survey-other-for]");
355        var index;
356        var input;
357        var selector;
358        var selected;
359
360        for (index = 0; index < otherInputs.length; index += 1) {
361            input = otherInputs[index];
362            selector = '[data-survey-option-answer][value="' + input.getAttribute("data-survey-other-for") + '"]:checked';
363            selected = form.querySelector(selector);
364            input.hidden = !selected;
365            if (!selected) {
366                input.value = "";
367            }
368        }
369    }
370
371    function collectSurveyAnswers(survey, form) {
372        var state = survey._surveyState;
373        var answers = [];
374        var index;
375        var question;
376        var answerType;
377        var selectedInputs;
378        var selectedAnswerIds;
379        var selectedIndex;
380        var otherInput;
381        var otherAnswer;
382        var textInput;
383
384        for (index = 0; index < state.questions.length; index += 1) {
385            question = state.questions[index];
386            answerType = Number(question.answerType);
387            if (answerType === 3) {
388                textInput = form.querySelector('[data-survey-text-answer="' + question.id + '"]');
389                otherAnswer = trimText(textInput ? textInput.value : "");
390                if (Number(question.isMustAnswer) === 1 && !otherAnswer) {
391                    return { error: "请完成“" + question.title + "”" };
392                }
393                if (otherAnswer) {
394                    answers.push({ questionId: question.id, otherAnswer: otherAnswer, answerSheetId: state.answerSheetId });
395                }
396                continue;
397            }
398
399            selectedInputs = form.querySelectorAll('input[name="survey-answer-' + question.id + '"]:checked');
400            if (Number(question.isMustAnswer) === 1 && !selectedInputs.length) {
401                return { error: "请完成“" + question.title + "”" };
402            }
403            if (!selectedInputs.length) {
404                continue;
405            }
406            selectedAnswerIds = [];
407            otherAnswer = "";
408            for (selectedIndex = 0; selectedIndex < selectedInputs.length; selectedIndex += 1) {
409                selectedAnswerIds.push(parseSurveyId(selectedInputs[selectedIndex].value));
410                otherInput = form.querySelector('[data-survey-other-for="' + selectedInputs[selectedIndex].value + '"]');
411                if (otherInput) {
412                    otherAnswer = trimText(otherInput.value);
413                    if (!otherAnswer) {
414                        return { error: "请补充“其他”内容" };
415                    }
416                }
417            }
418            answers.push({ questionId: question.id, selectedAnswerId: selectedAnswerIds, otherAnswer: otherAnswer, answerSheetId: state.answerSheetId });
419        }
420        return { answers: answers };
421    }
422
423    function loadReturnSurvey(survey) {
424        var state = survey._surveyState;
425        var content = survey.querySelector("[data-version-survey-content]");
426
427        content.innerHTML = '<p class="gs-version-survey__loading">问卷加载中...</p>';
428        setSurveySubmitState(survey, true, "提交问卷");
429        requestSurvey("/questionnaire/getQuestionnaireDetail", {
430            questionnaireId: SURVEY.id,
431            answerSheetId: 0
432        }, function (detailError, detail) {
433            var questionnaire;
434            if (detailError || !detail || detail.errorDescription || !detail.questionnaireModel) {
435                content.innerHTML = '<p class="gs-version-survey__loading">问卷加载失败,请关闭后重试。</p>';
436                return;
437            }
438            questionnaire = detail.questionnaireModel;
439            state.questions = getSurveyVisibleQuestions(questionnaire.questionArray || []);
440            renderSurveyQuestions(survey, state.questions);
441            if (!state.questions.length) {
442                return;
443            }
444            requestSurvey("/answersheet/createAnswerSheet", {
445                questionnaireId: SURVEY.id,
446                userId: getSurveyUserId()
447            }, function (createError, createResult) {
448                var answerSheet = createResult && createResult.answerSheetModel;
449                if (createError || !answerSheet || !answerSheet.id) {
450                    setSurveyNotice(survey, "问卷初始化失败,请关闭后重试。", true);
451                    return;
452                }
453                state.answerSheetId = answerSheet.id;
454                state.ready = true;
455                setSurveySubmitState(survey, false, "提交问卷");
456            });
457        });
458    }
459
460    function submitReturnSurvey(survey, form) {
461        var state = survey._surveyState;
462        var collected;
463        var userId;
464
465        if (!state.ready) {
466            setSurveyNotice(survey, "问卷正在初始化,请稍后再试。", true);
467            return;
468        }
469        syncSurveyOtherInputs(form);
470        collected = collectSurveyAnswers(survey, form);
471        if (collected.error) {
472            setSurveyNotice(survey, collected.error, true);
473            return;
474        }
475        setSurveyNotice(survey, "", false);
476        setSurveySubmitState(survey, true, "提交中...");
477        userId = getSurveyUserId();
478        requestSurvey("/answersheet/saveAnswerSheet", {
479            model: {
480                questionnaireId: SURVEY.id,
481                status: 1,
482                answers: collected.answers,
483                answerSheetId: state.answerSheetId,
484                userId: "",
485                channel: "",
486                user: {
487                    gamerskyUserId: userId,
488                    deviceInfo: "",
489                    surveyEnvironment: "PCWap"
490                }
491            }
492        }, function (saveError, saveResult) {
493            if (saveError || !saveResult || saveResult.msg !== "保存成功") {
494                setSurveyNotice(survey, "提交失败,请稍后重试。", true);
495                setSurveySubmitState(survey, false, "提交问卷");
496                return;
497            }
498            closeOverlay(survey);
499        });
500    }
501
502    function createSurvey() {
503        var body = closeButton() +
504            '<div class="gs-version-survey__art"><img class="gs-version-survey__header" src="https://image.gamersky.com/webimg13/test/nativeIndex/survey-header.png" alt="新版首页体验调研插画" /></div>' +
505            '<form class="gs-version-survey__body" data-version-survey><div class="gs-version-survey__title"><h2>请您协助改进新版首页</h2><p>您的感受和建议是我们持续改进的目标和方向!</p></div><div class="gs-version-survey__content" data-version-survey-content></div><button class="gs-version-primary-button gs-version-survey__submit" type="submit" data-version-survey-submit disabled>提交问卷</button></form>';
506        var survey = createOverlay("gs-version-survey", "新版首页体验调研", body);
507        survey._surveyState = {
508            answerSheetId: 0,
509            questions: [],
510            ready: false
511        };
512        return survey;
513    }
514
515    function openReturnSurveyOnOldHome() {
516        var survey = createSurvey();
517        var close = survey.querySelector("[data-version-close]");
518        var form = survey.querySelector("[data-version-survey]");
519
520        close.addEventListener("click", function () {
521            closeOverlay(survey);
522        });
523        form.addEventListener("change", function () {
524            syncSurveyOtherInputs(form);
525        });
526        form.addEventListener("submit", function (event) {
527            event.preventDefault();
528            submitReturnSurvey(survey, form);
529        });
530        openOverlay(survey);
531        reportStatistic(STATISTICS.newReturnSurveyShown);
532        loadReturnSurvey(survey);
533    }
534
535    function initNewHome() {
536        /* 进入新版即视为选择新版,不依赖弹窗、右上角入口或直接访问等来源。 */
537        setCookie(COOKIE.preference, "new");
538
539        var navigationGrid = document.querySelector(".top-nav__secondary");
540        var returnButton = navigationGrid && navigationGrid.querySelector(".gs-version-return");
541        var returnTip = null;
542        var updateReturnTipPosition = null;
543
544        if (!returnButton) {
545            returnButton = document.createElement("button");
546            returnButton.className = "gs-version-return";
547            returnButton.type = "button";
548            returnButton.innerHTML = '<img class="gs-version-return__icon" src="https://image.gamersky.com/webimg13/test/nativeIndex/return-old-home.svg" alt="" /><span class="gs-version-return__label"><span class="gs-version-return__label-text">返回旧版</span><span class="gs-version-return__label-line" aria-hidden="true"></span></span>';
549            returnButton.setAttribute("aria-label", "返回旧版首页");
550            (navigationGrid || document.body).appendChild(returnButton);
551        }
552
553        function clearReturnTip() {
554            if (!returnTip) {
555                return;
556            }
557            returnTip.remove();
558            returnTip = null;
559            if (updateReturnTipPosition) {
560                window.removeEventListener("resize", updateReturnTipPosition);
561                window.removeEventListener("scroll", updateReturnTipPosition, true);
562                updateReturnTipPosition = null;
563            }
564        }
565
566        returnButton.addEventListener("click", function () {
567            if (returnTip) {
568                clearReturnTip();
569            }
570            if (getCookie(COOKIE.surveySeen) === "shown" || getCookie(COOKIE.surveySeen) === "1") {
571                chooseVersion("old");
572                return;
573            }
574            setCookie(COOKIE.surveySeen, "pending");
575            chooseVersion("old");
576        });
577
578        if (!getCookie(COOKIE.newReturnTipSeen)) {
579            var tip = document.createElement("span");
580            tip.className = "gs-version-return__tip";
581            tip.textContent = "点击此处返回旧版";
582            returnTip = tip;
583            document.body.appendChild(tip);
584            updateReturnTipPosition = function () {
585                var rect = returnButton.getBoundingClientRect();
586                tip.style.left = (rect.left + rect.width / 2) + "px";
587                tip.style.top = (rect.bottom + 14) + "px";
588            };
589            updateReturnTipPosition();
590            window.addEventListener("resize", updateReturnTipPosition);
591            window.addEventListener("scroll", updateReturnTipPosition, true);
592            setCookie(COOKIE.newReturnTipSeen, "1");
593            window.setTimeout(function () {
594                if (returnTip === tip) {
595                    clearReturnTip();
596                }
597            }, 5000);
598        }
599    }
600
601    document.addEventListener("keydown", function (event) {
602        if (event.key !== "Escape") {
603            return;
604        }
605        var overlay = document.querySelector(".gs-version-overlay:not([hidden])");
606        if (overlay) {
607            closeOverlay(overlay);
608        }
609    });
610
611    document.addEventListener("DOMContentLoaded", function () {
612        if (isNewHome) {
613            initNewHome();
614        } else {
615            initOldHome();
616        }
617    });
618})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.