PageSourceSearch

https://www.cxc.org/wp-content/plugins/cxc-woocommerce-orders/public/js/jquery.form-repeater.js?ver=1.0.0

js cxc.org collected 2026-10-02 02:57:01 UTC 15,410 bytes, 415 lines download raw bytes

1/**
2 * jQuery Form Repeater Plugin 0.1.0
3 *
4 * Copyright (c) 2011 Corey Ballou
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Example Usage:
26 *
27 <div class="container">
28 <div class="r-group">
29 <p>
30 <label for="vehicle_0_0" data-pattern-text="Vehicle Name +=:">Vehicle Name 1:</label>
31 <input type="text" name="vehicle[0][name]" id="vehicle_0_name" data-pattern-name="vehicle[++][name]" data-pattern-id="vehicle_++_name" />
32 </p>
33 <p>
34 <label for="vehicle_0_0" data-pattern-text="Vehicle Type +=:">Vehicle Type 1:</label>
35 <input type="text" name="vehicle[0][type]" id="vehicle_0_type" data-pattern-name="vehicle[++][type]" data-pattern-id="vehicle_++_type" />
36 </p>
37 <p>
38 <-- Add a remove button for the item. If one didn't exist, it would be added to overall group -->
39 <button type="button" class="r-btnRemove">Remove -</button>
40 </p>
41 </div>
42 <button type="button" class="r-btnAdd">Add +</button>
43 </div>
44 <script type="text/javascript">
45 $('.container').repeater({
46	btnAddClass: 'r-btnAdd',
47	btnRemoveClass: 'r-btnRemove',
48	groupClass: 'r-group',
49	minItems: 1,
50	maxItems: 0,
51	startingIndex: 0,
52	reindexOnDelete: true,
53	repeatMode: 'append',
54	animation: null,
55	animationSpeed: 400,
56	animationEasing: 'swing',
57	clearValues: true
58});
59 </script>
60 */
61(function($) {
62
63    $.fn.repeater = function(options, data) {
64        var $container = $(this),
65            $btnAdd, $btnRemove, patternName, patternId, patternText,
66            idVal, nameVal, labelText, labelFor, $elem, elemName,
67            $label, row, $newClone, $formElems;
68
69        $container.opts = $.extend({}, $.fn.repeater.defaults, options);
70        $container.repeatCount = 0;
71
72        $btnAdd = $container.find('.' + $container.opts.btnAddClass);
73        if (!$btnAdd.length) {
74            alert('You must specify a valid jQuery selector for the add button option in Form Repeater.');
75            return false;
76        }
77
78        // parse out group details
79        $container.group = $('.' + $container.opts.groupClass);
80        if (!$container.group.length) {
81            alert('You must specify a valid jQuery selector for the form element grouping option in Form Repeater.');
82            return false;
83        }
84
85        // ensure the remove button exists
86        $btnRemove = $container.group.find('.' + $container.opts.btnRemoveClass);
87        if (!$btnRemove.length) {
88            $btnRemove = $('<button type="button" name="rBtnRemove" class="' + $container.opts.btnRemoveClass + '" style="display:none" />')
89            $btnRemove.appendTo($container);
90        } else {
91            // default hidden
92            $btnRemove.hide();
93        }
94
95        // narrow the group down to the first copy
96        $container.group = $container.group.eq(0);
97        // retrieve form elements
98        $container.groupClone = $container.group.clone();
99        // watch for remove
100        //$container.find('.' + $container.opts.btnRemoveClass).live('click', removeRepeater);
101        $container.delegate('.' + $container.opts.btnRemoveClass, 'click', $container, removeRepeater);
102        // watch for add
103        //$container.find('.' + $container.opts.btnAddClass).live('click', addRepeater);
104        $container.delegate('.' + $container.opts.btnAddClass, 'click', $container, addRepeater);
105
106        // allows for initial population of form data
107        if (data && data.length) {
108
109            // create grouping for every row of data
110            for (row in data) {
111
112                // keep cloning
113                $newClone = $container.groupClone.clone();
114
115                if ($.isFunction($container.opts.beforeAdd)) {
116                    $newClone = $container.opts.beforeAdd.call(this, $newClone);
117                }
118
119                $formElems = $newClone.find(':input');
120                if ($formElems.length) {
121
122                    // populate each input field
123                    $formElems.each(function() {
124                        $elem = $(this),
125                        elemName = $elem.data('name');
126
127                        // check for matching value
128                        if (typeof data[row][elemName] != 'undefined') {
129                            $elem.val(data[row][elemName]);
130                        } else {
131                            $elem.val('');
132                        }
133
134                        patternName = $elem.data('pattern-name');
135                        if (patternName) {
136                            nameVal = $elem.attr('name');
137                            nameVal = parsePattern(patternName, nameVal, row, $container);
138                            $elem.attr('name', nameVal);
139                        }
140
141                        patternId = $elem.data('pattern-id');
142                        if (patternId) {
143                            idVal = $elem.attr('id');
144                            idVal = parsePattern(patternId, idVal, row, $container);
145                            $elem.attr('id', idVal);
146                        }
147
148                        $label = $newClone.find('label[for=' + $elem.attr('id')  + ']');
149                        if (!$label.length) $label = $elem.parent('label');
150                        if (!$label.length) $label = $elem.siblings('label');
151                        if ($label.length) {
152                            // ensure we have one copy
153                            $label = $label.eq(0);
154                            // update label text
155                            patternText = $label.data('pattern-text');
156                            labelText = $label.html();
157                            if (labelText) {
158                                labelText = parsePattern(patternText, labelText, row, $container);
159                                $label.html(labelText);
160                            }
161                            // update label attribute
162                            labelFor = $label.attr('for');
163                            if (labelFor && idVal) {
164                                $label.attr('for', idVal);
165                            }
166                        }
167                    });
168
169                }
170
171                // append new clone to container
172                $newClone.insertAfter($('.' + $container.opts.groupClass).last(
172));
173
174                if ($container.group) {
175                    $container.group.remove();
176                    $container.group = null;
177                }
178
179                if ($.isFunction($container.opts.afterAdd)) {
180                    $container.opts.afterAdd.call(this, $newClone);
181                }
182
183            }
184
185            // show removal buttons
186            $('.' + $container.opts.groupClass + ' .' + $container.opts.btnRemoveClass).show();
187
188        }
189
190        // daisy chain
191        return this;
192    }
193
194    /**
195     * Add a new repeater.
196     */
197    function addRepeater(data) {
198        var container = data.data,
199            tmpCount = container.repeatCount + 1,
200            $doppleganger = container.groupClone.clone();
201
202        if ($.isFunction(container.opts.beforeAdd)) {
203            $doppleganger = container.opts.beforeAdd.call(this, $doppleganger);
204        }
205
206        // don't exceed the max allowable items
207        if (container.opts.maxItems > 0 && container.repeatCount == container.opts.maxItems) {
208            alert('You have hit the maximum allowable items.');
209            return false;
210        }
211
212        _reindex($doppleganger, tmpCount, container);
213
214        // ensure remove button is showing
215        $doppleganger.find('.' + container.opts.btnRemoveClass).show();
216
217        // append repeater to container
218        if (container.opts.repeatMode == 'append') {
219            $doppleganger.appendTo(container);
220        } else if (container.opts.repeatMode == 'prepend') {
221            $doppleganger.prependTo(container);
222        } else if (container.opts.repeatMode == 'insertAfterLast') {
223            $doppleganger.insertAfter(container.find('.' + container.opts.groupClass).last());
224        }
225
226        container.repeatCount++;
227
228        if ($.isFunction(container.opts.afterAdd)) {
229            container.opts.afterAdd.call(this, $doppleganger);
230        }
231
232        return false;
233    }
234
235    /**
236     * Remove a repeater.
237     */
238    function removeRepeater(data) {
239        var $btn = $(this),
240            container = data.data,
241            $repeaters = container.find('.' + container.opts.groupClass);
242            numRepeaters = $repeaters.length,
243            $match;
244
245        if (numRepeaters > container.opts.minItems) {
246
247            // check if removing a specific repeater instance
248            $match = $btn.closest('.' + container.opts.groupClass);
249            if (!$match.length) {
250                // determine if removing first or last repeater
251                if (container.opts.repeatMode == 'append') {
252                    var $match = $repeaters.filter(':last');
253                } else if (container.opts.repeatMode == 'prepend') {
254                    var $match = $repeaters.filter(':first');
255                } else if (container.opts.repeatMode == 'insertAfterLast') {
256                    var $match = $repeaters.filter(':last');
257                }
258            }
259
260            // ensure we have a match
261            if ($match.length) {
262                // remove the repeater
263                if (container.opts.animation) {
264                    if (container.opts.animation == 'slide') {
265                        $match.slideUp(container.opts.animationSpeed, container.opts.animationEasing, function() {
266                            _remove($match, container);
267                        });
268                    } else if (container.opts.animation == 'fade') {
269                        $match.fadeOut(container.opts.animationSpeed, container.opts.animationEasing, function() {
270                            _remove($match, container);
271                        });
272                    } else if (typeof container.opts.animation == 'object') {
273                        $match.animate(container.opts.animation, container.opts.animationSpeed, container.opts.animationEasing, function() {
274                            _remove($match, container);
275                        });
276                    }
277                } else {
278                    _remove($match, container);
279                }
280
281            }
282
283        }
284
285        return false;
286    }
287
288    /**
289     * Parse the pattern.
290     */
291    function parsePattern(pattern, replaceText, count, container) {
292        var returnVal = replaceText;
293
294        count = parseInt(count);
295        if (pattern) {
296            // check pattern type
297            if (pattern.indexOf('+=') > -1) {
298                var matches = pattern.match(/\+=(\d+)/i);
299                if (matches && matches.length && matches[1]) {
300                    var incr = parseInt(matches[1]);
301                    returnVal = pattern.replace(/\+=(\d)+/i, container.opts.startingIndex + count + incr);
302                }
303            }
304
305            if (pattern.indexOf('++') > -1) {
306                returnVal = pattern.replace(/\+\+/gi, container.opts.startingIndex + count);
307            }
308        }
309        return returnVal;
310    }
311
312    /**
313     * Wrapper to handle re-indexing form elements in a group.
314     */
315    function reindex(container) {
316        var $repeaters = container.find('.' + container.opts.groupClass),
317            startIndex = container.opts.startingIndex,
318            $curGroup;
319
320        $repeaters.each(function() {
321            $curGroup = $(this);
322            _reindex($curGroup, startIndex, container);
323            startIndex++;
324        });
325    }
326
327    /**
328     * Remove a match and reindex.
329     */
330    function _remove($match, container) {
331        $match.remove();
332        if (container.repeatCount) {
333            container.repeatCount--;
334        }
335
336        reindex(container);
337
338        if ($.isFunction(container.opts.afterDelete)) {
339            container.opts.afterDelete.call(this, $match);
340        }
341    }
342
343    /**
344     * Handle reindexing each form element in a group.
345     */
346    function _reindex($curGroup, index, container) {
347        var $formElems = $curGroup.find(':input'),
348            patternName, patternId, patternText,
349            idVal, nameVal, labelText, labelFor,
350            $elem;
351
352        if ($formElems.length) {
353            $formElems.each(function() {
354                $elem = $(this);
355
356                patternName = $elem.data('pattern-name');
357                if (patternName) {
358                    nameVal = $elem.attr('name');
359                    nameVal = parsePattern(patternName, nameVal, index, container);
360                    $elem.attr('name', nameVal);
361                }
362
363                patternId = $elem.data('pattern-id');
364                if (patternId) {
365                    idVal = $elem.attr('id');
366                    idVal = parsePattern(patternId, idVal, index, container);
367                    $elem.attr('id', idVal);
368                }
369
370                $label = $curGroup.find('label[for=' + $elem.attr('id')  + ']');
371                if (!$label.length) $label = $elem.parent('label');
372                if (!$label.length) $label = $elem.siblings('label');
373                if ($label.length) {
374                    // ensure we have one copy
375                    $label = $label.eq(0);
376                    // update label text
377                    patternText = $label.data('pattern-text');
378                    labelText = $label.html();
379                    if (labelText) {
380                        labelText = parsePattern(patternText, labelText, index, container);
381                        $label.html(labelText);
382                    }
383                    // update label attribute
384                    labelFor = $label.attr('for');
385                    if (labelFor && idVal) {
386                        $label.attr('for', idVal);
387                    }
388                }
389            });
390        }
391
392        return $curGroup;
393    }
394
395})(jQuery);
396
397// default values
398jQuery.fn.repeater.defaults = {
399    groupClass: 'r-group',
400    btnAddClass: 'r-btnAdd',
401    btnRemoveClass: 'r-btnRemove',
402    minItems: 1,
403    maxItems: 0,
404    startingIndex: 0,
405    reindexOnDelete: true,
406    repeatMode: 'insertAfterLast', // append, prepend, insertAfterLast
407    animation: null,
408    animationSpeed: 400,
409    animationEasing: 'swing',
410    clearValues: true,
411    beforeAdd: function($doppleganger) { return $doppleganger; },
412    afterAdd: function($doppleganger) { },
413    beforeDelete: function() { },
414    afterDelete: function() { }
415};

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.