NextJS: 404 page not rendered for [store]/account/details route

I’m trying to implement 404 pages in my react-next project,
i have a route [store]/account where [store] is dynamic. till the account page the 404 is properly thrown, but when i try to load [store]/account/asdasdasd(random page to trigger 404) the screen is blank and shows nothing.

note: i have handled 404 in the getStaticProps for both [store],/account page.

Please help with this, stuck on this for quite sometime.

Scroll to the end of h1 tag thats overflow is hidden in reactjs

So i have an h1 tag which has its overflow hidden and what i want to do is make it so it auto scrolls to the end of the text without showing the scroll bar. I’ve tried a lot of ways but I couldn’t find any suitable for me.
I tried using refs

myref.current.scrollIntoView()

It didn’t work then I tried

myref.current.scrollTo(1000)

but that didn’t do anything it just showed an error in the console.

Unable to detect Canvas tag inside ngfor iteration – Angular

I want to work with Canvas tag inside ngfor but every times it showing undefined or null. I tried in many ways but not worked. Please help me.

HTML:

<div class="col-sm-6 col-lg-4 pb-30 blog-parent" *ngFor="let item of blogList; let i = index;">
    <div class="blog-item">
        <a href="#">
            <div class="blog-item-figure">
                <canvas class="blog-canvas" id="canvas"></canvas>
            </div>
        </a>
    </div>
</div>

TS:
ngOnInit(): void {
    this.cropImage();
}
cropImage() {
    let canvas: any = document.getElementsByClassName("blog-canvas");
    for (let i = 0; i < this.blogList.length; i++) {
        console.log("canvas: ", canvas[i]);
    }

}

Masking the given number while on typing before clicking on save button

I am developing the SSN number in react native.Now in my code I am masking the number like 123 – 45 – xxxx OR xxx – 45 – 6789 only after clicking the save button.But now I wanted to mask that number like 123 – 45 – xxxx OR xxx – 45 – 6789
while typing the number before any clicking save button.
Note: in my code, I am referring the values of splitby, numOfSplits, pattern, position, mask, length, maskBy through my metadata.

my code

import React from ‘react’;
import {
Controller
} from ‘react-hook-form’;
import {
StyleProp,
ViewStyle
} from ‘react-native’;
import {
useSelector
} from ‘react-redux’;
import {
Icon,
Input,
Layout
} from ‘_atoms’;
import {
Label
} from ‘_organisms’;
import {
fillColor
} from ‘_utils’;
import {
style
} from ‘../style’;

