Случайны выбор дневника Раскрыть/свернуть полный список возможностей


Найдено 10775 сообщений
Cообщения с меткой

html - Самое интересное в блогах

Следующие 30  »
rss_rss_hh_new

Переходим на WebMarkupMin 2.X

Вторник, 26 Июля 2016 г. 22:47 (ссылка)

Логотипы WebMarkupMin, .NET Core и NUglify

Весной прошлого года, когда ASP.NET 5 был еще в стадии Beta 3, я начал получать от пользователей письма с просьбами сделать WebMarkupMin совместимым с DNX 4.5.1 и DNX Core 5.0. Основной проблемой было то, что новый .NET не поддерживал настройку с помощью конфигурационных файлов App.config и Web.config. Переписывание WebMarkupMin.Core, WebMarkupMin.MsAjax и WebMarkupMin.Yui не должно было представлять особой сложности, потому что нужно было просто удалить весь код, использующий библиотеку System.Configuration. Серьезные проблемы должны были возникнуть при переписывании ASP.NET-расширений, потому что для них нужно было разработать совершенно новую модель конфигурации, а это, в свою очередь, требовало очень серьезных изменений в архитектуре. Эти изменения затрагивали не только код, но и структуру решения и NuGet-пакеты, поэтому я решил начать с чистого листа и сделал репозиторий на GitHub. На тот момент, до релиза стабильной версии нового ASP.NET оставалось как минимум полгода, поэтому нужно было одновременно поддерживать 2 ветви WebMarkupMin: стабильную 1.X на CodePlex и предварительную 2.X на GitHub.



Как известно всем, выход стабильных версий .NET Core 1.0 и ASP.NET Core 1.0 задержался еще на несколько месяцев и состоялся только в конце июня этого года. Вслед за релизом этих фреймворков, состоялся и релиз WebMarkupMin 2.0. В этой статье я расскажу вам о том, как обновить существующие приложения под WebMarkupMin 2.X, а также как добавить его в веб-приложения, написанные на ASP.NET Core.



Критические изменения и нововведения



Для того чтобы установить пакеты WebMarkupMin 2.X вам необходимо обновить NuGet Package Manager до версии 2.8.6 или выше.



Основным критическим изменением версии 2.X стал отказ от использования файлов Web.config и App.config для настройки WebMarkupMin. Теперь при настройке вместо декларативного подхода (использование конфигурационных файлов) используется императивный подход (использование программного кода).



Поэтому при обновлении WebMarkupMin до версии 2.X нужно обязательно сделать 2 вещи:




  1. Удалить пакет WebMarkupMin.ConfigurationIntelliSense, т.к. в нем больше нет необходимости.

  2. После удаления устаревших пакетов и обновления старых версий пакетов до новых, необходимо удалить группу конфигурационных секций webMarkupMin и ее объявление из файлов Web.config и App.config:




















Далее рассмотрим процедуру обновления для каждого пакета в отдельности.



Core



После обновления пакета WebMarkupMin.Core нужно в коде вашего приложения заменить все подключения пространств имен WebMarkupMin.Core.Minifiers и WebMarkupMin.Core.Settings на WebMarkupMin.Core.



Внешние минификаторы CSS- и JS-кода



К сожалению, модули WebMarkupMin.MsAjax и WebMarkupMin.Yui не поддерживают .NET Core, и поэтому могут использоваться только в приложениях .NET 4.X, веб-приложениях ASP.NET 4.X и веб-приложениях ASP.NET Core, созданных на основе шаблона «ASP.NET Core Web Application (.NET Framework)». Это вызвано тем, что авторы Microsoft Ajax Minifier и YUI Compressor for .NET не портировали свои библиотеки под .NET Core. Про YUI Compressor for .NET не могу сказать ничего определенного, возможно через какое-то время его все-таки портируют. Насчет Microsoft Ajax Minifier уже все предельно ясно: его разработка была прекращена в марте 2015 года (после ухода Рона Логана из Microsoft). Но не все так плохо, потому что существует «форк» Microsoft Ajax Minifier под названием NUglify, который совместим с .NET Core. В новой версии WebMarkupMin есть пакет, основанный на нем — WebMarkupMin.NUglify.



MS Ajax



После обновления пакета WebMarkupMin.MsAjax нужно в коде вашего приложения заменить все подключения пространств имен WebMarkupMin.MsAjax.Minifiers и WebMarkupMin.MsAjax.Settings на WebMarkupMin.MsAjax.



YUI



После обновления пакета WebMarkupMin.Yui нужно в коде вашего приложения заменить все подключения пространств имен WebMarkupMin.Yui.Minifiers и WebMarkupMin.Yui.Settings на WebMarkupMin.Yui.



NUglify



На данный момент, API WebMarkupMin.NUglify полностью идентичен WebMarkupMin.MsAjax. Поэтому при переходе с WebMarkupMin.MsAjax на WebMarkupMin.NUglify в коде приложения достаточно просто заменить префиксы MsAjax на NUglify.



Расширения для интеграции с ASP.NET



Все пакеты с ASP.NET-расширениями для версии 1.X (WebMarkupMin.Web, WebMarkupMin.Mvc и WebMarkupMin.WebForms) признаны устаревшими и не используются в WebMarkupMin 2.X.



Перечислю основные нововведения в расширениях для ASP.NET:




  1. Переход на императивный подход к настройке расширений.

  2. Теперь можно ассоциировать типы содержимого (MIME-типы) с соответствующими минификаторами разметки.

  3. Появилась возможность указывать минификатору какие страницы сайта он должен обработать.





ASP.NET 4.X HTTP modules



Чтобы обновить веб-приложение ASP.NET, которое использует HTTP-модули из пакета WebMarkupMin.Web нужно выполнить следующие действия:




  1. Удалить пакет WebMarkupMin.Web.

  2. Установить пакет WebMarkupMin.AspNet4.HttpModules.

  3. Обновить оставшиеся старые пакеты WebMarkupMin до версии 2.X.

  4. В файле Web.config нужно заменить: пространство имен WebMarkupMin.Web.HttpModules на WebMarkupMin.AspNet4.HttpModules, имя сборки WebMarkupMin.Web на WebMarkupMin.AspNet4.HttpModules и имя класса CompressionModule на HttpCompressionModule.



Благодаря появлению возможности указывать минификатору какие страницы сайта он должен обработать, HTTP-модули HtmlMinificationModule и XhtmlMinificationModule теперь могут использоваться вместе.



ASP.NET 4.X MVC



Чтобы обновить веб-приложение ASP.NET MVC, которое использует фильтры действий из пакета WebMarkupMin.Mvc нужно выполнить следующие действия:




  1. Удалить пакеты WebMarkupMin.Mvc и WebMarkupMin.Web.

  2. Установить пакет WebMarkupMin.AspNet4.Mvc.

  3. Обновить оставшиеся старые пакеты WebMarkupMin до версии 2.X.

  4. В коде вашего приложения заменить все подключения пространства имен WebMarkupMin.Mvc.ActionFilters на WebMarkupMin.AspNet4.Mvc.



Стоит также отметить, что в отличии от старых версий WebMarkupMin, в версии 2.X вы можете применять фильтры действий к контроллерам:




using System.Web.Mvc;

using WebMarkupMin.AspNet4.Mvc;


namespace WebMarkupMin.Sample.AspNet4.Mvc4.Controllers
{
[CompressContent]
[MinifyHtml]
[MinifyXhtml]
[MinifyXml]

public class HomeController : Controller
{

}
}


Кроме того, в версии 2.X можно применять фильтры действий на уровне всего веб-приложения. Для этого нужно отредактировать файл App_Start/FilterConfig.cs следующим образом:



using System.Web.Mvc;

using WebMarkupMin.AspNet4.Mvc;

namespace WebMarkupMin.Sample.AspNet4.Mvc4
{
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{

filters.Add(new CompressContentAttribute());
filters.Add(new MinifyHtmlAttribute());
filters.Add(new MinifyXhtmlAttribute());
filters.Add(new MinifyXmlAttribute());

}
}
}


Также в прошлое ушли ошибки вида «The 'MinifyXXXAttribute' attribute can not be applied to the 'XXX' action method of the 'XXX' controller, because it returns the result with not supported content type.». Теперь, если тип содержимого результата действия не соответствует фильтру, то к этому результату просто не применяется минификация.



ASP.NET 4.X Web Forms



Чтобы обновить веб-приложение ASP.NET Web Forms, которое использует классы страниц или мастер-страниц из пакета WebMarkupMin.WebForms нужно выполнить следующие действия:




  1. Удалить пакеты WebMarkupMin.WebForms и WebMarkupMin.Web.

  2. Установить пакет WebMarkupMin.AspNet4.WebForms.

  3. Обновить оставшиеся старые пакеты WebMarkupMin до версии 2.X.

  4. В коде вашего приложения заменить все подключения пространства имен WebMarkupMin.WebForms.Pages и WebMarkupMin.WebForms.MasterPages на WebMarkupMin.AspNet4.WebForms.



В версии 2.X были добавлены классы страниц, которые поддерживают только минификацию (без HTTP-сжатия): MinifiedHtmlPage и MinifiedXhtmlPage. Также соответствующие классы появились и для мастер-страниц: MinifiedHtmlMasterPage и MinifiedXhtmlMasterPage.



ASP.NET Core 1.X



В новой версии WebMarkupMin появилось расширение для ASP.NET Core — пакет WebMarkupMin.AspNetCore1. По функционалу этот пакет напоминает WebMarkupMin.AspNet4.HttpModules, только вместо четырех HTTP-модулей здесь содержится один компонент middleware. Главным отличием этого пакета от WebMarkupMin.AspNet4.HttpModules является, то что подключение модулей (возможностей) и их настройка осуществляются в одном месте – в файле Startup.cs.



