Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
namespace core\output\local\dropdown;
18
 
19
use core\output\named_templatable;
1441 ariadna 20
use core\output\renderable;
1 efrain 21
 
22
/**
23
 * Class to render a dropdown dialog element.
24
 *
25
 * A dropdown dialog allows to render any arbitrary HTML into a dropdown elements triggered
26
 * by a button.
27
 *
28
 * @package    core
29
 * @category   output
30
 * @copyright  2023 Ferran Recio <ferran@moodle.com>
31
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
32
 */
33
class dialog implements named_templatable, renderable {
34
    /** Dropdown dialog positions. */
35
    public const POSITION = [
1441 ariadna 36
        'start' => 'dropdown-menu-start',
37
        'end' => 'dropdown-menu-end',
1 efrain 38
    ];
39
 
40
    /** Dropdown dialog positions. */
41
    public const WIDTH = [
42
        'default' => '',
43
        'big' => 'dialog-big',
44
        'small' => 'dialog-small',
45
    ];
46
 
47
    /**
48
     * @var string content of dialog.
49
     */
50
    protected $dialogcontent = '';
51
 
52
    /**
53
     * @var bool if the footer should auto enable or not.
54
     */
55
    protected $buttoncontent = true;
56
 
57
    /**
58
     * @var string trigger button CSS classes.
59
     */
60
    protected $buttonclasses = '';
61
 
62
    /**
63
     * @var string component CSS classes.
64
     */
65
    protected $classes = '';
66
 
67
    /**
68
     * @var string the dropdown position.
69
     */
70
    protected $dropdownposition = self::POSITION['start'];
71
 
72
    /**
73
     * @var string dropdown preferred width.
74
     */
75
    protected $dropdownwidth = self::WIDTH['default'];
76
 
1441 ariadna 77
    /**
78
     * @var string dropdown autoclose behaviour.
79
     */
80
    protected $autoclose = 'true';
1 efrain 81
 
82
    /**
83
     * @var array extra HTML attributes (attribute => value).
84
     */
85
    protected $extras = [];
86
 
87
    /**
88
     * @var bool if the element is disabled.
89
     */
90
    protected $disabled = false;
91
 
92
    /**
93
     * Constructor.
94
     *
95
     * The definition object could contain the following keys:
96
     * - classes: component CSS classes.
97
     * - buttonclasses: the button CSS classes.
98
     * - dialogwidth: the dropdown width.
99
     * - dropdownposition: the dropdown position.
1441 ariadna 100
     * - autoclose: dropdown autoclose behaviour ('true' (default), 'false', 'inside', 'outside')
1 efrain 101
     * - extras: extra HTML attributes (attribute => value).
102
     *
103
     * @param string $buttoncontent the button content
104
     * @param string $dialogcontent the footer content
105
     * @param array $definition an optional array of the element definition
106
     */
107
    public function __construct(string $buttoncontent, string $dialogcontent, array $definition = []) {
108
        $this->buttoncontent = $buttoncontent;
109
        $this->dialogcontent = $dialogcontent;
110
        if (isset($definition['classes'])) {
111
            $this->classes = $definition['classes'];
112
        }
113
        if (isset($definition['buttonclasses'])) {
114
            $this->buttonclasses = $definition['buttonclasses'];
115
        }
116
        if (isset($definition['extras'])) {
117
            $this->extras = $definition['extras'];
118
        }
119
        if (isset($definition['dialogwidth'])) {
120
            $this->dropdownwidth = $definition['dialogwidth'];
121
        }
122
        if (isset($definition['dropdownposition'])) {
123
            $this->dropdownposition = $definition['dropdownposition'];
124
        }
1441 ariadna 125
        if (isset($definition['autoclose'])) {
126
            $this->autoclose = $definition['autoclose'];
127
        }
1 efrain 128
    }
129
 
130
    /**
131
     * Set the dialog contents.
132
     *
133
     * @param string $dialogcontent
134
     */
135
    public function set_content(string $dialogcontent) {
136
        $this->dialogcontent = $dialogcontent;
137
    }
138
 
139
    /**
140
     * Set the button contents.
141
     *
142
     * @param string $buttoncontent
143
     * @param string|null $buttonclasses the button classes
144
     */
145
    public function set_button(string $buttoncontent, ?string $buttonclasses = null) {
146
        $this->buttoncontent = $buttoncontent;
147
        if ($buttonclasses !== null) {
148
            $this->buttonclasses = $buttonclasses;
149
        }
150
    }
151
 
152
    /**
153
     * Set the dialog width.
154
     *
155
     * @param string $width
156
     */
157
    public function set_dialog_width(string $width) {
158
        $this->dropdownwidth = $width;
159
    }
160
 
161
    /**
162
     * Add extra classes to trigger butotn.
163
     *
164
     * @param string $buttonclasses the extra classes
165
     */
166
    public function set_button_classes(string $buttonclasses) {
167
        $this->buttonclasses = $buttonclasses;
168
    }
169
 
170
    /**
171
     * Add extra classes to the component.
172
     *
173
     * @param string $classes the extra classes
174
     */
175
    public function set_classes(string $classes) {
176
        $this->classes = $classes;
177
    }
178
 
179
    /**
180
     * Add extra extras to the sticky footer element.
181
     *
182
     * @param string $attribute the extra attribute
183
     * @param string $value the value
184
     */
185
    public function add_extra(string $attribute, string $value) {
186
        $this->extras[$attribute] = $value;
187
    }
188
 
189
    /**
190
     * Set the button element id.
191
     *
192
     * @param string $value the value
193
     */
194
    public function add_button_id(string $value) {
195
        $this->extras['buttonid'] = $value;
196
    }
197
 
198
    /**
199
     * Set the dropdown position.
200
     * @param string $position the position
201
     */
202
    public function set_position(string $position) {
203
        $this->dropdownposition = $position;
204
    }
205
 
206
    /**
207
     * Set the dropdown disabled attribute.
208
     * @param bool $disabled the disabled value
209
     */
210
    public function set_disabled(bool $disabled) {
211
        $this->disabled = $disabled;
212
    }
213
 
214
    /**
215
     * Export this data so it can be used as the context for a mustache template (core/inplace_editable).
216
     *
217
     * @param \renderer_base $output typically, the renderer that's calling this function
218
     * @return array data context for a mustache template
219
     */
220
    public function export_for_template(\renderer_base $output): array {
221
        $extras = [];
222
        // Id is required to add JS controls to the dropdown.
223
        $dropdownid = $this->extras['id'] ?? \html_writer::random_id('dropdownDialog_');
224
        if (isset($this->extras['id'])) {
225
            unset($this->extras['id']);
226
        }
227
        foreach ($this->extras as $attribute => $value) {
228
            $extras[] = [
229
                'attribute' => $attribute,
230
                'value' => $value,
231
            ];
232
        }
233
        $data = [
234
            // Id is required for the correct HTML labelling.
235
            'dropdownid' => $dropdownid,
236
            'buttonid' => $this->extras['buttonid'] ?? \html_writer::random_id('dropwdownbutton_'),
237
            'buttoncontent' => (string) $this->buttoncontent,
238
            'dialogcontent' => (string) $this->dialogcontent,
239
            'classes' => $this->classes,
240
            'buttonclasses' => $this->buttonclasses,
241
            'dialogclasses' => $this->dropdownwidth,
1441 ariadna 242
            'autoclose' => $this->autoclose,
1 efrain 243
            'extras' => $extras,
244
        ];
245
        if ($this->disabled) {
246
            $data['disabledbutton'] = true;
247
        }
248
        // Bootstrap 4 dropdown position still uses left and right literals.
249
        $data["position"] = $this->dropdownposition;
250
        if (right_to_left()) {
251
            $rltposition = [
252
                self::POSITION['start'] => self::POSITION['end'],
253
                self::POSITION['end'] => self::POSITION['end'],
254
            ];
255
            $data["position"] = $rltposition[$this->dropdownposition];
256
        }
257
        return $data;
258
    }
259
 
260
    /**
261
     * Get the name of the template to use for this templatable.
262
     *
263
     * @param \renderer_base $renderer The renderer requesting the template name
264
     * @return string the template name
265
     */
266
    public function get_template_name(\renderer_base $renderer): string {
267
        return 'core/local/dropdown/dialog';
268
    }
269
}