Web sites as unintended silos: The problem with getting data in and out of the web client

Прежде чем вы прочитаете, вот несколько ошибок, которые я хотел бы, чтобы вы стали звездой, которая появилась в конце этой статьи.

Сеть как открытая и совместимая платформа изменила мир. Это позволяет нам просматривать, взаимодействовать и обмениваться информацией с помощью открытого набора API технологий, в частности, Link, HTTP и HTML. С помощью этих простых инструментов мы можем создавать сложные приложения и сервисы, которые взаимодействуют между сервером и сервером, а с сервера - пользователю, использующему браузер.

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

Web Intents - это технология, которая была направлена ​​на то, чтобы веб-сайты на клиенте имели возможность взаимодействовать с окружающим миром сразу: другие сайты и приложения, с которыми пользователь взаимодействовал на своем устройстве. Web Intents был тупиком, но проблема все еще существует, и мы непреднамеренно создаем силосы, которые блокируются за именем пользователя и локальным хранилищем данных.

Я по-прежнему увлечен получением данных в веб-приложениях и из них полностью в клиенте, и у нас есть ряд инструментов в нашем распоряжении, но позвольте мне сказать вам, мы делаем это очень сложно.

Мне нравится тот факт, что каждый веб-сайт в браузере пользователя - это собственная безопасная песочница, но одна вещь, которую мне бы хотелось увидеть в Интернете, - это изменение шага в интерфейсах о том, как получить данные из системы пользователей в песочницу и через определенные интерфейсы вытаскивают данные из песочницы обратно в систему пользователей.

Я начал работу на этом посту после того, как увидел, что iOS 11 будет поддерживать API перетаскивания в Интернете и после просмотра моего хорошего друга и коллеги Сэма Торогуда в разделе «Перетаскивание» (проверьте его), я хотел изучить это пространство намного больше.

** Ввод для перетаскивания **

В каком-то контексте я хотел создать приложение, которое будет действовать как панель с нуля и вставить bin, то есть вы можете удалить любую часть контента на веб-страницу, а затем вернуть ее позже, и этот пост документирует некоторые о проблемах, которые я нашел на этом пути.

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

Доступные взаимодействия

Начнем с способов получения данных с устройства-клиента на веб-сайт:

  • <input type=file>
  • Вставить из буфера обмена на жесте пасты пользователя
  • Перетаскивание извне браузера
  • Откройте веб-страницу с хоста

Получение данных с веб-сайта обратно клиенту

  • <a download>
  • Добавить данные в буфер обмена на жесте пользователя
  • Перетаскивание из браузера клиенту

Загрузка через сборщик

Я не буду вдаваться в подробности, но <input type=file>работает невероятно хорошо, как просто простой сборщик файлов.

Вы можете ограничить сборщик файлами типа <input type="file" accept="image/png" />.

Вы можете позволить пользователю выбрать более одного файла <input type="file" multiple />.

Вы также можете интегрировать с пользовательскими подборщиками, такими как камера <input type="file" captuaccept="image/*" capture>.

" `element даже имеет интерфейс, который позволяет вам проверять выбранные файлы. Довольно легко получить файл в песочнице браузера, если пользователь его выберет.

** Проблема 1 **: если у вас есть этот файл, вы не можете сохранить какие-либо изменения обратно в тот же файл на хосте, вы фактически имеете дело с копией файла.

** Проблема 2 **: Если хост обновляет файл, пока вы держите копию, вы не увидите обновлений.

Загрузка файла в основную ОС

Мы можем загрузить удаленный ресурс, просто используя атрибут download, например:<a href="someurl.html" download="output.html">Download .

Мы также можем динамически создавать контент в клиенте и загружать его на хост следующим образом:

function download() {
  var url = URL.createObjectURL(new Blob(['hello world at ', Date.now()], {'type': 'text/plain'}));
  var a = document.createElement('a');
  document.body.appendChild(a);
  a.style = 'display: none';
  a.href = url;
  a.download = 'hello.txt';
  a.click();
  URL.revokeObjectURL(url);
}

download();

Он прост и эффективен и теперь получает поддержку в Safari.