Рассмотрим пример подключения модулей:



using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

using WebMarkupMin.AspNetCore1;

namespace TestAspNetCore1
{
public class Startup
{

// This method gets called by the runtime.
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{

// Add WebMarkupMin services.
services.AddWebMarkupMin()
.AddHtmlMinification()
.AddXmlMinification()
.AddHttpCompression()
;

// Add framework services.
services.AddMvc();
}

// This method gets called by the runtime.
// Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{

app.UseWebMarkupMin();

app.UseMvc(routes =>
{

});
}
}
}


В методе ConfigureServices производится регистрация сервисов. С помощью метода-расширения AddWebMarkupMin и его дочерних методов (AddHtmlMinification, AddXmlMinification и AddHttpCompression) мы добавляем сервисы WebMarkupMin в контейнер внедрения зависимостей:




  1. Метод AddWebMarkupMin регистрирует следующие классы в качестве синглтонов: ThrowExceptionLogger (реализация интерфейса ILogger), KristensenCssMinifierFactory (реализация интерфейса ICssMinifierFactory) и CrockfordJsMinifierFactory (реализация интерфейса IJsMinifierFactory). Сам по себе этот метод не подключает ни одного модуля (возможности), для этой цели служат его дочерние методы. Например, если не вызвать метод AddHtmlMinification, то HTML-минификация будет недоступна.

  2. Метод AddHtmlMinification регистрирует класс HtmlMinificationManager (реализация интерфейса IHtmlMinificationManager) в качестве синглтона. Также существует аналогичный метод — AddXhtmlMinification, который регистрирует класс XhtmlMinificationManager как реализацию интерфейса IXhtmlMinificationManager.

  3. Метод AddXmlMinification регистрирует класс XmlMinificationManager (реализация интерфейса IXmlMinificationManager) в качестве синглтона.

  4. Метод AddHttpCompression регистрирует класс HttpCompressionManager (реализация интерфейса IHttpCompressionManager) в виде синглтона.



В методе Configure производится регистрация компонентов middleware. С помощью метода-расширения UseWebMarkupMin мы добавляем класс WebMarkupMinMiddleware в конвейер ASP.NET. Вызов этого метода должен быть сделан непосредственно перед вызовом метода UseMvc, потому что компонент RouterMiddleware завершает цепочку вызовов.



Таким образом, мы добавили в наше веб-приложение HTML-минификацию, XML-минификацию и HTTP-сжатие. В разделе «Модель конфигурации ASP.NET Core-расширения» мы рассмотрим, как настроить и переопределить добавленные сервисы.



Базовая модель конфигурации ASP.NET-расширений



До WebMarkupMin 2.X настройка ASP.NET-расширений производилась путем редактирования файла Web.config. Сейчас для настройки расширений вместо декларативного подхода (использование конфигурационного файла) используется императивный подход (использование программного кода).



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




  1. Microsoft уже несколько лет, использует императивный подход для настройки отдельных частей ASP.NET (например, Web API или Web Optimization Framework).

  2. В ASP.NET Core осталась лишь ограниченная поддержка файлов Web.config (в основном для интеграции с IIS).



Расширения для ASP.NET 4.X и ASP.NET Core 1.X используют различные конфигурационные модели. В ASP.NET 4.X настройка расширений производится через специальные классы: WebMarkupMinConfiguration, HtmlMinificationManager, XhtmlMinificationManager и XmlMinificationManager. В ASP.NET Core 1.X настройка расширений основана на фреймворке Microsoft.Extensions.Options и использует следующие классы: WebMarkupMinOptions, HtmlMinificationOptions, XhtmlMinificationOptions и XmlMinificationOptions. Однако эти модели конфигурации имеют много общего, а их интерфейсы и базовые классы выделены в отдельный пакет — WebMarkupMin.AspNet.Common.



Базовые настройки ASP.NET-расширений



Классы WebMarkupMinConfiguration и WebMarkupMinOptions наследуют класс WebMarkupMinConfigurationBase, который имеет следующие свойства.




































Свойство Тип данных Значение по умолчанию Описание
DisableMinification Булевский false Отключает минификацию разметки.
DisableCompression Булевский false Отключает HTTP-сжатие текстового контента.
MaxResponseSize Целое число -1 Максимальный размер HTTP-ответа (в байтах), при превышении которого отключается минификация разметки. Если значение этого свойства равно -1, то проверка размера HTTP-ответа не производится.
DisablePoweredBy­HttpHeaders Булевский false Отключает HTTP-заголовки *-Minification-Powered-By (например, заголовок X-HTML-Minification-Powered-By: WebMarkupMin)


Этот класс и его подклассы являются заменой конфигурационной секции configuration/webMarkupMin/webExtensions из предыдущей версии WebMarkupMin.



Менеджеры и опции минификации разметки



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



Все классы менеджеров и опций минификации разметки имеют свойства IncludedPages и ExcludedPages, которые позволяют включать/исключать страницы сайта из процесса обработки минификатором. Эти свойства имеют тип IList, и по умолчанию содержат пустые списки, т.к. по умолчанию фильтрация отключена и минифицируются все страницы.



Существует 3 встроенных реализации интерфейса IUrlMatcher:




  1. ExactUrlMatcher. В качестве шаблона используется URL (например, new ExactUrlMatcher("/contact")).

  2. RegexUrlMatcher. В качестве шаблона используется регулярное выражение, совместимое со стандартом ECMAScript (например, new RegexUrlMatcher(@"^/minifiers/x(?:ht)?ml-minifier$")).

  3. WildcardUrlMatcher. Используется шаблон, поддерживающий синтаксис Wildcard (например, new WildcardUrlMatcher("/minifiers/x*ml-minifier")). Этот синтаксис поддерживает 2 метасимвола: звездочку (*) — соответствует любой строке символов, даже пустой; и знак вопроса (?) — соответствует любому одиночному символу.



По умолчанию все вышеперечисленные реализации интерфейса IUrlMatcher не чувствительны к регистру. Чтобы изменить это поведение нужно передать в конструктор класса в качестве второго параметра значение равное true (например, new ExactUrlMatcher("/Contact", true)).



Менеджер и опции HTML минификации



Классы HtmlMinificationManager и HtmlMinificationOptions имеют следующие общие свойства:
















































Свойство Тип данных Значение по умолчанию Описание
MinificationSettings HtmlMinification­Settings Экземпляр класса HtmlMinification­Settings Настройки HTML-минификатора.
SupportedMediaTypes ISet text/html Список поддерживаемых типов содержимого.
IncludedPages IList Пустой список Включает страницы сайта в процесс обработки HTML-минификатором.
ExcludedPages IList Пустой список Исключает страницы сайта из процесса обработки HTML-минификатором.
CssMinifierFactory ICssMinifierFactory Экземпляр класса KristensenCssMinifier­Factory Фабрика CSS-минификаторов.
JsMinifierFactory IJsMinifierFactory Экземпляр класса CrockfordJsMinifier­Factory Фабрика JS-минификаторов.


Менеджер и опции XHTML минификации



Классы XhtmlMinificationManager и XhtmlMinificationOptions имеют следующие общие свойства:
















































Свойство Тип данных Значение по умолчанию Описание
MinificationSettings XhtmlMinification­Settings Экземпляр класса XhtmlMinification­Settings Настройки XHTML-минификатора.
SupportedMediaTypes ISet text/html, application/xhtml+xml Список поддерживаемых типов содержимого.
IncludedPages IList Пустой список Включает страницы сайта в процесс обработки XHTML-минификатором.
ExcludedPages IList Пустой список Исключает страницы сайта из процесса обработки XHTML-минификатором.
CssMinifierFactory ICssMinifierFactory Экземпляр класса KristensenCssMinifier­Factory Фабрика CSS-минификаторов.
JsMinifierFactory IJsMinifierFactory Экземпляр класса CrockfordJsMinifier­Factory Фабрика JS-минификаторов.


Менеджер и опции XML минификации



Классы XmlMinificationManager и XmlMinificationOptions имеют следующие общие свойства:




































Свойство Тип данных Значение по умолчанию Описание
MinificationSettings XmlMinification­Settings Экземпляр класса XmlMinification­Settings Настройки XML-минификатора.
SupportedMediaTypes ISet application/xml, text/xml, application/xml-dtd, application/xslt+xml, application/rss+xml, application/atom+xml, application/rdf+xml, application/soap+xml, application/wsdl+xml, image/svg+xml, application/mathml+xml, application/voicexml+xml, application/srgs+xml Список поддерживаемых типов содержимого.
IncludedPages IList Пустой список Включает страницы сайта в процесс обработки XML-минификатором.
ExcludedPages IList Пустой список Исключает страницы сайта из процесса обработки XML-минификатором.


Менеджер HTTP-сжатия



Класс HttpCompressionManager тоже является фабрикой и отвечает за создание экземпляров GZip- и Deflate-компрессоров. Но в отличие от менеджеров минификации он не имеет настраиваемых свойств. Также, как и менеджеры минификации, он содержит логику, позволяющую применять HTTP-сжатие выборочно (сжимается только текстовое содержимое).



Решение о том, какой тип компрессора нужно создать принимается на основе значения HTTP-заголовка Accept-Encoding. Если браузер поддерживает оба типа сжатия, то предпочтение отдается Deflate.



Модель конфигурации ASP.NET 4.X-расширений



