source: pmb4.2/trunk/fuentes/pmb/classes/explnum_associate_svg.class.php @ 815

Last change on this file since 815 was 815, checked in by jrpelegrina, 4 years ago

Initial release of pmb 4.2

  • Property svn:executable set to *
File size: 48.1 KB
Line 
1<?php
2// +-------------------------------------------------+
3// © 2002-2005 PMB Services / www.sigb.net pmb@sigb.net et contributeurs (voir www.sigb.net)
4// +-------------------------------------------------+
5// $Id: explnum_associate_svg.class.php,v 1.5 2015-04-03 11:16:19 jpermanne Exp $
6
7
8if (stristr ($_SERVER['REQUEST_URI'], ".class.php"))
9        die ("no access");
10
11require_once($include_path."/templates/explnum_associate.tpl.php");
12
13/**
14 * Classe pour la génération de la structure svg pour l'interface d'association des locuteurs
15 */
16class explnum_associate_svg {
17        /**
18         * @var int
19         */
20        private $explnum_id;
21       
22        /**
23         * @var string
24         */
25        private $svg;
26       
27        /**
28         * @var string
29         */
30        private $js = "";
31       
32        /**
33         * @var array
34         */
35        private $speakers =  array();
36       
37        /**
38         * @var array
39         */
40        private $segments =  array();
41       
42        /**
43         * Tableau des dimensions des éléments svg
44         * @var array
45         */
46        private $dimensions = array();
47       
48        /**
49         * Durée du document
50         * @var int
51         */
52        private $duration = 0;
53       
54        /**
55         * @param int explnum_id Identifiant du document numérique
56         */
57        public function __construct($explnum_id) {
58                $this->explnum_id = $explnum_id;
59        }
60       
61        /**
62         * Renvoie le code svg généré
63         * @param boolean edit true pour activer la possibilité d'édition
64         * @return string
65         */
66        public function getSvg($edit = false) {
67                $this->getDimensions();
68                $this->svg = "<svg id='speech_timeline_svg' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' height='!!height!!' width='".($this->dimensions['totalWidth'])."' >";
69                $this->getBackground();
70                $this->getTimeScale();
71                $this->getSpeakers($edit);
72                $this->getSegments();
73                $this->getCursor();
74                if ($edit) {
75                        $this->getLeftCursor();
76                        $this->getRightCursor();
77                }
78                $this->svg .= "</svg>";
79                return $this->svg;
80        }
81       
82        /**
83         * Définit le tableau des dimensions
84         */
85        private function getDimensions() {
86                global $explnum_associate_speakers_svg_height;
87               
88                $this->dimensions = array(
89                                'totalWidth' => 1500,                                                                                           // Largeur totale
90                                // Dimensions fond
91                                'backgroundPadding' => 2,                                                                                       // Padding du background
92                                // Dimensions de la barre de graduations
93                                'scaleTextY' => 15,                                                                                                     // Ordonnée du texte de la barre de graduations
94                                'scaleTextFontSize' => 12,                                                                                      // Taille de police du texte de la barre de graduations
95                                'scaleBottom' => 40,                                                                                            // Ordonnée de la base de la barre de graduations
96                                'scaleTop' => 20,                                                                                                       // Ordonnée du sommet des grandes barres
97                                'scaleMiddle' => 30,                                                                                            // Ordonnée du sommet des petites barres
98                                // Dimensions locuteurs
99                                'speakerLeft' => 5,                                                                                                     // Abscisse de gauche de la colonne speaker
100                                'speakerTop' => 42,                                                                                                     // Ordonnée du haut de la colonne speaker
101                                'speakerWidth' => 150,                                                                                          // Largeur de la colonne speaker
102                                'speakerHeight' => $explnum_associate_speakers_svg_height,                      // Hauteur d'une case speaker
103                                'speakerMarginBottom' => 2,                                                                                     // Marge entre chaque speaker
104                                'speakerTextFontSize' => 12,                                                                            // Taille de police de texte
105                                'speakerTextX' => 3,                                                                                            // Abscisse de début de texte
106                                'speakerTextY' => 17,                                                                                           // Ordonnée du texte
107                                'speakerMarginRight' => 2,                                                                                      // Marge à droite
108                                );
109        }
110       
111        /**
112         * Construit la barre de graduation
113         */
114        private function getTimeScale() {
115                if (!count($this->segments)) {
116                        $this->getDatas();
117                }
118                global $explnum_associate_timescale_svg;
119                global $explnum_associate_timescale_svg_posX;
120                global $explnum_associate_timescale_svg_posY;
121                global $explnum_associate_timescale_svg_width;
122                global $explnum_associate_timescale_svg_height;
123                global $msg;
124               
125                // Un champ texte pour donner l'unité de temps
126                $this->svg .= '<text transform="matrix(1 0 0 1 '.($this->dimensions['speakerLeft'] + ($this->dimensions['speakerWidth'] / 2)).' '.$this->dimensions['scaleTextY'].')" font-family="\'LiberationSans-Regular\'" text-anchor="middle" font-size="'.$this->dimensions['scaleTextFontSize'].'">'.$msg['explnum_associate_minutes'].'</text>';
127               
128                $timescaleSvg = '<g transform="!!transform!!">'.$explnum_associate_timescale_svg.'</g>';
129               
130                $x = $this->dimensions['speakerLeft'] + $this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight'] + $this->dimensions['backgroundPadding'];
131               
132                // Calcul de la largeur totale disponible pour le ratio
133                $availableWidth = $this->dimensions['totalWidth'] - ($this->dimensions['speakerLeft'] + $this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight'] + (2 * $this->dimensions['backgroundPadding']));
134               
135                // Temps total
136                $duration = $this->duration;
137               
138                // On cherche l'intervalle idéal
139                $interval = 1;
140                // Calcul de la largeur pour l'intervalle
141                $widthForInterval = ($availableWidth*$interval*100) / $duration;
142                while (($widthForInterval*2) < 15) {
143                        $interval = $interval*2;
144                        $widthForInterval = ($availableWidth*$interval*100) / $duration;
145                }
146               
147                $tps = 0;
148                $cpt = 0;
149               
150                while ($x < $this->dimensions['totalWidth']) {
151                        // On regarde le compteur pour savoir la taille de la barre et si on affiche le texte
152                        $width = 10 * $widthForInterval / $explnum_associate_timescale_svg_width;
153                        if (!$cpt) {
154                                $transform = 'translate('.$x.', '.($this->dimensions['scaleBottom'] - $this->dimensions['scaleTop']).') scale('.$width.', '.($this->dimensions['scaleTop'] / $explnum_associate_timescale_svg_height).') translate('.(0 - $explnum_associate_timescale_svg_posX).', '.(0 - $explnum_associate_timescale_svg_posY).')';
155                               
156                                $currentTimescaleSvg = str_replace("!!transform!!", $transform, $timescaleSvg);
157                               
158                                $this->svg .= $currentTimescaleSvg;
159                        }
160                        if (!$cpt || $cpt == 5) {
161                                $this->svg .= '<text transform="matrix(1 0 0 1 '.$x.' '.$this->dimensions['scaleTextY'].')" font-family="\'LiberationSans-Regular\'" text-anchor="middle" font-size="'.$this->dimensions['scaleTextFontSize'].'">'.$this->getTimeToDisplay($tps).'</text>';
162                        }
163                       
164                        $cpt++;
165                        if ($cpt == 10) $cpt = 0;
166                        $tps += $interval;
167                        $x += $widthForInterval;
168                }
169        }
170       
171        /**
172         * Renvoie une chaine correspondant au temps à afficher (min:sec)
173         *
174         * @param int tps Temps en secondes
175         */
176        private function getTimeToDisplay($tps) {
177                $sec = $tps % 60;
178                $min = ($tps - $sec) / 60;
179               
180                $sec = str_pad($sec, 2, '0', STR_PAD_LEFT);
181                return $min.":".$sec;
182        }
183       
184        /**
185         * Construit les blocs locuteurs
186         * @param boolean edit true pour activer la possibilité d'édition
187         */
188        private function getSpeakers($edit) {
189                if (!count($this->speakers)) {
190                        $this->getDatas();
191                }
192                global $explnum_associate_speakers_svg;
193                global $explnum_associate_speakers_svg_posX;
194                global $explnum_associate_speakers_svg_posY;
195                global $explnum_associate_speakers_svg_width;
196                global $msg;
197               
198                $speakerSvg = '<g id="!!id!!" transform="!!transform!!">'.$explnum_associate_speakers_svg.'</g>';
199               
200                foreach ($this->speakers as $id => $speaker) {
201                        $y = $speaker['posY'];
202                       
203                        $transform = "translate(".$this->dimensions['speakerLeft'].", ".$y.") scale(".($this->dimensions['speakerWidth'] / $explnum_associate_speakers_svg_width).", 1) translate(".(0 - $explnum_associate_speakers_svg_posX).", ".(0 - $explnum_associate_speakers_svg_posY).")";
204                        $currentSpeakerSvg = str_replace("!!transform!!", $transform, $speakerSvg);
205                       
206                        $currentSpeakerSvg = str_replace("!!id!!", "speaker_svg_".$id, $currentSpeakerSvg);
207                       
208                        if ($edit) $no_author_message = $msg['explnum_associate_author'];
209                        else $no_author_message = $msg['explnum_associate_no_author'];
210                       
211                        $this->svg .= $currentSpeakerSvg.'
212                                <text transform="matrix(1 0 0 1 '.($this->dimensions['speakerLeft'] + $this->dimensions['speakerTextX']).' '.($y + $this->dimensions['speakerTextY']).')" font-family="\'Arial\'" font-size="'.$this->dimensions['speakerTextFontSize'].'">
213                                        '.($edit ? $speaker['id'] : '').'
214                                </text>
215                                <text id="explnum_associate_author_libelle_'.$id.'" transform="matrix(1 0 0 1 '.($this->dimensions['speakerLeft'] + $this->dimensions['speakerTextX']).' '.($y + 2 * $this->dimensions['speakerTextY']).')" font-family="\'Arial\'" font-size="'.$this->dimensions['speakerTextFontSize'].'" title="'.$msg['explnum_associate_author'].'" style="cursor:pointer;">
216                                        '.($speaker['author_libelle'] ? $speaker['author_libelle'] : $no_author_message).'
217                                </text>';
218                        if ($edit) {
219                                $this->svg .= '
220                                <image id="explnum_del_associate_speaker_'.$id.'" title="'.$msg['explnum_del_associate_speaker'].'" xlink:href="./images/trash.gif" y="'.($y + $this->dimensions['speakerTextY'] - $this->dimensions['speakerTextFontSize']).'" x="'.($this->dimensions['speakerWidth'] - 12).'" width="12" height="12" style="cursor:pointer;"/>';
221                        }
222                }
223               
224                $height = ($y + $this->dimensions['speakerHeight'] + $this->dimensions['speakerMarginBottom']);
225                $this->svg = str_replace("!!height!!", $height, $this->svg);
226        }
227       
228        /**
229         * Construit les segments
230         */
231        private function getSegments() {
232                if (!count($this->segments)) {
233                        $this->getDatas();
234                }
235                global $explnum_associate_segments_svg;
236                global $explnum_associate_segments_svg_posX;
237                global $explnum_associate_segments_svg_posY;
238                global $explnum_associate_segments_svg_width;
239                global $explnum_associate_segments_svg_height;
240               
241                $segmentSvg = '<g id="!!id!!" transform="!!transform!!">'.$explnum_associate_segments_svg.'</g>';
242               
243                // Calcul de la largeur totale disponible pour le ratio
244                $availableWidth = $this->dimensions['totalWidth'] - ($this->dimensions['speakerLeft'] + $this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight'] + (2 * $this->dimensions['backgroundPadding']));
245               
246                // Temps total
247                $duration = $this->duration;
248               
249                // Calcul ratio
250                $ratio = $availableWidth / $duration;
251               
252                foreach ($this->segments as $id => $segment) {
253                        $x = $this->dimensions['speakerLeft'] + $this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight'] + $this->dimensions['backgroundPadding'] + ($segment['start'] * $ratio);
254                        $y = $this->speakers[$segment['speaker']]['posY'];
255                        $width = ($segment['duration'] * $ratio) / $explnum_associate_segments_svg_width;
256                       
257                        $transform = 'translate('.$x.', '.$y.') scale('.$width.', '.($this->dimensions['speakerHeight'] / $explnum_associate_segments_svg_height).') translate('.(0 - $explnum_associate_segments_svg_posX).', '.(0 - $explnum_associate_segments_svg_posY).')';
258                        $currentSegmentSvg = str_replace("!!transform!!", $transform, $segmentSvg);
259                       
260                        $currentSegmentSvg = str_replace("!!id!!", "segment_svg_".$id, $currentSegmentSvg);
261                       
262                        $this->svg .= $currentSegmentSvg;
263                }
264        }
265       
266        /**
267         * Consulte la base de données
268         */
269        private function getDatas() {
270                $query = "select explnum_speaker_id, explnum_speaker_speaker_num, explnum_speaker_gender, explnum_speaker_author, author_name, author_rejete from explnum_speakers left join authors on explnum_speaker_author = author_id where explnum_speaker_explnum_num = ".$this->explnum_id;
271                $result = pmb_mysql_query($query);
272                if ($result && pmb_mysql_num_rows($result)) {
273                        $i = 0;
274                        while ($speaker = pmb_mysql_fetch_object($result)) {
275                                $this->speakers[$speaker->explnum_speaker_id] = array(
276                                                'id' => $speaker->explnum_speaker_speaker_num,
277                                                'gender' => $speaker->explnum_speaker_gender,
278                                                'author' => $speaker->explnum_speaker_author,
279                                                'author_libelle' => $speaker->author_name.($speaker->author_rejete ? ', '.$speaker->author_rejete : ''),
280                                                'posY' => $this->dimensions['speakerTop'] + ($i * ($this->dimensions['speakerHeight'] + $this->dimensions['speakerMarginBottom']))
281                                                );
282                                $i++;
283                        }
284                }
285               
286                $query = "select explnum_segment_id, explnum_segment_speaker_num, explnum_segment_start, explnum_segment_duration, explnum_segment_end from explnum_segments where explnum_segment_explnum_num = ".$this->explnum_id;
287                $result = pmb_mysql_query($query);
288                if ($result && pmb_mysql_num_rows($result)) {
289                        while ($segment = pmb_mysql_fetch_object($result)) {
290                                $this->segments[] = array(
291                                                'db_id' => $segment->explnum_segment_id,
292                                                'speaker' => $segment->explnum_segment_speaker_num,
293                                                'start' => $segment->explnum_segment_start,
294                                                'duration' => $segment->explnum_segment_duration,
295                                                'end' => $segment->explnum_segment_end
296                                                );
297                                if ($segment->explnum_segment_end > $this->duration) $this->duration = $segment->explnum_segment_end;
298                        }
299                }
300        }
301       
302        /**
303         * Construit le fond
304         */
305        private function getBackground() {
306                if (!count($this->speakers)) {
307                        $this->getDatas();
308                }
309                global $explnum_associate_background_svg;
310                global $explnum_associate_background_svg_posX;
311                global $explnum_associate_background_svg_posY;
312                global $explnum_associate_background_svg_width;
313                global $explnum_associate_background_svg_height;
314               
315                $backgroundSvg = '<g id="background_svg" transform="!!transform!!">'.$explnum_associate_background_svg.'</g>';
316               
317                $x = ($this->dimensions['speakerLeft'] + $this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight']);
318                $y = $this->dimensions['scaleBottom'];
319                $width = ($this->dimensions['totalWidth'] - ($this->dimensions['speakerLeft'] + $this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight'])) / $explnum_associate_background_svg_width;
320                $height = ($this->dimensions['speakerTop'] - $this->dimensions['scaleBottom'] + count($this->speakers) * ($this->dimensions['speakerHeight'] + $this->dimensions['speakerMarginBottom'])) / $explnum_associate_background_svg_height;
321               
322                $transform = "translate(".$x.", ".$y.") scale(".$width.", ".$height.") translate(".(0 - $explnum_associate_background_svg_posX).", ".(0 - $explnum_associate_background_svg_posY).")";
323               
324                $backgroundSvg = str_replace("!!transform!!", $transform, $backgroundSvg);
325               
326                $this->svg .= $backgroundSvg;
327        }
328       
329        /**
330         * Construit le curseur
331         */
332        private function getCursor() {
333                global $explnum_associate_cursor_svg;
334                global $explnum_associate_cursor_svg_posX;
335                global $explnum_associate_cursor_svg_posY;
336                global $explnum_associate_cursor_svg_width;
337                global $explnum_associate_cursor_svg_height;
338               
339                $cursorSvg = '<g id="cursor_svg" transform="!!transform!!" title="0:00">'.$explnum_associate_cursor_svg.'</g>';
340               
341                $x = ($this->dimensions['speakerLeft'] + $this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight'] + $this->dimensions['backgroundPadding']) - ($explnum_associate_cursor_svg_width / 2);
342                $height = ($this->dimensions['speakerTop'] + count($this->speakers) * ($this->dimensions['speakerHeight'] + $this->dimensions['speakerMarginBottom'])) / $explnum_associate_cursor_svg_height;
343               
344                $transform = "translate(".$x.", 0) scale(1, ".$height.") translate(".(0 - $explnum_associate_cursor_svg_posX).", ".(0 - $explnum_associate_cursor_svg_posY).")";
345               
346                $cursorSvg = str_replace("!!transform!!", $transform, $cursorSvg);
347               
348                $this->svg .= $cursorSvg;
349        }
350       
351        /**
352         * Construit le taquet de gauche
353         */
354        private function getLeftCursor() {
355                global $explnum_associate_left_cursor_svg;
356                global $explnum_associate_left_cursor_svg_posX;
357                global $explnum_associate_left_cursor_svg_posY;
358                global $explnum_associate_left_cursor_svg_width;
359                global $explnum_associate_left_cursor_svg_height;
360               
361                $leftCursorSvg = '<g id="left_cursor_svg" transform="!!transform!!" title="0:00" time="0">'.$explnum_associate_left_cursor_svg.'</g>';
362               
363                $x = ($this->dimensions['speakerLeft'] + $this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight'] + $this->dimensions['backgroundPadding']) - ($explnum_associate_left_cursor_svg_width);
364                $height = ($this->dimensions['speakerTop'] + count($this->speakers) * ($this->dimensions['speakerHeight'] + $this->dimensions['speakerMarginBottom'])) / $explnum_associate_left_cursor_svg_height;
365               
366                $transform = "translate(".$x.", 0) scale(1, ".$height.") translate(".(0 - $explnum_associate_left_cursor_svg_posX).", ".(0 - $explnum_associate_left_cursor_svg_posY).")";
367               
368                $leftCursorSvg = str_replace("!!transform!!", $transform, $leftCursorSvg);
369               
370                $this->svg .= $leftCursorSvg;
371        }
372       
373        /**
374         * Construit le taquet de droite
375         */
376        private function getRightCursor() {
377                global $explnum_associate_right_cursor_svg;
378                global $explnum_associate_right_cursor_svg_posX;
379                global $explnum_associate_right_cursor_svg_posY;
380                global $explnum_associate_right_cursor_svg_width;
381                global $explnum_associate_right_cursor_svg_height;
382               
383                $rightCursorSvg = '<g id="right_cursor_svg" transform="!!transform!!" title="0:00" time="0">'.$explnum_associate_right_cursor_svg.'</g>';
384               
385                $x = ($this->dimensions['speakerLeft'] + $this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight'] + $this->dimensions['backgroundPadding']);
386                $height = ($this->dimensions['speakerTop'] + count($this->speakers) * ($this->dimensions['speakerHeight'] + $this->dimensions['speakerMarginBottom'])) / $explnum_associate_right_cursor_svg_height;
387               
388                $transform = "translate(".$x.", 0) scale(1, ".$height.") translate(".(0 - $explnum_associate_right_cursor_svg_posX).", ".(0 - $explnum_associate_right_cursor_svg_posY).")";
389               
390                $rightCursorSvg = str_replace("!!transform!!", $transform, $rightCursorSvg);
391               
392                $this->svg .= $rightCursorSvg;
393        }
394       
395        /**
396         * Retourne la chaine JavaScript
397         * @param boolean edit true pour activer la possibilité d'édition
398         * @return string
399         */
400        public function getJs($edit = false) {
401                if ((!count($this->speakers)) || (!count($this->segments))) {
402                        $this->getDimensions();
403                        $this->getDatas();
404                }
405               
406                // Calcul de la largeur totale disponible pour le ratio
407                $availableWidth = $this->dimensions['totalWidth'] - ($this->dimensions['speakerLeft'] + $this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight'] + (2 * $this->dimensions['backgroundPadding']));
408               
409                // Temps total
410                $duration = $this->duration / 100;
411               
412                // Calcul ratio
413                $ratio = $availableWidth / $duration;
414               
415                // Récupération des variables en js
416                $this->js .= "
417                var duration = ".$duration.";
418                var ratio = ".$ratio.";
419                var player = videojs('videojs');
420                var segments = ".json_encode($this->segments).";";
421               
422                // Déplacement du curseur
423                $this->js .= "
424                function update_cursor(){
425                        document.getElementById('cursor_svg').transform.baseVal.getItem(0).setTranslate(".($this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight'] + $this->dimensions['backgroundPadding'])." + (player.currentTime() * ratio), 0);
426                        document.getElementById('cursor_svg').setAttribute('title', get_time_to_display(player.currentTime()));
427                }
428               
429                function get_time_to_display(tps){
430                        tps = Math.round(tps);
431                        var sec = tps % 60;
432                        var min = (tps - sec) / 60;
433                       
434                        sec = '' + sec;
435                        while (sec.length < 2) {
436                                sec = '0' + sec;
437                        }
438                       
439                        return min + ':' + sec;
440                }
441               
442                player.on('timeupdate', update_cursor);
443                ";
444               
445                // Accès au début d'un segment en passant son id
446                $this->js .= "
447                function move_cursor_on_segment(id) {
448                        for (var i in segments) {
449                                if (segments[i].db_id == id) {
450                                        player.currentTime(segments[i].start / 100);
451                                        return segments[i].start / 100;
452                                }
453                        }
454                        return 0;
455                }";
456               
457                // Drag du curseur
458                $this->js .= "
459                function start_drag_cursor(event) {
460                        event.preventDefault();
461                        document.addEventListener('mouseup', stop_drag_cursor, false);
462                        document.addEventListener('mousemove', drag_cursor, false);
463                }
464               
465                function drag_cursor(event) {
466                        update_video_time(event);
467                }
468               
469                function stop_drag_cursor() {
470                        document.removeEventListener('mousemove', drag_cursor, false);
471                        document.removeEventListener('mouseup', stop_drag_cursor, false);
472                }
473                ";
474               
475                // Mise à jour de la vidéo
476                $this->js .= "
477                function update_video_time(event) {
478                        event.preventDefault();
479                        player.currentTime((event.clientX - (findPos(document.getElementById('speech_timeline'))[0] + ". ($this->dimensions['speakerLeft'] + $this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight'] + 2 * $this->dimensions['backgroundPadding']).")) / ratio);
480                }";
481               
482                // Ajout du listener sur le background
483                $this->js .= "
484                document.getElementById('background_svg').addEventListener('click', update_video_time, false);";
485               
486                // Ajout du listener sur le curseur
487                $this->js .= "
488                document.getElementById('cursor_svg').addEventListener('mousedown', start_drag_cursor, false);";
489               
490                if ($edit) {
491                        $this->getJsEdit();
492                } else {
493                        // Ajout du listener sur un segment
494                        $this->js .= "
495                        for (var i in segments) {
496                                document.getElementById('segment_svg_' + i).addEventListener('click', update_video_time, false);
497                        }";
498                }
499               
500                // Positionnement du curseur
501                $this->js .= "
502                update_cursor();";
503               
504                return $this->js;
505        }
506       
507        /**
508         * Portion de la chaine JavaScript gérant l'édition
509         */
510        private function getJsEdit() {
511                global $base_path;
512                global $msg;
513               
514                // Récupération du tableau de locuteurs en js
515                $this->js .= "
516                var speakers = ".json_encode($this->utf8_normalize($this->speakers)).";
517                var segments_between_lr_cursors = new Array();";
518               
519                // Positionnement des taquets
520                global $explnum_associate_left_cursor_svg_width;
521                $this->js .= "
522                function update_lr_cursor(cursor_id) {
523                        var cursor = document.getElementById(cursor_id);
524                        var time = document.getElementById(cursor_id + '_pos').value.split(':');
525                        var sec = 0;
526                       
527                        if (time.length == 2) sec = time[0]*60 + time[1]*1;
528                        else sec = time[0];
529                       
530                        document.getElementById(cursor_id + '_pos').value = get_time_to_display(sec);
531                       
532                        var x = sec * ratio + ".($this->dimensions['speakerLeft'] + $this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight'] + $this->dimensions['backgroundPadding']).";
533                        if (cursor_id == 'left_cursor_svg') {
534                                x = x - ".$explnum_associate_left_cursor_svg_width.";
535                               
536                                if (x <= document.getElementById('right_cursor_svg').transform.baseVal.getItem(0).matrix.e) {
537                                        cursor.transform.baseVal.getItem(0).setTranslate(x, cursor.transform.baseVal.getItem(0).matrix.f);
538                                        cursor.setAttribute('title', document.getElementById(cursor_id + '_pos').value);
539                                        cursor.setAttribute('time', sec);
540                                        get_segments_between_lr_cursors();
541                                } else {
542                                        document.getElementById(cursor_id + '_pos').value = document.getElementById('right_cursor_svg_pos').value;
543                                        update_lr_cursor(cursor_id);
544                                }
545                        } else if (cursor_id == 'right_cursor_svg') {
546                                if (x > ".($this->dimensions['totalWidth'] - $this->dimensions['backgroundPadding']).") {
547                                        document.getElementById(cursor_id + '_pos').value = get_time_to_display(duration);
548                                        update_lr_cursor(cursor_id);
549                                } else if (x >= document.getElementById('left_cursor_svg').transform.baseVal.getItem(0).matrix.e) {
550                                        cursor.transform.baseVal.getItem(0).setTranslate(x, cursor.transform.baseVal.getItem(0).matrix.f);
551                                        cursor.setAttribute('title', document.getElementById(cursor_id + '_pos').value);
552                                        cursor.setAttribute('time', sec);
553                                        get_segments_between_lr_cursors();
554                                } else {
555                                        document.getElementById(cursor_id + '_pos').value = document.getElementById('left_cursor_svg_pos').value;
556                                        update_lr_cursor(cursor_id);
557                                }
558                        }
559                }
560               
561                update_lr_cursor('right_cursor_svg');
562                update_lr_cursor('left_cursor_svg');";
563               
564                // Fonction d'ouverture du popup
565                $this->js .= "
566                function openPopUpCall(id) {
567                        openPopUp('./select.php?what=auteur&callback=update_associate_author&caller=explnum_associate_speaker_' + id + '&param1=aut' + id + '_id&param2=aut' + id + '&deb_rech='+encodeURIComponent(document.getElementById('aut' + id).value), 'select_author0', 500, 400, -2, -2, 'scrollbars=yes, toolbar=no, dependent=yes, resizable=yes');
568                }";
569               
570                // Réinitialisation du formulaire
571                $this->js .= "
572                function clearAut(id) {
573                        document.getElementById('aut' + id).value='';
574                        document.getElementById('aut' + id + '_id').value='0';
575                        update_associate_author();
576                }";
577               
578                // Validation du formulaire
579                $this->js .= "
580                function update_associate_author() {
581                        var id = document.getElementById('id_current_author_associate_form').value;
582                        if (document.getElementById('aut' + id).value != '') {
583                                document.getElementById('explnum_associate_author_libelle_' + id).innerHTML = document.getElementById('aut' + id).value;
584                        } else {
585                                document.getElementById('explnum_associate_author_libelle_' + id).innerHTML = '".$msg['explnum_associate_author']."';
586                        }
587                        document.getElementById('author_associate_form_' + id).style.display = 'none';
588                       
589                        var author_id = document.getElementById('aut' + id + '_id').value;
590                       
591                        var req = new http_request();           
592                        req.request('$base_path/ajax.php?module=catalog&categ=explnum&quoifaire=update_associate_author&speaker_id=' + id + '&author_id=' + author_id,0,'',1,'','');
593                }";
594               
595                // Fermeture du formulaire
596                $this->js .= "
597                function close_author_associate_form(id) {
598                        document.getElementById('author_associate_form_' + id).style.display = 'none';
599                }";
600               
601                // Création des div de selection d'autorité
602                $this->js .= "
603                for (var i in speakers) {
604                        if (!document.getElementById('author_associate_form_' + i)) {
605                                var form = document.createElement('form');
606                                form.id = 'author_associate_form_' + i;
607                                form.className = 'form-catalog';
608                                form.name = 'explnum_associate_speaker_' + i;
609                                var x = findPos(document.getElementById('speech_timeline'))[0] + ".$this->dimensions['speakerLeft'].";
610                                var y = findPos(document.getElementById('speech_timeline'))[1] - 10 + speakers[i]['posY']*1;
611                                form.style = 'position: absolute; top: ' + y + 'px; left: ' + x + 'px;';
612                                form.addEventListener('submit', function(e){
613                                        e.preventDefault();
614                                        e.stopPropagation();
615                                },false);
616                               
617                                var label = document.createElement('label');
618                                label.className = 'etiquette';
619                                label.for = 'aut' + i;
620                                label.innerHTML = '".$msg['234']."';
621                               
622                                var img = document.createElement('img');
623                                img.src = './images/close.png';
624                                img.alt = '".$msg['197']."';
625                                img.title = '".$msg['197']."';
626                                img.className = 'right';
627                                img.setAttribute('field_id', i);
628                                img.style.cursor = 'pointer';
629                                img.addEventListener('click', function(){
630                                        close_author_associate_form(this.getAttribute('field_id'));
631                                }, false);
632                               
633                                var div = document.createElement('div');
634                                div.className = 'row';
635                               
636                                var span = document.createElement('span');
637                               
638                                var input1 = document.createElement('input');
639                                input1.type = 'text';
640                                input1.id = 'aut' + i;
641                                input1.className = 'saisie-20emr';
642                                input1.name = 'aut' + i;
643                                input1.setAttribute('autfield', 'aut' + i + '_id');
644                                input1.setAttribute('completion', 'authors');
645                                input1.setAttribute('autocompletion', 'on');
646                                input1.value = speakers[i].author_libelle;
647                                input1.setAttribute('callback', 'update_associate_author');
648                               
649                                var input2 = document.createElement('input');
650                                input2.type = 'button';
651                                input2.className = 'bouton';
652                                input2.value = '...';
653                                input2.setAttribute('field_id', i);
654                                input2.addEventListener('click', function(){
655                                        openPopUpCall(this.getAttribute('field_id'));
656                                }, false);
657                               
658                                var input3 = document.createElement('input');
659                                input3.type = 'button';
660                                input3.className = 'bouton';
661                                input3.value = 'X';
662                                input3.setAttribute('field_id', i);
663                                input3.addEventListener('click', function(){
664                                        clearAut(this.getAttribute('field_id'));
665                                }, false);
666                               
667                                var input4 = document.createElement('input');
668                                input4.type = 'hidden';
669                                input4.id = 'aut' + i + '_id';
670                                input4.name = 'aut' + i + '_id';
671                                input4.value = speakers[i].author;
672                               
673                                span.appendChild(input1);
674                                div.appendChild(span);
675                                div.appendChild(input2);
676                                div.appendChild(input3);
677                                div.appendChild(input4);
678                                form.appendChild(label);
679                                form.appendChild(img);
680                                form.appendChild(div);
681                                document.getElementById('att').appendChild(form);
682                               
683                                ajax_pack_element(document.getElementById('aut' + i));
684                                document.getElementById('author_associate_form_' + i).style.display = 'none';
685                        }
686                }
687               
688                var input = document.createElement('input');
689                input.type = 'hidden';
690                input.id = 'id_current_author_associate_form';
691                input.value = 0;
692               
693                document.getElementById('att').appendChild(input);
694                ";
695               
696                // Clic sur un auteur, on affiche le formulaire
697                $this->js .= "
698                function display_author_associate_form(event) {
699                        var current_id = document.getElementById('id_current_author_associate_form').value;
700                        if (current_id != 0) {
701                                document.getElementById('author_associate_form_' + current_id).style.display = 'none';
702                        }
703                        var id = event.currentTarget.id.replace('explnum_associate_author_libelle_','');
704                        document.getElementById('id_current_author_associate_form').value = id;
705                        document.getElementById('author_associate_form_' + id).style.display = 'block';
706                        document.getElementById('aut' + id).focus();
707                }
708                ";
709               
710                // Drag des segments
711                $this->js .= "
712                var current_drag_segment;
713                var last_pageY;
714                var current_drag_speaker_id;
715               
716                function set_current_speaker(id, is_current) {
717                        var current_drag_speaker = document.getElementById(id);
718                        if (is_current) {
719                                current_drag_speaker.setAttribute('stroke', 'red');
720                        } else {
721                                current_drag_speaker.removeAttribute('stroke');
722                        }
723                }
724               
725                function start_drag_segment(event) {
726                        current_drag_segment = event.currentTarget;
727                        last_pageY = event.pageY;
728                       
729                        var segment_id = current_drag_segment.id.replace('segment_svg_','');
730                        current_drag_speaker_id = 'speaker_svg_' + segments[segment_id]['speaker'];
731                        set_current_speaker(current_drag_speaker_id, true);
732                       
733                        document.addEventListener('mouseup', stop_drag_segment, false);
734                        document.addEventListener('mousemove', drag_segment, false);
735                        event.preventDefault();
736                       
737                        var clone = current_drag_segment.cloneNode(true);
738                        clone.id = clone.id + '_clone';
739                        clone.setAttribute('fill-opacity', 0.5);
740                        clone.setAttribute('stroke', 'red');
741                        clone.setAttribute('stroke-dasharray','5,5');
742                        document.getElementById('speech_timeline_svg').appendChild(clone);
743                }
744               
745                function drag_segment(event) {
746                        var clone = document.getElementById(current_drag_segment.id + '_clone');
747                        clone.transform.baseVal.getItem(0).setTranslate(clone.transform.baseVal.getItem(0).matrix.e, clone.transform.baseVal.getItem(0).matrix.f + event.pageY - last_pageY);
748                        last_pageY = event.pageY;
749                       
750                        var mouse_posY = event.pageY - findPos(document.getElementById('speech_timeline'))[1];
751                        var speaker_id = current_drag_speaker_id.replace('speaker_svg_', '');
752                        if ((speakers[speaker_id].posY*1 > mouse_posY) || ((speakers[speaker_id].posY*1 + ".$this->dimensions['speakerHeight'].") < mouse_posY)) {
753                                set_current_speaker(current_drag_speaker_id, false);
754                                for (var i in speakers) {
755                                        if ((speakers[i].posY*1 <= mouse_posY) && ((speakers[i].posY*1 + ".$this->dimensions['speakerHeight'].") >= mouse_posY)) {
756                                                current_drag_speaker_id = 'speaker_svg_' + i;
757                                                set_current_speaker(current_drag_speaker_id, true);
758                                                break;
759                                        }
760                                }
761                        }
762                }
763               
764                function stop_drag_segment(event) {
765                        document.removeEventListener('mousemove', drag_segment, false);
766                        document.removeEventListener('mouseup', stop_drag_segment, false);
767                       
768                        var clone = document.getElementById(current_drag_segment.id + '_clone');
769                        clone.remove();
770                       
771                        set_current_speaker(current_drag_speaker_id, false);
772                       
773                        var speaker_id = current_drag_speaker_id.replace('speaker_svg_', '');
774                        var segment_id = current_drag_segment.id.replace('segment_svg_','');
775                        var move_allowed = true;
776                       
777                        for (var i in segments) {
778                                if ((i != segment_id) && (speaker_id == segments[i].speaker)) {
779                                        if ((((segments[segment_id].start*1) > (segments[i].start*1)) && ((segments[segment_id].start*1) < (segments[i].end*1))) || (((segments[segment_id].end*1) > (segments[i].start*1)) && ((segments[segment_id].end*1) < (segments[i].end*1))) || (((segments[i].start*1) > (segments[segment_id].start*1)) && ((segments[i].start*1) < (segments[segment_id].end*1))) || (((segments[i].end*1) > (segments[segment_id].start*1)) && ((segments[i].end*1) < (segments[segment_id].end*1)))) {
780                                                move_allowed = false;
781                                                break;
782                                        }
783                                }
784                        }
785                       
786                        if ((segments[segment_id].speaker != speaker_id) && move_allowed) {
787                                current_drag_segment.transform.baseVal.getItem(0).setTranslate(current_drag_segment.transform.baseVal.getItem(0).matrix.e, speakers[speaker_id].posY*1);
788                                segments[segment_id].speaker = speaker_id;
789                               
790                                var req = new http_request();
791                                req.request('$base_path/ajax.php?module=catalog&categ=explnum&quoifaire=update_associate_speaker&segment_id=' + segments[segment_id].db_id + '&speaker_id=' + speaker_id,0,'',1,'','');
792                        } else if (!move_allowed) {
793                                alert('".$msg['explnum_associate_segments_move_forbidden']."');
794                        }
795                }
796                ";
797               
798                // Ajout d'un locuteur
799                $this->js .= "
800                function add_speaker(event) {
801                        var req = new http_request();
802                        req.request('$base_path/ajax.php?module=catalog&categ=explnum&quoifaire=add_new_speaker&explnum_id=".$this->explnum_id."',0,'',1,get_explnum_associate_ajax,'');
803                }";
804               
805                // Suppression d'un locuteur
806                $this->js .= "
807                function del_speaker(event) {
808                        var speaker_id = event.currentTarget.id.replace('explnum_del_associate_speaker_', '');
809                        hasSegment = false;
810                       
811                        for (var i in segments) {
812                                if (segments[i].speaker == speaker_id) {
813                                        hasSegment = true;
814                                        break;
815                                }
816                        }
817                       
818                        if (hasSegment) {
819                                alert('".$msg['explnum_del_associate_speaker_forbidden']."');
820                        } else if (confirm('".$msg['explnum_del_associate_speaker_confirm']."')) {
821                                var req = new http_request();
822                                req.request('$base_path/ajax.php?module=catalog&categ=explnum&quoifaire=delete_associate_speaker&speaker_id=' + speaker_id,0,'',1,get_explnum_associate_ajax,'');
823                        }
824                }";
825               
826                // Drag des taquets
827                global $explnum_associate_left_cursor_svg_width;
828               
829                $this->js .= "
830                var current_drag_lr_cursor;
831                var last_pageX;
832                var lr_cursor_pos;
833               
834                function start_drag_lr_cursor(event) {
835                        current_drag_lr_cursor = event.currentTarget;
836                        last_pageX = event.pageX;
837                       
838                        document.addEventListener('mouseup', stop_drag_lr_cursor, false);
839                        document.addEventListener('mousemove', drag_lr_cursor, false);
840                        event.preventDefault();
841                }
842               
843                function drag_lr_cursor(event) {
844                        var cond;
845               
846                        if (current_drag_lr_cursor.id == 'left_cursor_svg') {
847                                lr_cursor_pos = current_drag_lr_cursor.transform.baseVal.getItem(0).matrix.e + event.pageX - last_pageX + ".($explnum_associate_left_cursor_svg_width - ($this->dimensions['speakerLeft'] + $this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight'] + $this->dimensions['backgroundPadding'])).";
848                                cond = (((current_drag_lr_cursor.transform.baseVal.getItem(0).matrix.e + event.pageX - last_pageX + ".$explnum_associate_left_cursor_svg_width.") <= (document.getElementById('right_cursor_svg').transform.baseVal.getItem(0).matrix.e)) && (lr_cursor_pos >= 0));
849                        } else if (current_drag_lr_cursor.id == 'right_cursor_svg') {
850                                lr_cursor_pos = current_drag_lr_cursor.transform.baseVal.getItem(0).matrix.e + event.pageX - last_pageX - ".($this->dimensions['speakerLeft'] + $this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight'] + $this->dimensions['backgroundPadding']).";
851                                cond = (((current_drag_lr_cursor.transform.baseVal.getItem(0).matrix.e + event.pageX - last_pageX) >= (document.getElementById('left_cursor_svg').transform.baseVal.getItem(0).matrix.e + ".$explnum_associate_left_cursor_svg_width.")) && ((current_drag_lr_cursor.transform.baseVal.getItem(0).matrix.e + event.pageX - last_pageX) <= ".($this->dimensions['totalWidth'] - $this->dimensions['backgroundPadding'])."));
852                        }
853                       
854                        if (cond) {
855                                current_drag_lr_cursor.transform.baseVal.getItem(0).setTranslate(current_drag_lr_cursor.transform.baseVal.getItem(0).matrix.e + event.pageX - last_pageX, current_drag_lr_cursor.transform.baseVal.getItem(0).matrix.f);
856                                document.getElementById(current_drag_lr_cursor.id + '_pos').value = get_time_to_display(lr_cursor_pos / ratio);
857                                current_drag_lr_cursor.setAttribute('title', get_time_to_display(lr_cursor_pos / ratio));
858                                current_drag_lr_cursor.setAttribute('time', lr_cursor_pos / ratio);
859                               
860                                last_pageX = event.pageX;
861                               
862                                get_segments_between_lr_cursors();
863                        }
864                }
865               
866                function stop_drag_lr_cursor(event) {
867                        document.removeEventListener('mousemove', drag_lr_cursor, false);
868                        document.removeEventListener('mouseup', stop_drag_lr_cursor, false);
869                }";
870               
871                // Trouver les segments présents entre les taquets
872                $this->js .= "
873                function get_segments_between_lr_cursors() {
874                        var left_cursor_time = document.getElementById('left_cursor_svg').getAttribute('time');
875                        var right_cursor_time = document.getElementById('right_cursor_svg').getAttribute('time');
876                        var current_segment;
877                       
878                        segments_between_lr_cursors = [];
879                       
880                        for (var i in segments) {
881                                current_segment = document.getElementById('segment_svg_' + i);
882                                if (((segments[i].start/100) <= right_cursor_time) && ((segments[i].end/100) >= left_cursor_time)) {
883                                        is_between_lr_cursors(current_segment, true);
884                                        segments_between_lr_cursors[segments_between_lr_cursors.length] = segments[i];
885                                } else {
886                                        is_between_lr_cursors(current_segment, false);
887                                }
888                        }
889                }
890               
891                function is_between_lr_cursors(segment, is_between) {
892                        if (is_between) {
893                                segment.setAttribute('stroke', 'green');
894                                segment.setAttribute('stroke-width', '2px');
895                        } else {
896                                segment.removeAttribute('stroke');
897                                segment.removeAttribute('stroke-width');
898                        }
899                }";
900               
901                // Ajout d'un segment
902                $this->js .= "
903                function add_new_segment() {
904                        var left_cursor_time = Math.round(document.getElementById('left_cursor_svg').getAttribute('time')*100);
905                        var right_cursor_time = Math.round(document.getElementById('right_cursor_svg').getAttribute('time')*100);
906                       
907                        if (left_cursor_time != right_cursor_time) {
908                                var speakers_with_segment = new Array();
909                                var speaker_available = true;
910                                var speaker_id = 0;
911                               
912                                for (var i in segments_between_lr_cursors) {
913                                        if (speakers_with_segment.indexOf(segments_between_lr_cursors[i].speaker) == -1) {
914                                                speakers_with_segment[speakers_with_segment.length] = segments_between_lr_cursors[i].speaker;
915                                        }
916                                        if (speakers_with_segment.length == speakers.length) {
917                                                speaker_available = false;
918                                                break;
919                                        }
920                                }
921                               
922                                if (speaker_available) {
923                                        for (var i in speakers) {
924                                                if (speakers_with_segment.indexOf(i) == -1) {
925                                                        speaker_id = i;
926                                                        break;
927                                                }
928                                        }
929                                }
930                               
931                                var req = new http_request();
932                                req.request('$base_path/ajax.php?module=catalog&categ=explnum&quoifaire=add_new_segment&explnum_id=".$this->explnum_id."&speaker_id=' + speaker_id + '&start=' + left_cursor_time + '&end=' + right_cursor_time,0,'',1,get_explnum_associate_ajax,'');
933                        }
934                }";
935               
936                // Fonction de recherche des segments entre les taquets pour un locuteur donné
937                $this->js .= "
938                function get_speaker_segments(speaker_id) {
939                        var segments = new Array();
940                               
941                        if (speaker_id) {
942                                for (var i in segments_between_lr_cursors) {
943                                        if (segments_between_lr_cursors[i].speaker == speaker_id) {
944                                                segments[segments.length] = segments_between_lr_cursors[i];
945                                        }
946                                }
947                        }
948                               
949                        return segments;
950                }";
951               
952                // Suppression de segments
953                $this->js .= "
954                function del_segments(segments) {
955                        if (confirm('".$msg['explnum_associate_del_segments_confirm']."')) {
956                                var segments_ids = new Array();
957                                for (var i in segments) {
958                                        segments_ids[segments_ids.length] = segments[i].db_id;
959                                }
960                               
961                                var ids_list = segments_ids.join(',');
962                                       
963                                var req = new http_request();
964                                req.request('$base_path/ajax.php?module=catalog&categ=explnum&quoifaire=delete_segments&segments_ids=' + ids_list,0,'',1,get_explnum_associate_ajax,'');
965                        }
966                }";
967               
968                // Fusion de segments
969                $this->js .= "
970                function join_segments(segments) {
971                        if (confirm('".$msg['explnum_associate_join_segments_confirm']."')) {
972                                var segments_ids = new Array();
973                                var start = 0;
974                                var end = 0;
975                                var speaker_id = segments[0].speaker;
976                               
977                                for (var i in segments) {
978                                        segments_ids[segments_ids.length] = segments[i].db_id;
979                                        if ((!start) || (start > (segments[i].start*1))) {
980                                                start = segments[i].start*1;
981                                        }
982                                        if (end < (segments[i].end*1)) {
983                                                end = segments[i].end*1;
984                                        }
985                                }
986                               
987                                var ids_list = segments_ids.join(',');
988                                       
989                                var req = new http_request();
990                                req.request('$base_path/ajax.php?module=catalog&categ=explnum&quoifaire=delete_segments&segments_ids=' + ids_list,0,'',0,'','');
991                               
992                                var req = new http_request();
993                                req.request('$base_path/ajax.php?module=catalog&categ=explnum&quoifaire=add_new_segment&explnum_id=".$this->explnum_id."&speaker_id=' + speaker_id + '&start=' + start + '&end=' + end,0,'',1,get_explnum_associate_ajax,'');
994                        }
995                }";
996               
997                // Scission de segments
998                $this->js .= "
999                function cut_segments(segments) {
1000                        if (confirm('".$msg['explnum_associate_cut_segments_confirm']."')) {
1001                                var speaker_id = segments[0].speaker;
1002                                var left_cursor_time = Math.round(document.getElementById('left_cursor_svg').getAttribute('time')*100);
1003                                var right_cursor_time = Math.round(document.getElementById('right_cursor_svg').getAttribute('time')*100);
1004                                var start;
1005                                var end;
1006                                var exit = 0
1007                               
1008                                for (var i in segments) {
1009                                        start = 0;
1010                                        end = 0;
1011                                        if ((segments[i].start*1 < left_cursor_time) && (left_cursor_time < segments[i].end*1)) {
1012                                                start = left_cursor_time;
1013                                                var left_req = new http_request();
1014                                                left_req.request('$base_path/ajax.php?module=catalog&categ=explnum&quoifaire=add_new_segment&explnum_id=".$this->explnum_id."&speaker_id=' + speaker_id + '&start=' + segments[i].start*1 + '&end=' + left_cursor_time,0,'',0,'','');
1015                                                exit = exit+1;
1016                                        }
1017               
1018                                        if ((segments[i].start*1 < right_cursor_time) && (right_cursor_time < segments[i].end*1)) {
1019                                                end = right_cursor_time;
1020                                                var right_req = new http_request();
1021                                                right_req.request('$base_path/ajax.php?module=catalog&categ=explnum&quoifaire=add_new_segment&explnum_id=".$this->explnum_id."&speaker_id=' + speaker_id + '&start=' + right_cursor_time + '&end=' + segments[i].end*1,0,'',0,'','');
1022                                                exit = exit+1;
1023                                        }
1024                                       
1025                                        if (start || end) {
1026                                                var req = new http_request();
1027                                                req.request('$base_path/ajax.php?module=catalog&categ=explnum&quoifaire=update_segment_time&segment_id=' + segments[i].db_id + '&start=' + start + '&end=' + end,0,'',0,'','');
1028                                        }
1029                                       
1030                                        if (exit == 2) break;
1031                                }
1032                                get_explnum_associate_ajax();
1033                        }
1034                }";
1035               
1036                // Affichage du menu contextuel d'édition des segments
1037                $this->js .= "
1038                function display_edit_menu(event) {
1039                        event.preventDefault();
1040                               
1041                        var clickPosX = event.pageX - findPos(document.getElementById('speech_timeline'))[0];
1042                        var clickPosY = event.pageY - findPos(document.getElementById('speech_timeline'))[1];
1043                        var selectedSpeakerId = 0;
1044                               
1045                        for (var i in speakers) {
1046                                if ((clickPosY >= speakers[i].posY*1) && (clickPosY <= (speakers[i].posY*1 + ".$this->dimensions['speakerHeight']."))) {
1047                                        selectedSpeakerId = i;
1048                                        break;
1049                                }
1050                        }
1051                        var selectedSpeakerSegments = get_speaker_segments(selectedSpeakerId);
1052                               
1053                        if ((clickPosX > (document.getElementById('left_cursor_svg').transform.baseVal.getItem(0).matrix.e + ".$explnum_associate_left_cursor_svg_width.")) && (clickPosX < document.getElementById('right_cursor_svg').transform.baseVal.getItem(0).matrix.e)) {
1054                                document.addEventListener('mousedown', remove_edit_menu, false);
1055                               
1056                                var div = document.createElement('div');
1057                                div.id = 'speech_timeline_edit_menu';
1058                                div.style.position = 'absolute';
1059                                div.style.top = event.pageY + 'px';
1060                                div.style.left = event.pageX + 'px';
1061                               
1062                                var ul = document.createElement('ul');
1063                                       
1064                                var li = document.createElement('li');
1065                                li.innerHTML = '".$msg['explnum_associate_add_segment']."';
1066                                li.addEventListener('mousedown', add_new_segment, false);
1067                                ul.appendChild(li);
1068                                       
1069                                if (selectedSpeakerSegments.length) {
1070                                        var li = document.createElement('li');
1071                                        li.innerHTML = '".$msg['explnum_associate_del_segments']."';
1072                                        li.addEventListener('mousedown', function(){
1073                                                del_segments(selectedSpeakerSegments);
1074                                        }, false);
1075                                        ul.appendChild(li);
1076                                               
1077                                        var li = document.createElement('li');
1078                                        li.innerHTML = '".$msg['explnum_associate_cut_segments']."';
1079                                        li.addEventListener('mousedown', function(){
1080                                                cut_segments(selectedSpeakerSegments);
1081                                        }, false);
1082                                        ul.appendChild(li);
1083                                }
1084                                if (selectedSpeakerSegments.length > 1) {               
1085                                        var li = document.createElement('li');
1086                                        li.innerHTML = '".$msg['explnum_associate_join_segments']."';
1087                                        li.addEventListener('mousedown', function(){
1088                                                join_segments(selectedSpeakerSegments);
1089                                        }, false);
1090                                        ul.appendChild(li);
1091                                }
1092                               
1093                                div.appendChild(ul);
1094                                document.getElementById('speech_timeline').appendChild(div);
1095                        }
1096                }
1097                               
1098                function remove_edit_menu(event) {
1099                        document.removeEventListener('mousedown', remove_edit_menu, false);
1100                        if (document.getElementById('speech_timeline_edit_menu')) {
1101                                document.getElementById('speech_timeline').removeChild(document.getElementById('speech_timeline_edit_menu'));
1102                        }
1103                }";
1104               
1105                // Fonction de déplacement d'un taquet sur le cursor
1106                global $explnum_associate_cursor_svg_width;
1107                $this->js .= "
1108                function move_lr_cursor_on_cursor(cursor_id) {
1109                        var cursor_pos = document.getElementById('cursor_svg').transform.baseVal.getItem(0).matrix.e*1 + ".($explnum_associate_cursor_svg_width / 2).";
1110                        var allowed = true;
1111                               
1112                        if (cursor_id == 'left_cursor_svg') {
1113                                cursor_pos = cursor_pos - ".$explnum_associate_left_cursor_svg_width.";
1114                                var cursor_to_move = document.getElementById('left_cursor_svg');
1115                                var other_cursor = document.getElementById('right_cursor_svg');
1116                                var other_cursor_pos = document.getElementById('right_cursor_svg').transform.baseVal.getItem(0).matrix.e*1 - ".$explnum_associate_left_cursor_svg_width.";
1117                               
1118                                if (cursor_pos > other_cursor_pos) allowed = false;
1119                        } else {
1120                                var cursor_to_move = document.getElementById('right_cursor_svg');
1121                                var other_cursor = document.getElementById('left_cursor_svg');
1122                                var other_cursor_pos = document.getElementById('left_cursor_svg').transform.baseVal.getItem(0).matrix.e*1;
1123                               
1124                                if (cursor_pos < other_cursor_pos) allowed = false;
1125                        }
1126                               
1127                        if (allowed) {
1128                                cursor_to_move.transform.baseVal.getItem(0).setTranslate(cursor_pos, cursor_to_move.transform.baseVal.getItem(0).matrix.f);
1129                                var time = Math.round(player.currentTime());
1130                                cursor_to_move.setAttribute('time', time);
1131                                time = get_time_to_display(time);
1132                                document.getElementById(cursor_id + '_pos').value = time;
1133                                cursor_to_move.setAttribute('title', time);
1134                        } else {
1135                                cursor_to_move.transform.baseVal.getItem(0).setTranslate(other_cursor_pos, cursor_to_move.transform.baseVal.getItem(0).matrix.f);
1136                                document.getElementById(cursor_id + '_pos').value = other_cursor.getAttribute('title');
1137                                cursor_to_move.setAttribute('title', other_cursor.getAttribute('title'));
1138                                cursor_to_move.setAttribute('time', other_cursor.getAttribute('time'));
1139                        }
1140                               
1141                        get_segments_between_lr_cursors();
1142                }";
1143               
1144                // Ajout du listener sur un segment
1145                $this->js .= "
1146                for (var i in segments) {
1147                        document.getElementById('segment_svg_' + i).addEventListener('mousedown', start_drag_segment, false);
1148                }";
1149               
1150                // Ajout des listeners sur les locuteurs (Ouverture formulaire et suppression)
1151                $this->js .= "
1152                for (var i in speakers) {
1153                        document.getElementById('explnum_associate_author_libelle_' + i).addEventListener('click', display_author_associate_form, false);
1154                       
1155                        document.getElementById('explnum_del_associate_speaker_' + i).addEventListener('click', del_speaker, false);
1156                }";
1157               
1158                // Ajout du listener sur le bouton d'ajout d'un locuteur
1159                $this->js .= "
1160                document.getElementById('explnum_associate_add_speaker').addEventListener('click', add_speaker, false);";
1161               
1162                // Ajout des listeners sur les taquets
1163                $this->js .= "
1164                document.getElementById('left_cursor_svg').addEventListener('mousedown', start_drag_lr_cursor, false);
1165                document.getElementById('right_cursor_svg').addEventListener('mousedown', start_drag_lr_cursor, false);";
1166               
1167                // Ajout des listeners sur les champs position des taquets
1168                $this->js .= "
1169                document.getElementById('left_cursor_svg_pos').addEventListener('change', function(event) {
1170                        update_lr_cursor('left_cursor_svg');
1171                }, false);
1172                document.getElementById('right_cursor_svg_pos').addEventListener('change', function(event) {
1173                        update_lr_cursor('right_cursor_svg');
1174                }, false);";
1175               
1176                // Ajout du listener du clic droit
1177                $this->js .= "
1178                document.getElementById('speech_timeline').addEventListener('contextmenu', display_edit_menu, true);";
1179               
1180                // Ajout des listener pour déplacer un taquet sur le curseur
1181                $this->js .= "
1182                document.getElementById('left_cursor_svg_to_cursor').addEventListener('click', function(event) {
1183                        move_lr_cursor_on_cursor('left_cursor_svg');
1184                }, false);
1185                document.getElementById('right_cursor_svg_to_cursor').addEventListener('click', function(event) {
1186                        move_lr_cursor_on_cursor('right_cursor_svg');
1187                }, false);";
1188        }
1189       
1190        private function utf8_normalize($array) {
1191                global $charset;
1192                $rarray=array();
1193                foreach ($array as $key=>$val) {
1194                        if (is_array($val)) {
1195                                $rarray[$key]=$this->utf8_normalize($val);
1196                        } else $rarray[$key]=($charset!="utf-8"?utf8_encode($val):$val);
1197                }
1198                return $rarray;
1199        }
1200}
1201?>
Note: See TracBrowser for help on using the repository browser.