** Проблема 1 **: нет возможности интегрироваться с системами «Сохранить как», что означает, что пользователь не может выбрать, где файл будет выходить за пределы каталога загрузки браузера.

** Проблема 2 **: нет возможности записать файл обратно после его загрузки и на устройстве пользователя, как только он будет загружен, он исчезнет.

Использование буфера обмена для вставки данных в веб-страницу

Можно перехватить событие «onpaste», которое запускается, когда пользователь на странице вызывает жест жесткой системы, а затем совершает некоторую магию.

document.body.addEventListener("paste", function(e) {
  // You need to own it.
  e.preventDefault();

  // get all the types of things on the clipboard
  let types = e.clipboardData.types;

  // Get the text on the clipboard
  e.clipboardData.getData("text/plain"); 

  // Get a itterable list of items (Not on Safari)
  e.clipboardData.items
  
  // Get access to a file on the clipboard
  e.clipboardData.files[0]
});

Этот API выглядит относительно согласованным во многих браузерах (в отличие от этого)

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

** Проблема 1 **: больно отлаживать, консольное ведение журнала clipboardData не покажет вам правильные данные, вам нужно установить точку останова.

Использование буфера обмена для копирования пользовательских данных с веб-страницы

Можно перехватить события oncut и oncopy, которые запускаются, когда пользователь на странице вызывает копию системы и режет жесты, а затем добавляет ваш собственный пользовательский контент в системный буфер обмена.

document.body.addEventListener("copy", function(e) {
  // You need to own it.
  e.preventDefault();

  // Set some custom data on 
  e.clipboardData.setData("text/plain", "Hello World");

  // Add a user generated file to the clipboard
  e.clipboardData.items.add(new File(["Hello World"], "test.txt", {type: "text/plain"}));
});

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

** Проблема 1 **: Добавление файла в буфер обмена невозможно.

document.body.addEventListener("copy", function(e) {
  // You need to own it.
  e.preventDefault();

  // Add a user generated file to the clipboard
  e.clipboardData.items.add(new File(["Hello World"], "test.txt", {type: "text/plain"}));
});

API существует, но он нигде не работает. Если вы попытаетесь вставить на ту же страницу, которая добавила данные в объект clipboardData, свойствоclipboardData.files пусто. Если вы попытаетесь вставить результат в файловую систему, ничего не произойдет. Однако, если вы вставляете в текстовое поле, имя * * * вставлено *. Я не могу сказать, является ли это функцией безопасности, но она не документирована ни в одном из способов: mdash; Я задаю вопрос о существовании API, если это так.

** Проблема 2 **: предполагается, что все ваши буфера обмена будут работать синхронно в случае, это означает, что невозможно добавить данные в буфер обмена, который хранится в индексированном db.

document.body.addEventListener("copy", function(e) {
  // You need to own it.
  e.preventDefault();

  // Add a user generated file to the clipboard (Promise)
  getData.then(file => e.clipboardData.items.add(file));
});

Похоже, вам нужно мутировать буфер обмена в том же тике, что и событие, и это сильно ограничивает возможности API.

Перетаскивание с хоста на веб-страницу

API перетаскивания имеет много общего с API событий буфера обмена, поэтому теоретически это не удивительно сложно начать.

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

Как и в буфере обмена, у вас есть «элементы», и у вас также есть «файлы», чтобы вы могли видеть все вещи, которые были перетащены с хоста на страницу.

element.addEventListener('drop', e => {
  // Own it. nuff said.
  e.preventDefault();

  // Get the text on the clipboard
  e.dataTransfer.getData("text/plain"); 

  // Get a itterable list of items (Not on Safari)
  e.dataTransfer.items
  
  // Get access to a file on the clipboard
  e.dataTransfer.files[0]
});

Это на самом деле все выглядит довольно прилично.

Перетаскивание с веб-страницы на хост

API перетаскивания имеет много общего с API событий буфера обмена, поэтому теоретически это не удивительно сложно начать.

Существует нестандартный «mime-type», называемый DownloadURL. Это, похоже, не поддерживается в Firefox или iOS, оно поддерживается в Chrome. Вы даете браузеру URL-адрес для извлечения, и он инициирует загрузку после его перетаскивания за пределы браузера.

