{"id":370543,"date":"2024-05-21T04:27:38","date_gmt":"2024-05-21T04:27:38","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=370543"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=370543","title":{"rendered":"<span>\u0410\u043d\u0430\u0442\u043e\u043c\u0438\u044f htmx<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/wn\/mn\/0e\/wnmn0e4ug-jlj87dcflhgvzhxci.png\" data-src=\"https:\/\/habrastorage.org\/webt\/wn\/mn\/0e\/wnmn0e4ug-jlj87dcflhgvzhxci.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>Hello world!<\/p>\n<p>  <\/p>\n<p>\u041f\u043e \u0434\u0430\u043d\u043d\u044b\u043c <a href=\"https:\/\/risingstars.js.org\/2023\/en\">2023 JavaScript Rising Stars<\/a> \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 <a href=\"https:\/\/htmx.org\/\">htmx<\/a> \u0437\u0430\u043d\u044f\u043b\u0430 \u0432\u0442\u043e\u0440\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 <a href=\"https:\/\/risingstars.js.org\/2023\/en#section-framework\">Front-end Frameworks<\/a> (\u043f\u0435\u0440\u0432\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0432\u043f\u043e\u043b\u043d\u0435 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0438\u0442 <a href=\"https:\/\/react.dev\/\">React<\/a>) \u0438 \u0434\u0435\u0441\u044f\u0442\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 <a href=\"https:\/\/risingstars.js.org\/2023\/en#section-all\">Most Popular Projects Overall<\/a>.<\/p>\n<p>  <\/p>\n<p><code>htmx<\/code> \u2014 \u044d\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a <code>AJAX<\/code>, <code>\u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430\u043c CSS<\/code>, <code>WebSockets<\/code> \u0438 <code>Server Sent Events<\/code> \u043f\u0440\u044f\u043c\u043e \u0438\u0437 <code>HTML<\/code> \u0447\u0435\u0440\u0435\u0437 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b (\u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u2014 \u0434\u0440\u0443\u0433\u043e\u0439 \u0432\u043e\u043f\u0440\u043e\u0441), \u043f\u043e\u043b\u044c\u0437\u0443\u044f\u0441\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u043e\u0439 \u0438 \u043c\u043e\u0449\u044c\u044e \u0433\u0438\u043f\u0435\u0440\u0442\u0435\u043a\u0441\u0442\u0430. \u041d\u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f\u0448\u043d\u0438\u0439 \u0434\u0435\u043d\u044c \u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043f\u043e\u0447\u0442\u0438 30 000 \u0437\u0432\u0435\u0437\u0434 \u043d\u0430 <a href=\"https:\/\/github.com\/bigskysoftware\/htmx\">Github<\/a>. \u0423\u0434\u0438\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u0447\u0442\u043e \u0434\u043e \u0442\u0430\u043a\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043c\u044b \u0434\u043e\u0434\u0443\u043c\u0430\u043b\u0438\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u0439\u0447\u0430\u0441, \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044f, \u0447\u0442\u043e \u0432\u0435\u0441\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0431\u044b\u043b \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0443\u0436\u0435 10 \u043b\u0435\u0442 \u043d\u0430\u0437\u0430\u0434 (\u0432\u044b \u0441\u0430\u043c\u0438 \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c \u0432 \u044d\u0442\u043e\u043c, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0438\u0437\u0443\u0447\u0438\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 <code>htmx<\/code>).<\/p>\n<p>  <\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0441 \u0432\u0430\u043c\u0438 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f, \u043a\u0430\u043a <code>htmx<\/code> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u041d\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<p>\u041a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0432\u044b\u0434\u0435\u0440\u0436\u043a\u0438 \u0438\u0437 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 <code>htmx<\/code> (\u0444\u0430\u0439\u043b <code>public\/source-code.js<\/code>), \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 <a href=\"https:\/\/github.com\/harryheman\/blog-posts\/tree\/master\/htmx-testing\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<p>  <\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440<\/strong><\/p>\n<p>  <\/p>\n<p>\u0412\u043e\u0437\u044c\u043c\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 \u0440\u0430\u0437\u0434\u0435\u043b\u0430 <code>quick start<\/code> \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 <a href=\"https:\/\/htmx.org\/\"><code>\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0430\u0439\u0442\u0430 htmx<\/code><\/a> \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0435\u0433\u043e \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c.<\/p>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u0443\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e, \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u043d\u0435\u0435 \u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442 <a href=\"https:\/\/nodejs.org\/en\">Node.js<\/a>:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">mkdir htmx-testing cd htmx-testing npm i -yp<\/code><\/pre>\n<p>  <\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c <a href=\"https:\/\/expressjs.com\/ru\/\">express<\/a> \u0438 <a href=\"https:\/\/www.npmjs.com\/package\/\/nodemon\">nodemon<\/a>:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">npm i express npm i -D nodemon<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0442\u0438\u043f \u043a\u043e\u0434\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u0441\u043a\u0440\u0438\u043f\u0442 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432 \u0444\u0430\u0439\u043b\u0435 <code>package.json<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"json\">\"scripts\": {   \"dev\": \"nodemon\" }, \"type\": \"module\"<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0444\u0430\u0439\u043b <code>index.js<\/code> \u0441 \u0442\u0430\u043a\u0438\u043c \u043a\u043e\u0434\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import express from 'express'  \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 `express` const app = express() \/\/ \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u0441\u043e \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u043c\u0438 \u0444\u0430\u0439\u043b\u0430\u043c\u0438 app.use(express.static('public'))  \/\/ \u0420\u0430\u0437\u043c\u0435\u0442\u043a\u0430 1 const html1 = `&lt;div>   &lt;p>hello world&lt;\/p>   &lt;button     name=\"my-button\"     value=\"some-value\"     hx-get=\"\/clicked\"   >     click me   &lt;\/button> &lt;\/div>` \/\/ \u0420\u0430\u0437\u043c\u0435\u0442\u043a\u0430 2 const html2 = `&lt;span>no more swaps&lt;\/span>`  \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a POST-\u0437\u0430\u043f\u0440\u043e\u0441\u0430 app.post('\/clicked', (req, res) => {   \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043e\u0442\u0432\u0435\u0442 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443 1   res.send(html1) }) \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a GET-\u0437\u0430\u043f\u0440\u043e\u0441\u0430 app.get('\/clicked', (req, res) => {   \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043e\u0442\u0432\u0435\u0442 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443 2   res.send(html2) })  app.listen(3000)<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e <code>public<\/code> \u0438 \u0432 \u043d\u0435\u0439 2 \u0444\u0430\u0439\u043b\u0430:<\/p>\n<p>  <\/p>\n<ul>\n<li><code>index.html<\/code><\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"html\">&lt;!DOCTYPE html> &lt;html lang=\"en\">   &lt;head>     &lt;meta charset=\"UTF-8\" \/>     &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" \/>     &lt;title>Htmx test&lt;\/title>     &lt;!-- \u0425\u0430\u043a \u0434\u043b\u044f \u0444\u0430\u0432\u0438\u043a\u043e\u043d\u043a\u0438 -->     &lt;link rel=\"icon\" href=\"data:.\" \/>     &lt;!-- \u0421\u0442\u0438\u043b\u0438 -->     &lt;link rel=\"stylesheet\" href=\"style.css\" \/>     &lt;!-- \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c htmx -->     &lt;script       src=\"https:\/\/unpkg.com\/htmx.org@1.9.10\"       integrity=\"sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX\/SoJYkXDFfX37iInKRy5xLSi8nO7UC\"       crossorigin=\"anonymous\"     >&lt;\/script>   &lt;\/head>   &lt;body>     &lt;button       name=\"my-button\"       value=\"some-value\"       hx-post=\"\/clicked\"       hx-swap=\"outerHTML\"     >       click me     &lt;\/button>   &lt;\/body> &lt;\/html><\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li><code>style.css<\/code><\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"css\">body {   background-color: #333; }  p {   color: #ddd; }  \/* \u041a\u043d\u043e\u043f\u043a\u0430, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0430\u044f `span`, \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043d\u0435\u043a\u043b\u0438\u043a\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0439 *\/ button:has(span) {   pointer-events: none;   user-select: none;   color: rgba(0, 0, 0, 0.5); }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u044b <code>npm run dev<\/code> \u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 <code>http:\/\/localhost:3000<\/code>.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043a\u043d\u043e\u043f\u043a\u0438 \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 <code>http:\/\/localhost:3000\/clicked<\/code> \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f <code>POST-\u0437\u0430\u043f\u0440\u043e\u0441<\/code>. \u0412 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u044d\u0442\u043e\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f <code>\u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0430 1<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 <code>outerHTML<\/code> \u043a\u043d\u043e\u043f\u043a\u0438. \u041d\u043e\u0432\u0430\u044f \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0430\u0440\u0430\u0433\u0440\u0430\u0444 \u0438 \u043d\u043e\u0432\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u043e\u0432\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0438 \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 <code>http:\/\/localhost:3000\/clicked<\/code> \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f <code>GET-\u0437\u0430\u043f\u0440\u043e\u0441<\/code>. \u0412 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u044d\u0442\u043e\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f <code>\u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0430 2<\/code>, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0430\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442 <code>span<\/code> \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u043c. \u041d\u043e\u0432\u0430\u044f \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0430 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 <code>innerHTML<\/code> (\u0442\u0435\u043a\u0441\u0442) \u043a\u043d\u043e\u043f\u043a\u0438, \u0438 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0441\u0442\u0438\u043b\u044f\u043c \u043a\u043d\u043e\u043f\u043a\u0430 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043d\u0435\u043a\u043b\u0438\u043a\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0439.<\/p>\n<p>  <\/p>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 <code>name<\/code> \u0438 <code>value<\/code> \u0443 \u043a\u043d\u043e\u043f\u043e\u043a.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/7o\/m_\/51\/7om_51maunc3ayot_yfwgbqxhl8.png\" data-src=\"https:\/\/habrastorage.org\/webt\/7o\/m_\/51\/7om_51maunc3ayot_yfwgbqxhl8.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043f\u0435\u0440\u0432\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0438:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/mw\/ne\/1d\/mwne1dmx4kjabegrkabkpr-clai.png\" data-src=\"https:\/\/habrastorage.org\/webt\/mw\/ne\/1d\/mwne1dmx4kjabegrkabkpr-clai.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u0432\u0442\u043e\u0440\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0438:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/fc\/3a\/si\/fc3asiza0y1d-vrnr_5lpqqook0.png\" data-src=\"https:\/\/habrastorage.org\/webt\/fc\/3a\/si\/fc3asiza0y1d-vrnr_5lpqqook0.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430 <code>POST-\u0437\u0430\u043f\u0440\u043e\u0441\u0430<\/code> (\u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0432 \u0442\u0435\u043b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <code>application\/x-www-form-urlencoded<\/code>):<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/mk\/kr\/hs\/mkkrhsyyfpfjg3jz9vc1kreamd0.png\" data-src=\"https:\/\/habrastorage.org\/webt\/mk\/kr\/hs\/mkkrhsyyfpfjg3jz9vc1kreamd0.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041e\u0442\u0432\u0435\u0442 \u043d\u0430 <code>POST-\u0437\u0430\u043f\u0440\u043e\u0441<\/code>:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/bv\/ef\/bd\/bvefbd-4depr95zdvku8eui3rve.png\" data-src=\"https:\/\/habrastorage.org\/webt\/bv\/ef\/bd\/bvefbd-4depr95zdvku8eui3rve.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b <code>GET-\u0437\u0430\u043f\u0440\u043e\u0441\u0430<\/code> (<code>http:\/\/localhost:3000\/clicked?my-button=some-value<\/code>):<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/08\/0a\/6g\/080a6gw_hlfl-5et9iac7ddrqyy.png\" data-src=\"https:\/\/habrastorage.org\/webt\/08\/0a\/6g\/080a6gw_hlfl-5et9iac7ddrqyy.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041e\u0442\u0432\u0435\u0442 \u043d\u0430 <code>GET-\u0437\u0430\u043f\u0440\u043e\u0441<\/code>:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/w4\/7m\/6k\/w47m6kx7-e643laha0nltmb0m4g.png\" data-src=\"https:\/\/habrastorage.org\/webt\/w4\/7m\/6k\/w47m6kx7-e643laha0nltmb0m4g.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e. \u041d\u0430\u0447\u043d\u0435\u043c \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0432 <a href=\"https:\/\/github.com\/bigskysoftware\/htmx\"><code>\u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 htmx<\/code><\/a>.<\/p>\n<p>  <\/p>\n<p><strong>\u0420\u0435\u0432\u0435\u0440\u0441-\u0438\u043d\u0436\u0438\u043d\u0438\u0440\u0438\u043d\u0433<\/strong><\/p>\n<p>  <\/p>\n<p>\u0412\u0435\u0441\u044c \u043a\u043e\u0434 <code>htmx<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0432 \u043e\u0434\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 <a href=\"https:\/\/github.com\/bigskysoftware\/htmx\/blob\/master\/src\/htmx.js\">src\/htmx.js<\/a> \u0438 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 3905 \u0441\u0442\u0440\u043e\u043a. \u041a\u0440\u0430\u0442\u043a\u0430\u044f \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0430 \u2014 <code>var<\/code>\u044b \u0438 \u0442\u044b\u0441\u044f\u0447\u0430 \u0438 \u043e\u0434\u043d\u0430 \u0443\u0442\u0438\u043b\u0438\u0442\u0430 ?<\/p>\n<p>  <\/p>\n<p>\u042f \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043b \u0432\u0435\u0441\u044c \u043a\u043e\u0434 <code>htmx<\/code> \u0432 \u0444\u0430\u0439\u043b <code>public\/source-code.js<\/code> \u0438 \u043e\u0441\u0442\u0430\u0432\u0438\u043b \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u0434, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u2014 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c 1300 \u0441\u0442\u0440\u043e\u043a. \u0421 \u044d\u0442\u0438\u043c \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c ?<\/p>\n<p>  <\/p>\n<p><em>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435:<\/em> \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0439 \u0440\u0430\u0437\u0431\u043e\u0440 \u043a\u043e\u0434\u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u0435\u043d \u0434\u043b\u044f <code>htmx@1.9.10<\/code>. \u0412 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043a\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u0438 \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0441\u044f, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0434\u043e \u043d\u0435\u0443\u0437\u043d\u0430\u0432\u0430\u0435\u043c\u043e\u0441\u0442\u0438 ?<\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 <em>\u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435<\/em>, \u0447\u0442\u043e \u0441 \u0446\u0435\u043b\u044c\u044e \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u043e\u0431\u043b\u0435\u0433\u0447\u0435\u043d\u0438\u044f \u0435\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u0438\u044f\u0442\u0438\u044f \u044f \u0431\u0435\u0441\u043f\u043e\u0449\u0430\u0434\u043d\u043e \u0443\u0434\u0430\u043b\u044f\u043b \u0441\u0442\u0440\u043e\u043a\u0438 \u0438 \u0434\u0430\u0436\u0435 \u0446\u0435\u043b\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u043a\u043e\u0434\u0430 ?<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">var htmx = {   \/\/ \u0414\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 `htmx`   config: {     historyEnabled: true,     historyCacheSize: 10,     refreshOnHistoryMiss: false,     \/\/ \u0432\u0430\u0436\u043d\u043e! ---     defaultSwapStyle: 'innerHTML',     \/\/ --- !     defaultSwapDelay: 0,     defaultSettleDelay: 20,     includeIndicatorStyles: true,     indicatorClass: 'htmx-indicator',     \/\/ ! ---     requestClass: 'htmx-request',     addedClass: 'htmx-added',     settlingClass: 'htmx-settling',     swappingClass: 'htmx-swapping',     \/\/ --- !     allowEval: true,     allowScriptTags: true,     inlineScriptNonce: '',     \/\/ ! ---     attributesToSettle: ['class', 'style', 'width', 'height'],     \/\/ --- !     withCredentials: false,     timeout: 0,     wsReconnectDelay: 'full-jitter',     wsBinaryType: 'blob',     disableSelector: '[hx-disable], [data-hx-disable]',     useTemplateFragments: false,     scrollBehavior: 'smooth',     defaultFocusScroll: false,     getCacheBusterParam: false,     globalViewTransitions: false,     \/\/ !     methodsThatUseUrlParams: ['get'],     \/\/     selfRequestsOnly: false,     ignoreTitle: false,     scrollIntoViewOnBoost: true,     triggerSpecsCache: null,   }, }  function getDocument() {   return document }  var isReady = false getDocument().addEventListener('DOMContentLoaded', function () {   isReady = true })  function ready(fn) {   if (isReady || getDocument().readyState === 'complete') {     fn()   } else {     getDocument().addEventListener('DOMContentLoaded', fn)   } }  ready(function () {   var body = getDocument().body   processNode(body)    setTimeout(function () {     triggerEvent(body, 'htmx:load', {})     body = null   }, 0) })<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u0433\u043e\u0442\u043e\u0432\u043d\u043e\u0441\u0442\u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430 (\u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f <code>DOMContentLoaded<\/code>) \u0442\u0435\u043b\u043e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430 (<code>body<\/code>) \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>processNode<\/code>. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>triggerEvent<\/code> \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0435 <code>htmx:load<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c <code>triggerEvent<\/code> \u0438 \u0435\u0435 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function triggerEvent(elt, eventName, detail) {   \/\/ \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 `elt` - \u044d\u0442\u043e HTML-\u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0438\u043b\u0438 \u0441\u0442\u0440\u043e\u043a\u0430   elt = resolveTarget(elt)   if (detail == null) {     detail = {}   }   detail['elt'] = elt   \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0435   \/\/ https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/CustomEvent\/CustomEvent   var event = makeEvent(eventName, detail)   \/\/ \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0435   \/\/ https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/EventTarget\/dispatchEvent   var eventResult = elt.dispatchEvent(event)   return eventResult }  function resolveTarget(arg2) {   if (isType(arg2, 'String')) {     return find(arg2)   } else {     return arg2   } }  function isType(o, type) {   return Object.prototype.toString.call(o) === '[object ' + type + ']' }  function find(eltOrSelector, selector) {   if (selector) {     return eltOrSelector.querySelector(selector)   } else {     return find(getDocument(), eltOrSelector)   } }  function makeEvent(eventName, detail) {   var evt   if (window.CustomEvent &amp;&amp; typeof window.CustomEvent === 'function') {     evt = new CustomEvent(eventName, {       bubbles: true,       cancelable: true,       detail: detail,     })   } else {     evt = getDocument().createEvent('CustomEvent')     evt.initCustomEvent(eventName, true, true, detail)   }   return evt }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function triggerEvent(elt, eventName, detail) {   console.log({ elt, eventName, detail })   \/\/ ... }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/-o\/qu\/ed\/-oquedlv_lqgkluvpioq4e_aqsm.png\" data-src=\"https:\/\/habrastorage.org\/webt\/-o\/qu\/ed\/-oquedlv_lqgkluvpioq4e_aqsm.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043a\u043d\u043e\u043f\u043a\u0438:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/dp\/y8\/ia\/dpy8iazvg0pbtkbs0uwkrb7hxxq.png\" data-src=\"https:\/\/habrastorage.org\/webt\/dp\/y8\/ia\/dpy8iazvg0pbtkbs0uwkrb7hxxq.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041f\u043e \u044d\u0442\u0438\u043c \u043b\u043e\u0433\u0430\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u044c \u043e\u0431\u0449\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u044b <code>htmx<\/code>, \u043d\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0441\u043f\u0435\u0448\u0438\u0442\u044c.<\/p>\n<p>  <\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>processNode<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function processNode(elt) {   elt = resolveTarget(elt)   initNode(elt)   forEach(findElementsToProcess(elt), function (child) {     initNode(child)   }) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 <code>body<\/code>, \u0437\u0430\u0442\u0435\u043c \u0432\u0441\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0438\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>findElementsToProcess<\/code> \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>initNode<\/code>.<\/p>\n<p>  <\/p>\n<p><code>findElementsToProcess<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u0441\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u043f\u043e\u0434\u043b\u0435\u0436\u0430\u0449\u0438\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 <code>htmx<\/code> (\u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0441 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430\u043c\u0438 <code>htmx<\/code>):<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">var VERBS = ['get', 'post', 'put', 'delete', 'patch'] var VERB_SELECTOR = VERBS.map(function (verb) {   return '[hx-' + verb + '], [data-hx-' + verb + ']' }).join(', ')  function findElementsToProcess(elt) {   var boostedSelector =     ', [hx-boost] a, [data-hx-boost] a, a[hx-boost], a[data-hx-boost]'   var results = elt.querySelectorAll(     VERB_SELECTOR +       boostedSelector +       \", form, [type='submit'], [hx-sse], [data-hx-sse], [hx-ws],\" +       ' [data-hx-ws], [hx-ext], [data-hx-ext], [hx-trigger], [data-hx-trigger], [hx-on], [data-hx-on]',   )   return results }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0424\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">[hx-get], [data-hx-get], [hx-post], [data-hx-post], [hx-put], [data-hx-put], [hx-delete], [data-hx-delete], [hx-patch], [data-hx-patch], [hx-boost] a, [data-hx-boost] a, a[hx-boost], a[data-hx-boost], form, [type='submit'], [hx-sse], [data-hx-sse], [hx-ws], [data-hx-ws], [hx-ext], [data-hx-ext], [hx-trigger], [data-hx-trigger], [hx-on], [data-hx-on]<\/code><\/pre>\n<p>  <\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>initNode<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function initNode(elt) {   \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435   var nodeData = getInternalData(elt)   \/\/ \u0415\u0441\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0438\u0441\u044c \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 (\u043f\u0440\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0435)   if (nodeData.initHash !== attributeHash(elt)) {     \/\/ \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435     deInitNode(elt)     \/\/ \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0441\u0442\u0440\u043e\u043a\u0443 \u0445\u0435\u0448\u0430     nodeData.initHash = attributeHash(elt)      triggerEvent(elt, 'htmx:beforeProcessNode')      \/\/ \u0415\u0441\u043b\u0438 \u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0435\u0441\u0442\u044c \u0430\u0442\u0440\u0438\u0431\u0443\u0442 `value`     if (elt.value) {       nodeData.lastValue = elt.value     }      \/\/ \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u044b     var triggerSpecs = getTriggerSpecs(elt)     \/\/ \u041e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u044b     var hasExplicitHttpAction = processVerbs(elt, nodeData, triggerSpecs)      triggerEvent(elt, 'htmx:afterProcessNode')   } }  function getInternalData(elt) {   var dataProp = 'htmx-internal-data'   var data = elt[dataProp]   if (!data) {     data = elt[dataProp] = {}   }   return data }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u043c\u0438 \u0437\u0434\u0435\u0441\u044c \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>getTriggerSpecs<\/code> \u0438 <code>processVerbs<\/code>, \u043d\u043e \u043e \u043d\u0438\u0445 \u043f\u043e\u0437\u0436\u0435.<\/p>\n<p>  <\/p>\n<p>\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u0441\u0430\u043c\u043e\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0435. \u042d\u043b\u0435\u043c\u0435\u043d\u0442, \u043a\u0430\u043a \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435 \u0432 <code>JavaScript<\/code>, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c. \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430-\u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0435 <code>htmx-internal-data<\/code>. \u0412\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u043d\u043e\u043f\u043a\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function initNode(elt) {   var nodeData = getInternalData(elt)   console.log({ nodeData })   \/\/ ... }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/uy\/88\/iy\/uy88iye1nrerwnem9vsl_zntzh0.png\" data-src=\"https:\/\/habrastorage.org\/webt\/uy\/88\/iy\/uy88iye1nrerwnem9vsl_zntzh0.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438\u0437-\u0437\u0430 \u043c\u0443\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u0438 (\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u043e\u0441\u0442\u0438) <code>nodeData<\/code>. \u042d\u0442\u043e \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 <code>getTriggerSpecs<\/code> \u0438 <code>processVerbs<\/code>, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430 <code>getTriggerSpecs<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function initNode(elt) {   \/\/ ...   if (nodeData.initHash !== attributeHash(elt)) {     \/\/ ...     var triggerSpecs = getTriggerSpecs(elt)     var hasExplicitHttpAction = processVerbs(elt, nodeData, triggerSpecs)     console.log({ triggerSpecs, hasExplicitHttpAction })     \/\/ ...   } }  function getTriggerSpecs(elt) {   var triggerSpecs = []    if (triggerSpecs.length > 0) {     return triggerSpecs   } else if (matches(elt, 'form')) {     return [{ trigger: 'submit' }]   } else if (matches(elt, 'input[type=\"button\"], input[type=\"submit\"]')) {     return [{ trigger: 'click' }]   } else if (matches(elt, 'input, textarea, select')) {     return [{ trigger: 'change' }]   } else {     \/\/ \u0414\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 \u0442\u0440\u0438\u0433\u0433\u0435\u0440 - \u043d\u0430\u0448 \u0441\u043b\u0443\u0447\u0430\u0439     return [{ trigger: 'click' }]   } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ik\/u_\/yw\/iku_ywtqmyz4gglxxs-veclwwom.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ik\/u_\/yw\/iku_ywtqmyz4gglxxs-veclwwom.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>processVerbs<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function processVerbs(elt, nodeData, triggerSpecs) {   var explicitAction = false   \/\/ \u041f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0435\u043c \u0433\u043b\u0430\u0433\u043e\u043b\u044b (get, post, put \u0438 \u0442.\u0434.)   forEach(VERBS, function (verb) {     \/\/ \u0415\u0441\u043b\u0438 \u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0430\u0442\u0440\u0438\u0431\u0443\u0442,     \/\/ \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, `hx-post`     if (hasAttribute(elt, 'hx-' + verb)) {       \/\/ \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u043f\u0443\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, `\/clicked`       var path = getAttributeValue(elt, 'hx-' + verb)       explicitAction = true       nodeData.path = path       nodeData.verb = verb       \/\/ \u041f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0435\u043c \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u044b       triggerSpecs.forEach(function (triggerSpec) {         \/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430         addTriggerHandler(elt, triggerSpec, nodeData, function (elt, evt) {           \/\/ \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430 \u0441\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u0430           issueAjaxRequest(verb, path, elt, evt)         })       })     }   })   return explicitAction }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function addTriggerHandler(elt, triggerSpec, nodeData, handler) {   addEventListener(elt, handler, nodeData, triggerSpec) }  function addEventListener(elt, handler, nodeData, triggerSpec) {   var eltsToListenOn = [elt]    forEach(eltsToListenOn, function (eltToListenOn) {     \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a     var eventListener = function (evt) {       var eventData = getInternalData(evt)       eventData.triggerSpec = triggerSpec       if (eventData.handledFor == null) {         eventData.handledFor = []       }       if (eventData.handledFor.indexOf(elt) &lt; 0) {         eventData.handledFor.push(elt)          triggerEvent(elt, 'htmx:trigger')         \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u0430         handler(elt, evt)       }     }     if (nodeData.listenerInfos == null) {       nodeData.listenerInfos = []     }     \/\/ \u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438     nodeData.listenerInfos.push({       trigger: triggerSpec.trigger,       listener: eventListener,       on: eltToListenOn,     })     \/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430     eltToListenOn.addEventListener(triggerSpec.trigger, eventListener)   }) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>issueAjaxRequest<\/code> \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0430\u044f \u0432 \u043d\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>handleAjaxResponse<\/code> \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 <code>htmx<\/code>. \u041b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u043e, \u0447\u0442\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Fetch_API\">Fetch API<\/a>, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043e\u0436\u0438\u0434\u0430\u0442\u044c, \u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/developer.mozilla.org\/ru\/docs\/Web\/API\/XMLHttpRequest\">XMLHttpRequest<\/a>.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 <code>issueAjaxRequest<\/code> (\u0441 \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0435\u043d\u0438\u044f, \u044f \u043f\u0440\u043e\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u044e \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b):<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function issueAjaxRequest(verb, path, elt, event, etc, confirmed) {   console.log({ verb, path, elt, event, etc, confirmed })   var resolve = null   var reject = null   etc = etc != null ? etc : {}    var promise = new Promise(function (_resolve, _reject) {     resolve = _resolve     reject = _reject   })    \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043e\u0442\u0432\u0435\u0442\u0430   var responseHandler = etc.handler || handleAjaxResponse   var select = etc.select || null    var target = etc.targetOverride || elt    var eltData = getInternalData(elt)    var abortable = false    \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 `XMLHttpRequest`   var xhr = new XMLHttpRequest()   eltData.xhr = xhr   eltData.abortable = abortable    var endRequestLock = function () {     eltData.xhr = null     eltData.abortable = false     if (eltData.queuedRequests != null &amp;&amp; eltData.queuedRequests.length > 0) {       var queuedRequest = eltData.queuedRequests.shift()       queuedRequest()     }   }    \/\/ \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430   var headers = getHeaders(elt, target)    if (verb !== 'get' &amp;&amp; !usesFormData(elt)) {     headers['Content-Type'] = 'application\/x-www-form-urlencoded'   }    \/\/ \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0432 \u0442\u0435\u043b\u0435 \u0438\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430   var results = getInputValues(elt, verb)   var errors = results.errors   var rawParameters = results.values   \/\/ `hx-vars`, `hx-vals`   \/\/ var expressionVars = getExpressionVars(elt)   var expressionVars = {}   var allParameters = mergeObjects(rawParameters, expressionVars)   \/\/ `hx-params`   \/\/ var filteredParameters = filterValues(allParameters, elt)   var filteredParameters = allParameters   console.log({ results, filteredParameters })    \/\/ var requestAttrValues = getValuesForElement(elt, 'hx-request')   var requestAttrValues = {}    var eltIsBoosted = getInternalData(elt).boosted    var useUrlParams = htmx.config.methodsThatUseUrlParams.indexOf(verb) >= 0    var requestConfig = {     boosted: eltIsBoosted,     useUrlParams: useUrlParams,     parameters: filteredParameters,     unfilteredParameters: allParameters,     headers: headers,     target: target,     verb: verb,     errors: errors,     withCredentials:       etc.credentials ||       requestAttrValues.credentials ||       htmx.config.withCredentials,     timeout: etc.timeout || requestAttrValues.timeout || htmx.config.timeout,     path: path,     triggeringEvent: event,   }    \/\/ \u041d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439, \u0435\u0441\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442 \u0431\u044b\u043b \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0430\u043d   path = requestConfig.path   verb = requestConfig.verb   headers = requestConfig.headers   filteredParameters = requestConfig.parameters   errors = requestConfig.errors   useUrlParams = requestConfig.useUrlParams    var splitPath = path.split('#')   var pathNoAnchor = splitPath[0]   var anchor = splitPath[1]    var finalPath = path    \/\/ \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b GET-\u0437\u0430\u043f\u0440\u043e\u0441\u0430   if (useUrlParams) {     finalPath = pathNoAnchor     var values = Object.keys(filteredParameters).length !== 0     if (values) {       if (finalPath.indexOf('?') &lt; 0) {         finalPath += '?'       } else {         finalPath += '&amp;'       }       finalPath += urlEncode(filteredParameters)       if (anchor) {         finalPath += '#' + anchor       }     }   }    \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441   xhr.open(verb.toUpperCase(), finalPath, true)   xhr.overrideMimeType('text\/html')   xhr.withCredentials = requestConfig.withCredentials   xhr.timeout = requestConfig.timeout    if (requestAttrValues.noHeaders) {     \/\/ \u0418\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438   } else {     for (var header in headers) {       if (headers.hasOwnProperty(header)) {         var headerValue = headers[header]         safelySetHeaderValue(xhr, header, headerValue)       }     }   }    var responseInfo = {     xhr: xhr,     target: target,     requestConfig: requestConfig,     etc: etc,     boosted: eltIsBoosted,     select: select,     pathInfo: {       requestPath: path,       finalRequestPath: finalPath,       anchor: anchor,     },   }    \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430   xhr.onload = function () {     try {       var hierarchy = hierarchyForElt(elt)       responseInfo.pathInfo.responsePath = getPathFromResponse(xhr)       console.log({ hierarchy, responseInfo })       \/\/ \u0432\u0430\u0436\u043d\u043e! \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u0430       responseHandler(elt, responseInfo)        maybeCall(resolve)       endRequestLock()     } catch (e) {       console.error(         elt,         'htmx:onLoadError',         mergeObjects({ error: e }, responseInfo),       )       throw e     }   }    \/\/ \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043d\u0435 GET-\u0437\u0430\u043f\u0440\u043e\u0441\u0430   var params = useUrlParams     ? null     : encodeParamsForBody(xhr, elt, filteredParameters)   console.log({ params })    \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441   xhr.send(params)    return promise }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043f\u0435\u0440\u0432\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0438 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 <code>POST-\u0437\u0430\u043f\u0440\u043e\u0441\u0430<\/code>:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/zx\/xv\/kz\/zxxvkzaj5dh0lft3g4tivs_h9-u.png\" data-src=\"https:\/\/habrastorage.org\/webt\/zx\/xv\/kz\/zxxvkzaj5dh0lft3g4tivs_h9-u.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u0432\u0442\u043e\u0440\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0438 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 <code>GET-\u0437\u0430\u043f\u0440\u043e\u0441\u0430<\/code>:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ze\/7t\/cn\/ze7tcnjn3asv48infddlpgff6se.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ze\/7t\/cn\/ze7tcnjn3asv48infddlpgff6se.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041e\u0442\u0432\u0435\u0442 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <code>handleAjaxResponse<\/code>. \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0435 \u043d\u043e\u0432\u043e\u0439 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function handleAjaxResponse(elt, responseInfo) {   var xhr = responseInfo.xhr   var target = responseInfo.target   var etc = responseInfo.etc   var select = responseInfo.select    \/\/ \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0437\u0430\u043c\u0435\u043d\u044b \u0441\u0442\u0430\u0440\u043e\u0439 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438 \u043d\u0430 \u043d\u043e\u0432\u0443\u044e   var shouldSwap = xhr.status >= 200 &amp;&amp; xhr.status &lt; 400 &amp;&amp; xhr.status !== 204   var serverResponse = xhr.response   var isError = xhr.status >= 400   var ignoreTitle = htmx.config.ignoreTitle   var beforeSwapDetails = mergeObjects(     {       shouldSwap: shouldSwap,       serverResponse: serverResponse,       isError: isError,       ignoreTitle: ignoreTitle,     },     responseInfo,   )    target = beforeSwapDetails.target \/\/ \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0446\u0435\u043b\u0438   serverResponse = beforeSwapDetails.serverResponse \/\/ \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e   isError = beforeSwapDetails.isError \/\/ \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438   ignoreTitle = beforeSwapDetails.ignoreTitle \/\/ \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430    responseInfo.target = target   responseInfo.failed = isError   responseInfo.successful = !isError    if (beforeSwapDetails.shouldSwap) {     var swapOverride = etc.swapOverride      \/\/ \u0425\u0430\u0440\u0430\u043a\u0442\u0435\u0440 \u0437\u0430\u043c\u0435\u043d\u044b \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c\u044b\u0439 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c `hx-swap` (\u043d\u0430\u0448 `POST-\u0437\u0430\u043f\u0440\u043e\u0441`),     \/\/ \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e - `innerHTML` (\u043d\u0430\u0448 `GET-\u0437\u0430\u043f\u0440\u043e\u0441`)     var swapSpec = getSwapSpecification(elt, swapOverride)     \/\/ \u0434\u043b\u044f \u043f\u0435\u0440\u0432\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0438 - { swapStyle: 'outerHTML', swapDelay: 0, settleDelay: 20 }     \/\/ \u0434\u043b\u044f \u0432\u0442\u043e\u0440\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0438 - { swapStyle: 'innerHTML', swapDelay: 0, settleDelay: 20 }     console.log(swapSpec)      target.classList.add(htmx.config.swappingClass)      var settleResolve = null     var settleReject = null      \/\/ \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u043c\u0435\u043d\u044b     var doSwap = function () {       try {         var activeElt = document.activeElement         var selectionInfo = {}         try {           selectionInfo = {             elt: activeElt,             \/\/ @ts-ignore             start: activeElt ? activeElt.selectionStart : null,             \/\/ @ts-ignore             end: activeElt ? activeElt.selectionEnd : null,           }         } catch (e) {           \/\/ safari issue - see https:\/\/github.com\/microsoft\/playwright\/issues\/5894         }          var selectOverride         if (select) {           selectOverride = select         }          \/\/ \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447 \u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u0447\u0438\u0441\u0442\u043a\u0438 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u043c\u0435\u043d\u044b \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438         var settleInfo = makeSettleInfo(target)         \/\/ \u0432\u0430\u0436\u043d\u043e! \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u043c\u0435\u043d\u044b         selectAndSwap(           swapSpec.swapStyle,           target,           elt,           serverResponse,           settleInfo,           selectOverride,         )          target.classList.remove(htmx.config.swappingClass)         forEach(settleInfo.elts, function (elt) {           if (elt.classList) {             elt.classList.add(htmx.config.settlingClass)           }           triggerEvent(elt, 'htmx:afterSwap', responseInfo)         })          \/\/ \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0447\u0438\u0441\u0442\u043a\u0438 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u043c\u0435\u043d\u044b \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438         var doSettle = function () {           forEach(settleInfo.tasks, function (task) {             task.call()           })           forEach(settleInfo.elts, function (elt) {             if (elt.classList) {               elt.classList.remove(htmx.config.settlingClass)             }             triggerEvent(elt, 'htmx:afterSettle', responseInfo)           })            if (responseInfo.pathInfo.anchor) {             var anchorTarget = getDocument().getElementById(               responseInfo.pathInfo.anchor,             )             if (anchorTarget) {               anchorTarget.scrollIntoView({                 block: 'start',                 behavior: 'auto',               })             }           }            if (settleInfo.title &amp;&amp; !ignoreTitle) {             var titleElt = find('title')             if (titleElt) {               titleElt.innerHTML = settleInfo.title             } else {               window.document.title = settleInfo.title             }           }            maybeCall(settleResolve)         }          \/\/ \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0447\u0438\u0441\u0442\u043a\u0438, \u043a\u0430\u043a \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u043c\u0435\u043d\u044b \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439         if (swapSpec.settleDelay > 0) {           setTimeout(doSettle, swapSpec.settleDelay)         } else {           \/\/ \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043e\u0447\u0438\u0441\u0442\u043a\u0438           doSettle()         }       } catch (e) {         console.error(elt, 'htmx:swapError', responseInfo)         maybeCall(settleReject)         throw e       }     }      if (swapSpec.swapDelay > 0) {       setTimeout(doSwap, swapSpec.swapDelay)     } else {       \/\/ \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0437\u0430\u043c\u0435\u043d\u044b       doSwap()     }   } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>selectAndSwap<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function selectAndSwap(swapStyle, target, elt, responseText, settleInfo) {   console.log({     swapStyle,     target,     elt,     responseText,     settleInfo,   })   \/\/ `body`   var fragment = makeFragment(responseText)   if (fragment) {     return swap(swapStyle, elt, target, fragment, settleInfo)   } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>swap<\/code>, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0430\u044f \u0437\u0430 \u0437\u0430\u043c\u0435\u043d\u0443 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function swap(swapStyle, elt, target, fragment, settleInfo) {   console.log({ swapStyle, elt, target, fragment, settleInfo })   switch (swapStyle) {     case 'none':       return     \/\/ \u041f\u0435\u0440\u0432\u0430\u044f \u043a\u043d\u043e\u043f\u043a\u0430     case 'outerHTML':       swapOuterHTML(target, fragment, settleInfo)       return     case 'afterbegin':       \/\/ swapAfterBegin(target, fragment, settleInfo)       return     case 'beforebegin':       \/\/ swapBeforeBegin(target, fragment, settleInfo)       return     case 'beforeend':       \/\/ swapBeforeEnd(target, fragment, settleInfo)       return     case 'afterend':       \/\/ swapAfterEnd(target, fragment, settleInfo)       return     case 'delete':       \/\/ swapDelete(target, fragment, settleInfo)       return     default:       \/\/ \u0412\u0442\u043e\u0440\u0430\u044f \u043a\u043d\u043e\u043f\u043a\u0430       if (swapStyle === 'innerHTML') {         swapInnerHTML(target, fragment, settleInfo)       } else {         swap(htmx.config.defaultSwapStyle, elt, target, fragment, settleInfo)       }   } }  \/\/ \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u043c\u0435\u043d\u044b \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e (\u0432\u0441\u0435\u0433\u043e) `HTML` \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 function swapOuterHTML(target, fragment, settleInfo) {   if (target.tagName === 'BODY') {     \/\/ return swapInnerHTML(target, fragment, settleInfo)   } else {     var newElt     var eltBeforeNewContent = target.previousSibling     \/\/ \u0412\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u0435\u0440\u0435\u0434 \u0446\u0435\u043b\u0435\u0432\u044b\u043c     insertNodesBefore(parentElt(target), target, fragment, settleInfo)     \/\/ \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043e\u0447\u0438\u0441\u0442\u043a\u0443     if (eltBeforeNewContent == null) {       newElt = parentElt(target).firstChild     } else {       newElt = eltBeforeNewContent.nextSibling     }     settleInfo.elts = settleInfo.elts.filter(function (e) {       return e != target     })     while (newElt &amp;&amp; newElt !== target) {       if (newElt.nodeType === Node.ELEMENT_NODE) {         settleInfo.elts.push(newElt)       }       newElt = newElt.nextElementSibling     }     cleanUpElement(target)     parentElt(target).removeChild(target)   } }  function swapInnerHTML(target, fragment, settleInfo) {   var firstChild = target.firstChild   \/\/ \u0412\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u0435\u0440\u0435\u0434 \u0435\u0433\u043e \u043f\u0435\u0440\u0432\u044b\u043c \u043f\u043e\u0442\u043e\u043c\u043a\u043e\u043c   insertNodesBefore(target, firstChild, fragment, settleInfo)   \/\/ \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043e\u0447\u0438\u0441\u0442\u043a\u0443   if (firstChild) {     while (firstChild.nextSibling) {       cleanUpElement(firstChild.nextSibling)       target.removeChild(firstChild.nextSibling)     }     cleanUpElement(firstChild)     target.removeChild(firstChild)   } }  function insertNodesBefore(parentNode, insertBefore, fragment, settleInfo) {   console.log({ parentNode, insertBefore, fragment, settleInfo })   while (fragment.childNodes.length > 0) {     var child = fragment.firstChild     addClassToElement(child, htmx.config.addedClass)     parentNode.insertBefore(child, insertBefore)     if (       child.nodeType !== Node.TEXT_NODE &amp;&amp;       child.nodeType !== Node.COMMENT_NODE     ) {       settleInfo.tasks.push(makeAjaxLoadTask(child))     }   } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u043f\u0435\u0440\u0432\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0438:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/yn\/iu\/ak\/yniuakoxhivlbomwvkmyyiaunjc.png\" data-src=\"https:\/\/habrastorage.org\/webt\/yn\/iu\/ak\/yniuakoxhivlbomwvkmyyiaunjc.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u0432\u0442\u043e\u0440\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0438:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/dq\/_s\/k6\/dq_sk6uibptnwfigoevwurusdpg.png\" data-src=\"https:\/\/habrastorage.org\/webt\/dq\/_s\/k6\/dq_sk6uibptnwfigoevwurusdpg.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u0430\u0433\u0430\u044e, \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u044b \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442\u0435, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 htmx (\u043b\u043e\u0432\u043a\u043e\u0441\u0442\u044c \u0440\u0443\u043a \u0438 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u043c\u043e\u0448\u0435\u043d\u043d\u0438\u0447\u0435\u0441\u0442\u0432\u0430 ?), \u0438 \u0443\u0431\u0435\u0434\u0438\u043b\u0438\u0441\u044c \u0432 \u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e\u0441\u0442\u0438 \u043c\u043e\u0435\u0433\u043e \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f, \u0441\u0434\u0435\u043b\u0430\u043d\u043d\u043e\u0433\u043e \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438, \u043e \u0442\u043e\u043c, \u0447\u0442\u043e htmx \u0431\u044b\u043b \u0432\u043e\u0437\u043c\u043e\u0436\u0435\u043d \u0443\u0436\u0435 \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c 10 \u043b\u0435\u0442 \u043d\u0430\u0437\u0430\u0434, \u043d\u043e \u0443\u0434\u0438\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c &#171;\u0432\u044b\u0441\u0442\u0440\u0435\u043b\u0438\u043b&#187; \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u0439\u0447\u0430\u0441.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0436\u0430\u043b\u0443\u0439, \u044d\u0442\u043e \u0432\u0441\u0435, \u043e \u0447\u0435\u043c \u044f \u0445\u043e\u0442\u0435\u043b \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0430\u043c \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<p>  <\/p>\n<p>Happy coding!<\/p>\n<p>  <\/p>\n<hr\/>\n<p>  <\/p>\n<blockquote><p><a href=\"https:\/\/t.me\/timewebru\"><b>\u041d\u043e\u0432\u043e\u0441\u0442\u0438, \u043e\u0431\u0437\u043e\u0440\u044b \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432 \u0438 \u043a\u043e\u043d\u043a\u0443\u0440\u0441\u044b \u043e\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b Timeweb.Cloud \u2014 \u0432 \u043d\u0430\u0448\u0435\u043c Telegram-\u043a\u0430\u043d\u0430\u043b\u0435<\/b><\/a> <b>\u21a9<\/b><\/p><\/blockquote>\n<p><a href=\"https:\/\/timeweb.cloud\/?i=106909\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/b5\/pj\/of\/b5pjofdoxth14ro-rjsrn7sbmiy.png\" data-src=\"https:\/\/habrastorage.org\/webt\/b5\/pj\/of\/b5pjofdoxth14ro-rjsrn7sbmiy.png\"\/><\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/799555\/\"> https:\/\/habr.com\/ru\/articles\/799555\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/wn\/mn\/0e\/wnmn0e4ug-jlj87dcflhgvzhxci.png\" data-src=\"https:\/\/habrastorage.org\/webt\/wn\/mn\/0e\/wnmn0e4ug-jlj87dcflhgvzhxci.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>Hello world!<\/p>\n<p>  <\/p>\n<p>\u041f\u043e \u0434\u0430\u043d\u043d\u044b\u043c <a href=\"https:\/\/risingstars.js.org\/2023\/en\">2023 JavaScript Rising Stars<\/a> \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 <a href=\"https:\/\/htmx.org\/\">htmx<\/a> \u0437\u0430\u043d\u044f\u043b\u0430 \u0432\u0442\u043e\u0440\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 <a href=\"https:\/\/risingstars.js.org\/2023\/en#section-framework\">Front-end Frameworks<\/a> (\u043f\u0435\u0440\u0432\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0432\u043f\u043e\u043b\u043d\u0435 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0438\u0442 <a href=\"https:\/\/react.dev\/\">React<\/a>) \u0438 \u0434\u0435\u0441\u044f\u0442\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 <a href=\"https:\/\/risingstars.js.org\/2023\/en#section-all\">Most Popular Projects Overall<\/a>.<\/p>\n<p>  <\/p>\n<p><code>htmx<\/code> \u2014 \u044d\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a <code>AJAX<\/code>, <code>\u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430\u043c CSS<\/code>, <code>WebSockets<\/code> \u0438 <code>Server Sent Events<\/code> \u043f\u0440\u044f\u043c\u043e \u0438\u0437 <code>HTML<\/code> \u0447\u0435\u0440\u0435\u0437 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b (\u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u2014 \u0434\u0440\u0443\u0433\u043e\u0439 \u0432\u043e\u043f\u0440\u043e\u0441), \u043f\u043e\u043b\u044c\u0437\u0443\u044f\u0441\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u043e\u0439 \u0438 \u043c\u043e\u0449\u044c\u044e \u0433\u0438\u043f\u0435\u0440\u0442\u0435\u043a\u0441\u0442\u0430. \u041d\u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f\u0448\u043d\u0438\u0439 \u0434\u0435\u043d\u044c \u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043f\u043e\u0447\u0442\u0438 30 000 \u0437\u0432\u0435\u0437\u0434 \u043d\u0430 <a href=\"https:\/\/github.com\/bigskysoftware\/htmx\">Github<\/a>. \u0423\u0434\u0438\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u0447\u0442\u043e \u0434\u043e \u0442\u0430\u043a\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043c\u044b \u0434\u043e\u0434\u0443\u043c\u0430\u043b\u0438\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u0439\u0447\u0430\u0441, \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044f, \u0447\u0442\u043e \u0432\u0435\u0441\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0431\u044b\u043b \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0443\u0436\u0435 10 \u043b\u0435\u0442 \u043d\u0430\u0437\u0430\u0434 (\u0432\u044b \u0441\u0430\u043c\u0438 \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c \u0432 \u044d\u0442\u043e\u043c, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0438\u0437\u0443\u0447\u0438\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 <code>htmx<\/code>).<\/p>\n<p>  <\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0441 \u0432\u0430\u043c\u0438 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f, \u043a\u0430\u043a <code>htmx<\/code> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u041d\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-370543","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/370543","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=370543"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/370543\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=370543"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=370543"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=370543"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}