let SystemMask = ({
attribute,
data,
formOptions,
disable
}: any) => {

const {
    name,
    required,
    title,
    info,
    placeHolder,
    validationRegEx,
    defaultValue,
    canUpdate,
    unique,
    splitBy,
    pattern,
    numOfSplits,
    position,
    mask,
    length,
    maskBy,
    ...others
} = attribute;

const {
    control
}: any = formOptions || {};

let regEx = /^(?!(000|666|9))d{3}-?(?!(00))d{2}-?(?!(0000))d{4}$/

const {
    theme
} = useSelector((state: any) => state.app);

let color = fillColor(disable, theme);

const returnSum = (array: any) => {
    let sum = 0;
    array.map((e: any) => {
        sum = sum + e;
    });
    return sum;
};
let total = returnSum(pattern);

let splittedData = "";

// let numOfSplit = pattern.length - 1;

let splitData = (val: any) => {
    let splittedVal = "";
    if (val) {
        let numOfSplits = 0;
        val.split("").map((ele: any) => {
            if (ele === splitBy) {
                numOfSplits++;
            }
        });
        if (val.length <= total + numOfSplits) {
            val.split("").map((each: any, index: any) => {
                let sum = 0;
                pattern.map((e: any, i: any) => {
                    sum = sum + 1 + e;
                    if (index + 1 === sum && each !== splitBy) {
                        splittedVal += "".concat("", splitBy);
                    } else if (index + 1 === sum && each === splitBy) {
                        splittedVal += "".concat("", splitBy);
                    } else if (index + 1 !== sum && each === splitBy) {
                        splittedVal += "".concat("", "");
                    }
                });
                pattern.map((e: any, i: any) => {
                    sum = sum + 1 + e;
                    if (index + 1 !== sum && each === splitBy) {
                        each = "";
                    }
                });
                splittedVal += "".concat("", each !== maskBy ? each : "");
            });
            return splittedVal;
        }
    } else {
        return "";
    }
};

let maskData = (val: any) => {
    let maskedData = "";
    if (val) {
        splittedData = "";
        let numOfSplits = 0;
        val
            .replaceAll(splitBy, "")
            .split("")
            .map((each1: any, index1: any, array1: any) => {
                if (array1[index1 - 1] === splitBy) {
                    numOfSplits++;
                }
                if (
                    index1 + 1 <= length + numOfSplits &&
                    position === ("LEFT" || "left" || "Left") &&
                    each1 !== splitBy
                ) {
                    splittedData += "".concat("", mask ? maskBy : each1);
                } else if (
                    index1 + 1 >
                    val.replaceAll(splitBy, "").length - (length + numOfSplits) &&
                    position === ("RIGHT" || "right" || "Right") &&
                    each1 !== splitBy
                ) {
                    splittedData += "".concat("", mask ? maskBy : each1);
                } else {
                    splittedData += "".concat("", each1);
                }
            });
        splittedData.split("").map((each2, index2) => {
            let sum2 = 1;
            pattern.map((e2: any, i2: any) => {
                sum2 = sum2 + e2;
                if (index2 + 1 === sum2 && each2 !== splitBy) {
                    maskedData += "".concat("", `${splitBy}`);
                }
            });
            maskedData += "".concat("", each2);
        });
        return maskedData;
    } else {
        return "";
    }
};

const handleOnchange = (val: any, onChange: any) => {
    onChange(val);
};

const getMaskValue = (value: any, isDirty: any) => {
    return isDirty ? splitData(value) : maskData(value);
};

return ( <
    Layout style = {
        style.container as StyleProp < ViewStyle >
    } >
    <
    >
    <
    Label isRequired = {
        required
    }
    title = {
        title
    }
    description = {
        info
    }
    /> <
    /> <
    Controller control = {
        control
    }
    name = {
        name
    }
    render = {
        ({
            field,
            fieldState
        }: any) => {
            let {
                onChange,
                value,
                ref
            } = field || {};
            let {
                error,
                isDirty
            } = fieldState || {};
            let {
                message
            } = error || {};

            return ( <
                Input
                // ref={ref}
                placeholder = "123-45-6789"
                testID = {
                    name
                }
                disabled = {
                    disable
                }
                onChangeText = {
                    (value: any) => {
                        onChange(value);
                    }
                }
                // inputProps={{
                //     maxLength: total + numOfSplit,
                //   }}
                onChange = {
                    (val) => handleOnchange(val, onChange)
                }
                value = {
                    getMaskValue(value, isDirty)
                }
                status = {
                    error ? 'danger' : 'primary'
                }
                caption = {
                    error ? message || 'Required' : ''
                }
                accessoryRight = {
                    (props: any) => {
                        if (value) {
                            return ( <
                                Icon {
                                    ...props
                                }
                                fill = {
                                    color
                                }
                                name = {
                                    'close'
                                }
                                disabled = {
                                    disable
                                }
                                onPress = {
                                    () => onChange('')
                                }
                                />
                            );
                        } else return < > < />;
                    }
                }
                />
            )
        }
    }
    rules = {
        {
            required: required,
            pattern: {
                value: validationRegEx || regEx,
                message: 'Enter a valid SSN',
            },
            maxLength: {
                value: 11,
                message: "SSN length should be < 9",
            },
        }
    }
    defaultValue = {
        data || defaultValue || ''
    }
    /> <
    /Layout>
);

};

export default SystemMask;

Transform flat json to nested json using javascript

I am trying to transform flat json to nested json using javascript with some sort of relationship. Please see below for the sample json data i am working with:


[{"id":1,"lob":"IT","product":"mobile","title":"64-bit app"}, 
{"id":2,"lob":"SCI","product":"book","title":"a book"},
{"id":3,"lob":"IT","product":"laptop","title":"this is laptop"},  
{"id":4,"lob":"IT","product":"laptop","title":"another laptop"},
{"id":5,"lob":"ENG","product":"stick","title":"a magic stick"},
{"id":6,"lob":"ENG","product":"door","title":"a door"},
{"id":7,"lob":"IT","product":"mobile","title":"32-bit app"}, 
]