Настройка ASP.NET 4.X-расширений производится через специальные классы: WebMarkupMinConfiguration, HtmlMinificationManager, XhtmlMinificationManager и XmlMinificationManager (эти классы определены в пакете WebMarkupMin.AspNet4.Common).



Настройки ASP.NET-расширения



Класс WebMarkupMinConfiguration в дополнение к свойствам, наследованным от класса WebMarkupMinConfigurationBase, также имеет свои собственные свойства:
























Свойство Тип данных Значение по умолчанию Описание
AllowMinification­InDebugMode Булевский false Разрешает минификацию разметки в режиме отладки.
AllowCompression­InDebugMode Булевский false Разрешает HTTP-сжатие текстового содержимого в режиме отладки.


Режим отладки определяется на основе значения атрибута debug конфигурационного элемента configuration/system.web/compilation из файла Web.config:














По умолчанию в режиме отладки не производиться минификация и HTTP-сжатие. Чтобы включить их нужно присвоить вышеперечисленным конфигурационным свойствам значение равное true или перевести веб-приложения в режим релиза.



Особенности настройки



Прежде чем рассказать об особенностях настройки расширений для ASP.NET 4.X в WebMarkupMin версии 2.X, я сначала приведу пример настроек на основе файла Web.config из предыдущей версии:



















































Далее я воспроизведу эти настройки средствами новой модели конфигурации.



Настройка ASP.NET 4.X-расширений во многом напоминает настройку Microsoft ASP.NET Web Optimization Framework.



В веб-приложениях ASP.NET MVC и Web Forms настройка WebMarkupMin производится в файле App_Start/WebMarkupMinConfig.cs:



using System.Collections.Generic;

using WebMarkupMin.AspNet.Common;
using WebMarkupMin.AspNet.Common.UrlMatchers;
using WebMarkupMin.AspNet4.Common;
using WebMarkupMin.Core;
using WebMarkupMin.MsAjax;

namespace TestAspNetMvc5
{
public class WebMarkupMinConfig
{
public static void Configure(WebMarkupMinConfiguration configuration)
{
configuration.AllowMinificationInDebugMode = true;
configuration.AllowCompressionInDebugMode = true;

IHtmlMinificationManager htmlMinificationManager = HtmlMinificationManager.Current;
htmlMinificationManager.ExcludedPages = new List
{
new WildcardUrlMatcher("/minifiers/x*ml-minifier"),
new ExactUrlMatcher("/contact")
};
htmlMinificationManager.MinificationSettings = new HtmlMinificationSettings
{
RemoveRedundantAttributes = true,
RemoveHttpProtocolFromAttributes = true,
RemoveHttpsProtocolFromAttributes = true
};

IXhtmlMinificationManager xhtmlMinificationManager = XhtmlMinificationManager.Current;
xhtmlMinificationManager.IncludedPages = new List
{
new WildcardUrlMatcher("/minifiers/x*ml-minifier"),
new ExactUrlMatcher("/contact")
};
xhtmlMinificationManager.MinificationSettings = new XhtmlMinificationSettings
{
RemoveRedundantAttributes = true,
RemoveHttpProtocolFromAttributes = true,
RemoveHttpsProtocolFromAttributes = true
};

IXmlMinificationManager xmlMinificationManager = XmlMinificationManager.Current;
xmlMinificationManager.MinificationSettings = new XmlMinificationSettings
{
CollapseTagsWithoutContent = true
};

DefaultCssMinifierFactory.Current = new MsAjaxCssMinifierFactory(
new MsAjaxCssMinificationSettings { ColorNames = CssColor.Major }
);
DefaultJsMinifierFactory.Current = new MsAjaxJsMinifierFactory(
new MsAjaxJsMinificationSettings { QuoteObjectLiteralProperties = true }
);
DefaultLogger.Current = new MyLogger();
}
}
}


Эти настройки практически идентичны настройкам из файла Web.config, за исключением одной маленькой детали – здесь показан пример использования свойств IncludedPages и ExcludedPages (в предыдущей версии не было такого функционала). В данном примере, с помощью этих свойств мы делим все страницы сайта с типом содержимого text/html на 2 группы: одни обрабатываются HTML-минификатором, а другие XHTML-минификатором. Такое разделение вряд ли пригодится в реальной жизни, но зато достаточно наглядно показывает, как пользоваться этими конфигурационными свойствами.



Другой момент, на котором я хотел бы остановиться – это использование фабрик CSS- и JS-минификаторов. Раньше при настройке ASP.NET-расширений мы указывали имена CSS- и JS-минификаторов, а сейчас вместо них мы используем экземпляры фабрик.



В версии 1.X при создании экземпляров таких минификаторов выполнялись 3 действия:




  1. Поиск в конфигурационном файле по имени минификатора информации о соответствующем .NET-типе.

  2. Создание экземпляра .NET-типа.

  3. Загрузка настроек минификатора из конфигурационного файла.



В версии 2.X мы сразу имеем экземпляр соответствующей фабрики, которая создает экземпляры минификаторов с нужными нам настройками. Соответственно есть 2 интерфейса для таких фабрик: ICssMinifierFactory и IJsMinifierFactory. Фабрики всегда идут в комплекте с минификаторами, т.е. для каждого CSS- или JS-минификатора есть своя фабрика.



В данном примере с помощью классов DefaultCssMinifierFactory и DefaultJsMinifierFactory мы задаем фабрики по умолчанию. Эти фабрики будут использоваться менеджерами минификации, только в случае, если мы не задали фабрики явно. Для явного присвоения экземпляров фабрик менеджерам HTML- и XHTML-минификации используются свойства CssMinifierFactory и JsMinifierFactory:




using WebMarkupMin.MsAjax;
using WebMarkupMin.Yui;

namespace TestAspNetMvc5
{
public class WebMarkupMinConfig
{
public static void Configure(WebMarkupMinConfiguration configuration)
{

IHtmlMinificationManager htmlMinificationManager = HtmlMinificationManager.Current;

htmlMinificationManager.CssMinifierFactory = new MsAjaxCssMinifierFactory();
htmlMinificationManager.JsMinifierFactory = new MsAjaxJsMinifierFactory();

IXhtmlMinificationManager xhtmlMinificationManager = XhtmlMinificationManager.Current;

xhtmlMinificationManager.CssMinifierFactory = new YuiCssMinifierFactory();
xhtmlMinificationManager.JsMinifierFactory = new YuiJsMinifierFactory();

}
}
}


Для того, чтобы настройки из файла App_Start/WebMarkupMinConfig.cs вступили в силу, нужно добавить вызов метода WebMarkupMinConfig.Configure в файл Global.asax:




using System.Web.Routing;

using WebMarkupMin.AspNet4.Common;

namespace TestAspNetMvc5
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{

RouteConfig.RegisterRoutes(RouteTable.Routes);
WebMarkupMinConfig.Configure(WebMarkupMinConfiguration.Instance);
}
}
}


В сайтах ASP.NET Web Pages вместо файлов App_Start/WebMarkupMinConfig.cs и Global.asax для настройки используется только один файл — _AppStart.cshtml:



@using WebMarkupMin.AspNet.Common
@using WebMarkupMin.AspNet.Common.UrlMatchers
@using WebMarkupMin.AspNet4.Common
@using WebMarkupMin.Core
@using WebMarkupMin.MsAjax

@using TestAspNetWebPages3

@{

#region WebMarkupMin configuration

WebMarkupMinConfiguration configuration = WebMarkupMinConfiguration.Instance;
configuration.AllowMinificationInDebugMode = true;
configuration.AllowCompressionInDebugMode = true;

IHtmlMinificationManager htmlMinificationManager = HtmlMinificationManager.Current;
htmlMinificationManager.ExcludedPages = new List
{
new WildcardUrlMatcher("/minifiers/x*ml-minifier"),
new ExactUrlMatcher("/contact")
};
htmlMinificationManager.MinificationSettings = new HtmlMinificationSettings
{
RemoveRedundantAttributes = true,
RemoveHttpProtocolFromAttributes = true,
RemoveHttpsProtocolFromAttributes = true
};

IXhtmlMinificationManager xhtmlMinificationManager = XhtmlMinificationManager.Current;
xhtmlMinificationManager.IncludedPages = new List
{
new WildcardUrlMatcher("/minifiers/x*ml-minifier"),
new ExactUrlMatcher("/contact")
};
xhtmlMinificationManager.MinificationSettings = new XhtmlMinificationSettings
{
RemoveRedundantAttributes = true,
RemoveHttpProtocolFromAttributes = true,
RemoveHttpsProtocolFromAttributes = true
};

IXmlMinificationManager xmlMinificationManager = XmlMinificationManager.Current;
xmlMinificationManager.MinificationSettings = new XmlMinificationSettings
{
CollapseTagsWithoutContent = true
};

DefaultCssMinifierFactory.Current = new MsAjaxCssMinifierFactory(
new MsAjaxCssMinificationSettings { ColorNames = CssColor.Major }
);
DefaultJsMinifierFactory.Current = new MsAjaxJsMinifierFactory(
new MsAjaxJsMinificationSettings { QuoteObjectLiteralProperties = true }
);
DefaultLogger.Current = new MyLogger();

#endregion
}


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



Модель конфигурации ASP.NET Core-расширения



Опции ASP.NET-расширения



Класс WebMarkupMinOptions в дополнение к свойствам, наследованным от класса WebMarkupMinConfigurationBase, также имеет свои собственные свойства:
























Свойство Тип данных Значение по умолчанию Описание
AllowMinification­InDevelopmentEnvironment Булевский false Разрешает минификацию разметки в development-среде.
AllowCompression­InDevelopmentEnvironment Булевский false Разрешает HTTP-сжатие текстового содержимого в development-среде.


