source: pmb4.1/trunk/fuentes/pmb/classes/explnum_associate_svg.class.php @ 478

Last change on this file since 478 was 478, checked in by mabarracus, 4 years ago

copy trusty code 4.1

  • Property svn:executable set to *
File size: 47.8 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.2.2.1 2014-03-25 10:18:54 apetithomme 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 = mysql_query($query);
272                if ($result && mysql_num_rows($result)) {
273                        $i = 0;
274                        while ($speaker = 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 = mysql_query($query);
288                if ($result && mysql_num_rows($result)) {
289                        while ($segment = 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                                        break;
452                                }
453                        }
454                }";
455               
456                // Drag du curseur
457                $this->js .= "
458                function start_drag_cursor(event) {
459                        event.preventDefault();
460                        document.addEventListener('mouseup', stop_drag_cursor, false);
461                        document.addEventListener('mousemove', drag_cursor, false);
462                }
463               
464                function drag_cursor(event) {
465                        update_video_time(event);
466                }
467               
468                function stop_drag_cursor() {
469                        document.removeEventListener('mousemove', drag_cursor, false);
470                        document.removeEventListener('mouseup', stop_drag_cursor, false);
471                }
472                ";
473               
474                // Mise à jour de la vidéo
475                $this->js .= "
476                function update_video_time(event) {
477                        event.preventDefault();
478                        player.currentTime((event.clientX - (findPos(document.getElementById('speech_timeline'))[0] + ". ($this->dimensions['speakerLeft'] + $this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight'] + 2 * $this->dimensions['backgroundPadding']).")) / ratio);
479                }";
480               
481                // Ajout du listener sur le background
482                $this->js .= "
483                document.getElementById('background_svg').addEventListener('click', update_video_time, false);";
484               
485                // Ajout du listener sur le curseur
486                $this->js .= "
487                document.getElementById('cursor_svg').addEventListener('mousedown', start_drag_cursor, false);";
488               
489                if ($edit) {
490                        $this->getJsEdit();
491                } else {
492                        // Ajout du listener sur un segment
493                        $this->js .= "
494                        for (var i in segments) {
495                                document.getElementById('segment_svg_' + i).addEventListener('click', update_video_time, false);
496                        }";
497                }
498               
499                // Positionnement du curseur
500                $this->js .= "
501                update_cursor();";
502               
503                return $this->js;
504        }
505       
506        /**
507         * Portion de la chaine JavaScript gérant l'édition
508         */
509        private function getJsEdit() {
510                global $base_path;
511                global $msg;
512               
513                // Récupération du tableau de locuteurs en js
514                $this->js .= "
515                var speakers = ".json_encode($this->speakers).";
516                var segments_between_lr_cursors = new Array();";
517               
518                // Positionnement des taquets
519                global $explnum_associate_left_cursor_svg_width;
520                $this->js .= "
521                function update_lr_cursor(cursor_id) {
522                        var cursor = document.getElementById(cursor_id);
523                        var time = document.getElementById(cursor_id + '_pos').value.split(':');
524                        var sec = 0;
525                       
526                        if (time.length == 2) sec = time[0]*60 + time[1]*1;
527                        else sec = time[0];
528                       
529                        document.getElementById(cursor_id + '_pos').value = get_time_to_display(sec);
530                       
531                        var x = sec * ratio + ".($this->dimensions['speakerLeft'] + $this->dimensions['speakerWidth'] + $this->dimensions['speakerMarginRight'] + $this->dimensions['backgroundPadding']).";
532                        if (cursor_id == 'left_cursor_svg') {
533                                x = x - ".$explnum_associate_left_cursor_svg_width.";
534               
535                                if (x <= document.getElementById('right_cursor_svg').transform.baseVal.getItem(0).matrix.e) {
536                                        cursor.transform.baseVal.getItem(0).setTranslate(x, cursor.transform.baseVal.getItem(0).matrix.f);
537                                        cursor.setAttribute('title', document.getElementById(cursor_id + '_pos').value);
538                                        cursor.setAttribute('time', sec);
539                                        get_segments_between_lr_cursors();
540                                } else {
541                                        document.getElementById(cursor_id + '_pos').value = document.getElementById('right_cursor_svg_pos').value;
542                                        update_lr_cursor(cursor_id);
543                                }
544                        } else if (cursor_id == 'right_cursor_svg') {
545                                if (x > ".($this->dimensions['totalWidth'] - $this->dimensions['backgroundPadding']).") {
546                                        document.getElementById(cursor_id + '_pos').value = get_time_to_display(duration);
547                                        update_lr_cursor(cursor_id);
548                                } else if (x >= document.getElementById('left_cursor_svg').transform.baseVal.getItem(0).matrix.e) {
549                                        cursor.transform.baseVal.getItem(0).setTranslate(x, cursor.transform.baseVal.getItem(0).matrix.f);
550                                        cursor.setAttribute('title', document.getElementById(cursor_id + '_pos').value);
551                                        cursor.setAttribute('time', sec);
552                                        get_segments_between_lr_cursors();
553                                } else {
554                                        document.getElementById(cursor_id + '_pos').value = document.getElementById('left_cursor_svg_pos').value;
555                                        update_lr_cursor(cursor_id);
556                                }
557                        }
558                }
559               
560                update_lr_cursor('right_cursor_svg');
561                update_lr_cursor('left_cursor_svg');";
562               
563                // Fonction d'ouverture du popup
564                $this->js .= "
565                function openPopUpCall(id) {
566                        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');
567                }";
568               
569                // Réinitialisation du formulaire
570                $this->js .= "
571                function clearAut(id) {
572                        document.getElementById('aut' + id).value='';
573                        document.getElementById('aut' + id + '_id').value='0';
574                        update_associate_author();
575                }";
576               
577                // Validation du formulaire
578                $this->js .= "
579                function update_associate_author() {
580                        var id = document.getElementById('id_current_author_associate_form').value;
581                        if (document.getElementById('aut' + id).value != '') {
582                                document.getElementById('explnum_associate_author_libelle_' + id).innerHTML = document.getElementById('aut' + id).value;
583                        } else {
584                                document.getElementById('explnum_associate_author_libelle_' + id).innerHTML = '".$msg['explnum_associate_author']."';
585                        }
586                        document.getElementById('author_associate_form_' + id).style.display = 'none';
587                       
588                        var author_id = document.getElementById('aut' + id + '_id').value;
589                       
590                        var req = new http_request();           
591                        req.request('$base_path/ajax.php?module=catalog&categ=explnum&quoifaire=update_associate_author&speaker_id=' + id + '&author_id=' + author_id,0,'',1,'','');
592                }";
593               
594                // Fermeture du formulaire
595                $this->js .= "
596                function close_author_associate_form(id) {
597                        document.getElementById('author_associate_form_' + id).style.display = 'none';
598                }";
599               
600                // Création des div de selection d'autorité
601                $this->js .= "
602                for (var i in speakers) {
603                        if (!document.getElementById('author_associate_form_' + i)) {
604                                var form = document.createElement('form');
605                                form.id = 'author_associate_form_' + i;
606                                form.className = 'form-catalog';
607                                form.name = 'explnum_associate_speaker_' + i;
608                                var x = findPos(document.getElementById('speech_timeline'))[0] + ".$this->dimensions['speakerLeft'].";
609                                var y = findPos(document.getElementById('speech_timeline'))[1] - 10 + speakers[i]['posY'];
610                                form.style = 'position: absolute; top: ' + y + 'px; left: ' + x + 'px;';
611                                form.addEventListener('submit', function(e){
612                                        e.preventDefault();
613                                        e.stopPropagation();
614                                },false);
615                               
616                                var label = document.createElement('label');
617                                label.className = 'etiquette';
618                                label.for = 'aut' + i;
619                                label.innerHTML = '".$msg['234']."';
620                               
621                                var img = document.createElement('img');
622                                img.src = './images/close.png';
623                                img.alt = '".$msg['197']."';
624                                img.title = '".$msg['197']."';
625                                img.className = 'right';
626                                img.setAttribute('field_id', i);
627                                img.style.cursor = 'pointer';
628                                img.addEventListener('click', function(){
629                                        close_author_associate_form(this.getAttribute('field_id'));
630                                }, false);
631                               
632                                var div = document.createElement('div');
633                                div.className = 'row';
634                               
635                                var span = document.createElement('span');
636                               
637                                var input1 = document.createElement('input');
638                                input1.type = 'text';
639                                input1.id = 'aut' + i;
640                                input1.className = 'saisie-20emr';
641                                input1.name = 'aut' + i;
642                                input1.setAttribute('autfield', 'aut' + i + '_id');
643                                input1.setAttribute('completion', 'authors');
644                                input1.setAttribute('autocompletion', 'on');
645                                input1.value = speakers[i].author_libelle;
646                                input1.setAttribute('callback', 'update_associate_author');
647                               
648                                var input2 = document.createElement('input');
649                                input2.type = 'button';
650                                input2.className = 'bouton';
651                                input2.value = '...';
652                                input2.setAttribute('field_id', i);
653                                input2.addEventListener('click', function(){
654                                        openPopUpCall(this.getAttribute('field_id'));
655                                }, false);
656                               
657                                var input3 = document.createElement('input');
658                                input3.type = 'button';
659                                input3.className = 'bouton';
660                                input3.value = 'X';
661                                input3.setAttribute('field_id', i);
662                                input3.addEventListener('click', function(){
663                                        clearAut(this.getAttribute('field_id'));
664                                }, false);
665                               
666                                var input4 = document.createElement('input');
667                                input4.type = 'hidden';
668                                input4.id = 'aut' + i + '_id';
669                                input4.name = 'aut' + i + '_id';
670                                input4.value = speakers[i].author;
671                               
672                                span.appendChild(input1);
673                                div.appendChild(span);
674                                div.appendChild(input2);
675                                div.appendChild(input3);
676                                div.appendChild(input4);
677                                form.appendChild(label);
678                                form.appendChild(img);
679                                form.appendChild(div);
680                                document.getElementById('att').appendChild(form);
681                               
682                                ajax_pack_element(document.getElementById('aut' + i));
683                                document.getElementById('author_associate_form_' + i).style.display = 'none';
684                        }
685                }
686               
687                var input = document.createElement('input');
688                input.type = 'hidden';
689                input.id = 'id_current_author_associate_form';
690                input.value = 0;
691               
692                document.getElementById('att').appendChild(input);
693                ";
694               
695                // Clic sur un auteur, on affiche le formulaire
696                $this->js .= "
697                function display_author_associate_form(event) {
698                        var current_id = document.getElementById('id_current_author_associate_form').value;
699                        if (current_id != 0) {
700                                document.getElementById('author_associate_form_' + current_id).style.display = 'none';
701                        }
702                        var id = event.currentTarget.id.replace('explnum_associate_author_libelle_','');
703                        document.getElementById('id_current_author_associate_form').value = id;
704                        document.getElementById('author_associate_form_' + id).style.display = 'block';
705                        document.getElementById('aut' + id).focus();
706                }
707                ";
708               
709                // Drag des segments
710                $this->js .= "
711                var current_drag_segment;
712                var last_pageY;
713                var current_drag_speaker_id;
714               
715                function set_current_speaker(id, is_current) {
716                        var current_drag_speaker = document.getElementById(id);
717                        if (is_current) {
718                                current_drag_speaker.setAttribute('stroke', 'red');
719                        } else {
720                                current_drag_speaker.removeAttribute('stroke');
721                        }
722                }
723               
724                function start_drag_segment(event) {
725                        current_drag_segment = event.currentTarget;
726                        last_pageY = event.pageY;
727                       
728                        var segment_id = current_drag_segment.id.replace('segment_svg_','');
729                        current_drag_speaker_id = 'speaker_svg_' + segments[segment_id]['speaker'];
730                        set_current_speaker(current_drag_speaker_id, true);
731                       
732                        document.addEventListener('mouseup', stop_drag_segment, false);
733                        document.addEventListener('mousemove', drag_segment, false);
734                        event.preventDefault();
735                       
736                        var clone = current_drag_segment.cloneNode(true);
737                        clone.id = clone.id + '_clone';
738                        clone.setAttribute('fill-opacity', 0.5);
739                        clone.setAttribute('stroke', 'red');
740                        clone.setAttribute('stroke-dasharray','5,5');
741                        document.getElementById('speech_timeline_svg').appendChild(clone);
742                }
743               
744                function drag_segment(event) {
745                        var clone = document.getElementById(current_drag_segment.id + '_clone');
746                        clone.transform.baseVal.getItem(0).setTranslate(clone.transform.baseVal.getItem(0).matrix.e, clone.transform.baseVal.getItem(0).matrix.f + event.pageY - last_pageY);
747                        last_pageY = event.pageY;
748                       
749                        var mouse_posY = event.pageY - findPos(document.getElementById('speech_timeline'))[1];
750                        var speaker_id = current_drag_speaker_id.replace('speaker_svg_', '');
751                        if ((speakers[speaker_id].posY > mouse_posY) || ((speakers[speaker_id].posY + ".$this->dimensions['speakerHeight'].") < mouse_posY)) {
752                                set_current_speaker(current_drag_speaker_id, false);
753                                for (var i in speakers) {
754                                        if ((speakers[i].posY <= mouse_posY) && ((speakers[i].posY + ".$this->dimensions['speakerHeight'].") >= mouse_posY)) {
755                                                current_drag_speaker_id = 'speaker_svg_' + i;
756                                                set_current_speaker(current_drag_speaker_id, true);
757                                                break;
758                                        }
759                                }
760                        }
761                }
762               
763                function stop_drag_segment(event) {
764                        document.removeEventListener('mousemove', drag_segment, false);
765                        document.removeEventListener('mouseup', stop_drag_segment, false);
766                       
767                        var clone = document.getElementById(current_drag_segment.id + '_clone');
768                        clone.remove();
769                       
770                        set_current_speaker(current_drag_speaker_id, false);
771                       
772                        var speaker_id = current_drag_speaker_id.replace('speaker_svg_', '');
773                        var segment_id = current_drag_segment.id.replace('segment_svg_','');
774                        var move_allowed = true;
775                       
776                        for (var i in segments) {
777                                if ((i != segment_id) && (speaker_id == segments[i].speaker)) {
778                                        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)))) {
779                                                move_allowed = false;
780                                                break;
781                                        }
782                                }
783                        }
784                       
785                        if ((segments[segment_id].speaker != speaker_id) && move_allowed) {
786                                current_drag_segment.transform.baseVal.getItem(0).setTranslate(current_drag_segment.transform.baseVal.getItem(0).matrix.e, speakers[speaker_id].posY);
787                                segments[segment_id].speaker = speaker_id;
788                               
789                                var req = new http_request();
790                                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,'','');
791                        } else if (!move_allowed) {
792                                alert('".$msg['explnum_associate_segments_move_forbidden']."');
793                        }
794                }
795                ";
796               
797                // Ajout d'un locuteur
798                $this->js .= "
799                function add_speaker(event) {
800                        var req = new http_request();
801                        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,'');
802                }";
803               
804                // Suppression d'un locuteur
805                $this->js .= "
806                function del_speaker(event) {
807                        var speaker_id = event.currentTarget.id.replace('explnum_del_associate_speaker_', '');
808                        hasSegment = false;
809                       
810                        for (var i in segments) {
811                                if (segments[i].speaker == speaker_id) {
812                                        hasSegment = true;
813                                        break;
814                                }
815                        }
816                       
817                        if (hasSegment) {
818                                alert('".$msg['explnum_del_associate_speaker_forbidden']."');
819                        } else if (confirm('".$msg['explnum_del_associate_speaker_confirm']."')) {
820                                var req = new http_request();
821                                req.request('$base_path/ajax.php?module=catalog&categ=explnum&quoifaire=delete_associate_speaker&speaker_id=' + speaker_id,0,'',1,get_explnum_associate_ajax,'');
822                        }
823                }";
824               
825                // Drag des taquets
826                global $explnum_associate_left_cursor_svg_width;
827               
828                $this->js .= "
829                var current_drag_lr_cursor;
830                var last_pageX;
831                var lr_cursor_pos;
832               
833                function start_drag_lr_cursor(event) {
834                        current_drag_lr_cursor = event.currentTarget;
835                        last_pageX = event.pageX;
836                       
837                        document.addEventListener('mouseup', stop_drag_lr_cursor, false);
838                        document.addEventListener('mousemove', drag_lr_cursor, false);
839                        event.preventDefault();
840                }
841               
842                function drag_lr_cursor(event) {
843                        var cond;
844               
845                        if (current_drag_lr_cursor.id == 'left_cursor_svg') {
846                                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'])).";
847                                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));
848                        } else if (current_drag_lr_cursor.id == 'right_cursor_svg') {
849                                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']).";
850                                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'])."));
851                        }
852                       
853                        if (cond) {
854                                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);
855                                document.getElementById(current_drag_lr_cursor.id + '_pos').value = get_time_to_display(lr_cursor_pos / ratio);
856                                current_drag_lr_cursor.setAttribute('title', get_time_to_display(lr_cursor_pos / ratio));
857                                current_drag_lr_cursor.setAttribute('time', lr_cursor_pos / ratio);
858                               
859                                last_pageX = event.pageX;
860                               
861                                get_segments_between_lr_cursors();
862                        }
863                }
864               
865                function stop_drag_lr_cursor(event) {
866                        document.removeEventListener('mousemove', drag_lr_cursor, false);
867                        document.removeEventListener('mouseup', stop_drag_lr_cursor, false);
868                }";
869               
870                // Trouver les segments présents entre les taquets
871                $this->js .= "
872                function get_segments_between_lr_cursors() {
873                        var left_cursor_time = document.getElementById('left_cursor_svg').getAttribute('time');
874                        var right_cursor_time = document.getElementById('right_cursor_svg').getAttribute('time');
875                        var current_segment;
876                       
877                        segments_between_lr_cursors = [];
878                       
879                        for (var i in segments) {
880                                current_segment = document.getElementById('segment_svg_' + i);
881                                if (((segments[i].start/100) <= right_cursor_time) && ((segments[i].end/100) >= left_cursor_time)) {
882                                        is_between_lr_cursors(current_segment, true);
883                                        segments_between_lr_cursors[segments_between_lr_cursors.length] = segments[i];
884                                } else {
885                                        is_between_lr_cursors(current_segment, false);
886                                }
887                        }
888                }
889               
890                function is_between_lr_cursors(segment, is_between) {
891                        if (is_between) {
892                                segment.setAttribute('stroke', 'green');
893                                segment.setAttribute('stroke-width', '2px');
894                        } else {
895                                segment.removeAttribute('stroke');
896                                segment.removeAttribute('stroke-width');
897                        }
898                }";
899               
900                // Ajout d'un segment
901                $this->js .= "
902                function add_new_segment() {
903                        var left_cursor_time = Math.round(document.getElementById('left_cursor_svg').getAttribute('time')*100);
904                        var right_cursor_time = Math.round(document.getElementById('right_cursor_svg').getAttribute('time')*100);
905                       
906                        if (left_cursor_time != right_cursor_time) {
907                                var speakers_with_segment = new Array();
908                                var speaker_available = true;
909                                var speaker_id = 0;
910                               
911                                for (var i in segments_between_lr_cursors) {
912                                        if (speakers_with_segment.indexOf(segments_between_lr_cursors[i].speaker) == -1) {
913                                                speakers_with_segment[speakers_with_segment.length] = segments_between_lr_cursors[i].speaker;
914                                        }
915                                        if (speakers_with_segment.length == speakers.length) {
916                                                speaker_available = false;
917                                                break;
918                                        }
919                                }
920                               
921                                if (speaker_available) {
922                                        for (var i in speakers) {
923                                                if (speakers_with_segment.indexOf(i) == -1) {
924                                                        speaker_id = i;
925                                                        break;
926                                                }
927                                        }
928                                }
929                               
930                                var req = new http_request();
931                                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,'');
932                        }
933                }";
934               
935                // Fonction de recherche des segments entre les taquets pour un locuteur donné
936                $this->js .= "
937                function get_speaker_segments(speaker_id) {
938                        var segments = new Array();
939                               
940                        if (speaker_id) {
941                                for (var i in segments_between_lr_cursors) {
942                                        if (segments_between_lr_cursors[i].speaker == speaker_id) {
943                                                segments[segments.length] = segments_between_lr_cursors[i];
944                                        }
945                                }
946                        }
947                               
948                        return segments;
949                }";
950               
951                // Suppression de segments
952                $this->js .= "
953                function del_segments(segments) {
954                        if (confirm('".$msg['explnum_associate_del_segments_confirm']."')) {
955                                var segments_ids = new Array();
956                                for (var i in segments) {
957                                        segments_ids[segments_ids.length] = segments[i].db_id;
958                                }
959                               
960                                var ids_list = segments_ids.join(',');
961                                       
962                                var req = new http_request();
963                                req.request('$base_path/ajax.php?module=catalog&categ=explnum&quoifaire=delete_segments&segments_ids=' + ids_list,0,'',1,get_explnum_associate_ajax,'');
964                        }
965                }";
966               
967                // Fusion de segments
968                $this->js .= "
969                function join_segments(segments) {
970                        if (confirm('".$msg['explnum_associate_join_segments_confirm']."')) {
971                                var segments_ids = new Array();
972                                var start = 0;
973                                var end = 0;
974                                var speaker_id = segments[0].speaker;
975                               
976                                for (var i in segments) {
977                                        segments_ids[segments_ids.length] = segments[i].db_id;
978                                        if ((!start) || (start > (segments[i].start*1))) {
979                                                start = segments[i].start*1;
980                                        }
981                                        if (end < (segments[i].end*1)) {
982                                                end = segments[i].end*1;
983                                        }
984                                }
985                               
986                                var ids_list = segments_ids.join(',');
987                                       
988                                var req = new http_request();
989                                req.request('$base_path/ajax.php?module=catalog&categ=explnum&quoifaire=delete_segments&segments_ids=' + ids_list,0,'',0,'','');
990                               
991                                var req = new http_request();
992                                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,'');
993                        }
994                }";
995               
996                // Scission de segments
997                $this->js .= "
998                function cut_segments(segments) {
999                        if (confirm('".$msg['explnum_associate_cut_segments_confirm']."')) {
1000                                var speaker_id = segments[0].speaker;
1001                                var left_cursor_time = Math.round(document.getElementById('left_cursor_svg').getAttribute('time')*100);
1002                                var right_cursor_time = Math.round(document.getElementById('right_cursor_svg').getAttribute('time')*100);
1003                                var start;
1004                                var end;
1005                                var exit = 0
1006                               
1007                                for (var i in segments) {
1008                                        start = 0;
1009                                        end = 0;
1010                                        if ((segments[i].start*1 < left_cursor_time) && (left_cursor_time < segments[i].end*1)) {
1011                                                start = left_cursor_time;
1012                                                var left_req = new http_request();
1013                                                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,'','');
1014                                                exit = exit+1;
1015                                        }
1016               
1017                                        if ((segments[i].start*1 < right_cursor_time) && (right_cursor_time < segments[i].end*1)) {
1018                                                end = right_cursor_time;
1019                                                var right_req = new http_request();
1020                                                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,'','');
1021                                                exit = exit+1;
1022                                        }
1023                                       
1024                                        if (start || end) {
1025                                                var req = new http_request();
1026                                                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,'','');
1027                                        }
1028                                       
1029                                        if (exit == 2) break;
1030                                }
1031                                get_explnum_associate_ajax();
1032                        }
1033                }";
1034               
1035                // Affichage du menu contextuel d'édition des segments
1036                $this->js .= "
1037                function display_edit_menu(event) {
1038                        event.preventDefault();
1039                               
1040                        var clickPosX = event.pageX - findPos(document.getElementById('speech_timeline'))[0];
1041                        var clickPosY = event.pageY - findPos(document.getElementById('speech_timeline'))[1];
1042                        var selectedSpeakerId = 0;
1043                               
1044                        for (var i in speakers) {
1045                                if ((clickPosY >= speakers[i].posY) && (clickPosY <= (speakers[i].posY + ".$this->dimensions['speakerHeight']."))) {
1046                                        selectedSpeakerId = i;
1047                                        break;
1048                                }
1049                        }
1050                        var selectedSpeakerSegments = get_speaker_segments(selectedSpeakerId);
1051                               
1052                        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)) {
1053                                document.addEventListener('mousedown', remove_edit_menu, false);
1054                               
1055                                var div = document.createElement('div');
1056                                div.id = 'speech_timeline_edit_menu';
1057                                div.style.position = 'absolute';
1058                                div.style.top = event.pageY + 'px';
1059                                div.style.left = event.pageX + 'px';
1060                               
1061                                var ul = document.createElement('ul');
1062                                       
1063                                var li = document.createElement('li');
1064                                li.innerHTML = '".$msg['explnum_associate_add_segment']."';
1065                                li.addEventListener('mousedown', add_new_segment, false);
1066                                ul.appendChild(li);
1067                                       
1068                                if (selectedSpeakerSegments.length) {
1069                                        var li = document.createElement('li');
1070                                        li.innerHTML = '".$msg['explnum_associate_del_segments']."';
1071                                        li.addEventListener('mousedown', function(){
1072                                                del_segments(selectedSpeakerSegments);
1073                                        }, false);
1074                                        ul.appendChild(li);
1075                                               
1076                                        var li = document.createElement('li');
1077                                        li.innerHTML = '".$msg['explnum_associate_cut_segments']."';
1078                                        li.addEventListener('mousedown', function(){
1079                                                cut_segments(selectedSpeakerSegments);
1080                                        }, false);
1081                                        ul.appendChild(li);
1082                                }
1083                                if (selectedSpeakerSegments.length > 1) {               
1084                                        var li = document.createElement('li');
1085                                        li.innerHTML = '".$msg['explnum_associate_join_segments']."';
1086                                        li.addEventListener('mousedown', function(){
1087                                                join_segments(selectedSpeakerSegments);
1088                                        }, false);
1089                                        ul.appendChild(li);
1090                                }
1091                               
1092                                div.appendChild(ul);
1093                                document.getElementById('speech_timeline').appendChild(div);
1094                        }
1095                }
1096                               
1097                function remove_edit_menu(event) {
1098                        document.removeEventListener('mousedown', remove_edit_menu, false);
1099                        if (document.getElementById('speech_timeline_edit_menu')) {
1100                                document.getElementById('speech_timeline').removeChild(document.getElementById('speech_timeline_edit_menu'));
1101                        }
1102                }";
1103               
1104                // Fonction de déplacement d'un taquet sur le cursor
1105                global $explnum_associate_cursor_svg_width;
1106                $this->js .= "
1107                function move_lr_cursor_on_cursor(cursor_id) {
1108                        var cursor_pos = document.getElementById('cursor_svg').transform.baseVal.getItem(0).matrix.e*1 + ".($explnum_associate_cursor_svg_width / 2).";
1109                        var allowed = true;
1110                               
1111                        if (cursor_id == 'left_cursor_svg') {
1112                                cursor_pos = cursor_pos - ".$explnum_associate_left_cursor_svg_width.";
1113                                var cursor_to_move = document.getElementById('left_cursor_svg');
1114                                var other_cursor = document.getElementById('right_cursor_svg');
1115                                var other_cursor_pos = document.getElementById('right_cursor_svg').transform.baseVal.getItem(0).matrix.e*1 - ".$explnum_associate_left_cursor_svg_width.";
1116                               
1117                                if (cursor_pos > other_cursor_pos) allowed = false;
1118                        } else {
1119                                var cursor_to_move = document.getElementById('right_cursor_svg');
1120                                var other_cursor = document.getElementById('left_cursor_svg');
1121                                var other_cursor_pos = document.getElementById('left_cursor_svg').transform.baseVal.getItem(0).matrix.e*1;
1122                               
1123                                if (cursor_pos < other_cursor_pos) allowed = false;
1124                        }
1125                               
1126                        if (allowed) {
1127                                cursor_to_move.transform.baseVal.getItem(0).setTranslate(cursor_pos, cursor_to_move.transform.baseVal.getItem(0).matrix.f);
1128                                var time = Math.round(player.currentTime());
1129                                cursor_to_move.setAttribute('time', time);
1130                                time = get_time_to_display(time);
1131                                document.getElementById(cursor_id + '_pos').value = time;
1132                                cursor_to_move.setAttribute('title', time);
1133                        } else {
1134                                cursor_to_move.transform.baseVal.getItem(0).setTranslate(other_cursor_pos, cursor_to_move.transform.baseVal.getItem(0).matrix.f);
1135                                document.getElementById(cursor_id + '_pos').value = other_cursor.getAttribute('title');
1136                                cursor_to_move.setAttribute('title', other_cursor.getAttribute('title'));
1137                                cursor_to_move.setAttribute('time', other_cursor.getAttribute('time'));
1138                        }
1139                               
1140                        get_segments_between_lr_cursors();
1141                }";
1142               
1143                // Ajout du listener sur un segment
1144                $this->js .= "
1145                for (var i in segments) {
1146                        document.getElementById('segment_svg_' + i).addEventListener('mousedown', start_drag_segment, false);
1147                }";
1148               
1149                // Ajout des listeners sur les locuteurs (Ouverture formulaire et suppression)
1150                $this->js .= "
1151                for (var i in speakers) {
1152                        document.getElementById('explnum_associate_author_libelle_' + i).addEventListener('click', display_author_associate_form, false);
1153                       
1154                        document.getElementById('explnum_del_associate_speaker_' + i).addEventListener('click', del_speaker, false);
1155                }";
1156               
1157                // Ajout du listener sur le bouton d'ajout d'un locuteur
1158                $this->js .= "
1159                document.getElementById('explnum_associate_add_speaker').addEventListener('click', add_speaker, false);";
1160               
1161                // Ajout des listeners sur les taquets
1162                $this->js .= "
1163                document.getElementById('left_cursor_svg').addEventListener('mousedown', start_drag_lr_cursor, false);
1164                document.getElementById('right_cursor_svg').addEventListener('mousedown', start_drag_lr_cursor, false);";
1165               
1166                // Ajout des listeners sur les champs position des taquets
1167                $this->js .= "
1168                document.getElementById('left_cursor_svg_pos').addEventListener('change', function(event) {
1169                        update_lr_cursor('left_cursor_svg');
1170                }, false);
1171                document.getElementById('right_cursor_svg_pos').addEventListener('change', function(event) {
1172                        update_lr_cursor('right_cursor_svg');
1173                }, false);";
1174               
1175                // Ajout du listener du clic droit
1176                $this->js .= "
1177                document.getElementById('speech_timeline').addEventListener('contextmenu', display_edit_menu, true);";
1178               
1179                // Ajout des listener pour déplacer un taquet sur le curseur
1180                $this->js .= "
1181                document.getElementById('left_cursor_svg_to_cursor').addEventListener('click', function(event) {
1182                        move_lr_cursor_on_cursor('left_cursor_svg');
1183                }, false);
1184                document.getElementById('right_cursor_svg_to_cursor').addEventListener('click', function(event) {
1185                        move_lr_cursor_on_cursor('right_cursor_svg');
1186                }, false);";
1187        }
1188}
1189?>
Note: See TracBrowser for help on using the repository browser.