element.addEventListener('dragstart', e => {
  // Own it. nuff said.
  e.preventDefault();
  e.dataTransfer.dropEffect = "copy";
  e.dataTransfer.effectAllowed = "all";
  e.dataTransfer.setData("DownloadURL", `image/png:test.png:${$fileURL.href}`)
});

Это единственный известный способ перетащить файл из браузера и в ОС хост-пользователей.

** Проблема 1 **: DownloadURL полностью нестандартен и работает только в Chrome.

** Проблема 2 **: DownloadURL, похоже, не работает с URL-адресами Blob, это означает, что файлы, созданные в браузере, не могут быть вытащены.

** Задача 3 **: Запросы, управляемые с помощью DownloadURL, не обрабатываются Работодателем Сервиса.

** Проблема 4 **: dataTransfer имеет объектfiles, похожий на clipboardData, и так же, как интерфейсclipboardData, добавление файла к нему ничего не делает для операции перетаскивания.

** Проблема 5 **: опять же, подобно API-интерфейсу clipboardData, вы должны мутировать объект dataTransfer` синхронно в событии. Это делает невозможным взаимодействие с асинхронными хранилищами данных.

Изменения в веб-платформе, которые я хотел бы видеть

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

Стандартизировать DownloadURL для перетаскивания

Кажется, это разумно. Существует буквально нулевая ссылка на дизайн в любом месте в Интернете, и любые ссылки на списки спецификаций, кажется, были потеряны во времени.

Это похоже на то, как браузер управляет <a download>, аналогичен тому, как сегодня работает DownloadURL`, так что это может быть хорошим началом.

Разрешить добавление файлов в буфер обмена и операции перетаскивания

Я предполагаю, что есть причина, по которой он нигде не работает, но я ожидаю, что смогу «dataTransfer.files.add ([File])», и для этого это будет то, что находится в буфере обмена, и оно отбрасывается, когда пользовательский жест завершается.

Сделать события DOM, которые мутируют событие, хорошо работают с асинхронными операциями

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

Мне бы очень хотелось, чтобы эти события использовали ExtendableEvent, чтобы мы могли получить доступ кwaitUntil (или что-то подобное). По мере того, как сеть перемещается asnyc для операций хранилища данных, похоже, что мы также взаимодействуем с событиями.

Ввести API постоянных файлов

У нас нет разумного способа получить ссылку на файл и сохранить эту ссылку, чтобы ее можно было легко манипулировать. Мы можем сделать это в контексте нашего «веб-приложения» & mdash; сохранение файла IndexedDB не слишком сложное & mdash; но мы забиваем все наши данные внутри приложений и не позволяем им легко подключаться к хосту вокруг него.

Длинная игра

В настоящее время в экосистеме браузера существует несколько направлений развития, с одной стороны, у нас есть гонка в направлении Appiness и собственного паритета, а с другой - движение верности контента - внедрение API, таких как Grid, шрифты и чтобы мы могли доставлять контент быстро и качественно.

Многие из того, о чем я говорил сегодня, похоже, что он попадает в фокус «давайте сделаем веб-платформу приложений», и это, безусловно, является частью истории. Если нам нужен паритет с родным опытом, браузер и сайты в браузере должны действовать так, как будто они принадлежат к системе. Но я думаю, что для этого есть больше.

Я хочу видеть веб-сайт, где межсоединения между сайтами определяются не только ссылкой и HTTP-запросом на сервер, но и позволяют взаимодействовать между сайтами непосредственно на клиенте. Мы должны иметь возможность обнаруживать сервисы и возможности сайтов, которые пользователь использует и взаимодействует с ними, в то же время гарантируя, что идиомы хост-платформы доступны для всего контента в Интернете.

Я обеспокоен тем, что в долгосрочной перспективе, даже если у нас есть URL-адрес, у нас будет сеть, в которой легко получить данные в песочнице, но невозможно выйти на хост-систему или даже между другими сайтами в Интернете ,

Paul Kinlan

Trying to make the web and developers better.

RSS Github Medium