Ответы пользователя по тегу HTML
  • Нужно ли Frontend разработчику мониторить обновления?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    За обновлениями периодически нужно следить, просто, чтобы знать, что меняется, появляется или удаляется из новых версий. Нужно ли обновлять - это уже вопрос потребностей проекта, клиента, команды.

    Я обычно просматриваю изменения ключевых пакетов/библиотек раз в 1-3 месяца.

    В большом проекте ключевые пакеты/библиотеки может быть сложно обновить, особенно если меняется номер старшей (major) версии (например, Bootstrap v4 => v5). Несущественные изменения (minor), в некоторых случаях могут иметь ощутимые последствия, что-то может сломаться или изменится поведение.

    Я бы не стал просто так обновлять такой пакет, как Bootstrap. Если обновление ключевого пакета происходит, то это неизбежно увеличит нагрузку на QA команду (quality assurance - обеспечение качества, тестирование). В случае с Bootstrap, вероятно придется весь проект перетестировать. Без автоматического тестирования будет особенно тяжко.

    С мелкими пакетами, которые используются в изолированных частях проекта, проще, их можно хоть каждый день обновлять, если конечно появляются необходимые изменения.

    Если вы используете менеджер пакетов, например npm, то скорее всего он вам будет показывать предупреждения об обнаруженных уязвимостях в пакетах и варианты их устранения. За этим лучше следить, чтобы потом не было неприятных сюрпризов. Как правило, с менеджером пакетов это делать проще, достаточно будет проверить отдельные предупреждения, а не все пакеты.

    Ну и главное, не делать просто так обновления на текущей активной версии проекта. Чем дольше проект с обновленными пакетами будет находиться на тестировании, тем лучше.
    Ответ написан
    Комментировать
  • При отправки файла с сайта вместо одного приходит сразу два в чём проблема?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Две части с Content-Disposition и каждая attachment (вложение).

    5b1e48689868e497681523.png
    Ответ написан
    Комментировать
  • Как изменять картинки нажатием на кнопки "вперёд" "назад"?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Это WebFroms или MVC?

    Если WebFroms, то просто сделать обработчик нажатия по ссылке/кнопке, в котором установуть нужный файл в <asp:Image />.

    Например, код на странице может быть таким:
    <asp:LinkButton ID="lnkPrev" 
      Text="Назад" 
      RunAt="server"
      OnClick="lnkPrev_Click"
    />
    
    <asp:Image ID="Image1" 
      ImageUrl="~/img/1.jpg"
      RunAt="server"
    />
    
    <asp:LinkButton ID="lnkNext" 
      Text="Вперёд" 
      RunAt="server"
      OnClick="lnkNext_Click"
    />

    Код обработчиков может быть таким:

    protected void lnkPrev_Click(object sender, EventArgs e)
    {
      // получаем список файлов в папке ~/img
      var files = System.IO.Directory.GetFiles(Server.MapPath("~/img"));
      // текущий путь берем из Image1.ImageUrl
      var currentPath = Server.MapPath(Image1.ImageUrl);
    
      // ищем текущий путь среди полученных файлов
      int index = Array.IndexOf(files, currentPath);
    
      // проверяем, нашлось что-то или нет
      if (index != -1)
      {
        // проверяем, можно получить предыдущий файл или нет
        if (index - 1 > 0)
        {
          // можно, берем его
          Image1.ImageUrl = String.Format("~/img/{0}", System.IO.Path.GetFileName(files[index - 1]));
        }
        else
        {
          // нельзя, берем последний из списка
          Image1.ImageUrl = String.Format("~/img/{0}", System.IO.Path.GetFileName(files[files.Length - 1]));
        }
      }
    }
    
    protected void lnkNext_Click(object sender, EventArgs e)
    {
      var files = System.IO.Directory.GetFiles(Server.MapPath("~/img"));
      var currentPath = Server.MapPath(Image1.ImageUrl);
          
      int index = Array.IndexOf(files, currentPath);
    
      if (index != -1)
      {
        // проверяем, есть файлы впереди или нет
        if (files.Length > index + 1)
        {
          // есть, берем следующий файл
          Image1.ImageUrl = String.Format("~/img/{0}", System.IO.Path.GetFileName(files[index + 1]));
        }
        else
        {
          // нет, берем первый из списка
          Image1.ImageUrl = String.Format("~/img/{0}", System.IO.Path.GetFileName(files[0]));
        }
      }
    }


    При желании, можно сделать один обработчик для обоих ссылок/кнопок с помощью CommandArgument.
    <asp:LinkButton ID="lnkPrev" 
      Text="Назад" 
      RunAt="server"
      CommandArgument="-1"
      OnClick="LinkButton_Click"
    />
    
    <asp:Image ID="Image1" 
      ImageUrl="~/img/1.jpg"
      RunAt="server"
    />
    
    <asp:LinkButton ID="lnkNext" 
      Text="Вперёд" 
      RunAt="server"
      CommandArgument="1"
      OnClick="LinkButton_Click"
    />

    protected void LinkButton_Click(object sender, EventArgs e)
    {
      var lnk = (LinkButton)sender;
      var files = System.IO.Directory.GetFiles(Server.MapPath("~/img"));
      var currentPath = Server.MapPath(Image1.ImageUrl);
          
      int index = Array.IndexOf(files, currentPath);
    
      // если подумать, то этот блок кода можно уменьшить
      if (index != -1)
      {
        if (lnk.CommandArgument == "1")
        {
          if (files.Length > index + 1)
          {
            Image1.ImageUrl = String.Format("~/img/{0}", System.IO.Path.GetFileName(files[index + 1]));
          }
          else
          {
            Image1.ImageUrl = String.Format("~/img/{0}", System.IO.Path.GetFileName(files[0]));
          }
        }
        else
        {
          if (index - 1 > 0)
          {
            Image1.ImageUrl = String.Format("~/img/{0}", System.IO.Path.GetFileName(files[index - 1]));
          }
          else
          {
            Image1.ImageUrl = String.Format("~/img/{0}", System.IO.Path.GetFileName(files[files.Length - 1]));
          }
        }
      }
    }


    Для MVC будет совсем по-другому.

    Красивее всего это делать со стороны клиента, с помощью JavaScript.
    Ответ написан
  • Как добавить строку в таблицу в ReactJS?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Если вы хотите что-то изменить в текущем компоненте, то используйте состояние (setState).

    Если вы хотите изменить дочерний компонент, меняйте состояние текущего (setState) и передавайте измененные данные из состояния (state) дочернему компоненту через props.

    В вашем примере, корневой компонент - Table, в который вы передаете свойства (props): head_names и rows. Если вы хотите сделать возможность добавлять новую строку в Table, то вам следует сделать контейнер, в который поместить Table и кнопку (или другой элемент) для добавления новых строк. В состояние (state) контейнера нужно добавит head_names и rows, на основе которых и будет создаваться таблица.

    class TableManagement extends React.Component {
    
      constructor(props) {
        super(props);
        
        this.state = {
          head_names: ['qwe0', 'qwe1'],
          rows: [
            [1, 2],
            [3, 4]
          ]
        };
      }  
    
      AddRow() {
        let newRows = this.state.rows;
        newRows.push([0, 0]);
        this.setState({rows: newRows});
      }
    
      render() {
        return (
          <div>
            <Table head={this.state.head_names} rows={this.state.rows} />
            <hr />
            <button onClick={ this.AddRow.bind(this) }>Add row</button>
          </div>
        );
      }
    }
    
    class Table extends React.Component {
      render() {
        return (
          <table>
            <thead>
              {this.genHead()}
            </thead>
            <tbody>
              {this.genRow()}
            </tbody>
          </table>
        );
      }
    
      genHead() {
        var head = this.props.head;
    
        return head.map(function(v, i) {
          return (
            <th key={'th' + i}>
              {v}
            </th>
          );
        });
      }
    
      genRow() {
        var rows = this.props.rows;
    
        return rows.map(function(v, i) {
          var tmp = v.map(function(v2, j) {
            return (
              <td key={'td' + i + '_' + j}>
                {v2}
              </td>
            );
          });
    
          return (
            <tr key={'tr' + i}>
              {tmp}
            </tr>
          )
        });
      }
    }
    
    ReactDOM.render(
      <TableManagement />,
      document.getElementById('root')
    );

    https://jsfiddle.net/m11x34fp/

    В процессе разработки, важно определиться, кто будет тупым, а кто умным :-)

    Тупые (простые) компоненты - это компоненты, которые ничего не делают, просто принимают свойства и рисуются.

    Умные компоненты способны управлять состоянием, как своим, так и передавать его своим тупым отпрыскам потомкам :-)

    Если компонентов много, и особенно, если много вложенных компонентов, то следует хорошо продумать роль каждого компонента. Один умный компонент с множеством тупых вложенных компонентов - это самый простой вариант. Если дети тоже будут умными и должны будут общаться с компонентами своего уровня (братьями и сестрами) или верхнего уровня (дедушками, бабушками и выше), то организовать взаимодействие между компонентами будет сложно, будут конфликты, лишние обновления, в худшем случае зацикливание. Для решения проблем таких масштабов можно использования библиотеки управления состоянием, такие как Redux, Flux и т.п.
    Ответ написан
    2 комментария
  • Как в MS Visual Studio сделать фрагмент кода (html) inline?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    В самой студии такого не припомню.

    Можно макрос написать, но лучше расширение поискать.

    Например, в CodeMaid есть функция Joining для склейки нескольких строк в одну.

    Или JoinLines - более легкий вариант.

    По горячим клавишам, если будут проблемы или просто захочется их переопределить, то сделать это можно в настройках Visual Studio: меню Сервис => Параметры => Окружение => Клавиатура.

    50ca11b86dad4ea7a2a7a096072e27bd.png
    Ответ написан
    Комментировать
  • Datapicker криво отображает дату?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Используйте русскую локализацию:

    <script src="i18n/datepicker-ru.js"></script>
    $('#datepicker').datepicker($.datepicker.regional[ 'ru' ]);

    Скачать нужные ресурсы можно отсюда:
    https://github.com/jquery/jquery-ui/tree/master/ui/i18n

    Если вам нужен календарь на английском (или другом) языке, то задать первый день недели можно следующим образом:

    $('#datepicker').datepicker({ firstDay: 1 });
    // или
    $('#datepicker').datepicker('option', 'firstDay', 1);

    Посмотреть рабочий пример

    0 - воскресенье (Su - Sunday)
    1 - понедельник (Mo - Monday)
    и т.д.
    Ответ написан
    Комментировать
  • Как создавать свои атрибуты без проблем с валидацией?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    data-любоеИмя
    Ответ написан
    Комментировать
  • Как использовать встроенные стили css?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Встроенные стили имеет смысл использовать, когда нужно создать одну страничку, чтобы не было дополнительных файлов.

    В некоторых случаях, можно использовать внедренные стили для оформления процесса загрузки страницы, до момента подтягивания внешних файлов (стилей, шрифтов, скриптов).

    Встроенные стили могут использовать для корректировки существующих стилей, если лень ковыряться в файлах CSS и количество исправлений незначительное и единоразовое.

    Приложения JavaScript могут содержать упакованные стили и встраивают их в HTML при инициализации. Это вполне нормальная практика. Однако если стилей очень много, их обычно выносят в отдельный файл.
    Ответ написан
    Комментировать
  • Как сделать связанные select?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Каскадные списки (cascade dropdown) это называется:
    https://github.com/dnasir/jquery-cascading-dropdown
    www.dnasir.com/github/jquery-cascading-dropdown/de...
    Ответ написан
    Комментировать
  • Как по клику заменить слово на другое и при повторном клике обратно?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    <div class="clickme">
    Нажми на меня!
    </div>

    $('.clickme').click(function(){
      if (!$(this).data('status')) {
        $(this).html('Молодец! А еще раз слабо?');
        $(this).data('status', true);
      }
      else {
        $(this).html('Ну ты гигант! А может еще раз?');
        $(this).data('status', false);
      }
    });

    https://jsfiddle.net/alekseynemiro/bu0zfgz4/
    Ответ написан
    1 комментарий
  • Как правильно создать кнопку "поделиться" в facebook?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Адрес нужно указывать. В вашем примере, вместо адреса передается текст "URL".

    Можно сделать передачу параметров через объект, для гибкости:
    Share = {
      getParams: function(params) {
        // используем полученные параметры, 
        // либо создаем пустой объект, чтобы не было ошибок
        params = params || {};
        // в качестве url используем params.url,
        // либо адрес текущей страницы (window.location.href), если params.url не указан
        params.url = params.url || window.location.href;
        // используем params.title, либо заголовок документа
        params.title = params.title || document.title;
        // и т.п.
        params.description = params.description || '';
        params.img = params.img || '';
    
        return params;
      },
    
      vkontakte: function(params) {
        params = Share.getParams(params);
        url = 'http://vkontakte.ru/share.php?';
        url += 'url=' + encodeURIComponent(params.url);
        url += '&title=' + encodeURIComponent(params.title);
        url += '&description=' + encodeURIComponent(params.description);
        url += '&image=' + encodeURIComponent(params.img);
        url += '&noparse=true';
        Share.popup(url);
      },
    
      facebook: function(params) {
      	params = Share.getParams(params);
        url = 'http://www.facebook.com/sharer.php?s=100';
        url += '&p[title]=' + encodeURIComponent(params.title);
        url += '&p[summary]=' + encodeURIComponent(params.description);
        url += '&p[url]=' + encodeURIComponent(params.url);
        url += '&p[images][0]=' + encodeURIComponent(params.img);
        Share.popup(url);
      },
    
      twitter: function(params) {
        params = Share.getParams(params);
        url = 'http://twitter.com/share?';
        url += 'text=' + encodeURIComponent(params.description);
        url += '&url=' + encodeURIComponent(params.img);
        url += '&counturl=' + encodeURIComponent(params.img);
        Share.popup(url);
      },
    
      popup: function(url) {
        window.open(url, '', 'toolbar=0,status=0,width=626,height=436');
      }
    };

    <span title="Поделиться в Facebook">
      <a onclick="Share.facebook({url: 'https://toster.ru/q/294480'})">
        <i class="facebook square icon">Facebook</i>
      </a>
    </span>
    <span title="Поделиться в Twitter">
      <a onclick="Share.twitter({description: 'Hello world!'})">
        <i class="twitter square icon">Twitter</i>
      </a>
    </span>
    <span title="Поделиться ВКонтакте">
      <a onclick="Share.vkontakte({url: 'https://toster.ru/q/294480', description: 'Ответ на вопрос', 
    title: 'Как правильно создать кнопку «поделиться» в facebook?'})">
      <i class="vk icon">VK</i>
      </a>
    </span>

    Посмотреть.

    Если память не изменяет, Facebook с недавних пор (или уже давних) игнорирует передаваемые описания и заголовки страниц и извлекает необходимую информацию самостоятельно, непосредственно с указанной ссылки (преимущественно из тегов Open Graph).
    Ответ написан
    1 комментарий
  • Кнопка поделиться в соц сетях для каждой записи?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Share42 - неплохой готовый скрипт.

    <h2>Запись #1</h2>
    <div class="share42init" 
      data-url="http://ссылка на запись" 
      data-title="Заголовок записи" 
      data-description="Описание записи">
    </div>
    
    <h2>Запись #2</h2>
    <div class="share42init" 
      data-url="http://ссылка на запись 2"
      data-title="Заголовок записи 2">
    </div>
    
    <h2>Запись #3</h2>
    <div class="share42init" 
      data-url="http://ссылка на запись 3" 
      data-title="Заголовок записи 3">
    </div>
    
    <script type="text/javascript" src="http://site.name/share42/share42.js"></script>
    Ответ написан
    Комментировать
  • Как указать корень локального сайта?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Указать mysite.ru.local в файле конфигурации сайта:
    <VirtualHost 127.0.0.1:80>
      DocumentRoot /home/mysite.ru/www
      ServerName mysite.ru.local
      # ServerAlias mysite.ru
      # ...все остальное...
    </VirtualHost>

    Чтобы в браузере сайт открывался по указанному адресу, можно прописать его в файле hosts.

    Под Linux см. файл /etc/hosts.
    Под Windows см. C:\Windows\System32\drivers\etc\hosts.
    (с правами администратора)

    В файл hosts нужно указать имя хоста и IP сервера. Например:

    127.0.0.1 mysite.ru.local

    Вместо .local лучше использовать другую зону, т.к. с .local могут быть проблемы. Можно просто mysite, либо mysite.serverName.
    Ответ написан
    Комментировать
  • Как защитить HTML5 игры?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Flash можно же декомпилировать, так что уповать на то, что исходный код будет защищен, не стоит.

    Пишите код, патентуйте, отслеживайте и судитесь с нарушителями.

    Основной функционал можно вывести на сервер, чтобы клиентская часть была бесполезной.

    Клиентский код можно сделать плохочитаемым, обфусцировать.
    Ответ написан
    Комментировать
  • Как вставить в HTML полученную строку из адресной строки?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Выделить нужную часть адреса после решетки (#) можно примерно так:
    var hash = window.location.hash;
    
    if (hash.length > 1) 
    {
        alert('Маркер доступа: ' + hash.substring(hash.indexOf('=') + 1));
    }

    Пример

    Этот код должен быть на странице, указанной в redirect_uri, т.е. в данном случае, на странице:
    http://localhost

    Как видно, маркер доступа (access token) вырезается из window.location.hash. Его можно передать, например, в переменную:
    var access_token = hash.substring(hash.indexOf('=') + 1);


    Если планируется использовать другой адрес, то необходимо указать его в настройках конкретного приложения.

    К сожалению, Instagram, на данный момент, позволяет указывать только один адрес обратного вызова для одного приложения.

    Адрес обратного вызова (redirect_uri) в запросе на авторизацию должен полностью совпадать с тем, который указан в настройках приложения (исключая параметры запроса).

    ----------------------------------------------------------------

    ?client_id=64c696ae6b32405a8efcd83889c571be&redirect_uri=http://localhost&response_type=token

    Лучше кодировать параметры URL, чтобы не было проблем.

    PS: Если маркер доступа (access token) в тексте вопроса настоящий, то это небезопасно. Лучше удалить и получить новый.
    Ответ написан
    1 комментарий
  • Вчера работал jQuery, cегодня нет. Поможете разобраться?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Дело в коде, размещенного в переменной $js:
    $(document).ready(function(){
      $(".debug_loginbutton").click(function(){
        $("#div_debug_loginbutton").css("display": "none");
        $("#a_load").css("display": "block");
        $("#content").load("ajax/login");
      })
    })

    Неправильный разделитель:
    $("#div_debug_loginbutton").css("display": "none");
    $("#a_load").css("display": "block");

    Запятая должна быть:

    $("#div_debug_loginbutton").css("display", "none");
    $("#a_load").css("display", "block");

    Выявил за несколько секунд методом тупого исключения, о котором писал в комментариях выше :-)

    На правах рекламы:
    Метод тупого исключения - надежный метод поиска ошибок в коде, особенно вечером, когда глаза не видят, мозг не думает, а отладчик не работает или его вообще нет. Воспользуйся методом тупого исключения сейчас и получи дополнительное время в подарок!
    Ответ написан
  • Как отсортировать элементы по атрибуту?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Пример с использованием jQuery:
    $('li[sort]').sort(function (a, b) {
      return parseInt($(a).attr('sort'), 10) < parseInt($(b).attr('sort'), 10) ? -1: 1;
    }).appendTo('ul');

    Посмотреть результат.

    И да, для пользовательских атрибутов лучше использовать префикс data-, чтобы все соответствовало стандартам :-)

    Вот еще пример, с изменением направления сортировки.
    Ответ написан
    Комментировать
  • Как воспользоваться zeroclipboard?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Довольно капризная штука. Сколько раз сталкивался, постоянно какие-то проблемы.

    <div class="main-body">
    	<div class="result">
    		<div id="source">Скопируй меня, если не боишься!</div>
    	</div>
    	<button id="ButtonCopy">Копировать</button>
    </div>
    
    <script src="ZeroClipboard.min.js" type="text/javascript"></script>
    
    
    <script type="text/javascript">
    	var CopyText = document.getElementById('source').innerHTML;
    	var clip = new ZeroClipboard(document.getElementById('ButtonCopy'), { moviePath: 'ZeroClipboard.swf' });
    
    	clip.on('mousedown', function (client) {
    		client.setText(CopyText);
    	});
    
    	clip.on('complete', function (client, args) {
    		alert('Текст: "' + args.text + '" успешно помещен в буфер обмана!');
    	});
    
    	clip.on('noflash', function (client) {
    		alert("А <s>компот</s> Flash?");
    	});
    </script>


    Если просто в браузере открыть, может не сработать. Нужно с localhost или с сайта смотреть.

    Вот пример, у меня работает.
    Ответ написан
    1 комментарий
  • Как сделать переход в jquery autocomplette?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Обрабатывать события change, select и close. Использовать дополнительный атрибут, который будет содержать признак выбранности значения из списка:
    $( "#tags" ).autocomplete({
          source: availableTags,
          change: function(){
            $(this).attr('data-select', $(this).val() != '');
          },
          select: function(){
            $(this).attr('data-select', true);
          },
          close: function(){
            if($(this).attr('data-select')!='true'){
              $(this).val('');
            }
          }
    });

    Посмотреть, как это работает.

    Если понадобится использование autocomplete жестко, чтобы пользователь мог выбирать только из списка, то можно добавить дополнительный обработчик change текстовому полю и удалять введенные данные, если они не были выбраны из списка:
    $( "#tags" ).change(function(){
        if($(this).attr('data-select')!='true'){
          $(this).val('');
        }
    });

    Посмотреть на работу можно тут.
    Ответ написан
    Комментировать
  • Как нужно чтоб выглядел текст?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Как я понимаю, проблема в шрифтах?

    Если так, то просто нужно указать необходимый шрифт(ы) в font-family:
    .detail{
        width: 100%;
        background-color: #dcd6c6;
        font-family: Calibri,Candara,Segoe,Segoe UI,Optima,Arial,sans-serif; 
    }

    Какой именно нужен, не скажу, поставил что первое попалось :)

    font-size можно еще поиграть.
    и color до кучи.
    В общем, проблема обширная, можно диссертацию писать :)
    Ответ написан
    2 комментария