From a4c72b69e8b9e32d0a1dd5c09797ac65a25ddb92 Mon Sep 17 00:00:00 2001 From: Davo Smith Date: Mon, 15 Dec 2014 22:00:37 +0000 Subject: [PATCH] MDL-43462 assignfeedback_editpdf: fix display of landscape PDFs The size of the drawing canvas is now set from the size of the generated page image, with automatic scrolling if it is too wide to display Absolutely-positioned nodes (comments + stamps) are repositioned as the drawing canvas is scrolled --- mod/assign/feedback/editpdf/ajax.php | 7 ++ .../feedback/editpdf/classes/renderer.php | 5 +- mod/assign/feedback/editpdf/styles.css | 12 ++- ...dle-assignfeedback_editpdf-editor-debug.js | 95 ++++++++++++++++++- ...oodle-assignfeedback_editpdf-editor-min.js | 16 ++-- .../moodle-assignfeedback_editpdf-editor.js | 95 ++++++++++++++++++- .../yui/src/editor/js/annotationstamp.js | 2 + .../editpdf/yui/src/editor/js/comment.js | 2 + .../editpdf/yui/src/editor/js/drawable.js | 36 +++++++ .../editpdf/yui/src/editor/js/editor.js | 55 ++++++++++- 10 files changed, 298 insertions(+), 27 deletions(-) diff --git a/mod/assign/feedback/editpdf/ajax.php b/mod/assign/feedback/editpdf/ajax.php index 8baf3ffb7f8..c66b726e4d3 100644 --- a/mod/assign/feedback/editpdf/ajax.php +++ b/mod/assign/feedback/editpdf/ajax.php @@ -91,6 +91,13 @@ if ($action == 'loadallpages') { '/', $pagefile->get_filename())->out(); $page->comments = $comments; + if ($imageinfo = $pagefile->get_imageinfo()) { + $page->width = $imageinfo['width']; + $page->height = $imageinfo['height']; + } else { + $page->width = 0; + $page->height = 0; + } $annotations = page_editor::get_annotations($grade->id, $index, $draft); $page->annotations = $annotations; array_push($response->pages, $page); diff --git a/mod/assign/feedback/editpdf/classes/renderer.php b/mod/assign/feedback/editpdf/classes/renderer.php index a5d32e00f79..eca306de83e 100644 --- a/mod/assign/feedback/editpdf/classes/renderer.php +++ b/mod/assign/feedback/editpdf/classes/renderer.php @@ -209,9 +209,8 @@ class assignfeedback_editpdf_renderer extends plugin_renderer_base { $loading = html_writer::div($progressbar . $progressbarlabel, 'loading'); $canvas = html_writer::div($loading, 'drawingcanvas'); - $body .= html_writer::div($canvas, 'drawingregion'); - - $body .= '
'; + $canvas = html_writer::div($canvas, 'drawingregion'); + $body .= html_writer::div($canvas, 'hideoverflow'); $footer = ''; diff --git a/mod/assign/feedback/editpdf/styles.css b/mod/assign/feedback/editpdf/styles.css index d596434bdc6..2180dfb91e7 100644 --- a/mod/assign/feedback/editpdf/styles.css +++ b/mod/assign/feedback/editpdf/styles.css @@ -8,8 +8,14 @@ .assignfeedback_editpdf_widget .drawingcanvas { position: relative; min-width: 817px; - min-height: 1169px; + min-height: 400px; cursor: crosshair; + background-repeat: no-repeat; + background-color: #ccc; +} +.assignfeedback_editpdf_widget .drawingregion { + overflow: auto; + width: 842px; /* A4 portrait should not need a horizontal scrollbar */ } .assignfeedback_editpdf_widget { @@ -280,3 +286,7 @@ ul.assignfeedback_editpdf_menu { .assignfeedback_editpdf_widget .drawingcanvas .loading .progressbarlabel { text-align: center; } +.hideoverflow { + overflow: hidden; + position: relative; +} diff --git a/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-debug.js b/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-debug.js index bdf66653afc..f088c8d269c 100644 --- a/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-debug.js +++ b/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-debug.js @@ -468,6 +468,42 @@ DRAWABLE = function(editor) { } }; + /** + * Update the positions of all absolutely positioned nodes, when the drawing canvas is scrolled + * @public + * @method scroll_update + * @param scrollx int + * @param scrolly int + */ + this.scroll_update = function(scrollx, scrolly) { + var i, x, y; + for (i = 0; i < this.nodes.length; i++) { + x = this.nodes[i].getData('x'); + y = this.nodes[i].getData('y'); + if (x !== undefined && y !== undefined) { + this.nodes[i].setX(parseInt(x, 10) - scrollx); + this.nodes[i].setY(parseInt(y, 10) - scrolly); + } + } + }; + + /** + * Store the initial position of the node, so it can be updated when the drawing canvas is scrolled + * @public + * @method store_position + * @param container + * @param x + * @param y + */ + this.store_position = function(container, x, y) { + var drawingregion, scrollx, scrolly; + + drawingregion = Y.one(SELECTOR.DRAWINGREGION); + scrollx = parseInt(drawingregion.get('scrollLeft'), 10); + scrolly = parseInt(drawingregion.get('scrollTop'), 10); + container.setData('x', x + scrollx); + container.setData('y', y + scrolly); + }; }; M.assignfeedback_editpdf = M.assignfeedback_editpdf || {}; @@ -1533,6 +1569,7 @@ Y.extend(ANNOTATIONSTAMP, M.assignfeedback_editpdf.annotation, { drawingregion.append(node); node.setX(position.x); node.setY(position.y); + drawable.store_position(node, position.x, position.y); // Pass throught the event handlers on the div. node.on('gesturemovestart', this.editor.edit_start, null, this.editor); @@ -1576,6 +1613,7 @@ Y.extend(ANNOTATIONSTAMP, M.assignfeedback_editpdf.annotation, { drawingregion.append(node); node.setX(position.x); node.setY(position.y); + drawable.store_position(node, position.x, position.y); drawable.nodes.push(node); @@ -2493,6 +2531,7 @@ COMMENT = function(editor, gradeid, pageno, x, y, width, colour, rawtext) { container.setStyle('position', 'absolute'); container.setX(position.x); container.setY(position.y); + drawable.store_position(container, position.x, position.y); drawable.nodes.push(container); node.set('value', this.rawtext); scrollheight = node.get('scrollHeight'), @@ -2600,6 +2639,7 @@ COMMENT = function(editor, gradeid, pageno, x, y, width, colour, rawtext) { windowlocation = this.editor.get_window_coordinates(newlocation); node.ancestor().setX(windowlocation.x); node.ancestor().setY(windowlocation.y); + this.drawable.store_position(node.ancestor(), windowlocation.x, windowlocation.y); }, null, this); this.menu = new M.assignfeedback_editpdf.commentmenu({ @@ -3296,7 +3336,7 @@ EDITOR.prototype = { * @method link_handler */ link_handler : function(e) { - var drawingcanvas; + var drawingcanvas, drawingregion, resize = true; e.preventDefault(); if (!this.dialogue) { @@ -3318,6 +3358,9 @@ EDITOR.prototype = { drawingcanvas = Y.one(SELECTOR.DRAWINGCANVAS); this.graphic = new Y.Graphic({render : SELECTOR.DRAWINGCANVAS}); + drawingregion = Y.one(SELECTOR.DRAWINGREGION); + drawingregion.on('scroll', this.move_canvas, this); + if (!this.get('readonly')) { drawingcanvas.on('gesturemovestart', this.edit_start, null, this); drawingcanvas.on('gesturemove', this.edit_move, null, this); @@ -3327,10 +3370,18 @@ EDITOR.prototype = { } this.load_all_pages(); + drawingcanvas.on('windowresize', this.resize, this); + + resize = false; } this.dialogue.centerDialogue(); this.dialogue.show(); - drawingcanvas.on('windowresize', this.resize, this); + + // Redraw when the dialogue is moved, to ensure the absolute elements are all positioned correctly. + this.dialogue.dd.on('drag:end', this.redraw, this); + if (resize) { + this.resize(); // When re-opening the dialog call redraw, to make sure the size + layout is correct. + } }, /** @@ -3843,7 +3894,21 @@ EDITOR.prototype = { * @method resize */ resize : function() { + var drawingregion, drawregionheight; + + if (!this.dialogue.get('visible')) { + return; + } this.dialogue.centerDialogue(); + + // Make sure the dialogue box is not bigger than the max height of the viewport. + drawregionheight = Y.one('body').get('winHeight') - 120; // Space for toolbar + titlebar. + if (drawregionheight < 100) { + drawregionheight = 100; + } + drawingregion = Y.one(SELECTOR.DRAWINGREGION); + drawingregion.setStyle('maxHeight', drawregionheight +'px'); + this.redraw(); return true; }, @@ -3944,6 +4009,9 @@ EDITOR.prototype = { page; page = this.pages[this.currentpage]; + if (page === undefined) { + return; // Can happen if a redraw is triggered by an event, before the page has been selected. + } while (this.drawables.length > 0) { this.drawables.pop().erase(); } @@ -3984,11 +4052,13 @@ EDITOR.prototype = { page = this.pages[this.currentpage]; this.loadingicon.hide(); drawingcanvas.setStyle('backgroundImage', 'url("' + page.url + '")'); + drawingcanvas.setStyle('width', page.width + 'px'); + drawingcanvas.setStyle('height', page.height + 'px'); // Update page select. Y.one(SELECTOR.PAGESELECT).set('value', this.currentpage); - this.redraw(); + this.resize(); // Internally will call 'redraw', after checking the dialogue size. }, /** @@ -4056,10 +4126,25 @@ EDITOR.prototype = { this.currentpage = this.pages.length - 1; } this.change_page(); + }, + + /** + * Update any absolutely positioned nodes, within each drawable, when the drawing canvas is scrolled + * @protected + * @method move_canvas + */ + move_canvas: function() { + var drawingregion, x, y, i; + + drawingregion = Y.one(SELECTOR.DRAWINGREGION); + x = parseInt(drawingregion.get('scrollLeft'), 10); + y = parseInt(drawingregion.get('scrollTop'), 10); + + for (i = 0; i < this.drawables.length; i++) { + this.drawables[i].scroll_update(x, y); + } } - - }; Y.extend(EDITOR, Y.Base, EDITOR.prototype, { diff --git a/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-min.js b/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-min.js index 68b5228f09e..1c74be621bb 100644 --- a/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-min.js +++ b/mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-min.js @@ -1,8 +1,8 @@ -YUI.add("moodle-assignfeedback_editpdf-editor",function(e,t){var n=M.cfg.wwwroot+"/mod/assign/feedback/editpdf/ajax.php",r=M.cfg.wwwroot+"/mod/assign/feedback/editpdf/ajax_progress.php",s={DIALOGUE:"assignfeedback_editpdf_widget"},o={PREVIOUSBUTTON:"."+s.DIALOGUE+" .navigate-previous-button",NEXTBUTTON:"."+s.DIALOGUE+" .navigate-next-button",SEARCHCOMMENTSBUTTON:"."+s.DIALOGUE+" .searchcommentsbutton",SEARCHFILTER:".assignfeedback_editpdf_commentsearch input",SEARCHCOMMENTSLIST:".assignfeedback_editpdf_commentsearch ul",PAGESELECT:"."+s.DIALOGUE+" .navigate-page-select",LOADINGICON:"."+s.DIALOGUE+" .loading",PROGRESSBARCONTAINER:"."+s.DIALOGUE+" .progress-info.progress-striped",DRAWINGREGION:"."+s.DIALOGUE+" .drawingregion",DRAWINGCANVAS:"."+s.DIALOGUE+" .drawingcanvas",SAVE:"."+s.DIALOGUE+" .savebutton",COMMENTCOLOURBUTTON:"."+s.DIALOGUE+" .commentcolourbutton",COMMENTMENU:" .commentdrawable a",ANNOTATIONCOLOURBUTTON:"."+s.DIALOGUE+" .annotationcolourbutton",DELETEANNOTATIONBUTTON:"."+s.DIALOGUE+" .deleteannotationbutton",UNSAVEDCHANGESDIV:".assignfeedback_editpdf_unsavedchanges",STAMPSBUTTON:"."+s.DIALOGUE+" .currentstampbutton",DIALOGUE:"."+s.DIALOGUE},u="rgba(200, 200, 255, 0.9)",a="rgba(200, 200, 255, 0.5)",f="rgb(51, 51, 51)",l={white:"rgb(255,255,255)",yellow:"rgb(255,236,174)",red:"rgb(249,181,179)",green:"rgb(214,234,178)",blue:"rgb(203,217,237)",clear:"rgba(255,255,255, 0)"},c={white:"rgb(255,255,255)",yellow:"rgb(255,207,53)",red:"rgb(239,69,64)",green:"rgb(152,202,62)",blue:"rgb(125,159,211)",black:"rgb(51,51,51)"},h=300,p={comment:"."+s.DIALOGUE+" .commentbutton",pen:"."+s.DIALOGUE+" .penbutton",line:"."+s.DIALOGUE+" .linebutton",rectangle:"."+s.DIALOGUE+" .rectanglebutton",oval:"."+s.DIALOGUE+" .ovalbutton",stamp:"."+s.DIALOGUE+" .stampbutton",select:"."+s.DIALOGUE+" .selectbutton",highlight:"."+s.DIALOGUE+" .highlightbutton"},d=4;POINT=function(e,t){this.x=parseInt(e,10),this.y=parseInt(t,10),this.clip=function(e){return this.xe.x+e.width&&(this.x=e.x+e.width),this.ye.y+e.height&&(this.y=e.y+e.height),this}},M.assignfeedback_editpdf=M.assignfeedback_editpdf||{},M.assignfeedback_editpdf.point=POINT,RECT=function(e,t,n,r){this.x=e,this.y=t,this.width=n,this.height=r,this.bound=function(e){var t=0,n=0,r=0,i=0,s=0,o;for(s=0;sn||s===0)n=o.x;if(o.yi||s===0)i=o.y}return this.x=t,this.y=r,this.width=n-t,this.height=i-r,this},this.has_min_width=function(){return this.width>=5},this.has_min_height=function(){return this.height>=5},this.set_min_width=function(){this.width=5},this.set_min_height=function(){this.height=5}},M.assignfeedback_editpdf=M.assignfeedback_editpdf||{},M.assignfeedback_editpdf.rect=RECT,EDIT=function(){this.start=!1,this.end=!1,this.starttime=0,this.annotationstart=!1,this.tool="comment",this.commentcolour="yellow",this.annotationcolour="red",this.stamp="",this.path=[]},M.assignfeedback_editpdf=M.assignfeedback_editpdf||{},M.assignfeedback_editpdf.edit=EDIT,DRAWABLE=function(e){this.editor=e,this.shapes=[],this.nodes=[],this.erase=function(){if(this.shapes)while(this.shapes.length>0)this.editor.graphic.removeShape(this.shapes.pop());if(this.nodes)while(this.nodes.length>0)this.nodes.pop().remove()}},M.assignfeedback_editpdf=M.assignfeedback_editpdf||{},M.assignfeedback_editpdf.drawable=DRAWABLE,ANNOTATION=function(e){ANNOTATION.superclass.constructor.apply(this,[e])},ANNOTATION.NAME="annotation",ANNOTATION.ATTRS={},e.extend(ANNOTATION,e.Base,{editor:null,gradeid:0,pageno:0,x:0,y:0,endx:0,endy:0,path:"",type:"rect",colour:"red",drawable:!1,initializer:function(e){this.editor=e.editor||null,this.gradeid=parseInt(e.gradeid,10)||0,this.pageno=parseInt(e.pageno,10)||0,this.x=parseInt(e.x,10)||0,this.y=parseInt(e.y,10)||0,this.endx=parseInt(e.endx,10)||0,this.endy=parseInt(e.endy,10)||0,this.path=e.path||"",this.type=e.type||"rect",this.colour=e.colour||"red",this.drawable=!1},clean:function(){return{gradeid:this.gradeid,x:parseInt(this.x,10),y:parseInt(this.y,10),endx:parseInt(this.endx,10),endy:parseInt(this.endy,10),type:this.type,path:this.path,pageno:this.pageno,colour:this.colour}},draw_highlight:function(){var t,n=e.one(o.DRAWINGREGION),r=e.one(o.DRAWINGCANVAS).getXY(),i;if(this.editor.currentannotation===this){t=new M.assignfeedback_editpdf.rect,t.bound([new M.assignfeedback_editpdf.point(this.x,this.y),new M.assignfeedback_editpdf.point(this.endx,this.endy)]),i=this.editor.graphic.addShape({type:e.Rect,width:t.width,height:t.height,stroke:{weight:d,color:u},fill:{color:a},x:t.x,y:t.y}),this.drawable.shapes.push(i);var s=e.Node.create(''),f=e.Node.create('');s.setAttrs({alt:M.util.get_string("deleteannotation","assignfeedback_editpdf")}),s.setStyles({backgroundColor:"white"}),f.addClass("deleteannotationbutton"),f.append(s),n.append(f),f.setData("annotation",this),f.setStyle("zIndex","200"),f.on("click",this.remove,this),f.on("key",this.remove,"space,enter",this),f.setX(r[0]+t.x+t.width-18),f.setY(r[1]+t.y+6),this.drawable.nodes.push(f)}return this.drawable},draw:function(){return this.draw_highlight(),this.drawable},remove:function(e){var t;e.preventDefault(),t=this.editor.pages[this.editor.currentpage].annotations;for(i=0;i"),r.setStyles({position:"absolute",display:"inline-block",backgroundImage:"url("+this.editor.get_stamp_image_url(this.path)+")",width:this.endx-this.x,height:this.endy-this.y,backgroundSize:"100% 100%",zIndex:50}),n.append(r),r.setX(i.x),r.setY(i.y),r.on("gesturemovestart",this.editor.edit_start,null,this.editor),r.on("gesturemove",this.editor.edit_move,null,this.editor),r.on("gesturemoveend",this.editor.edit_end,null,this.editor),t.nodes.push(r),this.drawable=t,ANNOTATIONSTAMP.superclass.draw.apply(this)},draw_current_edit:function(t){var n=new M.assignfeedback_editpdf.rect,r=new M.assignfeedback_editpdf.drawable(this.editor),i=e.one(o.DRAWINGREGION),s,u;return n.bound([t.start,t.end]),u=this.editor.get_window_coordinates(new M.assignfeedback_editpdf.point(n.x,n.y)),s=e.Node.create("
"),s.setStyles({position:"absolute",display:"inline-block",backgroundImage:"url("+this.editor.get_stamp_image_url(t.stamp)+")",width:n.width,height:n.height,backgroundSize:"100% 100%",zIndex:50}),i.append(s),s.setX(u.x),s.setY(u.y),r.nodes.push(s),r},init_from_edit:function(e){var t=new M.assignfeedback_editpdf.rect;return t.bound([e.start,e.end]),t.width<40&&(t.width=40),t.height<40&&(t.height=40),this.gradeid=this.editor.get("gradeid"),this.pageno=this.editor.currentpage,this.x=t.x,this.y=t.y,this.endx=t.x+t.width,this.endy=t.y+t.height,this.colour=e.annotationcolour,this.path=e.stamp,!0},move:function(e,t){var n=e-this.x,r=t-this.y;this.x+=n,this.y+=r,this.endx+=n,this.endy+=r,this.drawable&&this.drawable.erase(),this.editor.drawables.push(this.draw())}}),M.assignfeedback_editpdf=M.assignfeedback_editpdf||{},M.assignfeedback_editpdf.annotationstamp=ANNOTATIONSTAMP;var v="Dropdown menu",m;m=function(e){e.draggable=!1,e.centered=!1,e.width="auto",e.visible=!1,e.footerContent="",m.superclass.constructor.apply(this,[e])},e.extend(m,M.core.dialogue,{initializer:function(t){var n,r,i,s;m.superclass.initializer.call(this,t),s=this.get("boundingBox"),s.addClass("assignfeedback_editpdf_dropdown"),n=this.get("buttonNode"),r=this.bodyNode,i=e.Node.create("

"),i.addClass("accesshide"),i.setHTML(this.get("headerText")),r.prepend(i),r.on("clickoutside",function(e){this.get("visible")&&e.target.get("id")!==n.get("id")&&e.target.ancestor().get("id")!==n.get("id")&&(e.preventDefault(),this.hide())},this),n.on("click",function(e){e.preventDefault(),this.show()},this),n.on("key",this.show,"enter,space",this)},show:function(){var t=this.get("buttonNode");result=m.superclass.show.call(this),this.align(t,[e.WidgetPositionAlign.TL,e.WidgetPositionAlign.BL])}},{NAME:v,ATTRS:{headerText:{value:""},buttonNode:{value:null}}}),e.Base.modifyAttrs(m,{modal:{getter:function(){return!1}}}),M.assignfeedback_editpdf=M.assignfeedback_editpdf||{},M.assignfeedback_editpdf.dropdown=m;var g="Colourpicker",b;b=function(e){b.superclass.constructor.apply(this,[e])},e.extend(b,M.assignfeedback_editpdf.dropdown,{initializer:function(t){var n=e.Node.create('