and then please see below for the expected output:


[
    {
      lob: "IT",
        product: [
            {
            name: "mobile",
            titles: [
                    {
                        title: "64-bit app",
                    },
                    {
                        title: "32-bit app",
                    }
                ]
            },
            {
                name: "laptop",
                titles: [
                        {
                            title: "this is laptop",
                        },
                        {
                            title: "another laptop",
                        }
                    ]
                }
            
        ]
    },
    {
        lob: "ENG",
          product: [
              {
              name: "stick",
              titles: [
                      {
                          title: "64-bit app",
                      },
                      {
                          title: "32-bit app",
                      }
                  ]
              },
              {
                  name: "laptop",
                  titles: [
                          {
                              title: "a magic stick",
                          },
                          {
                              title: "a door",
                          }
                      ]
                  }
              
          ]
      }

]

How do I achieve this using javascript, or are there any package/library i can use.

Transfer a row of data from one object to another

My goal is to transfer a row of data from one object to another, where selected_city_codes would state which items to remove from airport_data_2 to airport_data_1 by using city_id

Not sure how to approach appending the data from airport_data_2 to airport_data_1 but I illustrated my result to removing the row from airport_data_2.

Is there a more efficient way to transfer data between two object?

airport_data_1 = [{"departure_time":"12:00","arrival_time":"03:00","city_id":"BOS"},  
{"departure_time" :"12:00","arrival_time":"03:00","city_id":"BOS"},
{"departure_time" :"01:00","arrival_time":"04:00","city_id":"SFO"},
{"departure_time" :"03:00","arrival_time":"05:00","city_id":"BOS"},
{"departure_time" :"03:00","arrival_time":"05:00","city_id":"SFO"}]; 


airport_data_2 = [{"departure_time" :"03:00","arrival_time":"05:00","city_id":"DEN"},
{"departure_time" :"04:00","arrival_time":"06:00","city_id":"SJC"},
{"departure_time" :"04:00","arrival_time":"06:00","city_id":"JFK"},
{"departure_time" :"06:00","arrival_time":"09:00","city_id":"SJC"}]; 


selected_city_codes = ['SJC','JFK']; //items to remove from `airport_data_2` to `airport_data_1`

//my attempt to remove the listed values from selected_city_codes
for(i in selected_city_codes) { 
    airport_data_2 = airport_data_2.filter(item => item.city_id != selected_city_codes[i]);
}

Result Before

airport_data_1 = [{"departure_time":"12:00","arrival_time":"03:00","city_id":"BOS"},  
{"departure_time" :"12:00","arrival_time":"03:00","city_id":"BOS"},
{"departure_time" :"01:00","arrival_time":"04:00","city_id":"SFO"},
{"departure_time" :"03:00","arrival_time":"05:00","city_id":"BOS"},
{"departure_time" :"03:00","arrival_time":"05:00","city_id":"SFO"}]; 


airport_data_2 = [{"departure_time" :"03:00","arrival_time":"05:00","city_id":"DEN"},
{"departure_time" :"04:00","arrival_time":"06:00","city_id":"SJC"},
{"departure_time" :"04:00","arrival_time":"06:00","city_id":"JFK"},
{"departure_time" :"06:00","arrival_time":"09:00","city_id":"SJC"}]; 

Result After — our desired result

airport_data_1 = [{"departure_time":"12:00","arrival_time":"03:00","city_id":"BOS"},  
{"departure_time" :"12:00","arrival_time":"03:00","city_id":"BOS"},
{"departure_time" :"01:00","arrival_time":"04:00","city_id":"SFO"},
{"departure_time" :"03:00","arrival_time":"05:00","city_id":"BOS"},
{"departure_time" :"03:00","arrival_time":"05:00","city_id":"SFO"},
{"departure_time" :"04:00","arrival_time":"06:00","city_id":"SJC"},
{"departure_time" :"04:00","arrival_time":"06:00","city_id":"JFK"},
{"departure_time" :"06:00","arrival_time":"09:00","city_id":"SJC"}];

