فهرست منبع

Add .once modifer

Caleb Porzio 5 سال پیش
والد
کامیت
d270383841
8فایلهای تغییر یافته به همراه79 افزوده شده و 15 حذف شده
  1. 6 1
      README.md
  2. 2 2
      dist/mix-manifest.json
  3. 18 5
      dist/project-x.js
  4. 0 0
      dist/project-x.min.js
  5. 10 1
      index.html
  6. 1 1
      package.json
  7. 17 5
      src/component.js
  8. 25 0
      test/on.spec.js

+ 6 - 1
README.md

@@ -139,7 +139,7 @@ In this example, the "hidden" class will only be applied when the value of the `
 For example:
 `<button x-bind:disabled="myVar">Click me</button>`
 
-This will add or remove the `disabled` attribute when `myVar` is true or false respectively. 
+This will add or remove the `disabled` attribute when `myVar` is true or false respectively.
 
 Most common boolean attributes are supported, like `readonly`, `required`, etc.
 
@@ -178,6 +178,11 @@ Adding `.stop` to an event listener will call `stopPropagation` on the triggered
 
 Adding `.window` to an event listener will install the listener on the global window object instead of the DOM node on which it is declared. This is useful for when you want to modify component state when something changes with the window, like the resize event. In this example, when the window grows larger than 768 pixels wide, we will close the modal/dropdown, otherwise maintain the same state.
 
+**`.once` modifier**
+**Example:** `<button x-on:mouseenter.once="fetchSomething()"></button>`
+
+Adding the `.once` modifer to an event listener will ensure that the listener will only be handled once. This is useful for things you only want to do once, like fetching HTML partials and such.
+
 ---
 
 ### `x-model`

+ 2 - 2
dist/mix-manifest.json

@@ -1,4 +1,4 @@
 {
-    "/project-x.js": "/project-x.js?id=6a940bba5ac7fd0b68e1",
-    "/project-x.min.js": "/project-x.min.js?id=39ed1c431c27b0184930"
+    "/project-x.js": "/project-x.js?id=ec509918933bb1813fd2",
+    "/project-x.min.js": "/project-x.min.js?id=8bba743308e09dcd7d20"
 }

+ 18 - 5
dist/project-x.js

@@ -1094,8 +1094,7 @@ function () {
       var _this2 = this;
 
       if (modifiers.includes('away')) {
-        // Listen for this event at the root level.
-        document.addEventListener(event, function (e) {
+        var handler = function handler(e) {
           // Don't do anything if the click came form the element or within it.
           if (el.contains(e.target)) return; // Don't do anything if this element isn't currently visible.
 
@@ -1103,15 +1102,29 @@ function () {
           // is from outside it, let's run the expression.
 
           _this2.runListenerHandler(expression, e);
-        });
+
+          if (modifiers.includes('once')) {
+            document.removeEventListener(event, handler);
+          }
+        }; // Listen for this event at the root level.
+
+
+        document.addEventListener(event, handler);
       } else {
         var node = modifiers.includes('window') ? window : el;
-        node.addEventListener(event, function (e) {
+
+        var _handler = function _handler(e) {
           if (modifiers.includes('prevent')) e.preventDefault();
           if (modifiers.includes('stop')) e.stopPropagation();
 
           _this2.runListenerHandler(expression, e);
-        });
+
+          if (modifiers.includes('once')) {
+            node.removeEventListener(event, _handler);
+          }
+        };
+
+        node.addEventListener(event, _handler);
       }
     }
   }, {

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/project-x.min.js


+ 10 - 1
index.html

@@ -5,7 +5,7 @@
             [x-cloak] { display: none; }
         </style>
 
-        <script src="https://cdn.jsdelivr.net/gh/calebporzio/project-x@v0.4.3/dist/project-x.min.js" defer></script>
+        <script src="https://cdn.jsdelivr.net/gh/calebporzio/project-x@v0.4.4/dist/project-x.min.js" defer></script>
     </head>
     <body>
         <table>
@@ -138,6 +138,15 @@
                     </td>
                 </tr>
 
+                <tr>
+                    <td>x-on:click.once</td>
+                    <td>
+                        <div x-data="{ count: 0 }">
+                            <button x-on:click.once="count++">I've been clicked: <span x-text="count"></span></button>
+                        </div>
+                    </td>
+                </tr>
+
                 <tr>
                     <td>Append DOM</td>
                     <td>

+ 1 - 1
package.json

@@ -1,7 +1,7 @@
 {
   "main": "dist/project-x.js",
   "name": "project-x",
-  "version": "0.4.3",
+  "version": "0.4.4",
   "repository": {
     "type": "git",
     "url": "git://github.com/calebporzio/project-x.git"

+ 17 - 5
src/component.js

@@ -177,8 +177,7 @@ export default class Component {
 
     registerListener(el, event, modifiers, expression) {
         if (modifiers.includes('away')) {
-            // Listen for this event at the root level.
-            document.addEventListener(event, e => {
+            const handler = e => {
                 // Don't do anything if the click came form the element or within it.
                 if (el.contains(e.target)) return
 
@@ -188,16 +187,29 @@ export default class Component {
                 // Now that we are sure the element is visible, AND the click
                 // is from outside it, let's run the expression.
                 this.runListenerHandler(expression, e)
-            })
+
+                if (modifiers.includes('once')) {
+                    document.removeEventListener(event, handler)
+                }
+            }
+
+            // Listen for this event at the root level.
+            document.addEventListener(event, handler)
         } else {
             const node = modifiers.includes('window') ? window : el
 
-            node.addEventListener(event, e => {
+            const handler = e => {
                 if (modifiers.includes('prevent')) e.preventDefault()
                 if (modifiers.includes('stop')) e.stopPropagation()
 
                 this.runListenerHandler(expression, e)
-            })
+
+                if (modifiers.includes('once')) {
+                    node.removeEventListener(event, handler)
+                }
+            }
+
+            node.addEventListener(event, handler)
         }
     }
 

+ 25 - 0
test/on.spec.js

@@ -1,5 +1,6 @@
 import projectX from 'project-x'
 import { wait } from '@testing-library/dom'
+const timeout = ms => new Promise(resolve => setTimeout(resolve, ms))
 
 global.MutationObserver = class {
     observe() {}
@@ -96,6 +97,30 @@ test('.window modifier', async () => {
     await wait(() => { expect(document.querySelector('span').getAttribute('foo')).toEqual('baz') })
 })
 
+test('.once modifier', async () => {
+    document.body.innerHTML = `
+        <div x-data="{ count: 0 }">
+            <button x-on:click.once="count = count+1"></button>
+
+            <span x-bind:foo="count"
+        </div>
+    `
+
+    projectX.start()
+
+    expect(document.querySelector('span').getAttribute('foo')).toEqual('0')
+
+    document.querySelector('button').click()
+
+    await wait(() => { expect(document.querySelector('span').getAttribute('foo')).toEqual('1') })
+
+    document.querySelector('button').click()
+
+    await timeout(25)
+
+    expect(document.querySelector('span').getAttribute('foo')).toEqual('1')
+})
+
 test('click away', async () => {
     // Because jsDom doesn't support .offsetHeight and offsetWidth, we have to
     // make our own implementation using a specific class added to the class. Ugh.

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است