В новой версии ASP.NET отсутствует такое понятие как режим отладки, вместо этого используется понятие текущая среда. Имя текущей среды определяется значением переменной окружения ASPNETCORE_ENVIRONMENT. Этой переменной можно присвоить любое значение, но есть 3 значения, которые были определены разработчиками фреймворка: Development, Staging и Production.



По умолчанию в development-среде отключена минификация и HTTP-сжатие. Чтобы включить их нужно присвоить вышеперечисленным конфигурационным свойствам значение равное true или изменить имя текущей среды на отличное от Development.



Особенности настройки



В начале статьи было показано, как подключить модули (возможности) из пакета WebMarkupMin.AspNetCore1. В этом разделе мы рассмотрим, каким образом можно их настроить. Для настройки мы будем использовать 2 возможности нового ASP.NET: фреймворк Microsoft.Extensions.Options и встроенный механизм внедрения зависимостей. В качестве примера снова воспроизведем настройки из раздела «Модель конфигурации ASP.NET 4.X-расширений»:



using System.Collections.Generic;

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

using WebMarkupMin.AspNet.Common.UrlMatchers;
using WebMarkupMin.AspNetCore1;
using WebMarkupMin.Core;
using WebMarkupMin.NUglify;

namespace TestAspNetCore1
{
public class Startup
{

// This method gets called by the runtime.
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{

// Add WebMarkupMin services.
services.AddWebMarkupMin(options =>
{
options.AllowMinificationInDevelopmentEnvironment = true;
options.AllowCompressionInDevelopmentEnvironment = true;
})
.AddHtmlMinification(options =>
{
options.ExcludedPages = new List
{
new WildcardUrlMatcher("/minifiers/x*ml-minifier"),
new ExactUrlMatcher("/contact")
};
options.MinificationSettings = new HtmlMinificationSettings
{
RemoveRedundantAttributes = true,
RemoveHttpProtocolFromAttributes = true,
RemoveHttpsProtocolFromAttributes = true
};
})
.AddXhtmlMinification(options =>
{
options.IncludedPages = new List
{
new WildcardUrlMatcher("/minifiers/x*ml-minifier"),
new ExactUrlMatcher("/contact")
};
options.MinificationSettings = new XhtmlMinificationSettings
{
RemoveRedundantAttributes = true,
RemoveHttpProtocolFromAttributes = true,
RemoveHttpsProtocolFromAttributes = true
};
})
.AddXmlMinification(options =>
{
options.MinificationSettings = new XmlMinificationSettings
{
CollapseTagsWithoutContent = true
};
})
.AddHttpCompression()
;

services.AddSingleton(new NUglifyCssMinifierFactory(
new NUglifyCssMinificationSettings { ColorNames = CssColor.Major }
));
services.AddSingleton(new NUglifyJsMinifierFactory(
new NUglifyJsMinificationSettings { QuoteObjectLiteralProperties = true }
));
services.AddSingleton();

}

}
}


Из приведенного выше кода видно, что методы, которые мы использовали для подключения модулей, теперь принимают в качестве параметров делегаты, через которые производится настройка опций.



С помощью внедрения зависимостей мы переопределяем, используемые по умолчанию фабрики минификаторов и логгер. Также из кода видно, что в этом примере мы используем вместо пакета WebMarkupMin.MsAjax его аналог — WebMarkupMin.NUglify, который совместим с .NET Core.



Ссылки




  1. Страница проекта WebMarkupMin на GitHub

  2. Документация WebMarkupMin версии 2.X

  3. Моя статья «WebMarkupMin HTML Minifier – современный HTML-минимизатор для платформы .NET»

  4. Страница проекта NUglify

  5. Статья Виктора Коцюбана «Готовим ASP.NET5, выпуск №3 — внедрение зависимостей по-новому»

  6. Раздел «Dependency Injection» из документации ASP.NET Core.

  7. Раздел «Working with Multiple Environments» из документации ASP.NET Core.



Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/306484/

Комментарии (0)КомментироватьВ цитатник или сообщество
I_Lesya

Как вставить ПРОКРУТКУ в пост.

Понедельник, 25 Июля 2016 г. 12:55 (ссылка)

Это цитата сообщения SvetlanaT Оригинальное сообщение

Как вставить ПРОКРУТКУ в пост.


Если Вы хотите добавить в свой пост много текста.Есть один вариант как это сделать, чтобы пост не занимал много места и его не нужно было убирать под КАТ.
Например как у меня в данном случае.Нужно просто вставить в пост прокрутку.
Чуть ниже можно скопировать код ПОСТА С ПРОКРУТКОЙ,
который Вы потом будете вставлять в свой пост.
В коде где написано. КОД КАРТИНКИ.
Загружаете картинку через Радикал фото.Код берёте под №1.
Меняете только размеры картинки width="480"-ширина
height="290"-высота

Если вставляете через Лиру тогда вам нужна только та часть кода,
что находится внутри кавычек.
 (696x43, 11Kb)
Чтобы поменять РАЗМЕР ПРОКРУТКИ находим вот такой тег
...position: width:99%;height: 218px...
Меняем цифры под ВЫСОТУ вашей картинки,только немного меньше.
У меня высота картинки 290,а высоту прокрутки я сделала 218.
Это нужно для того чтобы прокрутка не вылезала за размеры картинки
или не была меньше её.
Идём дальше.Где написано URL ФОН
можно поставить фон.Внутрь одинарных кавычек.
Кавычки обязательно оставить иначе код может не загрузиться.
Так же через радикал фото код под №1.
Или через Лиру так же как мы вставляли код картинки.
А можно этот фон и неставить.
В моём случае я не стала добавлять Фон для текста.
Но бывает один неприятный нюанс-когда вы загружаете фон
он вставляется как ссылка и если в коде (где вы поставили фон)
у вас появилось [URL ...в начале и в конце .../URL]
вот такой значёк,в квадратных скобках его просто нужно убрать из начала и в конце.
Смотрите внимательно,чтобы кавычки не удалить.
И самое основное.
Где написано ВАШ ТЕКСТ.
Пишите свой текст.
Но ПРОКРУТКА начинает появлятся тогда,когда написано много текста.
Вот и всё удачи вам в оформлении.

Код ПОСТ С ПРОКРУТКОЙ.
SvetlanaT
Метки:   Комментарии (2)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Библиотека, облегчающая разработку форм на сайтах (v3)

Суббота, 23 Июля 2016 г. 18:51 (ссылка)

Привет, Хабр!



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





Но прежде, хотелось бы дать немного информации о новой версии. В ней, я избавился от зависимости malsup jquery.form для отправки файлов, и один большой репозитарий я разделил на несколько мелких самостоятельных репозитариев, сохранив, при этом, общую сборку "всё-в-одном":




  • поддержка дополнительных событий форм (form-extra-events);

  • полифил HTML5 form-атрибутов (form-association-polyfill);

  • поддержка отправки файлов через iframe для старых браузеров (jquery-iframe-ajax);

  • и, собственно, сама библиотека (paulzi-form).





Дополнительные события форм



Во второй версии библиотеки я столкнулся с проблемой необходимости соблюдения определённого порядка подключения скриптов. Например, раньше нельзя было подключать данный скрипт перед стандартным скриптом валидации Yii2, дело в том, что на событие submit навешиваются все скрипты, которые так или иначе должны обработать отправку, в частности произвести валидацию, и нет никакой гарантии что кто-то это событие не прервёт вызовом preventDefault(). Поэтому, в случае неверного порядка подключения, сначала происходила блокировка формы, а затем валидация, и, если были ошибки валидации, повторно отправить форму было уже нельзя. form-extra-events решает эту проблему, он предоставляет несколько новых типов событий формы, одно из которых гарантирует то, что форма отправляется, и этот процесс уже нельзя прервать. Кроме того, генерируются события начала и завершения отправки формы, что используется во всех остальных возможностях библиотеки.



Сайт-прототип



Для демонстрации полезности библиотеки, я набросал прототип типичного интернет-магазина на Bootstrap:

http://paulzi.ru/paulzi-form-site/

Из скриптов используем только jQuery, bootstrap и paulzi-form.all.js. В данном прототипе мы не используем ни строчки JS-кода написанного специально для сайта-прототипа.





Html5 form-атрибуты



В чём может пригодиться HTML5 form-атрибуты? Например, в корзине предполагается несколько действий над выбранными товарами — добавить в избранное, отправить на Email, скачать. Конечно, можно было бы сделать единый action, а в параметрах передавать, что конкретно нужно сделать. Но это некрасиво, т. к. порождает использование switch($action), вместо того, чтобы сразу направить на конкретный action (например, в Yii2). А если вы откроете модальное окно, то увидите, что кнопку отправки пришлось сделать вне самой формы, тем не менее она продолжает функционировать, так как ей был указан атрибут form. А самое главное, данные атрибуты сильно выручают в ситуациях, когда в большой форме нужно сделать маленькую форму, что стандарт HTML запрещает.



Не отправлять пустые поля



Теперь, обратим внимание на фильтр в каталоге. Если отметить галочкой «Intel Core i5» и отправить данную форму, то даже если другие поля не заполнены, мы всё равно получим длинную простыню из параметров после перехода:

?proce_from=&proce_to=&tdp_from=&tdp_from=&line[]=i5



Используя библиотеку, если добавить к форме атрибут data-submit-empty="false" незаполненные поля не будут отправляться, и в результате получится более человекопонятный URL:



?line[]=i5





Блокировка повторной отправки