airport_data_2 = [{"departure_time" :"03:00","arrival_time":"05:00","city_id":"DEN"}]; 

How to play sound effects in Vue 3 app with Composition API

I am attempting to setup a basic button click in Vue 3 Composition API to trigger a sound effect. Currently, my setup function includes an mp3 sound effect imported from the assets folder then passed into a ref method with an HTMLAudioElement type, then assigned to a const called “play”. After adding the “play” constant to the return, I then added “play” to a click handler in the button. I’m not getting errors in the console, but the button is still not triggering the sound effect. How can I go about configuring the setup function and button to trigger the sound effect? Here is my code:

<template>
  <div div class="flex justify-center">
    <button @click="play">Click</button>
  </div>
</template>

<script>
import { ref } from 'vue' 
import { trumpetSfx } from '../assets/demo_src_assets_fanfare.mp3'

export default {
  name: 'Button',
  components: {},
  setup() {
    const play = ref<HTMLAudioElement>(trumpetSfx);

    return { play }
  }
}
</script>

404 error with POST request using express server

I am running this function that should post data to my express server. The function is called when a button is clicked.

const fetchData = async () => {
    const response = await fetch('http://localhost:1337/api/test', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        message: 'hello world'
      }),
    })

    // const data = await response.json()
    const data = await response
    console.log(data)
  }

Here is my express configuration

const express = require('express')
const cors = require('cors')

const app = express()
app.use(cors())
app.use(express.json())

app.get('/api/test', (req: any, res: any) => {
  console.log(req.body)
  res.json({ status: 'ok' })
})

app.listen(1337, () => {
  console.log('Server started on 1337')
})

The problem is that when I click the button I receive a 404 error for the POST request and my console.log(response) results in the following.

Response { type: "cors", url: "http://localhost:1337/api/test", redirected: false, status: 404, ok: false, statusText: "Not Found", headers: Headers, body: ReadableStream, bodyUsed: false }
​
body: ReadableStream { locked: false }
​
bodyUsed: false
​
headers: Headers {  }
​
ok: false
​
redirected: false
​
status: 404
​
statusText: "Not Found"
​
type: "cors"
​
url: "http://localhost:1337/api/test"
​
<prototype>: ResponsePrototype { clone: clone(), arrayBuffer: arrayBuffer(), blob: blob(), … }

NodeJS return data from for() function

This might be a very basic question but I’ve never done it and I can’t
make it so far, so I’m gonna asking it here!

I have a function in separate js file and it supposed to return messages from for loop data but not sure where the return has to go!

this is my code:

function test(x,y) {
    for(let i in y) {
        if(y[i].value == 'x') {
            return bot.message(y[i]);
        }
        sleep(1500);
    }
}

this doesn’t return anything.

So what I’m trying to do here is to send multiple messages from my loop and put 1.5 seconds sleep between each message.

What did I do wrong?

how to define and register a custom lable in Vue in google chrome extension

I am using vue "vue": "^1.0.24" to develop a google chrome extension right now. This is my widget template.html file:

<st-div id="__selection-translator__">
  <st-div class="__st-box__" v-el:st-box :style="boxStyle">
    <st-header v-if="!inline" v-el:st-drag>
      <st-span class="st-icon-pin" title="固定" @click="pinned=!pinned" :class="{'__pinned__':pinned}"></st-span>
      <st-span class="st-icon-down-open" :class="{'__open__':showForm}" :title="showForm?'收起':'展开'" @click="showForm=!showForm"></st-span>
      <st-span class="st-icon-cog" title="设置" @click="openOptions"></st-span>
    </st-header>
    <st-div class="__query-form__" v-show="showForm">
      <st-div>
        <textarea placeholder="输入要翻译的句子或单词" v-model="query.text" v-el:textarea @keyup.enter="ctrlEnter" @keyup="safeTranslate | debounce 600"></textarea>
      </st-div>
      <st-div>
        <select v-model="query.from" @change="safeTranslate">
          <option value="">自动判断</option>
          <option v-for="locale in locales" track-by="localeId" :value="locale.localeId" v-text="locale['zh-CN']"></option>
        </select>
        <st-div class="__exchange__">
          <st-span class="st-icon-exchange" @click="exchangeLocale"></st-span>
        </st-div>
        <select v-model="query.to" @change="safeTranslate">
          <option value="">自动选择</option>
          <option v-for="locale in locales" track-by="localeId" :value="locale.localeId" v-text="locale['zh-CN']"></option>
        </select>
      </st-div>
      <st-div>
        <select v-model="query.api" @change="safeTranslate">
          <option value="YouDao">有道翻译</option>
          <option value="BaiDu">百度翻译</option>
          <!-- <option value="Bing">必应翻译</option> -->
          <option value="Google">谷歌翻译</option>
          <option value="GoogleCN">谷歌翻译(国内)</option>
          <option value="Reddwarf">红矮星翻译</option>
        </select>
        <st-div class="__action-list__">
          <st-div class="__button__ __btn-translate__" @click="safeTranslate">翻译
            <st-span class="st-icon-down-dir"></st-span>
          </st-div>
          <st-div class="__expand__">
            <st-div class="__button__" @click="play(query.text,query.from)">朗读</st-div>
            <st-div class="__button__" @click="copy(query.text,$event)">复制</st-div>
          </st-div>
        </st-div>
      </st-div>
    </st-div>
    <st-div class="__translate-result__" v-show="loading">正在查询,请稍候……</st-div>
    <st-div class="__translate-result__" v-show="showResult && !loading">
      <st-div v-show="result.error">
        <st-span v-text="result.error"></st-span>
        <st-span class="__retry__" @click="safeTranslate">重试</st-span>
      </st-div>
      <st-div v-else>
        <st-div class="__phonetic__">
          <st-span v-show="result.phonetic" v-text="result.phonetic"></st-span>
          <st-span class="__copy-and-read__">
            <st-span @click="play(query.text,query.from)">朗读</st-span>
            <st-span v-show="result.phonetic" @click="copy(result.phonetic,$event)">复制</st-span>
            <st-span v-show="result.phonetic" @click="addGlossary(query.text,query.from)">添加到单词本</st-span>
          </st-span>
        </st-div>
        <st-div v-show="result.dict && result.dict.length">
          <st-ul>
            <st-li v-for="d in result.dict" v-text="d"></st-li>
          </st-ul>
          <st-div class="__copy-and-read__">
            <st-span class="__copy-and-read__" @click="copy(result.dict,$event)">复制</st-span>
          </st-div>
        </st-div>
        <st-div v-show="result.result&&result.result.length">
          <st-div v-for="text in result.result" v-text="text"></st-div>
          <st-div class="__copy-and-read__">
            <st-span class="__copy-and-read__" @click="play(result.result,result.to)">朗读</st-span>
            <st-span class="__copy-and-read__" @click="copy(result.result,$event)">复制</st-span>
          </st-div>
        </st-div>
      </st-div>
    </st-div>
    <st-footer>
      <st-span v-show="!loading && apiName">via
        <a :href="result.link" target="_blank" v-text="apiName"></a></st-span>
    </st-footer>
  </st-div>
  <st-div class="__st-btn__" v-el:st-btn :style="btnStyle">译</st-div>
</st-div>

when I run this extension, the console show warning like this:

vue.common.js:1137 [Vue warn]: Unknown custom element: <st-span> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

and this is index.js file:

/**
 * @files 基础 ST 组件,内容脚本和弹出页都会用到
 */

import '../fontello/css/selection-translator.css';
import './style.scss';
import Vue from 'vue';
import widgetMixin from './vue-st';
import chromeCall from 'chrome-call';

import locales from '../locales';
import template from './template.html';
// const request = require('superagent');



// 去掉 locales 里的 *-* 类语种,除了 zh-CN、zh-TW 和 zh-HK(百度翻译里的粤语)
const translateLocales = [];

locales.forEach( locale => {
  const {localeId} = locale;

  if ( !localeId.includes( '-' ) || ( localeId === 'zh-CN' || localeId == 'zh-TW' || localeId == 'zh-HK' ) ) {
    translateLocales.push( locale );
  }
} );

const resolvedEmptyPromise = Promise.resolve() ,
  noop = ()=> {};

/**
 * 翻译窗口的基础 Vue 构造函数。
 * 注意:这个构造函数需要一个额外的 options:client
 */
