on-demand release 2.6beta+
[moodle.git] / mod / assign / feedback / editpdf / yui / build / moodle-assignfeedback_editpdf-editor / moodle-assignfeedback_editpdf-editor.js
CommitLineData
5c386472
DW
1YUI.add('moodle-assignfeedback_editpdf-editor', function (Y, NAME) {
2
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * A list of globals used by this module.
20 *
21 * @module moodle-assignfeedback_editpdf-editor
22 */
23var AJAXBASE = M.cfg.wwwroot + '/mod/assign/feedback/editpdf/ajax.php',
aa3e4bde 24 AJAXBASEPROGRESS = M.cfg.wwwroot + '/mod/assign/feedback/editpdf/ajax_progress.php',
5c386472
DW
25 CSS = {
26 DIALOGUE : 'assignfeedback_editpdf_widget'
27 },
28 SELECTOR = {
29 PREVIOUSBUTTON : '.' + CSS.DIALOGUE + ' .navigate-previous-button',
30 NEXTBUTTON : '.' + CSS.DIALOGUE + ' .navigate-next-button',
31 SEARCHCOMMENTSBUTTON : '.' + CSS.DIALOGUE + ' .searchcommentsbutton',
32 SEARCHFILTER : '.assignfeedback_editpdf_commentsearch input',
33 SEARCHCOMMENTSLIST : '.assignfeedback_editpdf_commentsearch ul',
34 PAGESELECT : '.' + CSS.DIALOGUE + ' .navigate-page-select',
35 LOADINGICON : '.' + CSS.DIALOGUE + ' .loading',
aa3e4bde 36 PROGRESSBARCONTAINER : '.' + CSS.DIALOGUE + ' .progress-info.progress-striped',
5c386472
DW
37 DRAWINGREGION : '.' + CSS.DIALOGUE + ' .drawingregion',
38 DRAWINGCANVAS : '.' + CSS.DIALOGUE + ' .drawingcanvas',
39 SAVE : '.' + CSS.DIALOGUE + ' .savebutton',
40 COMMENTCOLOURBUTTON : '.' + CSS.DIALOGUE + ' .commentcolourbutton',
41 COMMENTMENU : ' .commentdrawable a',
42 ANNOTATIONCOLOURBUTTON : '.' + CSS.DIALOGUE + ' .annotationcolourbutton',
43 DELETEANNOTATIONBUTTON : '.' + CSS.DIALOGUE + ' .deleteannotationbutton',
44 UNSAVEDCHANGESDIV : '.assignfeedback_editpdf_unsavedchanges',
45 STAMPSBUTTON : '.' + CSS.DIALOGUE + ' .currentstampbutton',
46 DIALOGUE : '.' + CSS.DIALOGUE
47 },
48 SELECTEDBORDERCOLOUR = 'rgba(200, 200, 255, 0.9)',
49 SELECTEDFILLCOLOUR = 'rgba(200, 200, 255, 0.5)',
1d38083c 50 COMMENTTEXTCOLOUR = 'rgb(51, 51, 51)',
5c386472
DW
51 COMMENTCOLOUR = {
52 'white' : 'rgb(255,255,255)',
1d38083c
DW
53 'yellow' : 'rgb(255,236,174)',
54 'red' : 'rgb(249,181,179)',
55 'green' : 'rgb(214,234,178)',
56 'blue' : 'rgb(203,217,237)',
5c386472
DW
57 'clear' : 'rgba(255,255,255, 0)'
58 },
59 ANNOTATIONCOLOUR = {
60 'white' : 'rgb(255,255,255)',
1d38083c
DW
61 'yellow' : 'rgb(255,207,53)',
62 'red' : 'rgb(239,69,64)',
63 'green' : 'rgb(152,202,62)',
64 'blue' : 'rgb(125,159,211)',
65 'black' : 'rgb(51,51,51)'
5c386472
DW
66 },
67 CLICKTIMEOUT = 300,
68 TOOLSELECTOR = {
69 'comment': '.' + CSS.DIALOGUE + ' .commentbutton',
70 'pen': '.' + CSS.DIALOGUE + ' .penbutton',
71 'line': '.' + CSS.DIALOGUE + ' .linebutton',
72 'rectangle': '.' + CSS.DIALOGUE + ' .rectanglebutton',
73 'oval': '.' + CSS.DIALOGUE + ' .ovalbutton',
74 'stamp': '.' + CSS.DIALOGUE + ' .stampbutton',
75 'select': '.' + CSS.DIALOGUE + ' .selectbutton',
76 'highlight': '.' + CSS.DIALOGUE + ' .highlightbutton'
77 },
78 STROKEWEIGHT = 4;
79// This file is part of Moodle - http://moodle.org/
80//
81// Moodle is free software: you can redistribute it and/or modify
82// it under the terms of the GNU General Public License as published by
83// the Free Software Foundation, either version 3 of the License, or
84// (at your option) any later version.
85//
86// Moodle is distributed in the hope that it will be useful,
87// but WITHOUT ANY WARRANTY; without even the implied warranty of
88// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
89// GNU General Public License for more details.
90//
91// You should have received a copy of the GNU General Public License
92// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
93
94/**
95 * Class representing a 2d point.
96 *
97 * @module moodle-assignfeedback_editpdf-editor
98 */
99
100/**
101 * POINT
102 *
103 * @namespace M.assignfeedback_editpdf
104 * @param int x
105 * @param int y
106 * @class point
107 */
108POINT = function(x, y) {
109
110 /**
111 * X coordinate.
112 * @property x
113 * @type int
114 * @public
115 */
116 this.x = parseInt(x, 10);
117
118 /**
119 * Y coordinate.
120 * @property y
121 * @type int
122 * @public
123 */
124 this.y = parseInt(y, 10);
125
126 /**
127 * Clip this point to the rect
128 * @method clip
129 * @param M.assignfeedback_editpdf.point
130 * @public
131 */
132 this.clip = function(bounds) {
133 if (this.x < bounds.x) {
134 this.x = bounds.x;
135 }
136 if (this.x > (bounds.x + bounds.width)) {
137 this.x = bounds.x + bounds.width;
138 }
139 if (this.y < bounds.y) {
140 this.y = bounds.y;
141 }
142 if (this.y > (bounds.y + bounds.height)) {
143 this.y = bounds.y + bounds.height;
144 }
145 // For chaining.
146 return this;
147 };
148};
149
150M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
151M.assignfeedback_editpdf.point = POINT;
152// This file is part of Moodle - http://moodle.org/
153//
154// Moodle is free software: you can redistribute it and/or modify
155// it under the terms of the GNU General Public License as published by
156// the Free Software Foundation, either version 3 of the License, or
157// (at your option) any later version.
158//
159// Moodle is distributed in the hope that it will be useful,
160// but WITHOUT ANY WARRANTY; without even the implied warranty of
161// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
162// GNU General Public License for more details.
163//
164// You should have received a copy of the GNU General Public License
165// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
166
167/**
168 * Class representing a 2d rect.
169 *
170 * @module moodle-assignfeedback_editpdf-editor
171 */
172
173/**
174 * RECT
175 *
176 * @namespace M.assignfeedback_editpdf
177 * @param int x
178 * @param int y
179 * @param int width
180 * @param int height
181 * @class rect
182 */
183RECT = function(x, y, width, height) {
184
185 /**
186 * X coordinate.
187 * @property x
188 * @type int
189 * @public
190 */
191 this.x = x;
192
193 /**
194 * Y coordinate.
195 * @property y
196 * @type int
197 * @public
198 */
199 this.y = y;
200
201 /**
202 * Width
203 * @property width
204 * @type int
205 * @public
206 */
207 this.width = width;
208
209 /**
210 * Height
211 * @property height
212 * @type int
213 * @public
214 */
215 this.height = height;
216
217 /**
218 * Set this rect to represent the smallest possible rectangle containing this list of points.
219 * @method bounds
220 * @param M.assignfeedback_editpdf.point[]
221 * @public
222 */
223 this.bound = function(points) {
224 var minx = 0,
225 maxx = 0,
226 miny = 0,
227 maxy = 0,
228 i = 0,
229 point;
230
231 for (i = 0; i < points.length; i++) {
232 point = points[i];
233 if (point.x < minx || i === 0) {
234 minx = point.x;
235 }
236 if (point.x > maxx || i === 0) {
237 maxx = point.x;
238 }
239 if (point.y < miny || i === 0) {
240 miny = point.y;
241 }
242 if (point.y > maxy || i === 0) {
243 maxy = point.y;
244 }
245 }
246 this.x = minx;
247 this.y = miny;
248 this.width = maxx - minx;
249 this.height = maxy - miny;
250 // Allow chaining.
251 return this;
252 };
253};
254
255M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
256M.assignfeedback_editpdf.rect = RECT;
257// This file is part of Moodle - http://moodle.org/
258//
259// Moodle is free software: you can redistribute it and/or modify
260// it under the terms of the GNU General Public License as published by
261// the Free Software Foundation, either version 3 of the License, or
262// (at your option) any later version.
263//
264// Moodle is distributed in the hope that it will be useful,
265// but WITHOUT ANY WARRANTY; without even the implied warranty of
266// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
267// GNU General Public License for more details.
268//
269// You should have received a copy of the GNU General Public License
270// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
271
272/**
273 * Class representing a partially completed edit operation.
274 *
275 * @module moodle-assignfeedback_editpdf-editor
276 */
277
278/**
279 * EDIT
280 *
281 * @namespace M.assignfeedback_editpdf
282 * @class edit
283 */
284EDIT = function() {
285
286 /**
287 * Starting point for the edit.
288 * @property start
289 * @type M.assignfeedback_editpdf.point|false
290 * @public
291 */
292 this.start = false;
293
294 /**
295 * Finishing point for the edit.
296 * @property end
297 * @type M.assignfeedback_editpdf.point|false
298 * @public
299 */
300 this.end = false;
301
302 /**
303 * Starting time for the edit.
304 * @property starttime
305 * @type int
306 * @public
307 */
308 this.starttime = 0;
309
310 /**
311 * Starting point for the currently selected annotation.
312 * @property annotationstart
313 * @type M.assignfeedback_editpdf.point|false
314 * @public
315 */
316 this.annotationstart = false;
317
318 /**
319 * The currently selected tool
320 * @property tool
321 * @type String
322 * @public
323 */
324 this.tool = "comment";
325
326 /**
327 * The currently comment colour
328 * @property commentcolour
329 * @type String
330 * @public
331 */
332 this.commentcolour = 'yellow';
333
334 /**
335 * The currently annotation colour
336 * @property annotationcolour
337 * @type String
338 * @public
339 */
340 this.annotationcolour = 'red';
341
342 /**
343 * The current stamp image.
344 * @property stamp
345 * @type String
346 * @public
347 */
348 this.stamp = '';
349
350 /**
351 * List of points the the current drawing path.
352 * @property path
353 * @type M.assignfeedback_editpdf.point[]
354 * @public
355 */
356 this.path = [];
357};
358
359M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
360M.assignfeedback_editpdf.edit = EDIT;
361// This file is part of Moodle - http://moodle.org/
362//
363// Moodle is free software: you can redistribute it and/or modify
364// it under the terms of the GNU General Public License as published by
365// the Free Software Foundation, either version 3 of the License, or
366// (at your option) any later version.
367//
368// Moodle is distributed in the hope that it will be useful,
369// but WITHOUT ANY WARRANTY; without even the implied warranty of
370// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
371// GNU General Public License for more details.
372//
373// You should have received a copy of the GNU General Public License
374// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
375
376/**
377 * Class representing a drawable thing which contains both
378 * Y.Nodes, and Y.Shapes.
379 *
380 * @module moodle-assignfeedback_editpdf-editor
381 */
382
383/**
384 * DRAWABLE
385 *
386 * @namespace M.assignfeedback_editpdf
387 * @param M.assignfeedback_editpdf.editor editor
388 * @class drawable
389 */
390DRAWABLE = function(editor) {
391
392 /**
393 * Reference to M.assignfeedback_editpdf.editor.
394 * @property editor
395 * @type M.assignfeedback_editpdf.editor
396 * @public
397 */
398 this.editor = editor;
399
400 /**
401 * Array of Y.Shape
402 * @property shapes
403 * @type Y.Shape[]
404 * @public
405 */
406 this.shapes = [];
407
408 /**
409 * Array of Y.Node
410 * @property nodes
411 * @type Y.Node[]
412 * @public
413 */
414 this.nodes = [];
415
416 /**
417 * Delete the shapes from the drawable.
418 * @protected
419 * @method erase_drawable
420 */
421 this.erase = function() {
422 if (this.shapes) {
423 while (this.shapes.length > 0) {
424 this.editor.graphic.removeShape(this.shapes.pop());
425 }
426 }
427 if (this.nodes) {
428 while (this.nodes.length > 0) {
429 this.nodes.pop().remove();
430 }
431 }
432 };
433
434};
435
436M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
437M.assignfeedback_editpdf.drawable = DRAWABLE;
438// This file is part of Moodle - http://moodle.org/
439//
440// Moodle is free software: you can redistribute it and/or modify
441// it under the terms of the GNU General Public License as published by
442// the Free Software Foundation, either version 3 of the License, or
443// (at your option) any later version.
444//
445// Moodle is distributed in the hope that it will be useful,
446// but WITHOUT ANY WARRANTY; without even the implied warranty of
447// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
448// GNU General Public License for more details.
449//
450// You should have received a copy of the GNU General Public License
451// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
452
453/**
454 * Class representing a list of annotations.
455 *
456 * @module moodle-assignfeedback_editpdf-editor
457 */
458ANNOTATION = function(config) {
459 ANNOTATION.superclass.constructor.apply(this, [config]);
460};
461
462ANNOTATION.NAME = "annotation";
463ANNOTATION.ATTRS = {};
464
465Y.extend(ANNOTATION, Y.Base, {
466 /**
467 * Reference to M.assignfeedback_editpdf.editor.
468 * @property editor
469 * @type M.assignfeedback_editpdf.editor
470 * @public
471 */
472 editor : null,
473
474 /**
475 * Grade id
476 * @property gradeid
477 * @type Int
478 * @public
479 */
480 gradeid : 0,
481
482 /**
483 * Comment page number
484 * @property pageno
485 * @type Int
486 * @public
487 */
488 pageno : 0,
489
490 /**
491 * X position
492 * @property x
493 * @type Int
494 * @public
495 */
496 x : 0,
497
498 /**
499 * Y position
500 * @property y
501 * @type Int
502 * @public
503 */
504 y : 0,
505
506 /**
507 * Ending x position
508 * @property endx
509 * @type Int
510 * @public
511 */
512 endx : 0,
513
514 /**
515 * Ending y position
516 * @property endy
517 * @type Int
518 * @public
519 */
520 endy : 0,
521
522 /**
523 * Path
524 * @property path
525 * @type String - list of points like x1,y1:x2,y2
526 * @public
527 */
528 path : '',
529
530 /**
531 * Tool.
532 * @property type
533 * @type String
534 * @public
535 */
536 type : 'rect',
537
538 /**
539 * Annotation colour.
540 * @property colour
541 * @type String
542 * @public
543 */
544 colour : 'red',
545
546 /**
547 * Reference to M.assignfeedback_editpdf.drawable
548 * @property drawable
549 * @type M.assignfeedback_editpdf.drawable
550 * @public
551 */
552 drawable : false,
553
554 /**
555 * Initialise the annotation.
556 *
557 * @method initializer
558 * @return void
559 */
560 initializer : function(config) {
561 this.editor = config.editor || null;
562 this.gradeid = parseInt(config.gradeid, 10) || 0;
563 this.pageno = parseInt(config.pageno, 10) || 0;
564 this.x = parseInt(config.x, 10) || 0;
565 this.y = parseInt(config.y, 10) || 0;
566 this.endx = parseInt(config.endx, 10) || 0;
567 this.endy = parseInt(config.endy, 10) || 0;
568 this.path = config.path || '';
569 this.type = config.type || 'rect';
570 this.colour = config.colour || 'red';
571 this.drawable = false;
572 },
573
574 /**
575 * Clean a comment record, returning an oject with only fields that are valid.
576 * @public
577 * @method clean
578 * @return {}
579 */
580 clean : function() {
581 return {
582 gradeid : this.gradeid,
583 x : parseInt(this.x, 10),
584 y : parseInt(this.y, 10),
585 endx : parseInt(this.endx, 10),
586 endy : parseInt(this.endy, 10),
587 type : this.type,
588 path : this.path,
589 pageno : this.pageno,
590 colour : this.colour
591 };
592 },
593
594 /**
595 * Draw a selection around this annotation if it is selected.
596 * @public
597 * @method draw_highlight
598 * @return M.assignfeedback_editpdf.drawable
599 */
600 draw_highlight : function() {
601 var bounds,
602 drawingregion = Y.one(SELECTOR.DRAWINGREGION),
603 offsetcanvas = Y.one(SELECTOR.DRAWINGCANVAS).getXY(),
604 shape;
605
606 if (this.editor.currentannotation === this) {
607 // Draw a highlight around the annotation.
608 bounds = new M.assignfeedback_editpdf.rect();
609 bounds.bound([new M.assignfeedback_editpdf.point(this.x, this.y),
610 new M.assignfeedback_editpdf.point(this.endx, this.endy)]);
611
612 shape = this.editor.graphic.addShape({
613 type: Y.Rect,
614 width: bounds.width,
615 height: bounds.height,
616 stroke: {
617 weight: STROKEWEIGHT,
618 color: SELECTEDBORDERCOLOUR
619 },
620 fill: {
621 color: SELECTEDFILLCOLOUR
622 },
623 x: bounds.x,
624 y: bounds.y
625 });
626 this.drawable.shapes.push(shape);
627
628 // Add a delete X to the annotation.
629 var deleteicon = Y.Node.create('<img src="' + M.util.image_url('trash', 'assignfeedback_editpdf') + '"/>'),
630 deletelink = Y.Node.create('<a href="#" role="button"></a>');
631
632 deleteicon.setAttrs({
633 'alt': M.util.get_string('deleteannotation', 'assignfeedback_editpdf')
634 });
635 deleteicon.setStyles({
636 'backgroundColor' : 'white'
637 });
638 deletelink.addClass('deleteannotationbutton');
639 deletelink.append(deleteicon);
640
641 drawingregion.append(deletelink);
642 deletelink.setData('annotation', this);
643 deletelink.setStyle('zIndex', '200');
644
645 deletelink.on('click', this.remove, this);
646 deletelink.on('key', this.remove, 'space,enter', this);
647
648 deletelink.setX(offsetcanvas[0] + bounds.x + bounds.width - 18);
649 deletelink.setY(offsetcanvas[1] + bounds.y + 6);
650 this.drawable.nodes.push(deletelink);
651 }
652 return this.drawable;
653 },
654
655 /**
656 * Draw an annotation
657 * @public
658 * @method draw
659 * @return M.assignfeedback_editpdf.drawable|false
660 */
661 draw : function() {
662 // Should be overridden by the subclass.
663 this.draw_highlight();
664 return this.drawable;
665 },
666
667 /**
668 * Delete an annotation
669 * @protected
670 * @method remove
671 * @param event
672 */
114913e3 673 remove : function(e) {
5c386472
DW
674 var annotations;
675
114913e3
DS
676 e.preventDefault();
677
5c386472
DW
678 annotations = this.editor.pages[this.editor.currentpage].annotations;
679 for (i = 0; i < annotations.length; i++) {
680 if (annotations[i] === this) {
681 annotations.splice(i, 1);
682 if (this.drawable) {
683 this.drawable.erase();
684 }
685 this.editor.currentannotation = false;
686 this.editor.save_current_page();
687 return;
688 }
689 }
690 },
691
692 /**
693 * Move an annotation to a new location.
694 * @public
695 * @param int newx
696 * @param int newy
697 * @method move_annotation
698 */
699 move : function(newx, newy) {
700 var diffx = newx - this.x,
701 diffy = newy - this.y,
702 newpath, oldpath, xy,
703 x, y;
704
705 this.x += diffx;
706 this.y += diffy;
707 this.endx += diffx;
708 this.endy += diffy;
709
710 if (this.path) {
711 newpath = [];
712 oldpath = this.path.split(':');
713 Y.each(oldpath, function(position) {
714 xy = position.split(',');
715 x = parseInt(xy[0], 10);
716 y = parseInt(xy[1], 10);
717 newpath.push((x + diffx) + ',' + (y + diffy));
718 });
719
720 this.path = newpath.join(':');
721
722 }
723 if (this.drawable) {
724 this.drawable.erase();
725 }
726 this.editor.drawables.push(this.draw());
727 },
728
729 /**
730 * Draw the in progress edit.
731 *
732 * @public
733 * @method draw_current_edit
734 * @param M.assignfeedback_editpdf.edit edit
735 */
736 draw_current_edit : function(edit) {
737 var noop = edit && false;
738 // Override me please.
739 return noop;
740 },
741
742 /**
743 * Promote the current edit to a real annotation.
744 *
745 * @public
746 * @method init_from_edit
747 * @param M.assignfeedback_editpdf.edit edit
748 */
749 init_from_edit : function(edit) {
750 var bounds = new M.assignfeedback_editpdf.rect();
751 bounds.bound([edit.start, edit.end]);
752
753 this.gradeid = this.editor.get('gradeid');
754 this.pageno = this.editor.currentpage;
755 this.x = bounds.x;
756 this.y = bounds.y;
757 this.endx = bounds.x + bounds.width;
758 this.endy = bounds.y + bounds.height;
759 this.colour = edit.annotationcolour;
760 this.path = '';
761 }
762
763});
764
765M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
766M.assignfeedback_editpdf.annotation = ANNOTATION;
767// This file is part of Moodle - http://moodle.org/
768//
769// Moodle is free software: you can redistribute it and/or modify
770// it under the terms of the GNU General Public License as published by
771// the Free Software Foundation, either version 3 of the License, or
772// (at your option) any later version.
773//
774// Moodle is distributed in the hope that it will be useful,
775// but WITHOUT ANY WARRANTY; without even the implied warranty of
776// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
777// GNU General Public License for more details.
778//
779// You should have received a copy of the GNU General Public License
780// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
781
782/**
783 * Class representing a line.
784 *
785 * @namespace M.assignfeedback_editpdf
786 * @class annotationline
787 * @extends annotation
788 * @module moodle-assignfeedback_editpdf-editor
789 */
790ANNOTATIONLINE = function(config) {
791 ANNOTATIONLINE.superclass.constructor.apply(this, [config]);
792};
793
794ANNOTATIONLINE.NAME = "annotationline";
795ANNOTATIONLINE.ATTRS = {};
796
797Y.extend(ANNOTATIONLINE, M.assignfeedback_editpdf.annotation, {
798 /**
799 * Draw a line annotation
800 * @protected
801 * @method draw
802 * @return M.assignfeedback_editpdf.drawable
803 */
804 draw : function() {
805 var drawable,
806 shape;
807
808 drawable = new M.assignfeedback_editpdf.drawable(this.editor);
809
810 shape = this.editor.graphic.addShape({
811 type: Y.Path,
812 fill: false,
813 stroke: {
814 weight: STROKEWEIGHT,
815 color: ANNOTATIONCOLOUR[this.colour]
816 }
817 });
818
819 shape.moveTo(this.x, this.y);
820 shape.lineTo(this.endx, this.endy);
821 shape.end();
822 drawable.shapes.push(shape);
823 this.drawable = drawable;
824
825 return ANNOTATIONLINE.superclass.draw.apply(this);
826 },
827
828 /**
829 * Draw the in progress edit.
830 *
831 * @public
832 * @method draw_current_edit
833 * @param M.assignfeedback_editpdf.edit edit
834 */
835 draw_current_edit : function(edit) {
836 var drawable = new M.assignfeedback_editpdf.drawable(this.editor),
837 shape;
838
839 shape = this.editor.graphic.addShape({
840 type: Y.Path,
841 fill: false,
842 stroke: {
843 weight: STROKEWEIGHT,
844 color: ANNOTATIONCOLOUR[edit.annotationcolour]
845 }
846 });
847
848 shape.moveTo(edit.start.x, edit.start.y);
849 shape.lineTo(edit.end.x, edit.end.y);
850 shape.end();
851
852 drawable.shapes.push(shape);
853
854 return drawable;
855 },
856
857 /**
858 * Promote the current edit to a real annotation.
859 *
860 * @public
861 * @method init_from_edit
862 * @param M.assignfeedback_editpdf.edit edit
863 */
864 init_from_edit : function(edit) {
865 this.gradeid = this.editor.get('gradeid');
866 this.pageno = this.editor.currentpage;
867 this.x = edit.start.x;
868 this.y = edit.start.y;
869 this.endx = edit.end.x;
870 this.endy = edit.end.y;
871 this.colour = edit.annotationcolour;
872 this.path = '';
873 }
874
875});
876
877M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
878M.assignfeedback_editpdf.annotationline = ANNOTATIONLINE;
879// This file is part of Moodle - http://moodle.org/
880//
881// Moodle is free software: you can redistribute it and/or modify
882// it under the terms of the GNU General Public License as published by
883// the Free Software Foundation, either version 3 of the License, or
884// (at your option) any later version.
885//
886// Moodle is distributed in the hope that it will be useful,
887// but WITHOUT ANY WARRANTY; without even the implied warranty of
888// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
889// GNU General Public License for more details.
890//
891// You should have received a copy of the GNU General Public License
892// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
893
894/**
895 * Class representing a rectangle.
896 *
897 * @namespace M.assignfeedback_editpdf
898 * @class annotationrectangle
899 * @extends annotation
900 * @module moodle-assignfeedback_editpdf-editor
901 */
902ANNOTATIONRECTANGLE = function(config) {
903 ANNOTATIONRECTANGLE.superclass.constructor.apply(this, [config]);
904};
905
906ANNOTATIONRECTANGLE.NAME = "annotationrectangle";
907ANNOTATIONRECTANGLE.ATTRS = {};
908
909Y.extend(ANNOTATIONRECTANGLE, M.assignfeedback_editpdf.annotation, {
910 /**
911 * Draw a rectangle annotation
912 * @protected
913 * @method draw
914 * @return M.assignfeedback_editpdf.drawable
915 */
916 draw : function() {
917 var drawable,
918 shape;
919
920 drawable = new M.assignfeedback_editpdf.drawable(this.editor);
921
922 bounds = new M.assignfeedback_editpdf.rect();
923 bounds.bound([new M.assignfeedback_editpdf.point(this.x, this.y),
924 new M.assignfeedback_editpdf.point(this.endx, this.endy)]);
925
926 shape = this.editor.graphic.addShape({
927 type: Y.Rect,
928 width: bounds.width,
929 height: bounds.height,
930 stroke: {
931 weight: STROKEWEIGHT,
932 color: ANNOTATIONCOLOUR[this.colour]
933 },
934 x: bounds.x,
935 y: bounds.y
936 });
937 drawable.shapes.push(shape);
938 this.drawable = drawable;
939
940 return ANNOTATIONRECTANGLE.superclass.draw.apply(this);
941 },
942
943 /**
944 * Draw the in progress edit.
945 *
946 * @public
947 * @method draw_current_edit
948 * @param M.assignfeedback_editpdf.edit edit
949 */
950 draw_current_edit : function(edit) {
951 var drawable = new M.assignfeedback_editpdf.drawable(this.editor),
952 shape,
953 bounds;
954
955 bounds = new M.assignfeedback_editpdf.rect();
956 bounds.bound([new M.assignfeedback_editpdf.point(edit.start.x, edit.start.y),
957 new M.assignfeedback_editpdf.point(edit.end.x, edit.end.y)]);
958
959 shape = this.editor.graphic.addShape({
960 type: Y.Rect,
961 width: bounds.width,
962 height: bounds.height,
963 stroke: {
964 weight: STROKEWEIGHT,
965 color: ANNOTATIONCOLOUR[edit.annotationcolour]
966 },
967 x: bounds.x,
968 y: bounds.y
969 });
970
971 drawable.shapes.push(shape);
972
973 return drawable;
974 }
975});
976
977M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
978M.assignfeedback_editpdf.annotationrectangle = ANNOTATIONRECTANGLE;
979// This file is part of Moodle - http://moodle.org/
980//
981// Moodle is free software: you can redistribute it and/or modify
982// it under the terms of the GNU General Public License as published by
983// the Free Software Foundation, either version 3 of the License, or
984// (at your option) any later version.
985//
986// Moodle is distributed in the hope that it will be useful,
987// but WITHOUT ANY WARRANTY; without even the implied warranty of
988// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
989// GNU General Public License for more details.
990//
991// You should have received a copy of the GNU General Public License
992// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
993
994/**
995 * Class representing a oval.
996 *
997 * @namespace M.assignfeedback_editpdf
998 * @class annotationoval
999 * @extends annotation
1000 * @module moodle-assignfeedback_editpdf-editor
1001 */
1002ANNOTATIONOVAL = function(config) {
1003 ANNOTATIONOVAL.superclass.constructor.apply(this, [config]);
1004};
1005
1006ANNOTATIONOVAL.NAME = "annotationoval";
1007ANNOTATIONOVAL.ATTRS = {};
1008
1009Y.extend(ANNOTATIONOVAL, M.assignfeedback_editpdf.annotation, {
1010 /**
1011 * Draw a oval annotation
1012 * @protected
1013 * @method draw
1014 * @return M.assignfeedback_editpdf.drawable
1015 */
1016 draw : function() {
1017 var drawable,
1018 shape;
1019
1020 drawable = new M.assignfeedback_editpdf.drawable(this.editor);
1021
1022 bounds = new M.assignfeedback_editpdf.rect();
1023 bounds.bound([new M.assignfeedback_editpdf.point(this.x, this.y),
1024 new M.assignfeedback_editpdf.point(this.endx, this.endy)]);
1025
1026 shape = this.editor.graphic.addShape({
1027 type: Y.Ellipse,
1028 width: bounds.width,
1029 height: bounds.height,
1030 stroke: {
1031 weight: STROKEWEIGHT,
1032 color: ANNOTATIONCOLOUR[this.colour]
1033 },
1034 x: bounds.x,
1035 y: bounds.y
1036 });
1037 drawable.shapes.push(shape);
1038 this.drawable = drawable;
1039
1040 return ANNOTATIONOVAL.superclass.draw.apply(this);
1041 },
1042
1043 /**
1044 * Draw the in progress edit.
1045 *
1046 * @public
1047 * @method draw_current_edit
1048 * @param M.assignfeedback_editpdf.edit edit
1049 */
1050 draw_current_edit : function(edit) {
1051 var drawable = new M.assignfeedback_editpdf.drawable(this.editor),
1052 shape,
1053 bounds;
1054
1055 bounds = new M.assignfeedback_editpdf.rect();
1056 bounds.bound([new M.assignfeedback_editpdf.point(edit.start.x, edit.start.y),
1057 new M.assignfeedback_editpdf.point(edit.end.x, edit.end.y)]);
1058
1059 shape = this.editor.graphic.addShape({
1060 type: Y.Ellipse,
1061 width: bounds.width,
1062 height: bounds.height,
1063 stroke: {
1064 weight: STROKEWEIGHT,
1065 color: ANNOTATIONCOLOUR[edit.annotationcolour]
1066 },
1067 x: bounds.x,
1068 y: bounds.y
1069 });
1070
1071 drawable.shapes.push(shape);
1072
1073 return drawable;
1074 }
1075});
1076
1077M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
1078M.assignfeedback_editpdf.annotationoval = ANNOTATIONOVAL;
1079// This file is part of Moodle - http://moodle.org/
1080//
1081// Moodle is free software: you can redistribute it and/or modify
1082// it under the terms of the GNU General Public License as published by
1083// the Free Software Foundation, either version 3 of the License, or
1084// (at your option) any later version.
1085//
1086// Moodle is distributed in the hope that it will be useful,
1087// but WITHOUT ANY WARRANTY; without even the implied warranty of
1088// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1089// GNU General Public License for more details.
1090//
1091// You should have received a copy of the GNU General Public License
1092// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
1093
1094/**
1095 * Class representing a pen.
1096 *
1097 * @namespace M.assignfeedback_editpdf
1098 * @class annotationpen
1099 * @extends annotation
1100 * @module moodle-assignfeedback_editpdf-editor
1101 */
1102ANNOTATIONPEN = function(config) {
1103 ANNOTATIONPEN.superclass.constructor.apply(this, [config]);
1104};
1105
1106ANNOTATIONPEN.NAME = "annotationpen";
1107ANNOTATIONPEN.ATTRS = {};
1108
1109Y.extend(ANNOTATIONPEN, M.assignfeedback_editpdf.annotation, {
1110 /**
1111 * Draw a pen annotation
1112 * @protected
1113 * @method draw
1114 * @return M.assignfeedback_editpdf.drawable
1115 */
1116 draw : function() {
1117 var drawable,
1118 shape,
1119 first,
1120 positions,
1121 xy;
1122
1123 drawable = new M.assignfeedback_editpdf.drawable(this.editor);
1124
1125 shape = this.editor.graphic.addShape({
1126 type: Y.Path,
1127 fill: false,
1128 stroke: {
1129 weight: STROKEWEIGHT,
1130 color: ANNOTATIONCOLOUR[this.colour]
1131 }
1132 });
1133
1134 first = true;
1135 // Recreate the pen path array.
1136 positions = this.path.split(':');
1137 // Redraw all the lines.
1138 Y.each(positions, function(position) {
1139 xy = position.split(',');
1140 if (first) {
1141 shape.moveTo(xy[0], xy[1]);
1142 first = false;
1143 } else {
1144 shape.lineTo(xy[0], xy[1]);
1145 }
1146 }, this);
1147
1148 shape.end();
1149
1150 drawable.shapes.push(shape);
1151 this.drawable = drawable;
1152
1153 return ANNOTATIONPEN.superclass.draw.apply(this);
1154 },
1155
1156 /**
1157 * Draw the in progress edit.
1158 *
1159 * @public
1160 * @method draw_current_edit
1161 * @param M.assignfeedback_editpdf.edit edit
1162 */
1163 draw_current_edit : function(edit) {
1164 var drawable = new M.assignfeedback_editpdf.drawable(this.editor),
1165 shape,
1166 first;
1167
1168 shape = this.editor.graphic.addShape({
1169 type: Y.Path,
1170 fill: false,
1171 stroke: {
1172 weight: STROKEWEIGHT,
1173 color: ANNOTATIONCOLOUR[edit.annotationcolour]
1174 }
1175 });
1176
1177 first = true;
1178 // Recreate the pen path array.
1179 // Redraw all the lines.
1180 Y.each(edit.path, function(position) {
1181 if (first) {
1182 shape.moveTo(position.x, position.y);
1183 first = false;
1184 } else {
1185 shape.lineTo(position.x, position.y);
1186 }
1187 }, this);
1188
1189 shape.end();
1190
1191 drawable.shapes.push(shape);
1192
1193 return drawable;
1194 },
1195
1196
1197 /**
1198 * Promote the current edit to a real annotation.
1199 *
1200 * @public
1201 * @method init_from_edit
1202 * @param M.assignfeedback_editpdf.edit edit
1203 */
1204 init_from_edit : function(edit) {
1205 var bounds = new M.assignfeedback_editpdf.rect(),
1206 pathlist = [],
1207 i = 0;
1208
1209 // This will get the boundaries of all points in the path.
1210 bounds.bound(edit.path);
1211
1212 for (i = 0; i < edit.path.length; i++) {
1213 pathlist.push(parseInt(edit.path[i].x, 10) + ',' + parseInt(edit.path[i].y, 10));
1214 }
1215
1216 this.gradeid = this.editor.get('gradeid');
1217 this.pageno = this.editor.currentpage;
1218 this.x = bounds.x;
1219 this.y = bounds.y;
1220 this.endx = bounds.x + bounds.width;
1221 this.endy = bounds.y + bounds.height;
1222 this.colour = edit.annotationcolour;
1223 this.path = pathlist.join(':');
1224 }
1225
1226
1227});
1228
1229M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
1230M.assignfeedback_editpdf.annotationpen = ANNOTATIONPEN;
1231// This file is part of Moodle - http://moodle.org/
1232//
1233// Moodle is free software: you can redistribute it and/or modify
1234// it under the terms of the GNU General Public License as published by
1235// the Free Software Foundation, either version 3 of the License, or
1236// (at your option) any later version.
1237//
1238// Moodle is distributed in the hope that it will be useful,
1239// but WITHOUT ANY WARRANTY; without even the implied warranty of
1240// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1241// GNU General Public License for more details.
1242//
1243// You should have received a copy of the GNU General Public License
1244// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
1245
1246/**
1247 * Class representing a highlight.
1248 *
1249 * @namespace M.assignfeedback_editpdf
1250 * @class annotationhighlight
1251 * @extends annotation
1252 * @module moodle-assignfeedback_editpdf-editor
1253 */
1254ANNOTATIONHIGHLIGHT = function(config) {
1255 ANNOTATIONHIGHLIGHT.superclass.constructor.apply(this, [config]);
1256};
1257
1258ANNOTATIONHIGHLIGHT.NAME = "annotationhighlight";
1259ANNOTATIONHIGHLIGHT.ATTRS = {};
1260
1261Y.extend(ANNOTATIONHIGHLIGHT, M.assignfeedback_editpdf.annotation, {
1262 /**
1263 * Draw a highlight annotation
1264 * @protected
1265 * @method draw
1266 * @return M.assignfeedback_editpdf.drawable
1267 */
1268 draw : function() {
1269 var drawable,
1270 shape,
1271 bounds,
1272 highlightcolour;
1273
1274 drawable = new M.assignfeedback_editpdf.drawable(this.editor);
1275 bounds = new M.assignfeedback_editpdf.rect();
1276 bounds.bound([new M.assignfeedback_editpdf.point(this.x, this.y),
1277 new M.assignfeedback_editpdf.point(this.endx, this.endy)]);
1278
1279 highlightcolour = ANNOTATIONCOLOUR[this.colour];
1280
1281 // Add an alpha channel to the rgb colour.
1282
1283 highlightcolour = highlightcolour.replace('rgb', 'rgba');
1284 highlightcolour = highlightcolour.replace(')', ',0.5)');
1285
1286 shape = this.editor.graphic.addShape({
1287 type: Y.Rect,
1288 width: bounds.width,
1289 height: bounds.height,
1290 stroke: false,
1291 fill: {
1292 color: highlightcolour
1293 },
1294 x: bounds.x,
1295 y: bounds.y
1296 });
1297
1298 drawable.shapes.push(shape);
1299 this.drawable = drawable;
1300
1301 return ANNOTATIONHIGHLIGHT.superclass.draw.apply(this);
1302 },
1303
1304 /**
1305 * Draw the in progress edit.
1306 *
1307 * @public
1308 * @method draw_current_edit
1309 * @param M.assignfeedback_editpdf.edit edit
1310 */
1311 draw_current_edit : function(edit) {
1312 var drawable = new M.assignfeedback_editpdf.drawable(this.editor),
1313 shape,
1314 bounds,
1315 highlightcolour;
1316
1317 bounds = new M.assignfeedback_editpdf.rect();
1318 bounds.bound([new M.assignfeedback_editpdf.point(edit.start.x, edit.start.y),
1319 new M.assignfeedback_editpdf.point(edit.end.x, edit.end.y)]);
1320
1321 highlightcolour = ANNOTATIONCOLOUR[edit.annotationcolour];
1322 // Add an alpha channel to the rgb colour.
1323
1324 highlightcolour = highlightcolour.replace('rgb', 'rgba');
1325 highlightcolour = highlightcolour.replace(')', ',0.5)');
1326
1327 // We will draw a box with the current background colour.
1328 shape = this.editor.graphic.addShape({
1329 type: Y.Rect,
1330 width: bounds.width,
1331 height: 16,
1332 stroke: false,
1333 fill: {
1334 color: highlightcolour
1335 },
1336 x: bounds.x,
1337 y: edit.start.y
1338 });
1339
1340 drawable.shapes.push(shape);
1341
1342 return drawable;
1343 },
1344
1345 /**
1346 * Promote the current edit to a real annotation.
1347 *
1348 * @public
1349 * @method init_from_edit
1350 * @param M.assignfeedback_editpdf.edit edit
1351 */
1352 init_from_edit : function(edit) {
1353 var bounds = new M.assignfeedback_editpdf.rect();
1354 bounds.bound([edit.start, edit.end]);
1355
1356 this.gradeid = this.editor.get('gradeid');
1357 this.pageno = this.editor.currentpage;
1358 this.x = bounds.x;
1359 this.y = edit.start.y;
1360 this.endx = bounds.x + bounds.width;
1361 this.endy = edit.start.y + 16;
1362 this.colour = edit.annotationcolour;
1363 this.page = '';
1364 }
1365
1366});
1367
1368M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
1369M.assignfeedback_editpdf.annotationhighlight = ANNOTATIONHIGHLIGHT;
1370// This file is part of Moodle - http://moodle.org/
1371//
1372// Moodle is free software: you can redistribute it and/or modify
1373// it under the terms of the GNU General Public License as published by
1374// the Free Software Foundation, either version 3 of the License, or
1375// (at your option) any later version.
1376//
1377// Moodle is distributed in the hope that it will be useful,
1378// but WITHOUT ANY WARRANTY; without even the implied warranty of
1379// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1380// GNU General Public License for more details.
1381//
1382// You should have received a copy of the GNU General Public License
1383// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
1384
1385/**
1386 * Class representing a stamp.
1387 *
1388 * @namespace M.assignfeedback_editpdf
1389 * @class annotationstamp
1390 * @extends annotation
1391 * @module moodle-assignfeedback_editpdf-editor
1392 */
1393ANNOTATIONSTAMP = function(config) {
1394 ANNOTATIONSTAMP.superclass.constructor.apply(this, [config]);
1395};
1396
1397ANNOTATIONSTAMP.NAME = "annotationstamp";
1398ANNOTATIONSTAMP.ATTRS = {};
1399
1400Y.extend(ANNOTATIONSTAMP, M.assignfeedback_editpdf.annotation, {
1401 /**
1402 * Draw a stamp annotation
1403 * @protected
1404 * @method draw
1405 * @return M.assignfeedback_editpdf.drawable
1406 */
1407 draw : function() {
1408 var drawable = new M.assignfeedback_editpdf.drawable(this.editor),
1409 drawingregion = Y.one(SELECTOR.DRAWINGREGION),
1410 node,
1411 position;
1412
1413 position = this.editor.get_window_coordinates(new M.assignfeedback_editpdf.point(this.x, this.y));
1414 node = Y.Node.create('<div/>');
1415 node.setStyles({
d79d1bd8 1416 'position': 'absolute',
5c386472
DW
1417 'display': 'inline-block',
1418 'backgroundImage': 'url(' + this.editor.get_stamp_image_url(this.path) + ')',
1419 'width': (this.endx - this.x),
1420 'height': (this.endy - this.y),
1421 'backgroundSize': '100% 100%',
1422 'zIndex': 50
1423 });
1424
1425 drawingregion.append(node);
1426 node.setX(position.x);
1427 node.setY(position.y);
1428
1429 // Pass throught the event handlers on the div.
1430 node.on('gesturemovestart', this.editor.edit_start, null, this.editor);
1431 node.on('gesturemove', this.editor.edit_move, null, this.editor);
1432 node.on('gesturemoveend', this.editor.edit_end, null, this.editor);
1433
1434 drawable.nodes.push(node);
1435
1436 this.drawable = drawable;
1437 return ANNOTATIONSTAMP.superclass.draw.apply(this);
1438 },
1439
1440 /**
1441 * Draw the in progress edit.
1442 *
1443 * @public
1444 * @method draw_current_edit
1445 * @param M.assignfeedback_editpdf.edit edit
1446 */
1447 draw_current_edit : function(edit) {
1448 var bounds = new M.assignfeedback_editpdf.rect(),
1449 drawable = new M.assignfeedback_editpdf.drawable(this.editor),
1450 drawingregion = Y.one(SELECTOR.DRAWINGREGION),
1451 node,
1452 position;
1453
1454 bounds.bound([edit.start, edit.end]);
1455 position = this.editor.get_window_coordinates(new M.assignfeedback_editpdf.point(bounds.x, bounds.y));
1456
1457 node = Y.Node.create('<div/>');
1458 node.setStyles({
d79d1bd8 1459 'position': 'absolute',
5c386472
DW
1460 'display': 'inline-block',
1461 'backgroundImage': 'url(' + this.editor.get_stamp_image_url(edit.stamp) + ')',
1462 'width': bounds.width,
1463 'height': bounds.height,
1464 'backgroundSize': '100% 100%',
1465 'zIndex': 50
1466 });
1467
1468 drawingregion.append(node);
1469 node.setX(position.x);
1470 node.setY(position.y);
1471
1472 drawable.nodes.push(node);
1473
1474 return drawable;
1475 },
1476
1477 /**
1478 * Promote the current edit to a real annotation.
1479 *
1480 * @public
1481 * @method init_from_edit
1482 * @param M.assignfeedback_editpdf.edit edit
1483 */
1484 init_from_edit : function(edit) {
1485 var bounds = new M.assignfeedback_editpdf.rect();
1486 bounds.bound([edit.start, edit.end]);
1487
1488 if (bounds.width < 40) {
1489 bounds.width = 40;
1490 }
1491 if (bounds.height < 40) {
1492 bounds.height = 40;
1493 }
1494 this.gradeid = this.editor.get('gradeid');
1495 this.pageno = this.editor.currentpage;
1496 this.x = bounds.x;
1497 this.y = bounds.y;
1498 this.endx = bounds.x + bounds.width;
1499 this.endy = bounds.y + bounds.height;
1500 this.colour = edit.annotationcolour;
1501 this.path = edit.stamp;
1502 },
1503
1504 /**
1505 * Move an annotation to a new location.
1506 * @public
1507 * @param int newx
1508 * @param int newy
1509 * @method move_annotation
1510 */
1511 move : function(newx, newy) {
1512 var diffx = newx - this.x,
1513 diffy = newy - this.y;
1514
1515 this.x += diffx;
1516 this.y += diffy;
1517 this.endx += diffx;
1518 this.endy += diffy;
1519
1520 if (this.drawable) {
1521 this.drawable.erase();
1522 }
1523 this.editor.drawables.push(this.draw());
1524 }
1525
1526});
1527
1528M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
1529M.assignfeedback_editpdf.annotationstamp = ANNOTATIONSTAMP;
1530var DROPDOWN_NAME = "Dropdown menu",
1531 DROPDOWN;
1532
1533/**
1534 * DROPDOWN
1535 * This is a drop down list of buttons triggered (and aligned to) a button.
1536 *
1537 * @namespace M.assignfeedback_editpdf.widget.dropdown
1538 * @class dropdown
1539 * @constructor
1540 * @extends Y.Base
1541 */
1542DROPDOWN = function(config) {
1543 config.draggable = false;
1544 config.centered = false;
1545 config.width = 'auto';
1546 config.lightbox = false;
1547 config.visible = false;
1548 config.zIndex = 100;
1549 config.footerContent = '';
1550 DROPDOWN.superclass.constructor.apply(this, [config]);
1551};
1552
1553Y.extend(DROPDOWN, M.core.dialogue, {
1554 /**
1555 * Initialise the menu.
1556 *
1557 * @method initializer
1558 * @return void
1559 */
1560 initializer : function(config) {
1561 var button, body, headertext, bb;
1562 DROPDOWN.superclass.initializer.call(this, config);
1563
1564 bb = this.get('boundingBox');
1565 bb.addClass('assignfeedback_editpdf_dropdown');
1566
1567 // Align the menu to the button that opens it.
1568 button = this.get('buttonNode');
1569
1570 // Close the menu when clicked outside (excluding the button that opened the menu).
1571 body = this.bodyNode;
1572
1573 headertext = Y.Node.create('<h3/>');
1574 headertext.addClass('accesshide');
1575 headertext.setHTML(this.get('headerText'));
1576 body.prepend(headertext);
1577
1578 body.on('clickoutside', function(e) {
1579 if (this.get('visible')) {
1580 if (e.target !== button && e.target.ancestor() !== button) {
1581 e.preventDefault();
1582 this.hide();
1583 }
1584 }
1585 }, this);
1586
114913e3 1587 button.on('click', function(e) {e.preventDefault(); this.show();}, this);
5c386472
DW
1588 button.on('key', this.show, 'enter,space', this);
1589 },
1590
1591 /**
1592 * Override the show method to align to the button.
1593 *
1594 * @method show
1595 * @return void
1596 */
1597 show : function() {
1598 var button = this.get('buttonNode');
1599
1600 result = DROPDOWN.superclass.show.call(this);
1601 this.align(button, [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.BL]);
1602 }
1603}, {
1604 NAME : DROPDOWN_NAME,
1605 ATTRS : {
1606 /**
1607 * The header for the drop down (only accessible to screen readers).
1608 *
1609 * @attribute headerText
1610 * @type String
1611 * @default ''
1612 */
1613 headerText : {
1614 value : ''
1615 },
1616
1617 /**
1618 * The button used to show/hide this drop down menu.
1619 *
1620 * @attribute buttonNode
1621 * @type Y.Node
1622 * @default null
1623 */
1624 buttonNode : {
1625 value : null
1626 }
1627 }
1628});
1629
1630M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
1631M.assignfeedback_editpdf.dropdown = DROPDOWN;
1632var COLOURPICKER_NAME = "Colourpicker",
1633 COLOURPICKER;
1634
1635/**
1636 * COLOURPICKER
1637 * This is a drop down list of colours.
1638 *
1639 * @namespace M.assignfeedback_editpdf.colourpicker
1640 * @class dropdown
1641 * @constructor
1642 * @extends Y.Base
1643 */
1644COLOURPICKER = function(config) {
1645 COLOURPICKER.superclass.constructor.apply(this, [config]);
1646};
1647
1648Y.extend(COLOURPICKER, M.assignfeedback_editpdf.dropdown, {
1649
1650 /**
1651 * Initialise the menu.
1652 *
1653 * @method initializer
1654 * @return void
1655 */
1656 initializer : function(config) {
1657 var colourlist = Y.Node.create('<ul role="menu" class="assignfeedback_editpdf_menu"/>'),
1658 body;
1659
1660 // Build a list of coloured buttons.
1661 Y.each(this.get('colours'), function(rgb, colour) {
1662 var button, listitem, title, img, iconname;
1663
1664 title = M.util.get_string(colour, 'assignfeedback_editpdf');
1665 iconname = this.get('iconprefix') + colour;
1666 img = M.util.image_url(iconname, 'assignfeedback_editpdf');
1667 button = Y.Node.create('<button><img alt="' + title + '" src="' + img + '"/></button>');
1668 button.setAttribute('data-colour', colour);
1669 button.setAttribute('data-rgb', rgb);
1670 button.setStyle('backgroundImage', 'none');
1671 listitem = Y.Node.create('<li/>');
1672 listitem.append(button);
1673 colourlist.append(listitem);
1674 }, this);
1675
1676 body = Y.Node.create('<div/>');
1677
1678 // Set the call back.
1679 colourlist.delegate('click', this.callback_handler, 'button', this);
1680 colourlist.delegate('key', this.callback_handler, 'down:13', 'button', this);
1681
1682 // Set the accessible header text.
1683 this.set('headerText', M.util.get_string('colourpicker', 'assignfeedback_editpdf'));
1684
1685 // Set the body content.
1686 body.append(colourlist);
1687 this.set('bodyContent', body);
1688
1689 COLOURPICKER.superclass.initializer.call(this, config);
1690 },
1691 callback_handler : function(e) {
114913e3
DS
1692 e.preventDefault();
1693
5c386472
DW
1694 var callback = this.get('callback'),
1695 callbackcontext = this.get('context'),
1696 bind;
1697
1698 this.hide();
1699
1700 // Call the callback with the specified context.
1701 bind = Y.bind(callback, callbackcontext, e);
1702
1703 bind();
1704 }
1705}, {
1706 NAME : COLOURPICKER_NAME,
1707 ATTRS : {
1708 /**
1709 * The list of colours this colour picker supports.
1710 *
1711 * @attribute colours
1712 * @type {String: String} (The keys of the array are the colour names and the values are localized strings)
1713 * @default {}
1714 */
1715 colours : {
1716 value : {}
1717 },
1718
1719 /**
1720 * The function called when a new colour is chosen.
1721 *
1722 * @attribute callback
1723 * @type function
1724 * @default null
1725 */
1726 callback : {
1727 value : null
1728 },
1729
1730 /**
1731 * The context passed to the callback when a colour is chosen.
1732 *
1733 * @attribute context
1734 * @type Y.Node
1735 * @default null
1736 */
1737 context : {
1738 value : null
1739 },
1740
1741 /**
1742 * The prefix for the icon image names.
1743 *
1744 * @attribute iconprefix
1745 * @type String
1746 * @default 'colour_'
1747 */
1748 iconprefix : {
1749 value : 'colour_'
1750 }
1751 }
1752});
1753
1754M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
1755M.assignfeedback_editpdf.colourpicker = COLOURPICKER;
1756var STAMPPICKER_NAME = "Colourpicker",
1757 STAMPPICKER;
1758
1759/**
1760 * STAMPPICKER
1761 * This is a drop down list of stamps.
1762 *
1763 * @namespace M.assignfeedback_editpdf.stamppicker
1764 * @class dropdown
1765 * @constructor
1766 * @extends Y.Base
1767 */
1768STAMPPICKER = function(config) {
1769 STAMPPICKER.superclass.constructor.apply(this, [config]);
1770};
1771
1772Y.extend(STAMPPICKER, M.assignfeedback_editpdf.dropdown, {
1773
1774 /**
1775 * Initialise the menu.
1776 *
1777 * @method initializer
1778 * @return void
1779 */
1780 initializer : function(config) {
1781 var stamplist = Y.Node.create('<ul role="menu" class="assignfeedback_editpdf_menu"/>');
1782
1783 // Build a list of stamped buttons.
1784 Y.each(this.get('stamps'), function(stamp) {
1785 var button, listitem, title;
1786
1787 title = M.util.get_string('stamp', 'assignfeedback_editpdf');
1788 button = Y.Node.create('<button><img height="40" alt="' + title + '" src="' + stamp + '"/></button>');
1789 button.setAttribute('data-stamp', stamp);
1790 button.setStyle('backgroundImage', 'none');
1791 listitem = Y.Node.create('<li/>');
1792 listitem.append(button);
1793 stamplist.append(listitem);
1794 }, this);
1795
1796
1797 // Set the call back.
1798 stamplist.delegate('click', this.callback_handler, 'button', this);
1799 stamplist.delegate('key', this.callback_handler, 'down:13', 'button', this);
1800
1801 // Set the accessible header text.
1802 this.set('headerText', M.util.get_string('stamppicker', 'assignfeedback_editpdf'));
1803
1804 // Set the body content.
1805 this.set('bodyContent', stamplist);
1806
1807 STAMPPICKER.superclass.initializer.call(this, config);
1808 },
1809 callback_handler : function(e) {
114913e3 1810 e.preventDefault();
5c386472
DW
1811 var callback = this.get('callback'),
1812 callbackcontext = this.get('context'),
1813 bind;
1814
1815 this.hide();
1816
1817 // Call the callback with the specified context.
1818 bind = Y.bind(callback, callbackcontext, e);
1819
1820 bind();
1821 }
1822}, {
1823 NAME : STAMPPICKER_NAME,
1824 ATTRS : {
1825 /**
1826 * The list of stamps this stamp picker supports.
1827 *
1828 * @attribute stamps
1829 * @type String[] - the stamp filenames.
1830 * @default {}
1831 */
1832 stamps : {
1833 value : []
1834 },
1835
1836 /**
1837 * The function called when a new stamp is chosen.
1838 *
1839 * @attribute callback
1840 * @type function
1841 * @default null
1842 */
1843 callback : {
1844 value : null
1845 },
1846
1847 /**
1848 * The context passed to the callback when a stamp is chosen.
1849 *
1850 * @attribute context
1851 * @type Y.Node
1852 * @default null
1853 */
1854 context : {
1855 value : null
1856 }
1857 }
1858});
1859
1860M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
1861M.assignfeedback_editpdf.stamppicker = STAMPPICKER;
1862var COMMENTMENUNAME = "Commentmenu",
1863 COMMENTMENU;
1864
1865/**
1866 * COMMENTMENU
1867 * This is a drop down list of comment context functions.
1868 *
1869 * @namespace M.assignfeedback_editpdf.editor
1870 * @class commentmenu
1871 * @constructor
1872 * @extends Y.Base
1873 */
1874COMMENTMENU = function(config) {
1875 COMMENTMENU.superclass.constructor.apply(this, [config]);
1876};
1877
1878Y.extend(COMMENTMENU, M.assignfeedback_editpdf.dropdown, {
1879
1880 /**
1881 * Initialise the menu.
1882 *
1883 * @method initializer
1884 * @return void
1885 */
1886 initializer : function(config) {
1887 var commentlinks,
1888 link,
1889 body,
1890 comment;
1891
1892 comment = this.get('comment');
1893 // Build the list of menu items.
1894 commentlinks = Y.Node.create('<ul role="menu" class="assignfeedback_editpdf_menu"/>');
1895
1896 link = Y.Node.create('<li><a tabindex="-1" href="#">' + M.util.get_string('addtoquicklist', 'assignfeedback_editpdf') + '</a></li>');
1897 link.on('click', comment.add_to_quicklist, comment);
1898 link.on('key', comment.add_to_quicklist, 'enter,space', comment);
1899
1900 commentlinks.append(link);
1901
1902 link = Y.Node.create('<li><a tabindex="-1" href="#">' + M.util.get_string('deletecomment', 'assignfeedback_editpdf') + '</a></li>');
114913e3 1903 link.on('click', function(e) { e.preventDefault(); this.menu.hide(); this.remove(); }, comment);
5c386472
DW
1904 link.on('key', function() { comment.menu.hide(); comment.remove(); }, 'enter,space', comment);
1905
1906 commentlinks.append(link);
1907
1908 link = Y.Node.create('<li><hr/></li>');
1909 commentlinks.append(link);
1910
1911 // Set the accessible header text.
1912 this.set('headerText', M.util.get_string('commentcontextmenu', 'assignfeedback_editpdf'));
1913
1914 body = Y.Node.create('<div/>');
1915
1916 // Set the body content.
1917 body.append(commentlinks);
1918 this.set('bodyContent', body);
1919
1920 COMMENTMENU.superclass.initializer.call(this, config);
1921 },
1922
1923 /**
1924 * Show the menu.
1925 *
1926 * @method show
1927 * @return void
1928 */
1929 show : function() {
1930 var commentlinks = this.get('boundingBox').one('ul');
1931 commentlinks.all('.quicklist_comment').remove(true),
1932 comment = this.get('comment');
1933
6e67d80d
DS
1934 comment.deleteme = false; // Cancel the deleting of blank comments.
1935
5c386472
DW
1936 // Now build the list of quicklist comments.
1937 Y.each(comment.editor.quicklist.comments, function(quickcomment) {
1938 var listitem = Y.Node.create('<li class="quicklist_comment"></li>'),
1939 linkitem = Y.Node.create('<a href="#" tabindex="-1">' + quickcomment.rawtext + '</a>'),
1940 deletelinkitem = Y.Node.create('<a href="#" tabindex="-1" class="delete_quicklist_comment">' +
1941 '<img src="' + M.util.image_url('t/delete', 'core') + '" ' +
1942 'alt="' + M.util.get_string('deletecomment', 'assignfeedback_editpdf') + '"/>' +
1943 '</a>');
1944 listitem.append(linkitem);
1945 listitem.append(deletelinkitem);
1946
1947 commentlinks.append(listitem);
1948
1949 linkitem.on('click', comment.set_from_quick_comment, comment, quickcomment);
1950 linkitem.on('key', comment.set_from_quick_comment, 'space,enter', comment, quickcomment);
1951
1952 deletelinkitem.on('click', comment.remove_from_quicklist, comment, quickcomment);
1953 deletelinkitem.on('key', comment.remove_from_quicklist, 'space,enter', comment, quickcomment);
1954 }, this);
1955
1956 COMMENTMENU.superclass.show.call(this);
1957 }
1958}, {
1959 NAME : COMMENTMENUNAME,
1960 ATTRS : {
1961 /**
1962 * The comment this menu is attached to.
1963 *
1964 * @attribute comment
1965 * @type M.assignfeedback_editpdf.comment
1966 * @default null
1967 */
1968 comment : {
1969 value : null
1970 }
1971
1972 }
1973});
1974
1975M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
1976M.assignfeedback_editpdf.commentmenu = COMMENTMENU;
1977var COMMENTSEARCHNAME = "commentsearch",
1978 COMMENTSEARCH;
1979
1980/**
1981 * COMMENTSEARCH
1982 * This is a searchable dialogue of comments.
1983 *
1984 * @namespace M.assignfeedback_editpdf.editor
1985 * @class commentsearch
1986 * @constructor
1987 * @extends Y.Base
1988 */
1989COMMENTSEARCH = function(config) {
1990 config.draggable = false;
1991 config.centered = true;
1992 config.width = '400px';
1993 config.lightbox = true;
1994 config.visible = false;
1995 config.headerContent = M.util.get_string('searchcomments', 'assignfeedback_editpdf');
1996 config.zIndex = 100;
1997 config.footerContent = '';
1998 COMMENTSEARCH.superclass.constructor.apply(this, [config]);
1999};
2000
2001Y.extend(COMMENTSEARCH, M.core.dialogue, {
2002 /**
2003 * Initialise the menu.
2004 *
2005 * @method initializer
2006 * @return void
2007 */
2008 initializer : function(config) {
2009 var editor,
2010 container,
2011 placeholder,
2012 commentfilter,
2013 commentlist,
2014 bb;
2015
2016 bb = this.get('boundingBox');
2017 bb.addClass('assignfeedback_editpdf_commentsearch');
2018
2019 editor = this.get('editor');
2020 container = Y.Node.create('<div/>');
2021
2022 placeholder = M.util.get_string('filter', 'assignfeedback_editpdf');
2023 commentfilter = Y.Node.create('<input type="text" size="20" placeholder="' + placeholder + '"/>');
2024 container.append(commentfilter);
2025 commentlist = Y.Node.create('<ul role="menu" class="assignfeedback_editpdf_menu"/>');
2026 container.append(commentlist);
2027
2028 commentfilter.on('keyup', this.filter_search_comments, null, this);
2029 commentlist.delegate('click', this.focus_on_comment, 'a', this);
2030 commentlist.delegate('key', this.focus_on_comment, 'enter,space', 'a', this);
2031
2032 // Set the body content.
2033 this.set('bodyContent', container);
2034
2035 COMMENTSEARCH.superclass.initializer.call(this, config);
2036 },
2037
2038 /**
2039 * Event handler to filter the list of comments.
2040 *
2041 * @protected
2042 * @method filter_search_comments
2043 */
2044 filter_search_comments : function() {
2045 var filternode,
2046 commentslist,
2047 filtertext;
2048
2049 filternode = Y.one(SELECTOR.SEARCHFILTER);
2050 commentslist = Y.one(SELECTOR.SEARCHCOMMENTSLIST);
2051
2052 filtertext = filternode.get('value');
2053
2054 commentslist.all('li').each(function (node) {
2055 if (node.get('text').indexOf(filtertext) !== -1) {
2056 node.show();
2057 } else {
2058 node.hide();
2059 }
2060 });
2061 },
2062
2063 /**
2064 * Event handler to focus on a selected comment.
2065 *
2066 * @param Event e
2067 * @protected
2068 * @method focus_on_comment
2069 */
2070 focus_on_comment : function(e) {
114913e3 2071 e.preventDefault();
5c386472
DW
2072 var target = e.target.ancestor('li'),
2073 comment = target.getData('comment'),
2074 editor = this.get('editor');
2075
2076 this.hide();
2077
2078 if (comment.pageno === editor.currentpage) {
2079 comment.drawable.nodes[0].one('textarea').focus();
2080 } else {
2081 // Comment is on a different page.
2082 editor.currentpage = comment.pageno;
2083 editor.change_page();
2084 comment.drawable.nodes[0].one('textarea').focus();
2085 }
2086 },
2087
2088 /**
2089 * Show the menu.
2090 *
2091 * @method show
2092 * @return void
2093 */
2094 show : function() {
2095 var commentlist = this.get('boundingBox').one('ul'),
2096 editor = this.get('editor');
2097
2098 commentlist.all('li').remove(true);
2099
2100 // Rebuild the latest list of comments.
2101 Y.each(editor.pages, function(page) {
2102 Y.each(page.comments, function(comment) {
2103 var commentnode = Y.Node.create('<li><a href="#" tabindex="-1"><pre>' + comment.rawtext + '</pre></a></li>');
2104 commentlist.append(commentnode);
2105 commentnode.setData('comment', comment);
2106 }, this);
2107 }, this);
2108
2109 this.centerDialogue();
2110 COMMENTSEARCH.superclass.show.call(this);
2111 }
2112}, {
2113 NAME : COMMENTSEARCHNAME,
2114 ATTRS : {
2115 /**
2116 * The editor this search window is attached to.
2117 *
2118 * @attribute editor
2119 * @type M.assignfeedback_editpdf.editor
2120 * @default null
2121 */
2122 editor : {
2123 value : null
2124 }
2125
2126 }
2127});
2128
2129M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
2130M.assignfeedback_editpdf.commentsearch = COMMENTSEARCH;
2131// This file is part of Moodle - http://moodle.org/
2132//
2133// Moodle is free software: you can redistribute it and/or modify
2134// it under the terms of the GNU General Public License as published by
2135// the Free Software Foundation, either version 3 of the License, or
2136// (at your option) any later version.
2137//
2138// Moodle is distributed in the hope that it will be useful,
2139// but WITHOUT ANY WARRANTY; without even the implied warranty of
2140// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2141// GNU General Public License for more details.
2142//
2143// You should have received a copy of the GNU General Public License
2144// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
2145
2146/**
2147 * Class representing a list of comments.
2148 *
2149 * @module moodle-assignfeedback_editpdf-editor
2150 */
2151
2152/**
2153 * COMMENT
2154 *
2155 * @namespace M.assignfeedback_editpdf
2156 * @class comment
2157 * @param M.assignfeedback_editpdf.editor editor
2158 * @param Int gradeid
2159 * @param Int pageno
2160 * @param Int x
2161 * @param Int y
2162 * @param Int width
2163 * @param String colour
2164 * @param String rawtext
2165 */
2166COMMENT = function(editor, gradeid, pageno, x, y, width, colour, rawtext) {
2167
2168 /**
2169 * Reference to M.assignfeedback_editpdf.editor.
2170 * @property editor
2171 * @type M.assignfeedback_editpdf.editor
2172 * @public
2173 */
2174 this.editor = editor;
2175
2176 /**
2177 * Grade id
2178 * @property gradeid
2179 * @type Int
2180 * @public
2181 */
2182 this.gradeid = gradeid || 0;
2183
2184 /**
2185 * X position
2186 * @property x
2187 * @type Int
2188 * @public
2189 */
2190 this.x = parseInt(x, 10) || 0;
2191
2192 /**
2193 * Y position
2194 * @property y
2195 * @type Int
2196 * @public
2197 */
2198 this.y = parseInt(y, 10) || 0;
2199
2200 /**
2201 * Comment width
2202 * @property width
2203 * @type Int
2204 * @public
2205 */
2206 this.width = parseInt(width, 10) || 0;
2207
2208 /**
2209 * Comment rawtext
2210 * @property rawtext
2211 * @type String
2212 * @public
2213 */
2214 this.rawtext = rawtext || '';
2215
2216 /**
2217 * Comment page number
2218 * @property pageno
2219 * @type Int
2220 * @public
2221 */
2222 this.pageno = pageno || 0;
2223
2224 /**
2225 * Comment background colour.
2226 * @property colour
2227 * @type String
2228 * @public
2229 */
2230 this.colour = colour || 'yellow';
2231
2232 /**
2233 * Reference to M.assignfeedback_editpdf.drawable
2234 * @property drawable
2235 * @type M.assignfeedback_editpdf.drawable
2236 * @public
2237 */
2238 this.drawable = false;
2239
2240 /**
2241 * Boolean used by a timeout to delete empty comments after a short delay.
2242 * @property deleteme
2243 * @type Boolean
2244 * @public
2245 */
2246 this.deleteme = false;
2247
2248 /**
2249 * Reference to the link that opens the menu.
2250 * @property menulink
2251 * @type Y.Node
2252 * @public
2253 */
2254 this.menulink = null;
2255
2256 /**
2257 * Reference to the dialogue that is the context menu.
2258 * @property menu
2259 * @type M.assignfeedback_editpdf.dropdown
2260 * @public
2261 */
2262 this.menu = null;
2263
2264 /**
2265 * Clean a comment record, returning an oject with only fields that are valid.
2266 * @public
2267 * @method clean
2268 * @return {}
2269 */
2270 this.clean = function() {
2271 return {
2272 gradeid : this.gradeid,
2273 x : parseInt(this.x, 10),
2274 y : parseInt(this.y, 10),
2275 width : parseInt(this.width, 10),
2276 rawtext : this.rawtext,
2277 pageno : this.currentpage,
2278 colour : this.colour
2279 };
2280 };
2281
2282 /**
2283 * Draw a comment.
2284 * @public
2285 * @method draw_comment
2286 * @param boolean focus - Set the keyboard focus to the new comment if true
2287 * @return M.assignfeedback_editpdf.drawable
2288 */
2289 this.draw = function(focus) {
2290 var drawable = new M.assignfeedback_editpdf.drawable(this.editor),
2291 node,
2292 drawingregion = Y.one(SELECTOR.DRAWINGREGION),
2293 container,
2294 menu,
2295 position,
2296 scrollheight;
2297
2298 // Lets add a contenteditable div.
2299 node = Y.Node.create('<textarea/>');
2300 container = Y.Node.create('<div class="commentdrawable"/>');
2301 menu = Y.Node.create('<a href="#"><img src="' + M.util.image_url('t/contextmenu', 'core') + '"/></a>');
2302
2303 this.menulink = menu;
2304 container.append(node);
2305
2306 if (!this.editor.get('readonly')) {
2307 container.append(menu);
2308 } else {
2309 node.setAttribute('readonly', 'readonly');
2310 }
2311 if (this.width < 100) {
2312 this.width = 100;
2313 }
2314
2315 position = this.editor.get_window_coordinates(new M.assignfeedback_editpdf.point(this.x, this.y));
2316 node.setStyles({
2317 width: this.width + 'px',
1d38083c
DW
2318 backgroundColor: COMMENTCOLOUR[this.colour],
2319 color: COMMENTTEXTCOLOUR
5c386472
DW
2320 });
2321
2322 drawingregion.append(container);
d79d1bd8 2323 container.setStyle('position', 'absolute');
5c386472
DW
2324 container.setX(position.x);
2325 container.setY(position.y);
2326 drawable.nodes.push(container);
2327 node.set('value', this.rawtext);
2328 scrollheight = node.get('scrollHeight'),
2329 node.setStyles({
2330 'height' : scrollheight + 'px',
2331 'overflow': 'hidden'
2332 });
2333 if (!this.editor.get('readonly')) {
2334 this.attach_events(node, menu);
2335 }
2336 if (focus) {
2337 node.focus();
2338 }
2339 this.drawable = drawable;
2340
2341
2342 return drawable;
2343 };
2344
2345 /**
2346 * Delete an empty comment if it's menu hasn't been opened in time.
2347 * @method delete_comment_later
2348 */
2349 this.delete_comment_later = function() {
2350 if (this.deleteme) {
2351 this.remove();
2352 }
2353 };
2354
2355 /**
2356 * Comment nodes have a bunch of event handlers attached to them directly.
2357 * This is all done here for neatness.
2358 *
2359 * @protected
2360 * @method attach_comment_events
2361 * @param node - The Y.Node representing the comment.
2362 * @param menu - The Y.Node representing the menu.
2363 */
2364 this.attach_events = function(node, menu) {
2365 // Save the text on blur.
2366 node.on('blur', function() {
2367 // Save the changes back to the comment.
2368 this.rawtext = node.get('value');
2369 this.width = parseInt(node.getStyle('width'), 10);
2370
2371 // Trim.
2372 if (this.rawtext.replace(/^\s+|\s+$/g, "") === '') {
2373 // Delete empty comments.
2374 this.deleteme = true;
2375 Y.later(400, this, this.delete_comment_later);
2376 }
2377 this.editor.save_current_page();
60b87080 2378 this.editor.editingcomment = false;
5c386472
DW
2379 }, this);
2380
2381 // For delegated event handler.
2382 menu.setData('comment', this);
2383
2384 node.on('keyup', function() {
2385 var scrollheight = node.get('scrollHeight'),
2386 height = parseInt(node.getStyle('height'), 10);
2387
2388 // Webkit scrollheight fix.
2389 if (scrollheight === height + 8) {
2390 scrollheight -= 8;
2391 }
2392 node.setStyle('height', scrollheight + 'px');
2393
2394 });
2395
2396 node.on('gesturemovestart', function(e) {
2397 node.setData('dragging', true);
2398 node.setData('offsetx', e.clientX - node.getX());
2399 node.setData('offsety', e.clientY - node.getY());
2400 });
2401 node.on('gesturemoveend', function() {
2402 node.setData('dragging', false);
2403 this.editor.save_current_page();
2404 }, null, this);
2405 node.on('gesturemove', function(e) {
2406 var x = e.clientX - node.getData('offsetx'),
2407 y = e.clientY - node.getData('offsety'),
2408 nodewidth,
2409 nodeheight,
2410 newlocation,
2411 windowlocation,
2412 bounds;
2413
2414 nodewidth = parseInt(node.getStyle('width'), 10);
2415 nodeheight = parseInt(node.getStyle('height'), 10);
2416
2417 newlocation = this.editor.get_canvas_coordinates(new M.assignfeedback_editpdf.point(x, y));
2418 bounds = this.editor.get_canvas_bounds(true);
2419 bounds.x = 0;
2420 bounds.y = 0;
2421
2422 bounds.width -= nodewidth + 42;
2423 bounds.height -= nodeheight + 8;
2424 // Clip to the window size - the comment size.
2425 newlocation.clip(bounds);
2426
2427 this.x = newlocation.x;
2428 this.y = newlocation.y;
2429
2430 windowlocation = this.editor.get_window_coordinates(newlocation);
2431 node.ancestor().setX(windowlocation.x);
2432 node.ancestor().setY(windowlocation.y);
2433 }, null, this);
2434
2435 this.menu = new M.assignfeedback_editpdf.commentmenu({
2436 buttonNode: this.menulink,
2437 comment: this
2438 });
2439 };
2440
2441 /**
2442 * Delete a comment.
2443 * @method remove
2444 */
2445 this.remove = function() {
2446 var i = 0, comments;
2447
2448 comments = this.editor.pages[this.editor.currentpage].comments;
2449 for (i = 0; i < comments.length; i++) {
2450 if (comments[i] === this) {
2451 comments.splice(i, 1);
2452 this.drawable.erase();
2453 this.editor.save_current_page();
2454 return;
2455 }
2456 }
2457 };
2458
2459 /**
2460 * Event handler to remove a comment from the users quicklist.
2461 *
2462 * @protected
2463 * @method remove_from_quicklist
2464 */
2465 this.remove_from_quicklist = function(e, quickcomment) {
114913e3
DS
2466 e.preventDefault();
2467
5c386472
DW
2468 this.menu.hide();
2469
2470 this.editor.quicklist.remove(quickcomment);
2471 };
2472
2473 /**
2474 * A quick comment was selected in the list, update the active comment and redraw the page.
2475 *
2476 * @param Event e
2477 * @protected
2478 * @method set_from_quick_comment
2479 */
2480 this.set_from_quick_comment = function(e, quickcomment) {
114913e3
DS
2481 e.preventDefault();
2482
5c386472
DW
2483 this.menu.hide();
2484
2485 this.rawtext = quickcomment.rawtext;
2486 this.width = quickcomment.width;
2487 this.colour = quickcomment.colour;
2488
2489 this.editor.save_current_page();
2490
2491 this.editor.redraw();
2492 };
2493
2494 /**
2495 * Event handler to add a comment to the users quicklist.
2496 *
2497 * @protected
2498 * @method add_to_quicklist
2499 */
114913e3
DS
2500 this.add_to_quicklist = function(e) {
2501 e.preventDefault();
5c386472
DW
2502 this.menu.hide();
2503 this.editor.quicklist.add(this);
2504 };
2505
2506 /**
2507 * Draw the in progress edit.
2508 *
2509 * @public
2510 * @method draw_current_edit
2511 * @param M.assignfeedback_editpdf.edit edit
2512 */
2513 this.draw_current_edit = function(edit) {
2514 var drawable = new M.assignfeedback_editpdf.drawable(this.editor),
2515 shape,
2516 bounds;
2517
2518 bounds = new M.assignfeedback_editpdf.rect();
2519 bounds.bound([edit.start, edit.end]);
2520
2521 // We will draw a box with the current background colour.
2522 shape = this.editor.graphic.addShape({
2523 type: Y.Rect,
2524 width: bounds.width,
2525 height: bounds.height,
2526 fill: {
2527 color: COMMENTCOLOUR[edit.commentcolour]
2528 },
2529 x: bounds.x,
2530 y: bounds.y
2531 });
2532
2533 drawable.shapes.push(shape);
2534
2535 return drawable;
2536 };
2537
2538 /**
2539 * Promote the current edit to a real comment.
2540 *
2541 * @public
2542 * @method init_from_edit
2543 * @param M.assignfeedback_editpdf.edit edit
2544 */
2545 this.init_from_edit = function(edit) {
2546 var bounds = new M.assignfeedback_editpdf.rect();
2547 bounds.bound([edit.start, edit.end]);
2548
2549 // Minimum comment width.
2550 if (bounds.width < 100) {
2551 bounds.width = 100;
2552 }
2553
2554 // Save the current edit to the server and the current page list.
2555
2556 this.gradeid = this.editor.get('gradeid');
2557 this.pageno = this.editor.currentpage;
2558 this.x = bounds.x;
2559 this.y = bounds.y;
2560 this.width = bounds.width;
2561 this.colour = edit.commentcolour;
2562 this.rawtext = '';
2563 };
2564
2565};
2566
2567M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
2568M.assignfeedback_editpdf.comment = COMMENT;
2569// This file is part of Moodle - http://moodle.org/
2570//
2571// Moodle is free software: you can redistribute it and/or modify
2572// it under the terms of the GNU General Public License as published by
2573// the Free Software Foundation, either version 3 of the License, or
2574// (at your option) any later version.
2575//
2576// Moodle is distributed in the hope that it will be useful,
2577// but WITHOUT ANY WARRANTY; without even the implied warranty of
2578// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2579// GNU General Public License for more details.
2580//
2581// You should have received a copy of the GNU General Public License
2582// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
2583
2584/**
2585 * Class representing a users quick comment.
2586 *
2587 * @module moodle-assignfeedback_editpdf-editor
2588 */
2589
2590/**
2591 * QUICKCOMMENT
2592 *
2593 * @namespace M.assignfeedback_editpdf
2594 * @class quickcomment
2595 */
2596QUICKCOMMENT = function(id, rawtext, width, colour) {
2597
2598 /**
2599 * Quick comment text.
2600 * @property rawtext
2601 * @type String
2602 * @public
2603 */
2604 this.rawtext = rawtext || '';
2605
2606 /**
2607 * ID of the comment
2608 * @property id
2609 * @type Int
2610 * @public
2611 */
2612 this.id = id || 0;
2613
2614 /**
2615 * Width of the comment
2616 * @property width
2617 * @type Int
2618 * @public
2619 */
2620 this.width = width || 100;
2621
2622 /**
2623 * Colour of the comment.
2624 * @property colour
2625 * @type String
2626 * @public
2627 */
2628 this.colour = colour || "yellow";
2629};
2630
2631M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
2632M.assignfeedback_editpdf.quickcomment = QUICKCOMMENT;
2633// This file is part of Moodle - http://moodle.org/
2634//
2635// Moodle is free software: you can redistribute it and/or modify
2636// it under the terms of the GNU General Public License as published by
2637// the Free Software Foundation, either version 3 of the License, or
2638// (at your option) any later version.
2639//
2640// Moodle is distributed in the hope that it will be useful,
2641// but WITHOUT ANY WARRANTY; without even the implied warranty of
2642// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2643// GNU General Public License for more details.
2644//
2645// You should have received a copy of the GNU General Public License
2646// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
2647
2648/**
2649 * Class representing a users list of quick comments.
2650 *
2651 * @module moodle-assignfeedback_editpdf-editor
2652 */
2653
2654/**
2655 * QUICKLIST
2656 *
2657 * @namespace M.assignfeedback_editpdf
2658 * @class quickcommentlist
2659 */
2660QUICKCOMMENTLIST = function(editor) {
2661
2662 /**
2663 * Reference to M.assignfeedback_editpdf.editor.
2664 * @property editor
2665 * @type M.assignfeedback_editpdf.editor
2666 * @public
2667 */
2668 this.editor = editor;
2669
2670 /**
2671 * Array of Comments
2672 * @property shapes
2673 * @type M.assignfeedback_editpdf.quickcomment[]
2674 * @public
2675 */
2676 this.comments = [];
2677
2678 /**
2679 * Add a comment to the users quicklist.
2680 *
2681 * @protected
2682 * @method add
2683 */
2684 this.add = function(comment) {
2685 var ajaxurl = AJAXBASE,
2686 config;
2687
2688 // Do not save empty comments.
2689 if (comment.rawtext === '') {
2690 return;
2691 }
2692
2693 config = {
2694 method: 'post',
2695 context: this,
2696 sync: false,
2697 data : {
2698 'sesskey' : M.cfg.sesskey,
2699 'action' : 'addtoquicklist',
2700 'userid' : this.editor.get('userid'),
2701 'commenttext' : comment.rawtext,
2702 'width' : comment.width,
2703 'colour' : comment.colour,
2704 'attemptnumber' : this.editor.get('attemptnumber'),
2705 'assignmentid' : this.editor.get('assignmentid')
2706 },
2707 on: {
2708 success: function(tid, response) {
2709 var jsondata, quickcomment;
2710 try {
2711 jsondata = Y.JSON.parse(response.responseText);
2712 if (jsondata.error) {
2713 return new M.core.ajaxException(jsondata);
2714 } else {
2715 quickcomment = new M.assignfeedback_editpdf.quickcomment(jsondata.id,
2716 jsondata.rawtext,
2717 jsondata.width,
2718 jsondata.colour);
2719 this.comments.push(quickcomment);
2720 }
2721 } catch (e) {
2722 return new M.core.exception(e);
2723 }
2724 },
2725 failure: function(tid, response) {
2726 return M.core.exception(response.responseText);
2727 }
2728 }
2729 };
2730
2731 Y.io(ajaxurl, config);
2732 };
2733
2734 /**
2735 * Remove a comment from the users quicklist.
2736 *
2737 * @public
2738 * @method remove
2739 */
2740 this.remove = function(comment) {
2741 var ajaxurl = AJAXBASE,
2742 config;
2743
2744 // Should not happen.
2745 if (!comment) {
2746 return;
2747 }
2748
2749 config = {
2750 method: 'post',
2751 context: this,
2752 sync: false,
2753 data : {
2754 'sesskey' : M.cfg.sesskey,
2755 'action' : 'removefromquicklist',
2756 'userid' : this.editor.get('userid'),
2757 'commentid' : comment.id,
2758 'attemptnumber' : this.editor.get('attemptnumber'),
2759 'assignmentid' : this.editor.get('assignmentid')
2760 },
2761 on: {
2762 success: function() {
2763 var i;
2764
2765 // Find and remove the comment from the quicklist.
2766 i = this.comments.indexOf(comment);
2767 if (i >= 0) {
2768 this.comments.splice(i, 1);
2769 }
2770 },
2771 failure: function(tid, response) {
2772 return M.core.exception(response.responseText);
2773 }
2774 }
2775 };
2776
2777 Y.io(ajaxurl, config);
2778 };
2779
2780 /**
2781 * Load the users quick comments list.
2782 *
2783 * @protected
2784 * @method load_quicklist
2785 */
2786 this.load = function() {
2787 var ajaxurl = AJAXBASE,
2788 config;
2789
2790 config = {
2791 method: 'get',
2792 context: this,
2793 sync: false,
2794 data : {
2795 'sesskey' : M.cfg.sesskey,
2796 'action' : 'loadquicklist',
2797 'userid' : this.editor.get('userid'),
2798 'attemptnumber' : this.editor.get('attemptnumber'),
2799 'assignmentid' : this.editor.get('assignmentid')
2800 },
2801 on: {
2802 success: function(tid, response) {
2803 var jsondata;
2804 try {
2805 jsondata = Y.JSON.parse(response.responseText);
2806 if (jsondata.error) {
2807 return new M.core.ajaxException(jsondata);
2808 } else {
2809 Y.each(jsondata, function(comment) {
2810 var quickcomment = new M.assignfeedback_editpdf.quickcomment(comment.id,
2811 comment.rawtext,
2812 comment.width,
2813 comment.colour);
2814 this.comments.push(quickcomment);
2815 }, this);
2816 }
2817 } catch (e) {
2818 return new M.core.exception(e);
2819 }
2820 },
2821 failure: function(tid, response) {
2822 return M.core.exception(response.responseText);
2823 }
2824 }
2825 };
2826
2827 Y.io(ajaxurl, config);
2828 };
2829};
2830
2831M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
2832M.assignfeedback_editpdf.quickcommentlist = QUICKCOMMENTLIST;
2833// This file is part of Moodle - http://moodle.org/
2834//
2835// Moodle is free software: you can redistribute it and/or modify
2836// it under the terms of the GNU General Public License as published by
2837// the Free Software Foundation, either version 3 of the License, or
2838// (at your option) any later version.
2839//
2840// Moodle is distributed in the hope that it will be useful,
2841// but WITHOUT ANY WARRANTY; without even the implied warranty of
2842// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2843// GNU General Public License for more details.
2844//
2845// You should have received a copy of the GNU General Public License
2846// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
2847
2848/**
2849 * Provides an in browser PDF editor.
2850 *
2851 * @module moodle-assignfeedback_editpdf-editor
2852 */
2853
2854/**
2855 * EDITOR
2856 * This is an in browser PDF editor.
2857 *
2858 * @namespace M.assignfeedback_editpdf.editor
2859 * @class Editor
2860 * @constructor
2861 * @extends Y.Base
2862 */
2863EDITOR = function() {
2864 EDITOR.superclass.constructor.apply(this, arguments);
2865};
2866EDITOR.prototype = {
2867
2868 // Instance variables.
2869 /**
2870 * The dialogue used for all action menu displays.
2871 * @property type
2872 * @type M.core.dialogue
2873 * @protected
2874 */
2875 dialogue : null,
2876
2877 /**
2878 * The number of pages in the pdf.
2879 * @property type
2880 * @type int
2881 * @protected
2882 */
2883 pagecount : 0,
2884
2885 /**
2886 * The active page in the editor.
2887 * @property type
2888 * @type int
2889 * @protected
2890 */
2891 currentpage : 0,
2892
2893 /**
2894 * A list of page objects. Each page has a list of comments and annotations.
2895 * @property type
2896 * @type array
2897 * @protected
2898 */
2899 pages : [],
2900
2901 /**
2902 * The yui node for the loading icon.
2903 * @property type
2904 * @type Y.Node
2905 * @protected
2906 */
2907 loadingicon : null,
2908
2909 /**
2910 * Image object of the current page image.
2911 * @property type
2912 * @type Image
2913 * @protected
2914 */
2915 pageimage : null,
2916
2917 /**
2918 * YUI Graphic class for drawing shapes.
2919 * @property type
2920 * @type Y.Graphic
2921 * @protected
2922 */
2923 graphic : null,
2924
2925 /**
2926 * Info about the current edit operation.
2927 * @property currentedit
2928 * @type M.assignfeedback_editpdf.edit
2929 * @protected
2930 */
2931 currentedit : new M.assignfeedback_editpdf.edit(),
2932
2933 /**
2934 * Current drawable.
2935 * @property currentdrawable
2936 * @type M.assignfeedback_editpdf.drawable (or false)
2937 * @protected
2938 */
2939 currentdrawable : false,
2940
2941 /**
2942 * Current drawables.
2943 * @property drawables
2944 * @type array(M.assignfeedback_editpdf.drawable)
2945 * @protected
2946 */
2947 drawables : [],
2948
2949 /**
2950 * Current comment when the comment menu is open.
2951 * @property currentcomment
2952 * @type M.assignfeedback_editpdf.comment
2953 * @protected
2954 */
2955 currentcomment : null,
2956
2957 /**
2958 * Current annotation when the select tool is used.
2959 * @property currentannotation
2960 * @type M.assignfeedback_editpdf.annotation
2961 * @protected
2962 */
2963 currentannotation : null,
2964
2965 /**
2966 * Last selected annotation tool
2967 * @property lastannotationtool
2968 * @type String
2969 * @protected
2970 */
2971 lastanntationtool : "pen",