forked from IgorRubinovich/ir-select
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathir-select.html
More file actions
216 lines (178 loc) · 6.92 KB
/
ir-select.html
File metadata and controls
216 lines (178 loc) · 6.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
<link rel="import" href="../iron-ajax/iron-ajax.html">
<link rel="import" href="../iron-input/iron-input.html">
<link rel="import" href="../iron-icons/iron-icons.html">
<link rel="import" href="../iron-selector/iron-selector.html">
<link rel="import" href="../iron-dropdown/iron-dropdown.html">
<link rel="import" href="../paper-menu/paper-menu.html">
<link rel="import" href="../paper-item/paper-item.html">
<link rel="import" href="./ir-select-item.html">
<!--
@license
Copyright (c) 2015 Igor Rubinovich <igor.rubinovich@gmail.com>. All rights reserved.
This code may only be used under the MIT license found at http://opensource.org/licenses/MIT
-->
<!--
# ir-select
# Tagging-style multiselect box for Polymer 1.0
This is a tagging-style custom element built entirely from the ground up on [Polymer](http://www.polymer-project.org) and iron-components.
Aims to provide the same functionality as Selectize, Chosen2 and friends, using only vanilla JS and Polymer.
Integrates with native form posting values upon submit as expected - no additional code required ([but how?](#native-form-integration)).
## Usage
<ir-select
placeholder="Type a tag..."
data-source="http://example.com/"
query-by-label="fields=title&query=.*[query].*"
query-by-value="fields=id&q="
min-length="3"
data-path="envelope.data"
value-path="value"
label-path="label"
prevent-default="true"
name="mySelectBox"
clone-to-native="true"
allow-create="false"
>
<ir-select-item label="label1" value="24"></iron-select-item>
<ir-select-item label="label2" value="42"></iron-select-item
</ir-select>
### Setting selection
- Preset in DOM: upon initialization (on 'ready') ir-select will pick up its Light DOM for `ir-select-item` elements and update its value accordingly. Use standard DOM operations to add/remove `iron-select-item`-s during runtime and iron-select will update its value instantly.
- Add and remove ir-select-items dynamically during runtime and the component will update its values
- Use `.setSelection()` to replace the entire set of selected items
### Getting selection
#### Dynamic integration
- The `.value` property, is always up to date, with a comma-separated list of values. If allowCreate is true `.value` may also contain labels - in such case it's up to the user to be able to tell labels from values.
- .getSelected() retuns an array of objects with labels and values at labelPath and valuePath respectively
- Events are fired for various conditions - see below.
<a name="native-form-integration"></a>
#### Native form integration
You might have been puzzled about how exactly a non-native component may be submitted as part of a static form. You might also be aware that it's not possibble to append child elements to input elements. Thus it's not possible to enrich an input with shadow dom.
iron-select solves this by adding a hidden native input to the form it belongs to, and reflecting its `.value` property to the hidden field. The name of the hidden field is determined by iron-input's `.name` property. You know the rest of the story.
Granted, this somewhat breaks the encapsulation and further experiments will show whether it's possible to have the input under iron-select's own light dom. However the benefits of not having to have any further js processing of the element overweigh this (subtle? temporary?) downside.
## Events
- item-added, item-removed speak for themselves
- change is fired when item was added or removed, after the more specific events above.
- item-duplicate will fire when a duplicate is being added
- item-unknown will fire when an item without value at valuePath is being added
## Style
Minimal styling is set internally.
- `iron-select-item` elements live in the Light DOM they may be styled by component user just like any element.
- Use `.ir-select-item-focus` class to to style item in focus.
The intent is to make the component fully customizable.
## User navigation
As expected:
- Left and right keys navigate selected items, backspace deletes the selection in focus
- Up and down keys navigate suggestions, Enter selects highlighter suggestion
## Key todos
- Option for visual feedback on duplicates and unknowns
- Style customization
- "Offline" suggestions from a predefined range of choices a-la native select
- Tests
## Contribution
Issues and pull requests are most welcome. Fork it [here](https://github.com/IgorRubinovich/ir-select).
@group GUI Elements
@element ir-select
@homepage http://igorrubinovich.github.io/ir-select/
@demo demo/index.html
-->
<dom-module id="ir-select">
<template>
<style>
:host {
display: block;
}
@media (max-width: 600px) {
h1.paper-font-display1 {
font-size: 24px;
}
}
#selectorContainer {
padding : 2px;
}
.selectedItem {
border : 1px solid lightgrey;
padding : 1px;
margin : 3px;
}
::slotted(.input) {
border : none;
border-bottom : 1px solid lightgrey
}
::slotted(.input):focus {
border : 0;
outline : none;
border-bottom : 1px solid lightgrey;
}
paper-menu {
--paper-item-focused : {
background-color : transparent;
}
--paper-item-focused-before : {
background-color : transparent;
}
--paper-item-focused-after : {
background-color : transparent;
}
}
#inputDiv iron-selector {
background : #ddd;
}
#inputDiv iron-selector .iron-selected {
/* background-color : white; */
box-shadow : 0 0 1px #555;
transform : translate(-1px,-1px);
}
#inputDiv iron-selector div {
padding : 2px;
/* background : #fafafa; */
}
#inputDiv {
padding : 0;
}
#selectBox div
{
cursor : default;
}
</style>
<div id="inputDiv" class="iron-font-body2">
<content select="ir-select-item">
</content>
<content select="input">
</content>
<!--slot name="ir-select-item"></slot>
<slot name="input"></slot-->
<iron-dropdown on-click="clickedSuggestion" on-iron-overlay-closed="_onOverlayClosed" on-iron-overlay-opened="_onOverlayOpened" vertical-align='top' vertical-offset="25" id='overlay'>
<paper-menu class="dropdown-content" id='selectBox'>
<template is="dom-repeat" items="{{ suggestions }}">
<paper-item on-mouseover="_focusSuggestion" item="{{ item }}" hidden$="{{ item.isHidden }}" value="{{ get(valuePath, item) }}">{{ get(labelPath, item) }}</paper-item>
</template>
</paper-menu>
</iron-dropdown>
<iron-ajax
id="optionsLoader"
url=""
method="GET"
on-response="_showOverlay"
handle-as="json"
debounce-duration="300"
last-response="{{ suggestedOptions }}"
last-error="{{ lastError }}"
verbose=true
>
</iron-ajax>
<iron-ajax
id="selectionLoader"
url=""
method="GET"
handle-as="json"
on-response="_setPreselectedOptions"
debounce-duration="300"
last-response="{{ loadedSelection }}"
last-error="{{ lastError }}"
verbose=true
>
</iron-ajax>
</div>
</template>
</dom-module>
<script src="ir-select.js"></script>