Skip to content
This repository was archived by the owner on Jan 22, 2021. It is now read-only.

Added on argument with hover and click value. #12

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
33 changes: 26 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ You can also use a separate template for the dropdown and dropdown trigger conte

Note that `dropdownTrigger` needs the template name in the `template` argument.

### Additional arguments
### Dropdown arguments

The `dropdown` helper takes additional arguments for positioning and custom classes. The names are:

Expand All @@ -92,6 +92,22 @@ The `dropdown` helper takes additional arguments for positioning and custom clas
{{/dropdown}}
```

### Trigger arguments

The `dropdownTrigger` helper takes additional arguments for change trigger event. The names are:
- `on` - Defaults to `click`. Set to `hover` for respond to the pointing of the mouse. Set `none` for disable trigger logic. You can use `usePosition` for write your own reactions logic.
- `timeout` - Defaults is `0`. Set a number to have time to move the mouse from the `dropdownTrigger` on the `dropdown`.
-
```html
{{#dropdownTrigger name="testDropdown4" on="hover" timeout=500}}
<button>Hover with timeout</button>
{{/dropdownTrigger}}

{{#dropdown name="testDropdown4" top="-10" direction="n"}}
<p>Custom dropdown.</p>
{{/dropdown}}
```

### Markup & Classes

The `dropdownTrigger` template helper doesn't produce any extra HTML around your content. `dropdown` on the other hand produces the following HTML:
Expand All @@ -105,7 +121,7 @@ The `dropdownTrigger` template helper doesn't produce any extra HTML around your

<button class="dropdown__trigger">A trigger</button>

{{#dropdown name="testDropdown4" align="center" top="20" left="10" classes="custom-class"}}
{{#dropdown name="testDropdown5" align="center" top="20" left="10" classes="custom-class"}}
<!-- Content [..] -->
{{/dropdown}}

Expand All @@ -115,7 +131,7 @@ The `dropdownTrigger` template helper doesn't produce any extra HTML around your
class="dropdown test-dropdown4 custom-class"
id="test-dropdown4"
style="position: absolute; left: XXpx; top: XXpx;"
data-dropdown-key="testDropdown4"
data-dropdown-key="testDropdown5"
data-dropdown-align="center"
data-dropdown-left="10"
data-dropdown-top="20">
Expand All @@ -137,8 +153,8 @@ Please note that the `name` template argument will be present as `id` and `class
In order to detect active, opened dropdowns, the global `dropdownIsActive` helper can be used:

```
{{#dropdownTrigger name="testDropdown5"}}
<button class="{{#if dropdownIsActive 'testDropdown5'}}dropdown--open{{/if}}">A trigger</button>
{{#dropdownTrigger name="testDropdown6"}}
<button class="{{#if dropdownIsActive 'testDropdown6'}}dropdown--open{{/if}}">A trigger</button>
{{/dropdownTrigger}}
```

Expand All @@ -155,11 +171,11 @@ Template.testTemplate.helpers(

```html
<template name="testTemplate">
{{#dropdownTrigger name="testDropdown6"}}
{{#dropdownTrigger name="testDropdown7"}}
<button>Dropdown with data</button>
{{/dropdownTrigger}}

{{#dropdown name="testDropdown6" classes="dropdown--menu" align="left"}}
{{#dropdown name="testDropdown7" classes="dropdown--menu" align="left"}}

<ul class="dropdown__menu">
{{#each items}}
Expand Down Expand Up @@ -275,6 +291,9 @@ Dropdowns.removeAll()
# Manually set a position of a dropdown. Both x and y are optional.
Dropdowns.setPosition('name', {x: Number, y: Number})

# Automatically calculate position based on trigger template for current dropdown.
Dropdowns.usePosition('name', dropdownTriggerTemplate)

# Hide all dropdowns except for `name` (can also be an array of names).
Dropdowns.hideAllBut('name')

Expand Down
47 changes: 44 additions & 3 deletions lib/dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ const factory = () => {

const removeAll = () =>
allKeys().forEach(remove);

const usePosition = (name, tmpl) =>
Tracker.afterFlush(positionDropdown(name, tmpl));

return {
all,
Expand All @@ -190,6 +193,7 @@ const factory = () => {
remove,
removeAll,
setPosition,
usePosition,
create: add,
animations: {
default: DEFAULT_ANIMATION
Expand Down Expand Up @@ -311,8 +315,13 @@ const positionDropdown = (key, reference) => {
}

const $dropdown = dropdown.element();
const $el = $(reference);


if (typeof(reference) === 'object' && reference instanceof Blaze.TemplateInstance)
var $el = $(reference.find('>'));
else
var $el = $(reference);


if ($dropdown.length === 0) {
console.error(`Dropdowns: Couldn't find a dropdown: ${key}`);
return;
Expand Down Expand Up @@ -372,15 +381,47 @@ const positionDropdown = (key, reference) => {
};
};

Dropdowns._timeout;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually no need to define this here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rewrite it to?

var timeout;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to declare it – you'll attach it further down, at this line anyway, and JS/Meteor doesn't care if the parameter passed to Meteor.clearTimeout is undefined.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I try. It does not work.


Template.dropdownTrigger.events({
click(evt, tmpl) {
if (tmpl.data.on && tmpl.data.on !== 'click') return;
evt.preventDefault();
const name = tmpl.data.name;

Meteor.clearTimeout(Dropdowns._timeout);
Dropdowns.hideAllBut(name);
Dropdowns.toggle(name);
Dropdowns.usePosition(name, tmpl);
},
mouseover(evt, tmpl) {
if (tmpl.data.on != 'hover') return;
evt.preventDefault();
const name = tmpl.data.name;

Tracker.afterFlush(positionDropdown(name, tmpl.find(DROPDOWN_TRIGGER)));
Meteor.clearTimeout(Dropdowns._timeout);
Dropdowns.hideAllBut(name);
Dropdowns.show(name);
Dropdowns.usePosition(name, tmpl);
},
mouseout(evt, tmpl) {
if (tmpl.data.on != 'hover') return;
evt.preventDefault();
const name = tmpl.data.name;

Meteor.clearTimeout(Dropdowns._timeout);
Dropdowns._timeout = Meteor.setTimeout(() => {
Dropdowns.hide(name);
}, tmpl.data.timeout);

Dropdowns.get(name).element().hover(() => {
Meteor.clearTimeout(Dropdowns._timeout);
}, () => {
Meteor.clearTimeout(Dropdowns._timeout);
Dropdowns._timeout = Meteor.setTimeout(() => {
Dropdowns.hide(name);
}, tmpl.data.timeout);
})
}
});

Expand Down
70 changes: 56 additions & 14 deletions test-app/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ <h1>Dropdowns for Meteor</h1>

<ol class="toc">
<li><a href="#basics">Basics</a></li>
<li><a href="#arguments">Additional Arguments</a></li>
<li><a href="#dropdown-arguments">Dropdown Arguments</a></li>
<li><a href="#trigger-arguments">Trigger Arguments</a></li>
<li><a href="#markup-classes">Markup &amp; Classes</a></li>
<li><a href="#helpers">Helpers</a></li>
<li><a href="#data">Data Contexts</a></li>
Expand Down Expand Up @@ -107,9 +108,9 @@ <h2 id="basics">Basics</h2>

<p>Note that <code>dropdownTrigger</code> needs the template name in the <code>template</code> argument.</p>

<h2 id="arguments">Additional arguments</h2>
<h2 id="dropdown-arguments">Dropdown arguments</h2>

<p>The <code>dropdown</code> helper takes additional arguments for positioning and custom classes. The names are:</p>
<p>The <code>dropdown</code> helper takes additional arguments for positioning and custom classes.<br>The names are:</p>

<dl>
<dt><code>align</code></dt>
Expand All @@ -127,6 +128,8 @@ <h2 id="arguments">Additional arguments</h2>
<dt><code>classes</code></dt>
<dd>Additional class names for the dropdown. None as default.</dd>
</dl>

<br>

<div class="test-area dropdown-container">
{{#dropdownTrigger name="testDropdownRight" }}
Expand Down Expand Up @@ -187,7 +190,7 @@ <h2 id="arguments">Additional arguments</h2>
<p>Placed to the right of trigger with <code>direction="e"</code>.</p>
{{/dropdown}}
</div>

<div class="test-area dropdown-container">
{{#dropdownTrigger name="testDropdownDirectionW" }}
<button>West direction</button>
Expand All @@ -199,13 +202,52 @@ <h2 id="arguments">Additional arguments</h2>
</div>

<pre><code>&#123;&#123;#dropdownTrigger name="testDropdown3"&#125;&#125;
&lt;button&gt;Custom dropdown&lt;/button&gt;
&lt;button&gt;Custom dropdown on click&lt;/button&gt;
&#123;&#123;/dropdownTrigger&#125;&#125;

&#123;&#123;#dropdown name="testDropdown3" align="right" top="20" left="10" direction="n" classes="custom-class another-one"&#125;&#125;
&lt;p&gt;Custom dropdown.&lt;/p&gt;
&#123;&#123;/dropdown&#125;&#125;</code></pre>

<h2 id="trigger-arguments">Trigger arguments</h2>

<p>The <code>dropdownTrigger</code> helper takes additional arguments for change trigger event.<br>The names are:</p>

<dl>
<dt><code>on</code></dt>
<dd> Defaults to <code>click</code>. Set to <code>hover</code> for respond to the pointing of the mouse. Set <code>none</code> for disable trigger logic. You can use <code>usePosition</code> for write your own reactions logic.</dd>

<dt><code>timeout</code></dt>
<dd>Defaults is <code>0</code>. Set a number to have time to move the mouse from the <code>dropdownTrigger</code> on the <code>dropdown</code>.</dd>
</dl>

<div class="test-area dropdown-container">
{{#dropdownTrigger name="testDropdownHover" on="hover"}}
<button>Hover</button>
{{/dropdownTrigger}}

{{#dropdown name="testDropdownHover" direction="n" top="-10"}}
<p>Trigger responds to hover event <code>on="hover"</code>.</p>
{{/dropdown}}
</div>

<div class="test-area dropdown-container">
{{#dropdownTrigger name="testDropdownHoverTimeout" on="hover" timeout=500}}
<button>Hover with timeout</button>
{{/dropdownTrigger}}

{{#dropdown name="testDropdownHoverTimeout" direction="n" top="-10"}}
<p>You can move your mouse to the dropdown with <code>on="hover" timeout=500</code>.</p>
{{/dropdown}}
</div>

<pre><code>&#123;&#123;#dropdownTrigger name="testDropdown4" on="hover" timeout=500&#125;&#125;
&lt;button&gt;Hover with timeout&lt;/button&gt;
&#123;&#123;/dropdownTrigger&#125;&#125;

&#123;&#123;#dropdown name="testDropdown4" top="-10" direction="n"&#125;&#125;
&lt;p&gt;Custom dropdown.&lt;/p&gt;
&#123;&#123;/dropdown&#125;&#125;</code></pre>

<h2 id="markup-classes">Markup &amp; Classes</h2>

Expand All @@ -221,7 +263,7 @@ <h2 id="markup-classes">Markup &amp; Classes</h2>

&lt;button class=&quot;dropdown__trigger&quot;&gt;A trigger&lt;/button&gt;

&#123;&#123;#dropdown name="testDropdown4" align="center" top="20" left="10" classes="custom-class"&#125;&#125;
&#123;&#123;#dropdown name="testDropdown5" align="center" top="20" left="10" classes="custom-class"&#125;&#125;
&lt;!-- Content [..] --&gt;
&#123;&#123;/dropdown&#125;&#125;

Expand All @@ -231,7 +273,7 @@ <h2 id="markup-classes">Markup &amp; Classes</h2>
class=&quot;dropdown test-dropdown4 custom-class&quot;
id=&quot;test-dropdown4&quot;
style=&quot;position: absolute; left: XXpx; top: XXpx;&quot;
data-dropdown-key=&quot;testDropdown4&quot;
data-dropdown-key=&quot;testDropdown5&quot;
data-dropdown-align=&quot;center&quot;
data-dropdown-left=&quot;10&quot;
data-dropdown-top=&quot;20&quot;&gt;
Expand All @@ -258,17 +300,17 @@ <h2 id="helpers">Helpers</h2>
</p>

<div class="test-area dropdown-container">
{{#dropdownTrigger name="testDropdown5" }}
<button class="{{#if dropdownIsActive 'testDropdown5'}}dropdown--open{{/if}}">A trigger</button>
{{#dropdownTrigger name="testDropdown6" }}
<button class="{{#if dropdownIsActive 'testDropdown6'}}dropdown--open{{/if}}">A trigger</button>
{{/dropdownTrigger}}

{{#dropdown name="testDropdown5" top="10"}}
{{#dropdown name="testDropdown6" top="10"}}
<p>A dropdown.</p>
{{/dropdown}}
</div>

<pre><code class="html">&#123;&#123;#dropdownTrigger name="testDropdown5"&#125;&#125;
&lt;button class="&#123;&#123;#if dropdownIsActive 'testDropdown5'&#125;&#125;dropdown--open&#123;&#123;/if&#125;&#125;"&gt;A trigger&lt;/button&gt;
<pre><code class="html">&#123;&#123;#dropdownTrigger name="testDropdown6"&#125;&#125;
&lt;button class="&#123;&#123;#if dropdownIsActive 'testDropdown6'&#125;&#125;dropdown--open&#123;&#123;/if&#125;&#125;"&gt;A trigger&lt;/button&gt;
&#123;&#123;/dropdownTrigger&#125;&#125;
</code></pre>

Expand All @@ -279,10 +321,10 @@ <h2 id="data">Data Contexts</h2>
</p>

<div class="test-area dropdown-container">
{{ > testTemplate "testDropdown6" }}
{{ > testTemplate "testDropdown7" }}
</div>

<pre><code class="html">&#123;&#123; &gt; testTemplate &quot;testDropdown6&quot; &#125;&#125;</code></pre>
<pre><code class="html">&#123;&#123; &gt; testTemplate &quot;testDropdown7&quot; &#125;&#125;</code></pre>

{{#markdown}}
```coffeescript
Expand Down