PluginProbe
Elementor Website Builder – more than just a page builder / 3.11.5
Elementor Website Builder – more than just a page builder v3.11.5
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / includes / widgets / toggle.php

toggle.php in Elementor Website Builder – more than just a page builder 3.11.5, at includes/widgets/toggle.php

697 lines 18.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor;
3
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit; // Exit if accessed directly.
6 }
7
8 use Elementor\Core\Kits\Documents\Tabs\Global_Colors;
9 use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
10
11 /**
12 * Elementor toggle widget.
13 *
14 * Elementor widget that displays a collapsible display of content in an toggle
15 * style, allowing the user to open multiple items.
16 *
17 * @since 1.0.0
18 */
19 class Widget_Toggle extends Widget_Base {
20
21 /**
22 * Get widget name.
23 *
24 * Retrieve toggle widget name.
25 *
26 * @since 1.0.0
27 * @access public
28 *
29 * @return string Widget name.
30 */
31 public function get_name() {
32 return 'toggle';
33 }
34
35 /**
36 * Get widget title.
37 *
38 * Retrieve toggle widget title.
39 *
40 * @since 1.0.0
41 * @access public
42 *
43 * @return string Widget title.
44 */
45 public function get_title() {
46 return esc_html__( 'Toggle', 'elementor' );
47 }
48
49 /**
50 * Get widget icon.
51 *
52 * Retrieve toggle widget icon.
53 *
54 * @since 1.0.0
55 * @access public
56 *
57 * @return string Widget icon.
58 */
59 public function get_icon() {
60 return 'eicon-toggle';
61 }
62
63 /**
64 * Get widget keywords.
65 *
66 * Retrieve the list of keywords the widget belongs to.
67 *
68 * @since 2.1.0
69 * @access public
70 *
71 * @return array Widget keywords.
72 */
73 public function get_keywords() {
74 return [ 'tabs', 'accordion', 'toggle' ];
75 }
76
77 /**
78 * Register toggle widget controls.
79 *
80 * Adds different input fields to allow the user to change and customize the widget settings.
81 *
82 * @since 3.1.0
83 * @access protected
84 */
85 protected function register_controls() {
86 $this->start_controls_section(
87 'section_toggle',
88 [
89 'label' => esc_html__( 'Toggle', 'elementor' ),
90 ]
91 );
92
93 $repeater = new Repeater();
94
95 $repeater->add_control(
96 'tab_title',
97 [
98 'label' => esc_html__( 'Title & Description', 'elementor' ),
99 'type' => Controls_Manager::TEXT,
100 'default' => esc_html__( 'Toggle Title', 'elementor' ),
101 'label_block' => true,
102 'dynamic' => [
103 'active' => true,
104 ],
105 ]
106 );
107
108 $repeater->add_control(
109 'tab_content',
110 [
111 'label' => esc_html__( 'Content', 'elementor' ),
112 'type' => Controls_Manager::WYSIWYG,
113 'default' => esc_html__( 'Toggle Content', 'elementor' ),
114 'show_label' => false,
115 'dynamic' => [
116 'active' => true,
117 ],
118 ]
119 );
120
121 $this->add_control(
122 'tabs',
123 [
124 'label' => esc_html__( 'Toggle Items', 'elementor' ),
125 'type' => Controls_Manager::REPEATER,
126 'fields' => $repeater->get_controls(),
127 'default' => [
128 [
129 'tab_title' => esc_html__( 'Toggle #1', 'elementor' ),
130 'tab_content' => esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
131 ],
132 [
133 'tab_title' => esc_html__( 'Toggle #2', 'elementor' ),
134 'tab_content' => esc_html__( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.', 'elementor' ),
135 ],
136 ],
137 'title_field' => '{{{ tab_title }}}',
138 ]
139 );
140
141 $this->add_control(
142 'view',
143 [
144 'label' => esc_html__( 'View', 'elementor' ),
145 'type' => Controls_Manager::HIDDEN,
146 'default' => 'traditional',
147 ]
148 );
149
150 $this->add_control(
151 'selected_icon',
152 [
153 'label' => esc_html__( 'Icon', 'elementor' ),
154 'type' => Controls_Manager::ICONS,
155 'separator' => 'before',
156 'fa4compatibility' => 'icon',
157 'default' => [
158 'value' => 'fas fa-caret' . ( is_rtl() ? '-left' : '-right' ),
159 'library' => 'fa-solid',
160 ],
161 'recommended' => [
162 'fa-solid' => [
163 'chevron-down',
164 'angle-down',
165 'angle-double-down',
166 'caret-down',
167 'caret-square-down',
168 ],
169 'fa-regular' => [
170 'caret-square-down',
171 ],
172 ],
173 'label_block' => false,
174 'skin' => 'inline',
175 ]
176 );
177
178 $this->add_control(
179 'selected_active_icon',
180 [
181 'label' => esc_html__( 'Active Icon', 'elementor' ),
182 'type' => Controls_Manager::ICONS,
183 'fa4compatibility' => 'icon_active',
184 'default' => [
185 'value' => 'fas fa-caret-up',
186 'library' => 'fa-solid',
187 ],
188 'recommended' => [
189 'fa-solid' => [
190 'chevron-up',
191 'angle-up',
192 'angle-double-up',
193 'caret-up',
194 'caret-square-up',
195 ],
196 'fa-regular' => [
197 'caret-square-up',
198 ],
199 ],
200 'skin' => 'inline',
201 'label_block' => false,
202 'condition' => [
203 'selected_icon[value]!' => '',
204 ],
205 ]
206 );
207
208 $this->add_control(
209 'title_html_tag',
210 [
211 'label' => esc_html__( 'Title HTML Tag', 'elementor' ),
212 'type' => Controls_Manager::SELECT,
213 'options' => [
214 'h1' => 'H1',
215 'h2' => 'H2',
216 'h3' => 'H3',
217 'h4' => 'H4',
218 'h5' => 'H5',
219 'h6' => 'H6',
220 'div' => 'div',
221 ],
222 'default' => 'div',
223 'separator' => 'before',
224 ]
225 );
226
227 $this->add_control(
228 'faq_schema',
229 [
230 'label' => esc_html__( 'FAQ Schema', 'elementor' ),
231 'type' => Controls_Manager::SWITCHER,
232 'separator' => 'before',
233 ]
234 );
235
236 $this->end_controls_section();
237
238 $this->start_controls_section(
239 'section_toggle_style',
240 [
241 'label' => esc_html__( 'Toggle', 'elementor' ),
242 'tab' => Controls_Manager::TAB_STYLE,
243 ]
244 );
245
246 $this->add_control(
247 'border_width',
248 [
249 'label' => esc_html__( 'Border Width', 'elementor' ),
250 'type' => Controls_Manager::SLIDER,
251 'size_units' => [ 'px', '%', 'em' ],
252 'range' => [
253 'px' => [
254 'max' => 20,
255 ],
256 'em' => [
257 'max' => 2,
258 ],
259 ],
260 'selectors' => [
261 '{{WRAPPER}} .elementor-tab-title' => 'border-width: {{SIZE}}{{UNIT}};',
262 '{{WRAPPER}} .elementor-tab-content' => 'border-width: {{SIZE}}{{UNIT}};',
263 ],
264 ]
265 );
266
267 $this->add_control(
268 'border_color',
269 [
270 'label' => esc_html__( 'Border Color', 'elementor' ),
271 'type' => Controls_Manager::COLOR,
272 'selectors' => [
273 '{{WRAPPER}} .elementor-tab-content' => 'border-bottom-color: {{VALUE}};',
274 '{{WRAPPER}} .elementor-tab-title' => 'border-color: {{VALUE}};',
275 ],
276 ]
277 );
278
279 $this->add_responsive_control(
280 'space_between',
281 [
282 'label' => esc_html__( 'Space Between', 'elementor' ),
283 'type' => Controls_Manager::SLIDER,
284 'range' => [
285 'px' => [
286 'min' => 0,
287 'max' => 100,
288 ],
289 ],
290 'selectors' => [
291 '{{WRAPPER}} .elementor-toggle-item:not(:last-child)' => 'margin-bottom: {{SIZE}}{{UNIT}}',
292 ],
293 ]
294 );
295
296 $this->add_group_control(
297 Group_Control_Box_Shadow::get_type(),
298 [
299 'name' => 'box_shadow',
300 'selector' => '{{WRAPPER}} .elementor-toggle-item',
301 ]
302 );
303
304 $this->end_controls_section();
305
306 $this->start_controls_section(
307 'section_toggle_style_title',
308 [
309 'label' => esc_html__( 'Title', 'elementor' ),
310 'tab' => Controls_Manager::TAB_STYLE,
311 ]
312 );
313
314 $this->add_control(
315 'title_background',
316 [
317 'label' => esc_html__( 'Background', 'elementor' ),
318 'type' => Controls_Manager::COLOR,
319 'selectors' => [
320 '{{WRAPPER}} .elementor-tab-title' => 'background-color: {{VALUE}};',
321 ],
322 ]
323 );
324
325 // The title selector specificity is to override Theme Style
326 $this->add_control(
327 'title_color',
328 [
329 'label' => esc_html__( 'Color', 'elementor' ),
330 'type' => Controls_Manager::COLOR,
331 'selectors' => [
332 '{{WRAPPER}} .elementor-toggle-title, {{WRAPPER}} .elementor-toggle-icon' => 'color: {{VALUE}};',
333 '{{WRAPPER}} .elementor-toggle-icon svg' => 'fill: {{VALUE}};',
334 ],
335 'global' => [
336 'default' => Global_Colors::COLOR_PRIMARY,
337 ],
338 ]
339 );
340
341 $this->add_control(
342 'tab_active_color',
343 [
344 'label' => esc_html__( 'Active Color', 'elementor' ),
345 'type' => Controls_Manager::COLOR,
346 'selectors' => [
347 '{{WRAPPER}} .elementor-tab-title.elementor-active a, {{WRAPPER}} .elementor-tab-title.elementor-active .elementor-toggle-icon' => 'color: {{VALUE}};',
348 ],
349 'global' => [
350 'default' => Global_Colors::COLOR_ACCENT,
351 ],
352 ]
353 );
354
355 $this->add_group_control(
356 Group_Control_Typography::get_type(),
357 [
358 'name' => 'title_typography',
359 'selector' => '{{WRAPPER}} .elementor-toggle-title',
360 'global' => [
361 'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
362 ],
363 ]
364 );
365
366 $this->add_group_control(
367 Group_Control_Text_Shadow::get_type(),
368 [
369 'name' => 'title_shadow',
370 'selector' => '{{WRAPPER}} .elementor-toggle-title',
371 ]
372 );
373
374 $this->add_responsive_control(
375 'title_padding',
376 [
377 'label' => esc_html__( 'Padding', 'elementor' ),
378 'type' => Controls_Manager::DIMENSIONS,
379 'size_units' => [ 'px', 'em', '%' ],
380 'selectors' => [
381 '{{WRAPPER}} .elementor-tab-title' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
382 ],
383 ]
384 );
385
386 $this->end_controls_section();
387
388 $this->start_controls_section(
389 'section_toggle_style_icon',
390 [
391 'label' => esc_html__( 'Icon', 'elementor' ),
392 'tab' => Controls_Manager::TAB_STYLE,
393 'condition' => [
394 'selected_icon[value]!' => '',
395 ],
396 ]
397 );
398
399 $this->add_control(
400 'icon_align',
401 [
402 'label' => esc_html__( 'Alignment', 'elementor' ),
403 'type' => Controls_Manager::CHOOSE,
404 'options' => [
405 'left' => [
406 'title' => esc_html__( 'Start', 'elementor' ),
407 'icon' => 'eicon-h-align-left',
408 ],
409 'right' => [
410 'title' => esc_html__( 'End', 'elementor' ),
411 'icon' => 'eicon-h-align-right',
412 ],
413 ],
414 'default' => is_rtl() ? 'right' : 'left',
415 'toggle' => false,
416 ]
417 );
418
419 $this->add_control(
420 'icon_color',
421 [
422 'label' => esc_html__( 'Color', 'elementor' ),
423 'type' => Controls_Manager::COLOR,
424 'selectors' => [
425 '{{WRAPPER}} .elementor-tab-title .elementor-toggle-icon i:before' => 'color: {{VALUE}};',
426 '{{WRAPPER}} .elementor-tab-title .elementor-toggle-icon svg' => 'fill: {{VALUE}};',
427 ],
428 ]
429 );
430
431 $this->add_control(
432 'icon_active_color',
433 [
434 'label' => esc_html__( 'Active Color', 'elementor' ),
435 'type' => Controls_Manager::COLOR,
436 'selectors' => [
437 '{{WRAPPER}} .elementor-tab-title.elementor-active .elementor-toggle-icon i:before' => 'color: {{VALUE}};',
438 '{{WRAPPER}} .elementor-tab-title.elementor-active .elementor-toggle-icon svg' => 'fill: {{VALUE}};',
439 ],
440 ]
441 );
442
443 $this->add_responsive_control(
444 'icon_space',
445 [
446 'label' => esc_html__( 'Spacing', 'elementor' ),
447 'type' => Controls_Manager::SLIDER,
448 'range' => [
449 'px' => [
450 'min' => 0,
451 'max' => 100,
452 ],
453 ],
454 'selectors' => [
455 '{{WRAPPER}} .elementor-toggle-icon.elementor-toggle-icon-left' => 'margin-right: {{SIZE}}{{UNIT}};',
456 '{{WRAPPER}} .elementor-toggle-icon.elementor-toggle-icon-right' => 'margin-left: {{SIZE}}{{UNIT}};',
457 ],
458 ]
459 );
460
461 $this->end_controls_section();
462
463 $this->start_controls_section(
464 'section_toggle_style_content',
465 [
466 'label' => esc_html__( 'Content', 'elementor' ),
467 'tab' => Controls_Manager::TAB_STYLE,
468 ]
469 );
470
471 $this->add_control(
472 'content_background_color',
473 [
474 'label' => esc_html__( 'Background', 'elementor' ),
475 'type' => Controls_Manager::COLOR,
476 'selectors' => [
477 '{{WRAPPER}} .elementor-tab-content' => 'background-color: {{VALUE}};',
478 ],
479 ]
480 );
481
482 $this->add_control(
483 'content_color',
484 [
485 'label' => esc_html__( 'Color', 'elementor' ),
486 'type' => Controls_Manager::COLOR,
487 'selectors' => [
488 '{{WRAPPER}} .elementor-tab-content' => 'color: {{VALUE}};',
489 ],
490 'global' => [
491 'default' => Global_Colors::COLOR_TEXT,
492 ],
493 ]
494 );
495
496 $this->add_group_control(
497 Group_Control_Typography::get_type(),
498 [
499 'name' => 'content_typography',
500 'selector' => '{{WRAPPER}} .elementor-tab-content',
501 'global' => [
502 'default' => Global_Typography::TYPOGRAPHY_TEXT,
503 ],
504 ]
505 );
506
507 $this->add_group_control(
508 Group_Control_Text_Shadow::get_type(),
509 [
510 'name' => 'content_shadow',
511 'selector' => '{{WRAPPER}} .elementor-tab-content',
512 ]
513 );
514
515 $this->add_responsive_control(
516 'content_padding',
517 [
518 'label' => esc_html__( 'Padding', 'elementor' ),
519 'type' => Controls_Manager::DIMENSIONS,
520 'size_units' => [ 'px', 'em', '%' ],
521 'selectors' => [
522 '{{WRAPPER}} .elementor-tab-content' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
523 ],
524 ]
525 );
526
527 $this->end_controls_section();
528 }
529
530 /**
531 * Render toggle widget output on the frontend.
532 *
533 * Written in PHP and used to generate the final HTML.
534 *
535 * @since 1.0.0
536 * @access protected
537 */
538 protected function render() {
539 $settings = $this->get_settings_for_display();
540
541 $id_int = substr( $this->get_id_int(), 0, 3 );
542 $migrated = isset( $settings['__fa4_migrated']['selected_icon'] );
543
544 if ( ! isset( $settings['icon'] ) && ! Icons_Manager::is_migration_allowed() ) {
545 // @todo: remove when deprecated
546 // added as bc in 2.6
547 // add old default
548 $settings['icon'] = 'fa fa-caret' . ( is_rtl() ? '-left' : '-right' );
549 $settings['icon_active'] = 'fa fa-caret-up';
550 $settings['icon_align'] = $this->get_settings( 'icon_align' );
551 }
552
553 $is_new = empty( $settings['icon'] ) && Icons_Manager::is_migration_allowed();
554 $has_icon = ( ! $is_new || ! empty( $settings['selected_icon']['value'] ) );
555
556 ?>
557 <div class="elementor-toggle" role="tablist">
558 <?php
559 foreach ( $settings['tabs'] as $index => $item ) :
560 $tab_count = $index + 1;
561
562 $tab_title_setting_key = $this->get_repeater_setting_key( 'tab_title', 'tabs', $index );
563
564 $tab_content_setting_key = $this->get_repeater_setting_key( 'tab_content', 'tabs', $index );
565
566 $this->add_render_attribute( $tab_title_setting_key, [
567 'id' => 'elementor-tab-title-' . $id_int . $tab_count,
568 'class' => [ 'elementor-tab-title' ],
569 'data-tab' => $tab_count,
570 'role' => 'tab',
571 'aria-controls' => 'elementor-tab-content-' . $id_int . $tab_count,
572 'aria-expanded' => 'false',
573 ] );
574
575 $this->add_render_attribute( $tab_content_setting_key, [
576 'id' => 'elementor-tab-content-' . $id_int . $tab_count,
577 'class' => [ 'elementor-tab-content', 'elementor-clearfix' ],
578 'data-tab' => $tab_count,
579 'role' => 'tabpanel',
580 'aria-labelledby' => 'elementor-tab-title-' . $id_int . $tab_count,
581 ] );
582
583 $this->add_inline_editing_attributes( $tab_content_setting_key, 'advanced' );
584 ?>
585 <div class="elementor-toggle-item">
586 <<?php Utils::print_validated_html_tag( $settings['title_html_tag'] ); ?> <?php $this->print_render_attribute_string( $tab_title_setting_key ); ?>>
587 <?php if ( $has_icon ) : ?>
588 <span class="elementor-toggle-icon elementor-toggle-icon-<?php echo esc_attr( $settings['icon_align'] ); ?>" aria-hidden="true">
589 <?php
590 if ( $is_new || $migrated ) { ?>
591 <span class="elementor-toggle-icon-closed"><?php Icons_Manager::render_icon( $settings['selected_icon'] ); ?></span>
592 <span class="elementor-toggle-icon-opened"><?php Icons_Manager::render_icon( $settings['selected_active_icon'], [ 'class' => 'elementor-toggle-icon-opened' ] ); ?></span>
593 <?php } else { ?>
594 <i class="elementor-toggle-icon-closed <?php echo esc_attr( $settings['icon'] ); ?>"></i>
595 <i class="elementor-toggle-icon-opened <?php echo esc_attr( $settings['icon_active'] ); ?>"></i>
596 <?php } ?>
597 </span>
598 <?php endif; ?>
599 <a href="" class="elementor-toggle-title"><?php $this->print_unescaped_setting( 'tab_title', 'tabs', $index ); ?></a>
600 </<?php Utils::print_validated_html_tag( $settings['title_html_tag'] ); ?>>
601
602 <div <?php $this->print_render_attribute_string( $tab_content_setting_key ); ?>><?php Utils::print_unescaped_internal_string( $this->parse_text_editor( $item['tab_content'] ) ); ?></div>
603 </div>
604 <?php endforeach; ?>
605 <?php
606 if ( isset( $settings['faq_schema'] ) && 'yes' === $settings['faq_schema'] ) {
607 $json = [
608 '@context' => 'https://schema.org',
609 '@type' => 'FAQPage',
610 'mainEntity' => [],
611 ];
612
613 foreach ( $settings['tabs'] as $index => $item ) {
614 $json['mainEntity'][] = [
615 '@type' => 'Question',
616 'name' => wp_strip_all_tags( $item['tab_title'] ),
617 'acceptedAnswer' => [
618 '@type' => 'Answer',
619 'text' => $this->parse_text_editor( $item['tab_content'] ),
620 ],
621 ];
622 }
623 ?>
624 <script type="application/ld+json"><?php echo wp_json_encode( $json ); ?></script>
625 <?php } ?>
626 </div>
627 <?php
628 }
629
630 /**
631 * Render toggle widget output in the editor.
632 *
633 * Written as a Backbone JavaScript template and used to generate the live preview.
634 *
635 * @since 2.9.0
636 * @access protected
637 */
638 protected function content_template() {
639 ?>
640 <div class="elementor-toggle" role="tablist">
641 <#
642 if ( settings.tabs ) {
643 var tabindex = view.getIDInt().toString().substr( 0, 3 ),
644 iconHTML = elementor.helpers.renderIcon( view, settings.selected_icon, {}, 'i' , 'object' ),
645 iconActiveHTML = elementor.helpers.renderIcon( view, settings.selected_active_icon, {}, 'i' , 'object' ),
646 migrated = elementor.helpers.isIconMigrated( settings, 'selected_icon' ),
647 titleHTMLTag = elementor.helpers.validateHTMLTag( settings.title_html_tag );
648
649 _.each( settings.tabs, function( item, index ) {
650 var tabCount = index + 1,
651 tabTitleKey = view.getRepeaterSettingKey( 'tab_title', 'tabs', index ),
652 tabContentKey = view.getRepeaterSettingKey( 'tab_content', 'tabs', index );
653
654 view.addRenderAttribute( tabTitleKey, {
655 'id': 'elementor-tab-title-' + tabindex + tabCount,
656 'class': [ 'elementor-tab-title' ],
657 'data-tab': tabCount,
658 'role': 'tab',
659 'aria-controls': 'elementor-tab-content-' + tabindex + tabCount,
660 'aria-expanded': 'false',
661 } );
662
663 view.addRenderAttribute( tabContentKey, {
664 'id': 'elementor-tab-content-' + tabindex + tabCount,
665 'class': [ 'elementor-tab-content', 'elementor-clearfix' ],
666 'data-tab': tabCount,
667 'role': 'tabpanel',
668 'aria-labelledby': 'elementor-tab-title-' + tabindex + tabCount
669 } );
670
671 view.addInlineEditingAttributes( tabContentKey, 'advanced' );
672 #>
673 <div class="elementor-toggle-item">
674 <{{{ titleHTMLTag }}} {{{ view.getRenderAttributeString( tabTitleKey ) }}}>
675 <# if ( settings.icon || settings.selected_icon ) { #>
676 <span class="elementor-toggle-icon elementor-toggle-icon-{{ settings.icon_align }}" aria-hidden="true">
677 <# if ( iconHTML && iconHTML.rendered && ( ! settings.icon || migrated ) ) { #>
678 <span class="elementor-toggle-icon-closed">{{{ iconHTML.value }}}</span>
679 <span class="elementor-toggle-icon-opened">{{{ iconActiveHTML.value }}}</span>
680 <# } else { #>
681 <i class="elementor-toggle-icon-closed {{ settings.icon }}"></i>
682 <i class="elementor-toggle-icon-opened {{ settings.icon_active }}"></i>
683 <# } #>
684 </span>
685 <# } #>
686 <a href="" class="elementor-toggle-title">{{{ item.tab_title }}}</a>
687 </{{{ titleHTMLTag }}}>
688 <div {{{ view.getRenderAttributeString( tabContentKey ) }}}>{{{ item.tab_content }}}</div>
689 </div>
690 <#
691 } );
692 } #>
693 </div>
694 <?php
695 }
696 }
697