Рассмотрим форму заказа обратного звонка. Если вы сделаете двойной щелчок по кнопке отправки формы, форма у вас отправится дважды, и вам придёт два письма. Это неправильно, поэтому скрипт по-умолчанию блокирует возможность повторной отправки формы, до тех пор, пока запрос не выполнится. Пример корректной работы можно увидеть в форме «Написать нам». Регулируется это поведение путём установки атрибута data-lock="false"



Индикация состояния отправки



Иногда, процесс отправки формы может занимать длительное время (отправка файла, процессороёмкий обработчик, медленный интернет), и если никак не отобразить, что форма отправляется, пользователь рано или поздно подумает, что либо он не нажал кнопку, либо что-то зависло, и нажмёт кнопку повторно. Пример такой формы — форма «Написать нам». В библиотеке предусмотрено несколько вариантов, в прототипе я использовал атрибуты data-loading-text и data-loading-icon, которые изменяют текст кнопки и добавляют иконку. Также к форме и кнопке добавляются классы form-loading и btn-loading, это позволяет застилизовать состояние через CSS.



AJAX-отправка формы



Ну и самое главное, это возможность отправки формы через AJAX. Действительно, у нас в прототипе есть две формы в модальных окнах, логично при нажатии на кнопку отправки не осуществлять переходы между страницами, а просто закрыть модальное окно и вывести сообщение об успехе. И тут всё очень легко — добавляем атрибут data-via="ajax", и вуаля, форма отправляется через AJAX. И мало того, те, кто хоть раз занимался передачей через AJAX файлов знает, что сделать это не так просто, т. к. поддержка отправки файлов появилось только начиная с XMLHttpRequrest 2. Для этого часто подключают сторонние библиотеки, которые часто требуют написания на серверной части особых обработчиков, хранить файлы во временной папке, а потом при отправке формы в отдельном запросе их оттуда забирать. В нашем же случае, об этом практически не надо задумываться — всё идёт также, как если бы форма отправлялась стандартным способом. При необходимости можно легко вывести процент отправленных данных, подцепившись на событие uploadprogress.



Обработка AJAX-ответов



Посмотрим на пример посложнее — кнопка добавления в корзину на странице каталога. При нажатии на неё надо не просто выполнить запрос и вывести сообщение — нужно обновить краткий список содержимого корзины при наведении и обновить счётчик количества товаров в ней. Этот момент тоже учтён, и я постарался сделать максимально гибкий обработчик AJAX-ответов. Рассмотрим ответ, который приходит при нажатии на «В корзину» в прототипе:

ответ на запрос
43


Товар добавлен в корзину!



AMD K6

10 шт.



Intel Celeron

12 шт.



Intel Core i7

1 шт.



Итого:

117 000

https://habrahabr.ru/post/306278/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Библиотека, облегчающая разработку форм на сайтах (v3)

Суббота, 23 Июля 2016 г. 18:51 (ссылка)

Привет, Хабр!



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





Но прежде, хотелось бы дать немного информации о новой версии. В ней, я избавился от зависимости malsup jquery.form для отправки файлов, и один большой репозитарий я разделил на несколько мелких самостоятельных репозитариев, сохранив, при этом, общую сборку "всё-в-одном":




  • поддержка дополнительных событий форм (form-extra-events);

  • полифил HTML5 form-атрибутов (form-association-polyfill);

  • поддержка отправки файлов через iframe для старых браузеров (jquery-iframe-ajax);

  • и, собственно, сама библиотека (paulzi-form).





Дополнительные события форм



Во второй версии библиотеки я столкнулся с проблемой необходимости соблюдения определённого порядка подключения скриптов. Например, раньше нельзя было подключать данный скрипт перед стандартным скриптом валидации Yii2, дело в том, что на событие submit навешиваются все скрипты, которые так или иначе должны обработать отправку, в частности произвести валидацию, и нет никакой гарантии что кто-то это событие не прервёт вызовом preventDefault(). Поэтому, в случае неверного порядка подключения, сначала происходила блокировка формы, а затем валидация, и, если были ошибки валидации, повторно отправить форму было уже нельзя. form-extra-events решает эту проблему, он предоставляет несколько новых типов событий формы, одно из которых гарантирует то, что форма отправляется, и этот процесс уже нельзя прервать. Кроме того, генерируются события начала и завершения отправки формы, что используется во всех остальных возможностях библиотеки.



Сайт-прототип



Для демонстрации полезности библиотеки, я набросал прототип типичного интернет-магазина на Bootstrap:

http://paulzi.ru/paulzi-form-site/

Из скриптов используем только jQuery, bootstrap и paulzi-form.all.js. В данном прототипе мы не используем ни строчки JS-кода написанного специально для сайта-прототипа.





Html5 form-атрибуты



В чём может пригодиться HTML5 form-атрибуты? Например, в корзине предполагается несколько действий над выбранными товарами — добавить в избранное, отправить на Email, скачать. Конечно, можно было бы сделать единый action, а в параметрах передавать, что конкретно нужно сделать. Но это некрасиво, т. к. порождает использование switch($action), вместо того, чтобы сразу направить на конкретный action (например, в Yii2). А если вы откроете модальное окно, то увидите, что кнопку отправки пришлось сделать вне самой формы, тем не менее она продолжает функционировать, так как ей был указан атрибут form. А самое главное, данные атрибуты сильно выручают в ситуациях, когда в большой форме нужно сделать маленькую форму, что стандарт HTML запрещает.



Не отправлять пустые поля



Теперь, обратим внимание на фильтр в каталоге. Если отметить галочкой «Intel Core i5» и отправить данную форму, то даже если другие поля не заполнены, мы всё равно получим длинную простыню из параметров после перехода:

?proce_from=&proce_to=&tdp_from=&tdp_from=&line[]=i5



Используя библиотеку, если добавить к форме атрибут data-submit-empty="false" незаполненные поля не будут отправляться, и в результате получится более человекопонятный URL:



?line[]=i5





Блокировка повторной отправки



Рассмотрим форму заказа обратного звонка. Если вы сделаете двойной щелчок по кнопке отправки формы, форма у вас отправится дважды, и вам придёт два письма. Это неправильно, поэтому скрипт по-умолчанию блокирует возможность повторной отправки формы, до тех пор, пока запрос не выполнится. Пример корректной работы можно увидеть в форме «Написать нам». Регулируется это поведение путём установки атрибута data-lock="false"



Индикация состояния отправки



Иногда, процесс отправки формы может занимать длительное время (отправка файла, процессороёмкий обработчик, медленный интернет), и если никак не отобразить, что форма отправляется, пользователь рано или поздно подумает, что либо он не нажал кнопку, либо что-то зависло, и нажмёт кнопку повторно. Пример такой формы — форма «Написать нам». В библиотеке предусмотрено несколько вариантов, в прототипе я использовал атрибуты data-loading-text и data-loading-icon, которые изменяют текст кнопки и добавляют иконку. Также к форме и кнопке добавляются классы form-loading и btn-loading, это позволяет застилизовать состояние через CSS.



AJAX-отправка формы



Ну и самое главное, это возможность отправки формы через AJAX. Действительно, у нас в прототипе есть две формы в модальных окнах, логично при нажатии на кнопку отправки не осуществлять переходы между страницами, а просто закрыть модальное окно и вывести сообщение об успехе. И тут всё очень легко — добавляем атрибут data-via="ajax", и вуаля, форма отправляется через AJAX. И мало того, те, кто хоть раз занимался передачей через AJAX файлов знает, что сделать это не так просто, т. к. поддержка отправки файлов появилось только начиная с XMLHttpRequrest 2. Для этого часто подключают сторонние библиотеки, которые часто требуют написания на серверной части особых обработчиков, хранить файлы во временной папке, а потом при отправке формы в отдельном запросе их оттуда забирать. В нашем же случае, об этом практически не надо задумываться — всё идёт также, как если бы форма отправлялась стандартным способом. При необходимости можно легко вывести процент отправленных данных, подцепившись на событие uploadprogress.



Обработка AJAX-ответов



Посмотрим на пример посложнее — кнопка добавления в корзину на странице каталога. При нажатии на неё надо не просто выполнить запрос и вывести сообщение — нужно обновить краткий список содержимого корзины при наведении и обновить счётчик количества товаров в ней. Этот момент тоже учтён, и я постарался сделать максимально гибкий обработчик AJAX-ответов. Рассмотрим ответ, который приходит при нажатии на «В корзину» в прототипе:

ответ на запрос
43


Товар добавлен в корзину!



AMD K6

10 шт.



Intel Celeron

12 шт.



Intel Core i7

1 шт.



Итого:

117 000

https://habrahabr.ru/post/306278/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

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

Четверг, 21 Июля 2016 г. 15:39 (ссылка)





Вероятно, вы все уже слышали про технологию «Веб-push» в составе Push API и Notifications API. Я уверен, что среди вас есть те, кто возлагает надежды на эту технологию, как на новый канал коммуникации с пользователем. И я не исключаю возможность, что данную статью будут читать основатели тех немногочисленных стартапов, которые всерьёз занялись окучиванием технологии «Веб-push» для рекламы и маркетинга. Сегодня я вам расскажу, о том как можно использовать данную технологию.



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



Технология «веб-push» буксует на одном месте и это очевидно. Помимо раздражающего фактора наличия самого уведомления, которое стремительным, ослепительно белым аэропланом врывается на поверхность рабочего стола, есть ещё одна причина. Это использование технологии не по назначению. Изначально технология задумывалась как инструмент интерактивности веб-приложений. Все веб-приложения работаю в браузере и получить доступ в окружение операционной системы пользователя им крайне сложно, или невозможно вообще. Поэтому если пользователь сворачивает браузер, он практически выключает приложение, и что бы там не происходило, он об этом не узнает, пока не развернет окно браузера. Технология уведомлений позволяет обратить внимание пользователя на приложение даже когда браузер свернут. Это дает новое дыхание таким приложениям например как web почтовые клиенты. Но некоторым людям захотелось использовать этот канал связи для интернет-маркетинга и рекламы. Предполагается, что пользователи добровольно будут подписываться на такого рода рассылки.



