PageSourceSearch

https://www.lghellovision.net/front/web/js/ui-base-select.js?ts=202609241908

js lghellovision.net collected 2026-09-24 10:08:40 UTC 10,499 bytes, 314 lines download raw bytes

1$(function () {
2    'use strict';
3
4    function baseSelect(_container, options) {
5
6        /* ==============================
7         * 1. 기본 설정
8         * ============================== */
9        var DEFAULTS = {
10            replaceMap: null,
11            theme: 'large',
12            defaultIdx: -1,
13            triggerOnlyInput: true,
14            componentEl: '.select-component',
15            buttonEl: '.select-button',
16            labelEl: '.select-label',
17            onAfterBuild: null,
18            onSelect: function () { }
19        };
20
21        var opts = $.extend(true, {}, DEFAULTS, options);
22        var $el = $(_container);
23
24        if (!$el.length) return;
25
26        var INSTANCE_ID = 'bs-' + Date.now() + '-' + Math.floor(Math.random() * 1000);
27        var EVENT_NS = '.base-select-' + INSTANCE_ID;
28
29        var $document = $(document);
30        var $html = $('html');
31
32        /* ==============================
33         * 2. 유틸
34         * ============================== */
35
36        function useReplaceMap(text) {
37            if (!opts.replaceMap) return text;
38            var result = text;
39            Object.keys(opts.replaceMap).forEach(function (key) {
40                result = result.split(key).join(opts.replaceMap[key]);
41            });
42            return result;
43        }
44
45        function getComponent($target) {
46            return $target.closest('.base-select');
47        }
48
49        function isOpened($component) {
50            return $component.hasClass('in');
51        }
52
53        /* ==============================
54         * 3. HTML 생성
55         * ============================== */
56
57        function createButtonHtml($select) {
58
59            var $selected = $select.find('[selected]') ? $select.find('[selected]') : $select.find(':selected');
60            var value = $selected.val() || '';
61            var text = useReplaceMap($selected.text()) || '';
62            var pureText = text.replace(/<[^>]+>/g, '');
63            var placeholder = $select.attr('placeholder') || '';
64            var isPlaceholder = (placeholder && !value) ? ' is-placeholder' : '';
65
66            return `
67                <a href="javascript:;"
68                   class="select-button${isPlaceholder}"
69                   data-placeholder="${placeholder}" rel="nosublink">
70                    <span class="select selected-item" data-value="${value}" data-text="${pureText}">
71                          ${text}
72                    </span>
73                </a>
74            `;
75        }
76
77        function createOptionHtml($select) {
78
79            var inputName = $select.attr('name');
80            var title = $select.parent().attr('data-select-title') || '';
81            var html = '';
82
83            $select.attr('data-instance', INSTANCE_ID);
84
85            $select.children().each(function (i) {
86
87                var $opt = $(this);
88                var value = $opt.val() || '';
89                var text = useReplaceMap($opt.text());
90                var pureText = text.replace(/<[^>]+>/g, '');
91                var inputId = inputName + '_' + INSTANCE_ID + '_' + i;
92                var noValueClass = !value ? ' no-value' : '';
93                var checked = ($opt.is('[selected]') || $opt.is(':selected')) ? 'checked' : '';
94
95                html += `
96                    <li class="select-item${noValueClass}">
97                        <label for="${inputId}" class="select-label" data-value="${value}" data-text="${pureText}">
98                            <input id="${inputId}" type="radio" name="${inputName}" value="${value}" ${checked}>
99                            <span>${text}</span>
100                        </label>
101                    </li>
102                `;
103            });
104
105            return `
106                <div class="select-inner">
107                    <p class="select-name"><span>${title}</span><a href="javascript:;" class="closer"><em class="sr-only">닫기</em></a></p>
108                    <ul class="select-list">
109                        ${html}
110                    </ul>
111                </div>
112            `;
113        }
114
115        /* ==============================
116         * 4. 상태 처리
117         * ============================== */
118
119        function activeCheckedLabel($component) {
120            $component
121                .find('.select-label')
122                .removeClass('in')
123                .end()
124                .find('input[type="radio"]:checked')
125                .closest('.select-label')
126                .addClass('in');
127        }
128
129        function open($component) {
130            closeAll();
131            $component.addClass('in');
132            $html.addClass('is-select-open');
133        }
134
135        function close($component) {
136            $component.removeClass('in');
137
138            if (!$('.base-select.in').length) {
139                $html.removeClass('is-select-open');
140            }
141        }
142
143        function closeAll() {
144            $('.base-select.in').removeClass('in');
145            $html.removeClass('is-select-open');
146        }
147
148        /* ==============================
149         * 5. 빌드
150         * ============================== */
151
152        function build() {
153
154            $el.each(function () {
155
156                var $wrap = $(this);
157                if ($wrap.hasClass('is-builded')) return;
158
159                var $select = $wrap.find('select');
160                if (!$select.attr('name')) return;
161
162                var _idx = ($select.find('[selected]').length ? $select.find('[selected]') : $select.find(':selected')).index();
163                if (_idx > -1) $select.children().removeAttr('selected').eq(_idx).attr('selected', 'selected');
164
165                $wrap.data('origin-select', $select.clone(true));
166                // console.log($select.clone(true));
167
168                $select.hide();
169
170                $wrap.addClass('is-builded')
171                     .wrap(`<div class="base-select select-component" data-theme="${opts.theme}" data-id="${INSTANCE_ID}"></div>`);
172
173                var $component = $wrap.parent();
174
175                $wrap.append(createButtonHtml($select));
176                $component.append(createOptionHtml($select));
177
178                $select.remove();
179
180                activeCheckedLabel($component);
181
182                if (typeof opts.onAfterBuild === 'function') {
183                    opts.onAfterBuild($component);
184                }
185            });
186        }
187
188        /* ==============================
189         * 6. 선택 처리
190         * ============================== */
191
192        function handleSelect($input) {
193
194            var $component = getComponent($input);
195            var value = $input.val();
196            var text = useReplaceMap(
197                $input.closest('label').text().trim()
198            );
199            var name = $input.attr('name');
200            var $button = $component.find('.selected-item');
201
202            $button
203                .attr('data-value', value)
204                .attr('data-text', text.replace(/<[^>]+>/g, '')) // text로만
205                .html(text);
206
207            activeCheckedLabel($component);
208
209            if (typeof opts.onSelect === 'function') {
210                opts.onSelect($input, name, value, text);
211            }
212
213            close($component);
214        }
215
216        /* ==============================
217         * 7. 이벤트
218         * ============================== */
219
220        function bindEvents() {
221
222            // 버튼
223            $document.on('click' + EVENT_NS, `[data-id="${INSTANCE_ID}"] .select-button`, function (e) {
224                e.preventDefault();
225                e.stopPropagation();
226                var $component = getComponent($(this));
227                isOpened($component) ? close($component) : open($component);
228            });
229
230            // 옵션
231            $document.on('click' + EVENT_NS, `[data-id="${INSTANCE_ID}"] input[type="radio"]`, function (e) {
232                e.stopPropagation();
233                handleSelect($(this));
234            });
235
236            // 외부 클릭
237            $document.on('click' + EVENT_NS, function (e) {
238                if (!$(e.target).closest(`[data-id="${INSTANCE_ID}"]`).length && !$(e.target).closest('.select-inner').length) {
239                    closeAll();
240                }
241            });
242
243            // 닫기
244            $document.on('click' + EVENT_NS, `[data-id="${INSTANCE_ID}"] .closer`, function (e) {
245                e.preventDefault();
246                e.stopPropagation();
247                var $component = getComponent($(this));
248                close($component);
249            });
250
251            // baseSelect 전체 닫기
252            $document.off('base-select-close-all').on('base-select-close-all', closeAll);
253        }
254
255        /* ==============================
256         * 8. destroy
257         * ============================== */
258
259        function destroy() {
260
261            $document.off(EVENT_NS);
262
263            $el.each(function () {
264
265                var $wrap = $(this);
266                var $component = $wrap.closest('.base-select');
267                var $origin = $wrap.data('origin-select');
268                if (!$component.length) return;
269
270                var selectedValue =
271                    $component.find('input[type="radio"]:checked').val() || '';
272
273                if ($origin) {
274                    $origin.val(selectedValue);
275                }
276
277                $component.find('.select-inner').remove();
278                $wrap.find('.select-button').remove();
279                $wrap.unwrap();
280
281                if ($origin) {
282                    $wrap.append($origin);
283                    $wrap.removeData('origin-select');
284                }
285
286                $wrap.removeClass('is-builded');
287            });
288        }
289
290        function rebuild(newOptions) {
291            $document.off(EVENT_NS);
292            if (newOptions) {
293                opts = $.extend(true, {}, opts, newOptions);
294            }
295            destroy();
296            build();
297            bindEvents();
298        }
299
300        /* ==============================
301         * 9. 초기 실행
302         * ============================== */
303
304        build();
305        bindEvents();
306
307        return {
308            destroy: destroy,
309            rebuild: rebuild
310        };
311    }
312
313    window.baseSelect = baseSelect;
314});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.