export default Vue.extend( {
  template ,
  data : ()=>({
    access_token: '', // 扇贝单词授权 token
    locales : translateLocales ,
    showForm : false ,
    query : {
      text : '' ,
      from : '' ,
      to : '' ,
      api : ''
    } ,
    result : {
      error : '' ,
      phonetic : '' ,
      dict : [] ,
      result : [] ,
      link : '',
    }
  }) ,
  created() {
    this.$options.client.on( 'disconnect' , ()=> {
      this.result = {
        error : 'index连接到翻译引擎时发生了错误,请刷新网页或重启浏览器后再试。'
      }
    } );
  } ,
  computed : {
    apiName() {
      return {
        YouDao: '有道翻译',
        Google: '谷歌翻译',
        GoogleCN: '谷歌翻译(国内)',
        BaiDu: '百度翻译',
        Reddwarf: '红矮星翻译'
      }[this.query.api] || ''
    }
  },
  methods : {

    /**
     * 翻译快捷键:Ctrl + Enter
     * @param event
     */
    ctrlEnter( event ) {
      if ( event.ctrlKey ) {
        this.safeTranslate();
      }
    } ,

    /**
     * 仅当有文本时才翻译
     */
    safeTranslate() {
      if ( this.query.text.trim() ) {
        this.translate();
      }
    } ,

    /**
     * 从后台网页获取查询结果
     * @returns {Promise}
     */
    getResult() {
      if ( this.$options.client.disconnected ) {
        return resolvedEmptyPromise;
      }
      return this.$options.client
        .send( 'get translate result' , this.query , true )
        .then( resultObj => {
          debugger;
          if ("200" !==resultObj.response.statusCode||"200" !== resultObj.response.resultCode) {
            let errMsg = {
              NETWORK_ERROR: '网络错误,请检查你的网络设置。',
              API_SERVER_ERROR: '接口返回了错误的数据,请稍候重试。',
              UNSUPPORTED_LANG: '不支持的语种,请使用谷歌翻译重试。',
              NETWORK_TIMEOUT: '查询超时:5 秒内没有查询到翻译结果,已中断查询。'
            }[resultObj.code]
            if (resultObj.error) {
              errMsg += resultObj.error
            }
            this.result = {error: errMsg}
          } else {
            const {phonetic} = resultObj;
            this.result = resultObj;
            this.result.error = '';
            this.result.phonetic = resultObj.response.result.translation;
          }
        } , noop );
      // 只有在一种特殊情况下才会走进 catch 分支:
      // 消息发送出去后但还没得到响应时就被后台断开了连接.
      // 不过出现这种情况的可能性极低.
    } ,

    /**
     * 交换源语种与目标语种
     */
    exchangeLocale() {
      const {to,from} = this.query;
      this.query.to = from;
      this.query.from = to;
    } ,

    /**
     * 打开设置页
     */
    openOptions() {
      this.$options.client.send( 'open options' );
    } ,

    /**
     * 复制文本
     * @param {String|String[]} textOrTextArray
     * @param {MouseEvent} event
     */
    copy( textOrTextArray , event ) {
      if ( Array.isArray( textOrTextArray ) ) {
        textOrTextArray = textOrTextArray.join( 'n' );
      }
      this.$options.client.send( 'copy' , textOrTextArray );

      const {target} = event ,
        original = target.textContent;
      target.textContent = '已复制';
      setTimeout( ()=> target.textContent = original , 2000 );
    } ,
    /**
     * 添加单词
     * @param {String|String[]} textOrTextArray
     * @param {MouseEvent} event
     */
    addWord(text, event) {
      chromeCall('storage.local.get', ['access_token'])
        .then((res) => {
          if (res.access_token) {
            this.access_token = res.access_token;
            this.queryWord(text, event);
          } else {
            alert('未绑定扇贝账号,请授权绑定')
            this.gotoAccessToken();
          }
        });
    },
    /**
     * 添加单词
     * @param {String|String[]} textOrTextArray
     * @param {MouseEvent} event
     */
     addGlossary(text, event) {
      chromeCall('storage.local.get', ['reddwarf_access_token'])
        .then((res) => {
          if (res.access_token) {
            this.access_token = res.access_token;
            this.queryWord(text, event);
          } else {
            alert('未绑定红矮星账号,请授权绑定')
            this.gotoReddwarfAccessToken();
          }
        });
    },
    gotoAccessToken() {
      chrome.runtime.sendMessage({ action: 'shanbay_authorize' })
    },
    gotoReddwarfAccessToken() {
      chrome.runtime.sendMessage({ action: 'reddwarf_authorize' })
    },
    queryWord(text, event) {
      let params = { word: text, access_token: this.access_token }
      request.get('https://api.shanbay.com/bdc/search/')
        .query(params)
        .end((err, res) => {
          switch (res.status) {
            case 200:
              let info = res.body
              if (info.status_code == 0) {
                this.realAddWord(info.data.id, event);
              } else {
                alert(`查词错误, ${info.msg}`)
              }
              break;
            case 401:
              alert('token 失效,请重新授权')
              this.gotoAccessToken()
              break;
            case 429:
              alert('今日请求次数过多')
              break;
            default:
              alert(`未知错误, ${err}`)
              break;
          }
        })
    },

    realAddWord(id, event) {
      let params = { id: id, access_token: this.access_token }
      request.post('https://api.shanbay.com/bdc/learning/')
        .type('form')
        .send(params)
        .end((err, res) => {
          switch (res.status) {
            case 200:
              let info = res.body
              if (info.status_code == 0) {
                const { target } = event;
                let original = target.textContent;
                target.textContent = '已添加';
                setTimeout(() => target.textContent = original, 2000);
              } else {
                alert(`添加单词发生错误, ${info.msg}`)
              }
              break;
            default:
              alert(`添加单词发生错误, ${err}`)
              break;
          }
        })
    },

    /**
     * 播放语音
     * @param {String|String[]} textOrTextArray
     * @param {String} [lang] - 文本的语种
     */
    play( textOrTextArray , lang ) {
      if ( Array.isArray( textOrTextArray ) ) {
        textOrTextArray = textOrTextArray.join( 'n' );
      }
      this.$options.client.send( 'play' , {
        text : textOrTextArray ,
        api : this.query.api ,
        from : lang
      } );
    }
  } ,
  mixins : [ widgetMixin ]
} );

