• Возможно ли изменить поведение contentEditable?

    Aetae
    @Aetae
    Тлен
    Поменять поведение - нельзя.
    Отслеживать изменения и переписывать - можно, но не нужно.
    Ответ написан
    Комментировать
  • Как сделать фильтрацию?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Чтоб сделать фильтрацию просто делаешь так:
    const [selected, setSelected] = useState('all');
    
      let filterdTodos;
      switch(selected) {
        case 'all':
          filterdTodos = todos;
          break;
        case 'checked':
          filterdTodos = todos.filter(t => t.checked);
          break;
        case 'notChecked':
          filterdTodos = todos.filter(t => !t.checked);
          break;
      }

    Или так, с оптимизацией:
    const [selected, setSelected] = useState('all');
    
      const filterdTodos = useMemo(() => {
        switch(selected) {
          case 'all':
            return todos;
          case 'checked':
            return todos.filter(t => t.checked);
          case 'notChecked':
            return todos.filter(t => !t.checked);
        }
      }, [selected, todos])

    <select className="todos__filter" onChange={(event) =>setSelected(event.target.value)}>
    ...
    {filterdTodos.map(...)}
    Ответ написан
  • Как решить проблему исчезновения данных товаров при перезагрузке страницы во Vue.js приложении?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Во-первых: не используй onMounted внутри стора. onMounted - это хук компонента, а не стора. Оно работает только благодаря стечению обстоятельств.
    Во вторых: products должны быть ref. Сейчас они не реактивны(никак не реагируют на изменения). При этом ты присваииваешь массиву value. То что это хоть как-то работало - очередное чудо.
    В-третьих: ты должен учитывать, что какое-то время данные будут грузиться и показывать лоадер пока их нет.

    В общем если загрузка должна начинаться в лбом случае при первой инициализации store'a(обычно загрузку привязывают к маршрутам или компонентам), то выглядеть оно будет как-то так:
    export const useAllMainFiltersStore = defineStore('allMainFilters', () => {
      const products = ref([]);
    
      try {
        async function getStoreData() {
          sidebarResizeStore.updateSidebarVisibility()
          const data = await productsData();
          products.value = data;
        }
        getStoreData()
      } catch (error) {
        console.error('Error:', error);
      }
      
      return {
        products,
      }
    })


    В компоненте:
    const route = useRoute();
    // продукт делаем вычисляемым, чтоб не городить вотчеров
    const product = computed(() => getProductById(route.params.id));
    
    function getProductById(id) {
      console.log('products component: ', mainFiltersStore.products) //при первой загрузке всё ок, при перезагрузке страницы всё ломается и пустой массив в придачу
      return products.find(product => product.id == id);
    }
    
    watch(product, current => {
      // проверяем что продукт есть
      if (current) fetchComments(current.id);
    }, { immediate: true })
    Ответ написан
    3 комментария
  • Откуда берутся iron icon?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Ну собсно как и всегда когдадокументация говно - идёшь на гитхаб, там открываешь код и смотришь как оно работает.
    Тут благо прямо в коде есть ссылка на описание кастомных иконсетов. Точно также как там в примере кастомный иконсет inline, тут используется кастомный иконсет settings.
    Ответ написан
  • Почему при отсчете времени на iPhone выводит 'NaN' вместо цифр?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Ну потому что 2023-10-21 7:00:00 PM GMT+0300 - это херпойми какой формат. То что его чудом жрёт хром - это случайность.
    Используй ISO: 2023-10-21T19:00:00+0300
    Ответ написан
    Комментировать
  • Какие символы разрешены в email?

    Aetae
    @Aetae
    Тлен
    Всё фигня, вот такой регулярки достаточно: /^\S+@\S+$/. Да это чуть шире чем можно, но именно что чуть, нет никакого смысла заморачиваться с чем-то большим. Не пройдёт письмо один раз из миллиона, ну и ладно.
    Ответ написан
    Комментировать
  • Почему на прод версии выдаёт ошибку?

    Aetae
    @Aetae Куратор тега Vue.js
    Тлен
    Ответ очевиден - не использовать недокументированные* свойства типа __vueParentComponent.:)

    Раз ты используешь options api у тебя есть this.$parent для родительского компонента или ты можешь использовать ref для выбора конкретного.

    Однако в любом случае обращение к родителю выглядит как говнокод. Пробрасывай значение в props из родителя и не городи огород.

    * Работа в режиме разработки и в режиме продакшена очень сильно отличается. Даже если ты видишь какие-то свойства в консоли, то, если они не документированы, значит полагаться на то, что ни будут там всегда - ни в коем случае нельзя. Особенно на явно помеченные как внутренние через нижнее подчёркивание.
    Ответ написан
    Комментировать
  • Можно ли передать нужный тип переменной в дженерик функции?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    getFormattedData тоже должен быть дженерик и собсно его(дженерик) прокидывать в нижестоящие.

    Типа того:
    type Type1 = 1;
    type Type2 = 2;
    type Type3 = 3;
     
    type ContainsType<T extends UniversalType = UniversalType> = {type: T};
    
    type UniversalType = Type1 | Type2 | Type3;
    
    
    class Cls {
      async getFormattedData<T extends UniversalType>(data: ContainsType<T>): Promise<T> {
            const anyDataObject = this.validateData(data);
            const result = this.formatDataByType(anyDataObject);
            return result;
      }
    
      validateData<T extends UniversalType = UniversalType>(data: ContainsType<T>): T {
        return data.type
      }
    
      formatDataByType<T extends UniversalType = UniversalType>(data: T): T {
        return data
      }
    
    }
    const foo = await new Cls().getFormattedData({type: 2}); // 2


    Если ты явно чему-то пропиваешь тип который никак не зависит от входного дженерика:
    const anyDataObject: Type1 | Type2 | Type3 = ...
    то какбэ всё - приехали, ты сам указал, что тут именно такой тип(во всём его многообразии) и пофиг на входные данные. Ты можешь дальше сузить тип внутри метода:
    if (anyDataObject === 2) {
      // тут anyDataObject для ts считается Type2
    }
    но это уже никак не повлияет на выходной тип.

    В общем выводить типы можно только если они зависят от входных данных(которые в свою очередь получаются через дженерик), иначе откуда TS узнает, что там от чего зависит.
    Если ты заранее даже приблизительно не знаешь, что придёт на вход, то и что пойдёт на выход ты ноже не знаешь, а не знаешь ты - не знает и, тем более, TS: там просто одни произвольные данные превратились в другие без использования логики. С тем же успехом можно попытаться вывести точный тип Math.random().
    Ответ написан
    Комментировать
  • Не видит значение input, как исправить?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Во-первых у input нет свойства length.
    var intxt=document.querySelector('input').length;
    intxt === undefined
    console.log вообще-то должен был тебе это показать.

    Далее: if(intxt.length<5){ тут ты пытаешься получить свойство length у unefined о чем тебе и пишет ошибка.

    Скорее всего ты хочешь что-то такое:
    var intxt=document.querySelector('input');
    ....
    if(intxt.value.length<5){
      ....
    } else {
    Ответ написан
    Комментировать
  • Почему пушатся коммиты которые я не делал в ветке?

    Aetae
    @Aetae
    Тлен
    Не бывает совсем "новых" веток - все ветки откуда-то растут.
    Если в запушеной ветке два коммита вместо одного, значит один из них уже был в той ветке, от которой вы отпочкованли "новую".
    Ответ написан
    Комментировать
  • Как убрать ободок от фона средствами CSS при использовании border-radius?

    Aetae
    @Aetae
    Тлен
    У тебя тут: .swiper-slide.category-banner__card::before чёрный background. Он и просвечивает.

    .swiper-slide.category-banner__card::before {
      background-color: transparent;
    }
    Ответ написан
  • При сборке к имени картинок добавляется хеш и картинки не отображаются. Как указывать путь к картинкам?

    Aetae
    @Aetae
    Тлен
    React - это тебе не Vue, он не умеет из коробки угадывать, что картинки надо импортировать.

    Для каждой картинки надо сделать руками:
    import img from './assets/img.jpeg'
    или использовать glob import.

    Ну либо положить картинки в public и брать их как есть по прямым путям относительно корня без всяких хэшей.

    Подробнее.
    Ответ написан
    Комментировать
  • Как расширить дженерик MutableRefObject добавив в него новое свойство?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Ну какбэ очевидно, что:
    interface MutableRefObject<T> {
      prev: null | HTMLParagraphElement; 
    }


    Если интeрфейс в либе, то:
    declare module 'lib-name' {
      interface MutableRefObject<T> {
        prev: null | HTMLParagraphElement; 
      }
    }

    Или, хуже:
    declare module 'lib-name/full/path/to/declaration.ts' {
      interface MutableRefObject<T> {
        prev: null | HTMLParagraphElement; 
      }
    }


    Но вообще, если для себя то делай так:
    interface MySuperMutableRefObject extends MutableRefObject<T> {
      prev?: null | HTMLParagraphElement; 
    }

    и не трогай библиотечный тип.
    Ответ написан
    6 комментариев
  • Можно ли сделать так, чтобы картинка которая прижата к правому краю экрана(с помощью position: absolute) не обрезалась при адаптирование?

    Aetae
    @Aetae
    Тлен
    Не прижимать её к правому краю с поморью absolute, вестимо.
    Например: положи во флекс и прижми с помощью flex-end. Потом моешь поставить ей max-width: полный размер, min-width: минимальный - чтоб сжималась если не влезает...
    Тащем верстай.
    Ответ написан
    Комментировать
  • При решении каких задач используют генераторы?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    В практике генераторы не используются. Конец. :)

    На самом деле я лично видел ровно два практических кейса использования генераторов:
    1. Использование для асинхронных операций с возможностью прерывания, примеры: redux-saga, mobx actions.
    Суть: допустим ты делаешь какую-то ступенчатую операцию, и нужна возможность резко остановить исполнение извне. На async-ax тебе придётся городить что-то типа:
    async function multiStep() {
      await step1();
      if (stop) throw new Error(stop);
      await step2();
      if (stop) throw new Error(stop);
      await step3();
      if (stop) throw new Error(stop);
    }
    и никак красивее не сделать.
    На генераторе ты можешь просто писать:
    function* multiStep() {
      yield step1();
      yield step2();
      yield step3();
    }

    и просто не брать следующее значение, если исполнение прервалось.

    2. До появления воркеров с их помощью можно было работать с очень большими массивами не вызывая зависания страницы.

    На этом всё.:)
    Ответ написан
    2 комментария
  • Почему в готовых шаблонах bootsnrap не подключают через cdn?

    Aetae
    @Aetae
    Тлен
    Возможно ты имеешь ввиду CDN?

    В таком случае всё зависит от преимуществ и недостатков, рассмотрим основные:
    Серьёзный недостаток: cdn под контролем третьей стороны: он может быть скомпрометирован, он может прекратить работу, он может тормозить.
    Потенциальное преимущество: cdn от крупных компаний может быть быстрее, т.к. сервера могут втыкаться прямо в точки обмена трафика и дублироваться максимально близко к пользователю.
    Устаревшее главное преимущество: раньше библиотека с cdn кэшировалась раз и навсегда для всех сайтов оную использующих. Закэшировал на одном сайте - на другом она уже в кэше. Увы, все современные браузеры "ради безопасности" реализуют cache partitioning или что-то подобное, где для каждого сайта свой кэш, что полностью исключает данное преимущество.

    Итого, в современном вебе недостаток перевешивает.
    Ответ написан
    3 комментария
  • Как использовать один компонент с разными типами данных?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Наверное ты хочешь этого:
    type Props = { data?: ITemplate } | {}
    const CreateTemplateForm: FC<Props> = (props) => {
      if ('data' in props && props.data) {
        
        return ...;
      }
    
      return ...;
    }
    Ответ написан
    5 комментариев
  • Как оптимизировать сайт под большие экраны?

    Aetae
    @Aetae
    Тлен
    Все ребята с большими экранами давно научились нажимать Ctrl++. Если ты хочешь тупо такое же масштабирование, то не надо*.

    Смысл что-то делать есть только если настоящий дизайнер разумно что-то придумает специально под такой масштаб.

    * Если очень хочется, то немного математики + transform: scale + изменение ширины скроллбаров, но результат будет - херня.:)
    Ответ написан
    Комментировать
  • Как добавить готоую форму amoCrm в Vue3?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Я хз что такое AmoCrm, но если надо тупо добавить не-vue скрипы как vue-компонент, то как-то так:
    import { ref, h } from 'vue';
    
    function loadScript(options, root = document.head) {
      return root.appendChild(Object.assign(document.createElement('script'), options));
    }
    
    const Comp = defineComponent(() => {
      const root = ref(null);
    
      onMounted(() => {
        loadScript(
          {
            innerHTML: `
          !(function (a, m, o, c, r, m) {
        (a[o + c] = a[o + c] || {
            setMeta: function (p) {
                this.params = (this.params || []).concat([p]);
            },
        }),
            (a[o + r] =
                a[o + r] ||
                function (f) {
                    a[o + r].f = (a[o + r].f || []).concat([f]);
                }),
            a[o + r]({
                id: "....",
                hash: "....",
                locale: "ru",
            }),
            (a[o + m] =
                a[o + m] ||
                function (f, k) {
                    a[o + m].f = (a[o + m].f || []).concat([[f, k]]);
                });
    })(window, 0, "amo_forms_", "params", "load", "loaded");
          `
          },
          root.value
        );
        loadScript(
          {
            id: 'amoforms_script_...',
            async: 'async',
            charset: 'utf-8',
            src: 'https://forms.amocrm.ru/forms/assets/js/amoforms.js?...'
          },
          root.value
        );
      });
    
      return () => h('div', { ref: root });
    });
    Ответ написан
  • Как запустить реакт код без локального сервера или как его получить?

    Aetae
    @Aetae
    Тлен
    Забудь о фронте без локального сервера. Это время ушло.
    Сейчас для локальных файлов столько ограничений, что работать с этим даже на чистом html уже толком невозможно.
    Ответ написан