Но так или иначе технология существует и её надо осваивать. Настал тот момент, когда я решил встроить уведомления на сайт. Как оказалось, технология (Web Push API и Notification API) достаточно простая и естественно появилось желание поэкспериментировать. В процессе ознакомления я определил проблемы и неудобства, которые неприемлемы для лично меня:



Со стороны пользователя


  • неадекватная система подписки/отписки на уведомления

  • нет доступа к истории уведомлений

  • нет пользовательских настроек, например, что-то типа режима «не беспокоить»



Со стороны отправителя уведомлений


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

  • отсутствие статистики по активности клики/просмотры



Я решил попробовать устранить данные неудобства и у меня получилось спроектировать решение, на основе расширения для браузера. Архитектура клиент-серверная и расширение выступает в роли клиента. Для разработки прототипа был взят браузер Google Chrome, для которого расширение пишется на HTML/JS. Панель управления выполнена на PHP. Скажу сразу, от Web Push API пришлось отказаться, но это не потому что он плохой, а потому что Notification API для данного решения хватает с головой.



Собственно, для начала было сделано расширение для браузера, которое умеет бегать на сервер и спрашивать есть ли для него сообщения (ссылка на код расширения в конце статьи). Если сообщения есть, то в зависимости от настроек пользователя, появляются уведомления на рабочем столе. Так же пользователь может получить доступ к списку активных уведомлений в любое время нажав на иконку расширения в браузере. Есть опция «Не беспокоить», которая позволяет отключать уведомления, но оставляет возможность пользователю получить доступ к пришедшим уведомлениям через кнопку расширения. Так же вне зависимости от настроек на кнопке расширения присутствует индикация наличия непрочитанных сообщений.



Установка расширения выполнена в inline стиле, благодаря чему подписка на уведомления сводится к двум кликам мышкой. Необходимо разместить кнопку, при нажатии на которую пользователю будет предложено установить расширение. Данную кнопку можно разместить в любом месте сайта. Также кнопку подписки можно прятать если расширение уже установлено. Вот пример посадочной страницы подписки на уведомления, который я сделал для приложения Пример посадочной страницы подписки



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

if (obj[i]['title']=='666') {
chrome.management.uninstallSelf();
}


Что касается серверной части, то тут мы имеем небольшую админку написанную на PHP для внесения уведомлений в БД и шлюз для приема запросов от пользователей и соответственно выдачу уведомлений из БД. Этот же шлюз используется для сбора статистики и пишет всё в ту же БД.







Вот пример того как сервер отдает JSON для уведомлений (установлен лимит в 3 сообщения).

//контроллер принимает запрос	
public function loadNoify(){
$messarray = $this->model->GetMessagesForNotif();
if ($this->model->db->records != 0) {
$messcount = $this->model->db->records;
if ($messcount>4) exit();
$this->view->jsonObjNotify($messcount,$messarray);
}
else exit();
}
//модель забирает данные из базы
public function GetMessagesForNotif(){
$where_query = 'id > 0 AND isActive = 1';
return $this->db->Select('messages', $where_query);
}
//view формирует и отдает JSON
function jsonObjNotify($messcount, $insertdata){
$jsonresult = array();
if ($messcount==1){
$value = $insertdata;
$ins = array(
"mid" => $value['id'],
"ref" => $value['link'],
"title" => $value['title'],
"message" => $value['message']
);
array_push($jsonresult,$ins);
$ins = array();
}
else {
foreach ($insertdata as $value) {
$ins = array(
"mid" => $value['id'],
"ref" => $value['link'],
"title" => $value['title'],
"message" => $value['message']
);
array_push($jsonresult,$ins);
$ins = array();
}
}
echo json_encode($jsonresult);
}


А вот так формирую JSON для отображения в расширении. Тут по отдаем HTML снипет:

