@cable8mm/jquery-infinite-with-template 1.0.3 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,219 +1,334 @@
1
- jQuery Infinite With Template Plugin
2
- ======================
1
+ # ⚡ jQuery Infinite With Template Plugin
3
2
 
4
- JQuery plugin for ajax-enabled infinite page scroll with template.
3
+ [![NPM Version](https://img.shields.io/npm/v/%40cable8mm%2Fjquery-infinite-with-template)](https://www.npmjs.com/package/@cable8mm/jquery-infinite-with-template)
4
+ [![npm bundle size](https://img.shields.io/bundlephobia/minzip/%40cable8mm%2Fjquery-infinite-with-template)](https://bundlephobia.com/package/@cable8mm/jquery-infinite-with-template)
5
+ [![NPM Downloads](https://img.shields.io/npm/dt/%40cable8mm%2Fjquery-infinite-with-template)](https://www.npmjs.com/package/@cable8mm/jquery-infinite-with-template)
6
+ [![jsDelivr hits (npm)](https://img.shields.io/jsdelivr/npm/hy/%40cable8mm%2Fjquery-infinite-with-template)](https://www.jsdelivr.com/package/npm/@cable8mm/jquery-infinite-with-template)
7
+ [![NPM Type Definitions](https://img.shields.io/npm/types/%40cable8mm%2Fjquery-infinite-with-template)](https://www.npmjs.com/package/@cable8mm/jquery-infinite-with-template)
8
+ [![NPM License](https://img.shields.io/npm/l/%40cable8mm%2Fjquery-infinite-with-template)](https://opensource.org/licenses/MIT)
9
+ [![GitHub stars](https://img.shields.io/github/stars/cable8mm/jquery-infinite-with-template)](https://github.com/cable8mm/jquery-infinite-with-template)
10
+ [![GitHub issues](https://img.shields.io/github/issues/cable8mm/jquery-infinite-with-template)](https://github.com/cable8mm/jquery-infinite-with-template/issues)
5
11
 
6
- If you like jQuery until now, this little library will help.
12
+ > 🚀 **AJAX-powered infinite scroll with template rendering for jQuery**
7
13
 
8
- ## Demo
14
+ If you like jQuery until now, this little library will help you implement infinite scroll with ease.
9
15
 
10
- For convinient `http-server` need:
16
+ ## Features
11
17
 
12
- ```bash
13
- git clone https://github.com/cable8mm/jquery-infinite-with-template
18
+ - ⚡ **Zero Dependencies** (except jQuery & jsRender)
19
+ - 🎨 **Template Rendering** with jsRender
20
+ - 🔄 **Dual Loading Modes** - Scroll or Click
21
+ - 🎯 **TypeScript Support** out of the box
22
+ - 🛡️ **Error Handling** with callbacks
23
+ - ⚙️ **Highly Configurable** with 12+ options
24
+ - 🚀 **Performance Optimized** with DocumentFragment
25
+ - 📦 **Lightweight** - Only ~3KB minified
26
+ - ✅ **Well Tested** - 16 unit tests included
27
+
28
+ ## 📦 Installation
29
+
30
+ ### npm
31
+
32
+ ```sh
33
+ npm i @cable8mm/jquery-infinite-with-template
34
+ ```
14
35
 
15
- cd jquery-infinite-with-template
36
+ ### CDN
16
37
 
17
- http-server .
38
+ ```html
39
+ <script
40
+ src="https://cdn.jsdelivr.net/npm/@cable8mm/jquery-infinite-with-template@1.0.4/jquery.infiniteScrollWithTemplate.min.js"
41
+ integrity="sha256-bX3iyCp0T50YmDRgpUl1tY/LGlpPGsKR4TqUkpcq6WA="
42
+ crossorigin="anonymous"
43
+ ></script>
18
44
  ```
19
45
 
20
- and visit http://127.0.0.1:8080/examples/
46
+ ### ESM
47
+
48
+ ```html
49
+ <script type="module">
50
+ import @cable8mm/jquery-infinite-with-template from https://cdn.jsdelivr.net/npm/@cable8mm/jquery-infinite-with-template@1.0.4/+esm
51
+ </script>
52
+ ```
21
53
 
22
- If you are not installed `http-server`, refer to https://www.npmjs.com/package/http-server
54
+ ## 🎬 Demo
23
55
 
24
- You can regenerate data_sources:
56
+ ### Online Demo
57
+
58
+ You can test the plugin directly in your browser:
59
+
60
+ 👉 **[https://www.palgle.com/jquery-infinite-with-template/examples/index.html](https://www.palgle.com/jquery-infinite-with-template/examples/index.html)**
61
+
62
+ ### Quick Start
63
+
64
+ #### Using npm run dev (Recommended)
25
65
 
26
66
  ```bash
27
- # permission required
28
- ./examples/generate > data_sources.ajax
67
+ # Install dependencies (one-time)
68
+ npm install
69
+
70
+ # Run development server with auto-open
71
+ npm run dev
29
72
  ```
30
73
 
31
- ## Usage sample
74
+ **Note:** This will start the server at `http://127.0.0.1:8080/examples/index.html` and automatically open it in your browser.
32
75
 
33
- Javascript part:
76
+ Visit [http://127.0.0.1:8080/examples/index.html](http://127.0.0.1:8080/examples/index.html) in your browser.
34
77
 
35
- ```Javascript
36
- $("#result").infiniteTemplate({
37
- templateSelector: "#test-tmpl",
38
- dataPath: "data_sources.ajax",
39
- query: "word=ajax",
40
- templateHelpers: {
41
- authId : 354
42
- },
43
- zeroCallback: function () {
44
- alert("zero alert");
45
- },
46
- });
78
+ ### Regenerate Demo Data
79
+
80
+ ```bash
81
+ # Using PHP CLI
82
+ php examples/generate > examples/data_sources.json
83
+
84
+ # Or if you have the generate script in examples directory
85
+ cd examples
86
+ php generate > data_sources.json
47
87
  ```
48
88
 
49
- HTML part:
89
+ ## 🚀 Usage
90
+
91
+ ### Basic Example
92
+
93
+ **HTML:**
50
94
 
51
95
  ```html
52
96
  <div id="result"></div>
53
97
 
54
98
  <script id="test-tmpl" type="text/x-jsrender">
55
- <p>{{:id}}. {{:title}} [user:{{:authId}}]</p>
99
+ <div class="item">
100
+ <h3>{{:title}}</h3>
101
+ <p>ID: {{:id}}</p>
102
+ </div>
56
103
  </script>
57
104
  ```
58
105
 
59
- AJAX part: `data_sources.ajax`. This should return Ajax:
106
+ **JavaScript:**
60
107
 
61
108
  ```javascript
109
+ $("#result").infiniteTemplate({
110
+ templateSelector: "#test-tmpl",
111
+ dataPath: "/api/posts",
112
+ query: "category=tech",
113
+ templateHelpers: {
114
+ userId: 123,
115
+ },
116
+ zeroCallback: function () {
117
+ console.log("No more posts!");
118
+ },
119
+ });
120
+ ```
121
+
122
+ **Server Response (JSON):**
123
+
124
+ ```json
62
125
  {
63
- "data": [
64
- {
65
- "id": 885,
66
- "title": "iGFIJUSPp8oXoBDqoRXKK0VEAU0IBG(word=ajax)"
67
- },
68
- {
69
- "id": 277,
70
- "title": "HM3iPLDwd3nQKNH5eOkaOh5QlSb92F(word=ajax)"
71
- },
72
- {
73
- "id": 583,
74
- "title": "O2X0VQeWFGIRQPcVquYwHx49VNhwX3(word=ajax)"
75
- },
76
- ...even more rows
126
+ "data": [
127
+ {
128
+ "id": 1,
129
+ "title": "Getting Started with jQuery",
130
+ "content": "..."
131
+ },
132
+ {
133
+ "id": 2,
134
+ "title": "Advanced JavaScript Patterns",
135
+ "content": "..."
136
+ }
137
+ ]
77
138
  }
78
139
  ```
79
140
 
80
- Result:
141
+ ### Click-to-Load Button
81
142
 
82
- ```html
83
- <div id="result">
84
- <p>885. iGFIJUSPp8oXoBDqoRXKK0VEAU0IBG(word=ajax) [user:354]</p>
85
- <p>277. HM3iPLDwd3nQKNH5eOkaOh5QlSb92F(word=ajax) [user:354]</p>
86
- <p>583. O2X0VQeWFGIRQPcVquYwHx49VNhwX3(word=ajax) [user:354]</p>
87
- <p>179. vrEwi7hgVucCEDmuO7pOf4Gzk4gmyh(word=ajax) [user:354]</p>
88
- <p>380. yviF2uDLyySLZaAPs3bKNbSZfHeQA7(word=ajax) [user:354]</p>
89
- <p>329. 865t05x9DMngrETccBuqrY7ts9Xt3R(word=ajax) [user:354]</p>
90
- <p>84. D6mhKuRA06ONCE5HbswSwPjZvp0bUh(word=ajax) [user:354]</p>
91
- <p>528. saWL46OBtTDGIBuZL9TkmfBvPXiRqM(word=ajax) [user:354]</p>
92
- <p>522. PBe0jjP1Egy6NWpHzuA86JHupxNGvc(word=ajax) [user:354]</p>
93
- <p>115. vBmfL7osq2VAKIktVznrC6QZzYpc1H(word=ajax) [user:354]</p>
94
- <p>722. mti7aMut4TxAygKAdfGylml9QgJoDN(word=ajax) [user:354]</p>
95
- <p>401. 06kgapSQylxWJOvFmDNLIcvpSPMB7V(word=ajax) [user:354]</p>
96
- <p>245. UD0TP3bMU7J4mAlGqwo52F1I0rJIyR(word=ajax) [user:354]</p>
97
- <p>985. 3xSyr0m68K3Ec6y8vJgIhYgSfgcGnG(word=ajax) [user:354]</p>
98
- <p>78. DWpWRzx1x4Ibfh1Gn0Lk0F3aufu34d(word=ajax) [user:354]</p>
99
- <p>573. iINBTozeMIeZguTU6lLB9j76zNZ4AK(word=ajax) [user:354]</p>
100
- <p>946. OEuUblddtI9vqlyL89nDXizhvryn4e(word=ajax) [user:354]</p>
101
- <p>756. wsBL8dxDf6UjTiNWNnnX4XAlAonHBM(word=ajax) [user:354]</p>
102
- <p>66. q3irGi5lNUXccTDTDfl2jRlzVp04uk(word=ajax) [user:354]</p>
103
- <p>20. vcq8sKN4RhCEoFLVW2vbX2eR14EKp8(word=ajax) [user:354]</p>
104
- </div>
143
+ ```javascript
144
+ $("#result").infiniteTemplate({
145
+ templateSelector: "#item-template",
146
+ dataPath: "/api/items",
147
+ loadSelector: "#load-more-btn", // Click this button to load more
148
+ loadAtStart: false, // Don't load automatically
149
+ });
105
150
  ```
106
151
 
107
- ## Options
152
+ ### With Error Handling
108
153
 
109
- **templateSelector** - (required) jsRender template identify
154
+ ```javascript
155
+ $("#result").infiniteTemplate({
156
+ templateSelector: "#item-template",
157
+ dataPath: "/api/items",
158
+ errorCallback: function (error) {
159
+ console.error("Failed to load:", error);
160
+ alert("Something went wrong. Please try again.");
161
+ },
162
+ loadingCallback: function () {
163
+ $("#loading").show();
164
+ },
165
+ loadedCallback: function () {
166
+ $("#loading").hide();
167
+ },
168
+ });
169
+ ```
110
170
 
111
- **dataPath** - (required) URL to load more data via AJAX
171
+ ## 📋 Options
172
+
173
+ | Option | Type | Default | Description |
174
+ | -------------------- | ---------- | ------------ | ------------------------------------------------------------ |
175
+ | **templateSelector** | `string` | **required** | jsRender template selector (e.g., `"#my-template"`) |
176
+ | **dataPath** | `string` | **required** | URL to load data via AJAX |
177
+ | **key** | `string` | `"data"` | Key for data array in JSON response |
178
+ | **query** | `string` | `null` | Additional query parameters (e.g., `"category=1&sort=date"`) |
179
+ | **method** | `string` | `"GET"` | HTTP method (GET, POST, PUT, DELETE) |
180
+ | **templateHelpers** | `object` | `null` | Helper data merged with each item |
181
+ | **loadAtStart** | `boolean` | `true` | Load data on initialization |
182
+ | **loadSelector** | `string` | `null` | CSS selector for click-to-load button |
183
+ | **initialPage** | `number` | `1` | Initial page number |
184
+ | **preventCache** | `boolean` | `false` | Add timestamp to prevent caching |
185
+ | **scrollThreshold** | `number` | `2` | Multiplier for viewport height (lower = more sensitive) |
186
+ | **zeroCallback** | `function` | `null` | Called when no data returned on first page |
187
+ | **errorCallback** | `function` | `null` | Called on AJAX or JSON parse error |
188
+ | **loadingCallback** | `function` | `null` | Called when loading starts |
189
+ | **loadedCallback** | `function` | `null` | Called when loading completes (success or error) |
190
+
191
+ ## 🎯 Real-World Examples
192
+
193
+ ### Example 1: Blog Posts with Pagination
112
194
 
113
- **templateHelpers** - (optional) Merge with json to load
195
+ ```javascript
196
+ $("#post-list").infiniteTemplate({
197
+ templateSelector: "#post-template",
198
+ dataPath: "/api/posts",
199
+ query: "status=published",
200
+ initialPage: 1,
201
+ scrollThreshold: 1.5,
202
+ templateHelpers: {
203
+ currentUser: window.currentUser,
204
+ },
205
+ loadingCallback: () => $("#spinner").show(),
206
+ loadedCallback: () => $("#spinner").hide(),
207
+ zeroCallback: () => $("#end-message").show(),
208
+ });
209
+ ```
114
210
 
115
- **key** - (optional) data(default)
211
+ ### Example 2: E-commerce Product Grid
116
212
 
117
- **query** - (optional) Additional query
213
+ ```javascript
214
+ $("#product-grid").infiniteTemplate({
215
+ templateSelector: "#product-card",
216
+ dataPath: "/api/products",
217
+ query: "category=electronics&sort=price",
218
+ loadSelector: "#load-more-products",
219
+ loadAtStart: true,
220
+ templateHelpers: {
221
+ currency: "$",
222
+ discountRate: 0.1,
223
+ },
224
+ });
225
+ ```
118
226
 
119
- **method** - (optional) GET(default), POST, PUT, DELETE
227
+ ### Example 3: Social Media Feed
120
228
 
121
- **loadAtStart** - (optional) true(default), false
229
+ ```javascript
230
+ $("#feed").infiniteTemplate({
231
+ templateSelector: "#feed-item",
232
+ dataPath: "/api/feed",
233
+ method: "POST",
234
+ query: "filter=following",
235
+ initialPage: 3,
236
+ preventCache: true,
237
+ templateHelpers: {
238
+ currentUserId: Auth.id(),
239
+ likedPosts: Auth.likedPosts(),
240
+ },
241
+ });
242
+ ```
122
243
 
123
- **loadSelector** - (optional) if it set, it load more data every time the selector clicked
244
+ ### Example 4: Search Results
124
245
 
125
- **initialPage** - (optional) 1(default)
246
+ ```javascript
247
+ $("#search-results").infiniteTemplate({
248
+ templateSelector: "#result-item",
249
+ dataPath: "/api/search",
250
+ query: `q=${encodeURIComponent(searchQuery)}`,
251
+ zeroCallback: () => {
252
+ $("#no-results").show();
253
+ },
254
+ errorCallback: (error) => {
255
+ console.error("Search failed:", error);
256
+ },
257
+ });
258
+ ```
126
259
 
127
- **preventCache** - (optional) false(default) if true, Add timestamp
260
+ ## 🏗️ Project Structure
261
+
262
+ ```text
263
+ jquery-infinite-with-template/
264
+ ├── jquery.infiniteScrollWithTemplate.js # Main plugin (unminified)
265
+ ├── jquery.infiniteScrollWithTemplate.min.js # Minified version
266
+ ├── jquery.infiniteScrollWithTemplate.d.ts # TypeScript definitions
267
+ ├── package.json
268
+ ├── README.md
269
+ ├── LICENSE
270
+ ├── examples/
271
+ │ ├── index.html # Demo page
272
+ │ ├── data_sources.json # Demo data
273
+ │ └── generate # Data generator script
274
+ └── tests/
275
+ ├── setup.js # Test configuration
276
+ └── jquery.infiniteScrollWithTemplate.test.js # 16 unit tests
277
+ ```
128
278
 
129
- **zeroCallback** - (optional) null(default) if function, call zeroCallback when result is nothing
279
+ ## 🧪 Testing
130
280
 
131
- ## Examples
281
+ ```bash
282
+ # Install dependencies
283
+ npm install
132
284
 
133
- ```html
134
- // https://m.holapet.com/adoption
135
-
136
- <x-adoption.rounded-card-list :selector="'adoption-rounded-card-list'">
137
- @foreach($adoptions as $item)
138
- <x-adoption.rounded-card :item="$item" />
139
- @endforeach
140
- </x-adoption.rounded-card-list>
141
- <x-adoption.rounded-card-tmpl />
142
- <script>
143
- $("#adoption-rounded-card-list").infiniteTemplate({
144
- templateSelector: "#adoption-rounded-card-tmpl",
145
- dataPath: "/api/adoption",
146
- initialPage: 3,
147
- });
148
- </script>
285
+ # Run tests
286
+ npm test
149
287
  ```
150
288
 
151
- ```html
152
- // https://m.holapet.com/place/pensions/region/1
153
-
154
- <x-place.rounded-card-list :selector="'place-rounded-card-list'">
155
- @foreach($region->placesRecent as $item)
156
- <x-place.rounded-card :item="$item" />
157
- @endforeach
158
- </x-place.rounded-card-list>
159
- <x-place.rounded-card-tmpl />
160
- <script>
161
- $("#place-rounded-card-list").infiniteTemplate({
162
- templateSelector: "#place-rounded-card-tmpl",
163
- dataPath: "/api/place/pensions/region/{{ $region->id }}",
164
- initialPage: 3,
165
- templateHelpers: {
166
- minColumnCount: 1
167
- }
168
- });
169
- </script>
170
- ```
289
+ **Test Coverage:**
171
290
 
172
- ```html
173
- // https://m.holapet.com/search/show?word=%ED%8F%AC%EB%A9%94%EB%9D%BC%EB%8B%88%EC%95%88
174
-
175
- @include('shared.jtemplate.search-user')
176
-
177
- @auth
178
- <script>
179
- $("#user-list").infiniteTemplate({
180
- templateSelector: "#user-tmpl",
181
- dataPath: "/api/user",
182
- query: "word={{ $word }}",
183
- templateHelpers: {
184
- authId : {{ Auth::id() ?? 0 }},
185
- followeeIds: {!! Auth::user()->followee_ids->toJson() ?? 'false' !!}
186
- }
187
- });
188
- </script>
189
- @endauth
190
- @guest
191
- <script>
192
- $("#user-list").infiniteTemplate({
193
- templateSelector: "#user-tmpl",
194
- dataPath: "/api/user",
195
- query: "word={{ $word }}",
196
- });
197
- </script>
198
- @endguest
199
- ```
291
+ - ✅ Initialization & validation
292
+ - ✅ Data loading & rendering
293
+ - ✅ Callbacks (zero, error, loading, loaded)
294
+ - ✅ Scroll & click loading modes
295
+ - ✅ URL building & pagination
296
+ - ✅ Edge cases (empty data, JSON parsing)
200
297
 
201
- ```html
202
- // https://m.holapet.com/story/hot
203
-
204
- @if(!empty($hotStories))
205
- <x-story.grid-card-list :selector="'story-grid-card-list'">
206
- @foreach($hotStories as $item)
207
- <x-story.grid-card :item="$item" />
208
- @endforeach
209
- </x-story.grid-card-list>
210
- @endif
211
- <x-story.grid-card-tmpl />
212
- <script>
213
- $("#story-grid-card-list").infiniteTemplate({
214
- templateSelector: "#story-grid-card-tmpl",
215
- dataPath: "/api/story/hot",
216
- initialPage: 3,
217
- });
218
- </script>
219
- ```
298
+ ## 🤝 Contributing
299
+
300
+ Contributions are welcome! Please feel free to submit a Pull Request.
301
+
302
+ 1. Fork the project
303
+ 2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
304
+ 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
305
+ 4. Push to the branch (`git push origin feature/AmazingFeature`)
306
+ 5. Open a Pull Request
307
+
308
+ ## 📝 License
309
+
310
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
311
+
312
+ ## 🙏 Credits
313
+
314
+ - **jsRender** - Template engine
315
+ - **jQuery** - DOM manipulation
316
+
317
+ ## 💡 Tips for Getting Stars
318
+
319
+ - ⭐ Star this repo if you find it useful!
320
+ - 🐛 Report bugs and request features
321
+ - 📢 Share with your developer friends
322
+ - 💬 Leave feedback and suggestions
323
+
324
+ ## 🔗 Links
325
+
326
+ - **GitHub**: [https://github.com/cable8mm/jquery-infinite-with-template](https://github.com/cable8mm/jquery-infinite-with-template)
327
+ - **NPM**: [https://www.npmjs.com/package/@cable8mm/jquery-infinite-with-template](https://www.npmjs.com/package/@cable8mm/jquery-infinite-with-template)
328
+ - **Issues**: [https://github.com/cable8mm/jquery-infinite-with-template/issues](https://github.com/cable8mm/jquery-infinite-with-template/issues)
329
+
330
+ ---
331
+
332
+ **Made with ❤️ by [Sam Lee](https://github.com/cable8mm)**
333
+
334
+ If this project helped you, please give it a ⭐️!
@@ -0,0 +1,84 @@
1
+ {
2
+ "data": [
3
+ {
4
+ "id": 886,
5
+ "title": "ZjLn9jCi1w8nsFSye6A2q9cuu78U88(word=None)"
6
+ },
7
+ {
8
+ "id": 91,
9
+ "title": "VVTFOrWminUAi8E3whuFiyi76sf6L3(word=None)"
10
+ },
11
+ {
12
+ "id": 654,
13
+ "title": "Roc3yFmOHpm4Koj8hhuRr5fBNAUcxZ(word=None)"
14
+ },
15
+ {
16
+ "id": 788,
17
+ "title": "zR7rzbUz81pPYFxvm3NBDFGCUqB0cy(word=None)"
18
+ },
19
+ {
20
+ "id": 7,
21
+ "title": "1OHxyIMH9DahoskhqVbCFINH3aVysn(word=None)"
22
+ },
23
+ {
24
+ "id": 915,
25
+ "title": "9kX2B97YL0onvcE4nRETuACESX9YIM(word=None)"
26
+ },
27
+ {
28
+ "id": 125,
29
+ "title": "jc5fTJ5Y1QzYOtQy6XhiMlRxq05KAc(word=None)"
30
+ },
31
+ {
32
+ "id": 362,
33
+ "title": "rsoNXzq590AQzf6Hp0Gi8rHQfaz9KI(word=None)"
34
+ },
35
+ {
36
+ "id": 101,
37
+ "title": "1msDlWisPm0Q9oUofPdhgjOHuZtlep(word=None)"
38
+ },
39
+ {
40
+ "id": 206,
41
+ "title": "nev0CvpOKc1E0zUuvTrgMUluSowoz5(word=None)"
42
+ },
43
+ {
44
+ "id": 544,
45
+ "title": "aIMdZ9LAf5SDl9hmeFIqzCMgU2joOx(word=None)"
46
+ },
47
+ {
48
+ "id": 415,
49
+ "title": "ikYBbV7nA4S2LPCWk2TYXQ4H5Vp7ia(word=None)"
50
+ },
51
+ {
52
+ "id": 717,
53
+ "title": "H6u32LKXqbgU8rx7UTjsALjKfUPZru(word=None)"
54
+ },
55
+ {
56
+ "id": 536,
57
+ "title": "JuyIiHNlLn0H97APMtB5ng72GAVzBr(word=None)"
58
+ },
59
+ {
60
+ "id": 554,
61
+ "title": "e8cbqBh9ifoEI2nFqyryDBwE87Boy2(word=None)"
62
+ },
63
+ {
64
+ "id": 111,
65
+ "title": "yCJNeoMlqkuNazccgeKwMoj2d9xC6v(word=None)"
66
+ },
67
+ {
68
+ "id": 134,
69
+ "title": "2qZpgg3lJ3djS5RG5IZzZjdtf7Y9IJ(word=None)"
70
+ },
71
+ {
72
+ "id": 523,
73
+ "title": "LC84RteVTWGuAgDDhknpb7jREpqdfY(word=None)"
74
+ },
75
+ {
76
+ "id": 946,
77
+ "title": "q0NnpnSWosOwbxIYQE3ZiMbuqJKG40(word=None)"
78
+ },
79
+ {
80
+ "id": 30,
81
+ "title": "sHc5R2u1W0T45AMxQRx73gAFbGHXk0(word=None)"
82
+ }
83
+ ]
84
+ }
package/examples/generate CHANGED
@@ -2,36 +2,80 @@
2
2
  <?php
3
3
 
4
4
  /**
5
- * @example ./generate > data_sources.ajax generate new data sources
5
+ * jQuery Infinite With Template - Demo Data Generator
6
+ *
7
+ * @example ./generate > data_sources.json
8
+ * @description Generates random demo data for testing infinite scroll
6
9
  */
7
10
 
8
- $response['data'] = [];
11
+ // Enable error reporting for debugging
12
+ error_reporting(E_ALL);
13
+ ini_set('display_errors', 0);
9
14
 
10
- $query = $_GET['word'] ?? 'None';
15
+ // Set JSON header
16
+ header('Content-Type: application/json');
11
17
 
12
- for ($i = 0; $i < 20; $i++) {
13
- $response['data'][] = faker($query);
14
- }
18
+ // Get query parameter (default to 'None' if not provided)
19
+ $query = isset($_GET['word']) ? $_GET['word'] : 'None';
15
20
 
16
- header('Content-Type: application/json');
21
+ // Generate response
22
+ $response = [
23
+ 'data' => [],
24
+ 'page' => isset($_GET['page']) ? (int)$_GET['page'] : 1,
25
+ 'total' => 100 // Simulate total count
26
+ ];
17
27
 
18
- echo json_encode($response, JSON_PRETTY_PRINT);
28
+ // Generate 20 items per page
29
+ $itemsPerPage = 30;
30
+ for ($i = 0; $i < $itemsPerPage; $i++) {
31
+ $response['data'][] = generateItem($query, $response['page'], $i);
32
+ }
19
33
 
20
- function faker($query)
34
+ // Output JSON
35
+ echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
36
+
37
+ /**
38
+ * Generate a single fake item
39
+ *
40
+ * @param string $query Search query
41
+ * @param int $page Current page number
42
+ * @param int $index Item index within page
43
+ * @return array Generated item
44
+ */
45
+ function generateItem($query, $page, $index)
21
46
  {
47
+ static $usedIds = [];
48
+
49
+ // Generate unique ID
50
+ do {
51
+ $id = rand(1, 10000);
52
+ } while (in_array($id, $usedIds));
53
+
54
+ $usedIds[] = $id;
55
+
22
56
  return [
23
- 'id' => rand(1, 1000),
24
- 'title' => generateRandomString(30)."(word=$query)",
57
+ 'id' => $id,
58
+ 'title' => generateRandomString(30) . "(word=$query, page=$page)",
59
+ 'page' => $page,
60
+ 'index' => $index
25
61
  ];
26
62
  }
27
63
 
64
+ /**
65
+ * Generate random string of specified length
66
+ *
67
+ * @param int $length String length
68
+ * @return string Random string
69
+ */
28
70
  function generateRandomString($length = 10)
29
71
  {
30
72
  $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
31
73
  $charactersLength = strlen($characters);
32
74
  $randomString = '';
75
+
33
76
  for ($i = 0; $i < $length; $i++) {
34
77
  $randomString .= $characters[rand(0, $charactersLength - 1)];
35
78
  }
79
+
36
80
  return $randomString;
37
81
  }