I read the docs that tell me should register the custom lable like this:

components : {
    'st-span' : <component>
  },

but I did not know how to implement the custom <component>, how to define the <component> of st-span/st-div/st-footer?

How to put div above another div and increase height of background div

I am new to html and css. I have seen this question asked many times but I can’t seems to get it working to fit my problem.

I have 3 div tags. when the user swipe the top div tag I want the the bottom div tag to increase its height and cause the web page to scroll. then move all the div tags align at the top.

The reason I am doing this is; this will cause webpage running on a mobile to go to full screen.

  <div id="backExpander" style="height: 100%; display: inline-block; position: relative;">
  </div>
  <div id="canvasHolder" style="width: 100%; height: 100%;background-color: transparent;">
  <canvas id="GameCanvas" oncontextmenu="event.preventDefault()" tabindex="0"></canvas>
  </div>

  <div id="swipeUpHolder" style="height: 100%; width: 100%; display:block;"  >
  </div>

The script I am using is;

document.getElementById("swipeUpHolder").addEventListener('touchmove', onTouchMove, {passive: false});

function onTouchMove(e)
{
  e.preventDefault

  document.getElementById("backExpander").style.height = "120%";
 
  setTimeout((function() {
                
        document.getElementById("swipeUpHolder").style.display = "none";
        window.scrollTo(0, 0);
          }
        ), 50);
}

As you can see I am increasing the height of background div but it does not do anything.

if I increase height of top div, this will work

document.getElementById("swipeUpHolder").style.height = "120%";

But I want to hide the top div. use the bottom div to push the page to go into scroll.

Can anyone provide some advice on how to fix this?

Where in the ECMAScript specification can I find the reason about why {} !== {}?

In JavaScript We all know that {} !== {} – they are different objects allocated on heap. But I was trying to find the reason at the language specification level.

at https://tc39.es/ecma262/#sec-samevaluenonnumeric it says

  1. If x and y are the same Object value, return true. Otherwise, return false.

But it is unclear to me how the spec defines exactly when two objects are considered to have the same Object value. Like {} and {} clearly do not have the same value but how exactly is it defined in the spec?