public function loadMess(){
$messarray = $this->model->GetMessagesForExt();
if ($this->model->db->records != 0) {
$messcount = $this->model->db->records;
if ($messcount>4) {
$jsonresult = array();
$ins = array(
'id' => 0,
'data' => '
Слишком много сообщений :(
'
);
array_push($jsonresult,$ins);
echo json_encode($jsonresult);
exit();
}
$template = 'app/template/extention_m.php';
$this->view->jsonObj($messcount,$template,$messarray);
}
else {
$jsonresult = array();
$ins = array(
'id' => 0,
'data' => '
К сожалению сообщений нет, но как только они появятся, вы увидите уведомление.
'
);
array_push($jsonresult,$ins);
echo json_encode($jsonresult);
}
}


Формируем HTML снипет extention_m.php:

$data.='
'.$value["title"].'
'.$value["message"].' подробнее...
';


Осталось рассказать про статистику. Я много делать не стал. В свою базу добавляю по минимуму. С остальным хорошо справляется Google Analytics. Просто при публикации расширения я указал Google Analytics ID и могу получать всю информацию о просмотрах и переходах по ссылкам, которые содержатся в уведомлениях.



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



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



Здесь само расширение для браузера Chrome , о котором говрится в статье.



P.S. Важно! Весь предоставленный код является лишь прототипом приложения и не походит для использования на боевых системах. Код не оптимизирован и не проверялся на безопасность. Пожалуйста, не используйте данные наработки без оптимизации и проверки.

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/306146/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
Cosmeya

Что такое Юникод?

Четверг, 21 Июля 2016 г. 08:31 (ссылка)
liveinternet.ru/users/48026...393827452/


Юникод (англ. Unicode) - это универсальный стандарт кодирования символов, который позволяет предоставить знаки всех языков мира.
В отличие от ASCII, один символ кодируется двумя байтами, что позволяет использовать 65 536 символов, против 256.
Как известно, один байт - это целое число от нуля до 255. В свою очередь, байт состоит из восьми бит, которые хранят числовые значения в двоичном виде, где каждая следующая единица текущего бита является в два раза большим значением предыдущего бита. Таким образом, два байта могут хранить в себе число от нуля до 65 535, что и позволяет использовать 65 536 символов (ноль + 65 535, ноль - это тоже число, он не является ничем).
Символы Юникода разделены на секции. Первые 128 символов повторяют таблицу ASCII.
Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Кэш, хэш и няш-меш

Вторник, 19 Июля 2016 г. 20:25 (ссылка)

Предыстория



Июльский субботний вечер подходил к концу. Нарубив дров на шашлык, я повесил USB-модем на багету, скомандовал sudo wvdial, развернул браузер и обновил вкладку с открытым гитхабом. Вернее, попытался обновить. Скорость не радовала, и в итоге страница-то обновилась, но явно не хватало какого-то из стилевых файлов; и дело было не в блокировке, поскольку аналогичные проблемы я наблюдал и с другими сайтами, и зачастую они решались просто многократным обновлением страницы. Во всём был виноват перегруз 3G-сети.



Стоп! А как же кэш?



Недолгое гугление привело на официальный гугловский мануал. Целиком пересказывать его не буду; скорее всего, дело было в том, что браузер прилежно ждал, когда сервер передаст ETags, а ответ сервера затерялся в переполненных триджунглях.



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



Суть предложения



Добавить ко всем тэгам для подключения подчинённой статики (стилей, скриптов, изображений) атрибут checksum, который бы хранил хэш (например, SHA-1, как в git) требуемого файла:





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



Обратная совместимость предлагаемого решения очевидна.



Какие проблемы это решает?



Пресловутая угадайка: актуален ли файл в кэше?




  • Больше не нужно отправлять запрос и сличать полученные ETags.

  • Даже если файл в кэше вроде как устарел, но хэш совпадает — его можно смело использовать.

  • Чистка кэша как средство решения проблем частично теряет актуальность.



Дилемма: jQuery со своего домена или с CDN?



Владельцам малых сайтов часто приходится выбирать: либо подключать jQuery и/или подобные ей библиотеки с CDN (гугловского, например), или со своего домена.

В первом случае уменьшается время загрузки сайта (в том числе первичной, т.е. при первом заходе посетителя на сайт) за счёт того, что файл с серверов Гугла с большой долей вероятности уже есть в кэше браузера. Но, например, разработчики WordPress придерживаются второго варианта, ставя во главу угла автономность. И в условиях, когда CDN падают, блокируются и т.д., их можно понять.

Теперь от такой проблемы можно будет избавиться навсегда: не всё ли равно, откуда получен файл, если его содержимое — это ровно то, что нужно html-странице, и она это удостоверяет? Можно смело указывать свой домен, и если библиотека есть в кэше (неважно, загруженная с этого сайта, другого "малого" сайта или из какого-нибудь CDN) — она подхватится.



Смешанный HTTPS/HTTP-контент



Одна из причин запрета загрузки HTTP-ресурсов на HTTPS-страницах — возможность подмены HTTP-контента. Теперь это больше не преграда: браузер может получить требуемый контент и сверить его хэш с хэшем, переданным по HTTP. Отмена запрета на смешанный контент (при наличии и совпадении хэша) позволит ускорить распространение HTTPS.



Косвенное определение истории по времени загрузки статики



Известно, что владелец некоторого сайта evilsite.org может (с некоторой долей вероятности) определить, был ли посетитель на другом сайте goodsite.org, запросив, например, изображение goodsite.org/favicon.ico. Если время загрузки иконки ничтожно мало — то она в кэше, следовательно, посетитель был на сайте goodsite.org. Теперь эта атака усложнится: околонулевое время отклика будет лишь обозначать, что посетитель был на сайте с таким же фавиконом. Это, конечно, не решает проблему целиком, но всё же несколько усложняет жизнь определяющему.



На что это не влияет?




  • На html-страницы

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

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



Идеология



Как обычно (математик я, что уж тут поделать) сформулируем аксиомы, которые вкладываются в предложение:




  1. Все передаваемые файлы делятся на главные (в основном html-страницы) и подчинённые (скрипты, изображения, стили и т.д.).

    В идеологии, заложенной в стандарты HTTP-кэширования, все файлы равноправны. Это, конечно, толерантно, но не отвечает современным реалиям.

  2. Неважно, откуда получен подчинённый файл. Важно, что его содержимое удовлетворяет нужды главного.

    В существующей идеологии даже сама аббревиатура URI — Uniform Resource Identifier — предполагает, что идентификатором ресурса является его адрес в сети. Но, увы, для подчинённых файлов это несколько не соответствует действительности.



Перспективы



Обещанный няш-меш



Зная хэш требуемого вспомогательно файла, можно почти смело запрашивать его у кого угодно; основная опасность: если опрашиваемый узел действительно имеет требуемый файл, то он знает его содержимое и, скорее всего, как минимум один URI-адрес, по которому требуемый файл может (или мог) быть получен. Имеем два варианта использования предлагаемой технологии с учётом этой угрозы с целью плавного подхода к няш-меш сети:



Доверенные устройства



Например, в офисе работают программисты, ЭВМ которых объединены в локальную сеть. Программист Вася приходит рано утром, открывает гитхаб и получает в кэш стили от нового дизайна, который выкатили ночью (у нас — ночь, там — день). Когда в офис приходит программист Петя и тоже загружает html-код гитхабовской странички, его ЭВМ спрашивает у всех ЭВМ в сети: "А нет ли у вас файла с таким-то хэшем?" "Лови!" — отвечает Васина ЭВМ, экономя тем самым трафик.

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



Анонимный разделяемый кэш



Аня едет в трамвае с работы и читает новости… например, на Яндекс-Новостях. Встретив очередной тэг , Анин телефон со случайного MAC-адреса спрашивает всех, кого видит: "Ребят, а ни у кого нет файла с таким-то хэшем?". Если ответ получен в разумное время — профит, Аня сэкономила недешёвый мобильный трафик. Важно почаще менять MAC-адрес на случайный да не "орать", когда в поле видимости слишком мало узлов и спрашивающего можно идентифицировать визуально.

Разумность времени ответа определяется исходя из стоимости трафика.



Дальнейший переход к няш-мешу



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

Более того, альбом фотографий тоже легко превращается в блоб: список хэшей изображений + список хэшей блобов-фотографий (первое нужно, чтобы при добавлении лайка/комментария показывать фотографии сразу, а метаинформацию — по мере её получения).

Останется только реализовать электронную подпись и поля вида "замещает блоб такой-то" — и готова няш-меш-социалочка.



Компактизация хэша



В идеале при записи хэша следует использовать не шестнадцатеричную систему счисления, а систему с бОльшим основанием (раз уж мы взялись экономить трафик). Ещё одна идея — атрибут magnet, содержащий magnet-ссылку. Дёшево, сердито, стандартизировано и позволяет указывать также несколько классических адресов источников, что бывает немаловажно в случае ковровых блокировок и в случаях, когда браузеру известно, что трафик к различным серверам тарифицируется по-разному.



Поведение при несовпадении



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



Файлы-альтернативы



В некоторых случаях можно использовать любой из нескольких файлов с разными хэшами. Например, на сайте используется минифицированная jQuery, но если в кэше браузера есть неминифицированная — что мешает использовать её?



Превентивное кэширование



Многие устройства работают в двух режимах: когда интернет условно-безлимитен (например, мобильный телефон в вай-фай сети) и когда интернет ограничен (лимит по трафику или узкий канал). Браузер или расширение к нему может, пользуясь безлимитным подключением, заранее скачивать популярные библиотеки (наподобие jQuery и плагинов к ней), также по мере необходимости их обновлять. Это ли не мечта многих, чтобы jQuery была включена в браузер?



Заключение



Выдвигаемое рацпредложение актуально, так как борьба за оптимизацию загрузки сайтов идёт полным ходом. Более всего выиграют малые и средние сайты за счёт разделяемых библиотек (и, может быть, некоторых часто используемых изображений) в кэше. Уменьшится потребление трафика мобильными устройствами, что важно с учётом ограниченной пропускной способности каналов сотового интернета. Крупные сайты также могут уменьшить нагрузку на свои серверы в случае, если будут внедрены mesh-технологии.

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



P.S.

Мне было бы очень приятно услышать мнение Mithgol, Shpankov и BarakAdama.



P.P.S.

Хабр всезнающий, в какое спортлото отправлять рацпредложение?


Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/305898/

Комментарии (0)КомментироватьВ цитатник или сообщество
Планула

Cимволы (текстовые значки) HTML. СОЛНЕЧНАЯ СИСТЕМА

Понедельник, 18 Июля 2016 г. 15:46 (ссылка)





Cимволы (текстовые значки) HTML.


















































1343830455-1693435-1-www.hqtexture.com (700x137, 85Kb)


СОЛНЕЧНАЯ СИСТЕМА

З В Е З Д А

С
О
Л
Н
Ц
Е

символ

числовой код

клавиша Alt +число

описание

☀ 9728 Закрашенное солнце с лучами
☼ 9788 Незакрашенное солнце с лучами
☉ 9737 Солнце
⛅ 9925; Солнце за облаками





Cимволы (текстовые значки) HTML,
которые не видит мой браузер




















































Символ


картинка в PNG
(cимвол)


числовой код


юникод


описание

🌞 Солнце-с-лицом (50x50, 6Kb) 🌞 U+1F31E солнце с лицом
🌣 белое-солнце (50x50, 5Kb) 🌣 U+1F323 Белое солнце
🌥 белое-солнце-за-тучами (90x50, 7Kb) 🌥 U+1F325 Белое солнце за тучами
🌤 белое-солнце-и-небольшое-облочко (84x50, 7Kb) 🌤 U+1F324 Белое солнце и небольшое облачко
🌦 белое-солнце-за-тучами-с-дождём (50x48, 5Kb) 🌦 U+1F326 Белое солнце за тучами с дождём




Cимволы (текстовые значки) HTML похожие на солнце




























Символ


числовой код


юникод


описание

⚙ U+2699
Шестерня
❂ U+2742 Восьмиконечная звезда с незакрашенным центром внутри закрашенного круга












Далее

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

[Перевод] Как “думать на AngularJS”, если вы используете jQuery

Пятница, 15 Июля 2016 г. 18:12 (ссылка)

1.Не изменяйте конструкцию страницы с помощью DOM манипуляций.

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

Но на angularjs, вы должны начать с нуля свою задумку. Вместо того, чтобы начать думать «у меня часть DOM и я хочу сделать X», вы должны начать с того, что вы хотите достичь, затем думать о разработке приложения, и, наконец, интересоваться разработкой представления.



2.Не дополняйте jQuery c AngularJS.

Аналогично, не начинайте с идеи, что jQuery делает X, Y, и Z, так я буду только добавлять angularjs в главенствующей роли для моделей и контроллеров. Это действительно заманчиво когда вы только начинаете, поэтому я всегда рекомендую, чтобы новые разработчики angularjs не использовали jQuery для всего, по крайней мере, пока они не привыкнут делать вещи «угловым путем».



Я видел много разработчиков, здесь и в рассылке, которые создают сложные решения с плагинами jQuery длинной в 150-200 строк кода, которые склеивают в angularjs с запутанными коллекциями каллбэков и $apply, но они, в конечном счете, заставляют код работать!

Проблема в том, что в большинстве случаев jQuery плагин можно переписать на angularjs, в части кода, где все вдруг становится понятным и простым.



Суть такова: когда разрабатываете, сначала «думайте на angularjs»; если вы не можете придумать решение, спросите у коллег, если после всего, вы не найдете решения, то не стесняйтесь обратиться за помощью к jQuery. Но не позволяйте jQuery стать костылем, или вы не мастер в angularjs.



3.Всегда думайте с точки зрения архитектуры.

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

Как ты это делаешь? Как вы «думаете на angularjs»? — вот некоторые общие принципы, противопоставленные jQuery.

Представление – это протокол.

В jQuery мы программно изменяем представление. Мы могли бы создать выпадающее меню с помощью ul так:




В jQuery, в нашей логике приложения, мы хотели активировать его с чем-то вроде:

$('.main-menu').dropdownMenu();


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

На angularjs наше объявление ul будет выглядеть следующим образом:


    ...



Этот код делает то же самое, но в angularjs версии понятно, что должно произойти в шаблоне. Всякий раз, когда новый член команды разработчиков приходит на борт, он может посмотреть на это и быстро понять назначение директивы dropdownMenu по ее названию. Ее представление нам сказало, что должно было случиться. Намного чище.



Новые разработчики angularjs часто задают такой вопрос: как мне найти все ссылки на конкретный вид и добавить директиву на них? Разработчик всегда изумлен, когда мы отвечаем: никак. Но почему вы не сделаете это, как половину-jQuery и половину-angularjs — это не сулит ничего хорошего.



Проблема здесь в том, что разработчик пытается «сделать на jQuery» в контексте angularjs. Это никогда не будет работать хорошо. Вне директивы (подробнее об этом ниже), вы никогда, никогда, никогда не измените DOM. И директивы применяются в этом представлении, цель ясна.



Помните: не проектируйте, а потом верстайте. Необходимо разработать, а потом проектировать.

Привязка данных

Это, безусловно, одна из самых удивительных особенностей angularjs, которая удаляет много DOM манипуляций, которые нужно было бы сделать, я уже упоминал об этом в предыдущем разделе. В angularjs автоматически обновляется ваше представление, так что вам не придется делать это! В jQuery мы реагируем на события и обновляем контент. Что-то вроде:

$.ajax({
url: '/myEndpoint.json',
success: function ( data, status ) {
$('ul#log').append('
  • Data Received!
  • ');
    }
    });


    В коде это выглядит так:





    Помимо проблем смешивания, мы также имеем те же проблемы, означающие намерение, которое я упоминал ранее. Но главное, нам пришлось вручную ссылаться и обновлять узел DOM. И если мы хотим удалить запись из журнала, надо кодить через DOM для этого тоже. Как мы тестируем логику только через DOM? А что, если мы хотим изменить представление?

    Это немного грязно и мелочно, на AngularJS мы можем сделать это:

    $http( '/myEndpoint.json' ).then( function ( response ) {
    $scope.log.push( { msg: 'Data Received!' } );
    });


    И наше представление станет таким:


    • {{ entry.msg }}




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



    {{ entry.msg }}




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



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




    И будет много радости.

    Отдельные модели уровня.

    В jQuery, DOM — вроде как модель. Но на angularjs, у нас есть различные уровни модели, которыми мы можем управлять в любом случае, как мы хотим, совершенно независимо от представления. Это помогает вышеуказанной привязке данных, поддерживает разделение обязанностей и вводит гораздо большую тестируемость. Другие ответы упомянули этот момент, поэтому закончим разговор об этом.

    Разделение обязанностей.

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

    Внедрение зависимости.

    Внедрение зависимости (di) поможет нам с разделением обязанностей. Если вы пришли из серверных языков (из java в PHP) вы, наверное, уже знакомы с этим понятием, но если вы на стороне клиента, пришли с jQuery, это понятие может показаться глупым и лишним. Но это не так. :-)

    С широкой точки зрения, di означает, что вы можете объявить компоненты очень свободно и потом просто попросите его экземпляр, и он будет предоставлен. Вы не должны знать о порядке загрузки, или о местоположении файлов, или что-нибудь подобное. Питание может не сразу быть видно, но я приведу только один (общий) пример: тестирование.

    Допустим, в нашем приложении, мы требуем службу, которая реализует серверные хранилища через RESTAPI и, в зависимости от состояния приложения, и локального хранилища.



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



    Говоря о тестировании…



    4.Разработка через тестирование – всегда.

    Это действительно часть 3 раздела по архитектуре, а это так важно, что я ставлю его во главе своего раздела.



    Из всего множества jQuery плагинов, которые вы видели, использовали, или написали, сколько из них имели сопутствующие тесты? Не очень много, потому что jQuery не очень склонна к этому. Но angularjs склонен.



    В jQuery, единственный способ для теста — это создать самостоятельно образец/демо-страницу, чтобы показать что наши тесты могут выполнять манипуляции DOM. Значит, мы должны разработать компоненты по отдельности, а затем интегрировать их в наше приложение. Как неудобно! Так много времени, когда разрабатываем с jQuery, мы выбираем итеративный путь, а не тестирование. И кто может обвинить нас?



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

    Hello


    Хорошо, теперь мы можем написать тест:

    it( 'should add "active" when the route changes', inject(function() {
    var elm = $compile( 'Hello' )( $scope );
    $location.path('/not-matching');
    expect( elm.hasClass('active') ).toBeFalsey();
    $location.path( '/hello' );
    expect( elm.hasClass('active') ).toBeTruthy();
    }));


    Мы запускаем наш тест и убеждаемся, что это не удается. Так что теперь мы можем написать наши директивы:

    .directive( 'whenActive', function ( $location ) {
    return {
    scope: true,
    link: function ( scope, element, attrs ) {
    scope.$on( '$routeChangeSuccess', function () {
    if ( $location.path() == element.attr( 'href' ) ) {
    element.addClass( 'active' );
    }
    else {
    element.removeClass( 'active' );
    }
    });
    }
    };
    });


    Теперь наш тест проходит, и наше меню выполняется позапросу. Наша разработка как итерационная и тестируемая вместе.



    5.Теоретически, директивы не упакованы jQuery.

    Вы часто будете слышать «только манипуляции DOM в директиве». Это необходимость. Относитесь к ней с уважением!

    Но давайте углубимся немного глубже…



    Некоторые директивы просто украшают то, что уже в представлении (думаю, ngClass) и поэтому иногда делаем манипуляций с DOM, а потом, в основном, выполняем. Но если директива как «виджет» и есть шаблон, необходимо также соблюдать разделение обязанностей. То есть, шаблон тоже должен оставаться в значительной степени независимым от его реализации в ссылке и функции контроллера.



    Angularjs поставляется с полным набором инструментов, чтобы сделать это очень легко; с ngClass можно динамически обновлять классы; ngBind позволяет проводить двустороннюю привязку данных; ngShow и ngHide программно показать или скрыть элемент; и многое другое, в том числе то, что мы сочиняем сами. Другими словами, мы можем сделать все преобразования, без манипуляций с DOM. Чем меньше манипуляций с DOM, тем легче директивы для теста, тем легче их стиль, тем легче они будут меняться в будущем, и более многоразовый и распространять их.



    Я вижу много новых разработчиков angularjs, использующих директивы как место, чтобы бросить кучу jQuery. Другими словами, они думают, что «раз я не могу манипулировать DOM в контроллере, я возьму этот код поставлю его в директиву». Хотя это конечно намного лучше, часто все равно неправильно.



    Логгер мы запрограммировали в главе 3. Даже если мы предположим, что в директиве, мы все же хотим сделать «угловой путь». Он по-прежнему не принимает никаких манипуляций с DOM! Есть много моментов, когда необходимы манипуляции с DOM, но это намного реже, чем вы думаете! Прежде чем делать манипуляции с DOM в вашем приложении, спросите себя, вам действительно нужно это? Может быть способ лучше.



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

    .directive( 'myDirective', function () {
    return {
    template: 'Toggle me!',
    link: function ( scope, element, attrs ) {
    var on = false;
    $(element).click( function () {
    if ( on ) {
    $(element).removeClass( 'active' );
    }
    else {
    $(element).addClass( 'active' );
    }
    on = !on;
    });
    }
    };
    });


    Здесь есть несколько неправильных моментов.

    Во-первых, jQuery и не надо было. Мы ничего не делали здесь, чтобы был нужен jQuery во всем!

    Во-вторых, даже если у нас уже есть jQuery на странице, нет никаких причин, чтобы использовать его здесь, мы можем просто использовать angular.element и компонент по-прежнему будет работать при перетаскивании в проект, который не имеет jQuery.

    В-третьих, даже если предположить, что jQuery был необходим для работы этой директивы, jqLite (angular.element) всегда будет использовать jQuery, если он был загружен! Поэтому мы не должны использовать $ — мы можем просто использовать angular.element.

    В-четвертых, тесно связанный с третьим, элементы jqLite не нужно было оборачивать в $ — элемент, который передается в функцию по ссылке, может быть уже элемент с jQuery!

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

    Эта директива может быть переписана (даже для очень сложных случаев!) гораздо проще, вот так:

    .directive( 'myDirective', function () {
    return {
    scope: true,
    template: 'Toggle me!',
    link: function ( scope, element, attrs ) {
    scope.on = false;
    scope.toggle = function () {
    scope.on = !scope.on;
    };
    }
    };
    });


    Опять же, наполнение шаблона, так вы (или ваши пользователи) можете легко поменять его на то, что соответствует любому нужному стилю, а логика никогда не должна быть задета. Повторное использование — бум!



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



    Так что директивы — не просто коллекции jQuery функций, какие они? Директивы –это расширения HTML-кода. Если HTML не делает что-то нужное, вы напишите директиву, чтобы она сделала это для вас, а затем будете использовать её так, как будто это было частью HTML.



    Иначе говоря, если angularjs не сделает что-нибудь из коробки, думаю, команда бы выполнила это с ngClick и ngClass вместе.



    Итог.

    Даже не используйте jQuery. Даже не включайте его. Оно будет тормозить вас. И когда вы приходите к проблеме, если вы думаете, что знаете, как решить проблему в jQuery, прежде чем тянуться за $, попробуйте подумать, как это сделать в рамках в в angularjs. Если Вы не знаете — спросите! 19 раз или 20, будет лучше, если вы сделаете приложение без jQuery, ведь оно, в результате, принесет больше работы для вас.
    Original source: habrahabr.ru (comments, light).

    https://habrahabr.ru/post/305734/

    Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
    милена70

    Htmlbook Рецепты CSS

    Пятница, 16 Июля 2016 г. 00:59 (ссылка)



     







    Вёрстка




    Изображения




    Добавление картинок




    Рамка вокруг изображений




    Читать далее...
    Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
    Ралиона

    HTML для чайников

    Четверг, 14 Июля 2016 г. 19:41 (ссылка)
    site-do.ru/html/

    Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество

    Следующие 30  »

    <html - Самое интересное в блогах

    Страницы: [1] 2 3 ..
    .. 10

    LiveInternet.Ru Ссылки: на главную|почта|знакомства|одноклассники|фото|открытки|тесты|чат
    О проекте: помощь|контакты|разместить рекламу|версия для pda