[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 // This file is part of Moodle - http://moodle.org/ 2 // 3 // Moodle is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // (at your option) any later version. 7 // 8 // Moodle is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 15 /* global SELECTOR, COMMENTCOLOUR, COMMENTTEXTCOLOUR */ 16 17 /** 18 * Provides an in browser PDF editor. 19 * 20 * @module moodle-assignfeedback_editpdf-editor 21 */ 22 23 /** 24 * Class representing a list of comments. 25 * 26 * @namespace M.assignfeedback_editpdf 27 * @class comment 28 * @param M.assignfeedback_editpdf.editor editor 29 * @param Int gradeid 30 * @param Int pageno 31 * @param Int x 32 * @param Int y 33 * @param Int width 34 * @param String colour 35 * @param String rawtext 36 */ 37 var COMMENT = function(editor, gradeid, pageno, x, y, width, colour, rawtext) { 38 39 /** 40 * Reference to M.assignfeedback_editpdf.editor. 41 * @property editor 42 * @type M.assignfeedback_editpdf.editor 43 * @public 44 */ 45 this.editor = editor; 46 47 /** 48 * Grade id 49 * @property gradeid 50 * @type Int 51 * @public 52 */ 53 this.gradeid = gradeid || 0; 54 55 /** 56 * X position 57 * @property x 58 * @type Int 59 * @public 60 */ 61 this.x = parseInt(x, 10) || 0; 62 63 /** 64 * Y position 65 * @property y 66 * @type Int 67 * @public 68 */ 69 this.y = parseInt(y, 10) || 0; 70 71 /** 72 * Comment width 73 * @property width 74 * @type Int 75 * @public 76 */ 77 this.width = parseInt(width, 10) || 0; 78 79 /** 80 * Comment rawtext 81 * @property rawtext 82 * @type String 83 * @public 84 */ 85 this.rawtext = rawtext || ''; 86 87 /** 88 * Comment page number 89 * @property pageno 90 * @type Int 91 * @public 92 */ 93 this.pageno = pageno || 0; 94 95 /** 96 * Comment background colour. 97 * @property colour 98 * @type String 99 * @public 100 */ 101 this.colour = colour || 'yellow'; 102 103 /** 104 * Reference to M.assignfeedback_editpdf.drawable 105 * @property drawable 106 * @type M.assignfeedback_editpdf.drawable 107 * @public 108 */ 109 this.drawable = false; 110 111 /** 112 * Boolean used by a timeout to delete empty comments after a short delay. 113 * @property deleteme 114 * @type Boolean 115 * @public 116 */ 117 this.deleteme = false; 118 119 /** 120 * Reference to the link that opens the menu. 121 * @property menulink 122 * @type Y.Node 123 * @public 124 */ 125 this.menulink = null; 126 127 /** 128 * Reference to the dialogue that is the context menu. 129 * @property menu 130 * @type M.assignfeedback_editpdf.dropdown 131 * @public 132 */ 133 this.menu = null; 134 135 /** 136 * Clean a comment record, returning an oject with only fields that are valid. 137 * @public 138 * @method clean 139 * @return {} 140 */ 141 this.clean = function() { 142 return { 143 gradeid: this.gradeid, 144 x: parseInt(this.x, 10), 145 y: parseInt(this.y, 10), 146 width: parseInt(this.width, 10), 147 rawtext: this.rawtext, 148 pageno: this.currentpage, 149 colour: this.colour 150 }; 151 }; 152 153 /** 154 * Draw a comment. 155 * @public 156 * @method draw_comment 157 * @param boolean focus - Set the keyboard focus to the new comment if true 158 * @return M.assignfeedback_editpdf.drawable 159 */ 160 this.draw = function(focus) { 161 var drawable = new M.assignfeedback_editpdf.drawable(this.editor), 162 node, 163 drawingregion = this.editor.get_dialogue_element(SELECTOR.DRAWINGREGION), 164 container, 165 menu, 166 position, 167 scrollheight; 168 169 // Lets add a contenteditable div. 170 node = Y.Node.create('<textarea/>'); 171 container = Y.Node.create('<div class="commentdrawable"/>'); 172 menu = Y.Node.create('<a href="#"><img src="' + M.util.image_url('t/contextmenu', 'core') + '"/></a>'); 173 174 this.menulink = menu; 175 container.append(node); 176 177 if (!this.editor.get('readonly')) { 178 container.append(menu); 179 } else { 180 node.setAttribute('readonly', 'readonly'); 181 } 182 if (this.width < 100) { 183 this.width = 100; 184 } 185 186 position = this.editor.get_window_coordinates(new M.assignfeedback_editpdf.point(this.x, this.y)); 187 node.setStyles({ 188 width: this.width + 'px', 189 backgroundColor: COMMENTCOLOUR[this.colour], 190 color: COMMENTTEXTCOLOUR 191 }); 192 193 drawingregion.append(container); 194 container.setStyle('position', 'absolute'); 195 container.setX(position.x); 196 container.setY(position.y); 197 drawable.store_position(container, position.x, position.y); 198 drawable.nodes.push(container); 199 node.set('value', this.rawtext); 200 scrollheight = node.get('scrollHeight'); 201 node.setStyles({ 202 'height': scrollheight + 'px', 203 'overflow': 'hidden' 204 }); 205 if (!this.editor.get('readonly')) { 206 this.attach_events(node, menu); 207 } 208 if (focus) { 209 node.focus(); 210 } 211 this.drawable = drawable; 212 213 214 return drawable; 215 }; 216 217 /** 218 * Delete an empty comment if it's menu hasn't been opened in time. 219 * @method delete_comment_later 220 */ 221 this.delete_comment_later = function() { 222 if (this.deleteme) { 223 this.remove(); 224 } 225 }; 226 227 /** 228 * Comment nodes have a bunch of event handlers attached to them directly. 229 * This is all done here for neatness. 230 * 231 * @protected 232 * @method attach_comment_events 233 * @param node - The Y.Node representing the comment. 234 * @param menu - The Y.Node representing the menu. 235 */ 236 this.attach_events = function(node, menu) { 237 // Save the text on blur. 238 node.on('blur', function() { 239 // Save the changes back to the comment. 240 this.rawtext = node.get('value'); 241 this.width = parseInt(node.getStyle('width'), 10); 242 243 // Trim. 244 if (this.rawtext.replace(/^\s+|\s+$/g, "") === '') { 245 // Delete empty comments. 246 this.deleteme = true; 247 Y.later(400, this, this.delete_comment_later); 248 } 249 this.editor.save_current_page(); 250 this.editor.editingcomment = false; 251 }, this); 252 253 // For delegated event handler. 254 menu.setData('comment', this); 255 256 node.on('keyup', function() { 257 var scrollheight = node.get('scrollHeight'), 258 height = parseInt(node.getStyle('height'), 10); 259 260 // Webkit scrollheight fix. 261 if (scrollheight === height + 8) { 262 scrollheight -= 8; 263 } 264 node.setStyle('height', scrollheight + 'px'); 265 266 }); 267 268 node.on('gesturemovestart', function(e) { 269 if (editor.currentedit.tool === 'select') { 270 e.preventDefault(); 271 node.setData('dragging', true); 272 node.setData('offsetx', e.clientX - node.getX()); 273 node.setData('offsety', e.clientY - node.getY()); 274 } 275 }); 276 node.on('gesturemoveend', function() { 277 if (editor.currentedit.tool === 'select') { 278 node.setData('dragging', false); 279 this.editor.save_current_page(); 280 } 281 }, null, this); 282 node.on('gesturemove', function(e) { 283 if (editor.currentedit.tool === 'select') { 284 var x = e.clientX - node.getData('offsetx'), 285 y = e.clientY - node.getData('offsety'), 286 nodewidth, 287 nodeheight, 288 newlocation, 289 windowlocation, 290 bounds; 291 292 nodewidth = parseInt(node.getStyle('width'), 10); 293 nodeheight = parseInt(node.getStyle('height'), 10); 294 295 newlocation = this.editor.get_canvas_coordinates(new M.assignfeedback_editpdf.point(x, y)); 296 bounds = this.editor.get_canvas_bounds(true); 297 bounds.x = 0; 298 bounds.y = 0; 299 300 bounds.width -= nodewidth + 42; 301 bounds.height -= nodeheight + 8; 302 // Clip to the window size - the comment size. 303 newlocation.clip(bounds); 304 305 this.x = newlocation.x; 306 this.y = newlocation.y; 307 308 windowlocation = this.editor.get_window_coordinates(newlocation); 309 node.ancestor().setX(windowlocation.x); 310 node.ancestor().setY(windowlocation.y); 311 this.drawable.store_position(node.ancestor(), windowlocation.x, windowlocation.y); 312 } 313 }, null, this); 314 315 this.menu = new M.assignfeedback_editpdf.commentmenu({ 316 buttonNode: this.menulink, 317 comment: this 318 }); 319 }; 320 321 /** 322 * Delete a comment. 323 * @method remove 324 */ 325 this.remove = function() { 326 var i = 0; 327 var comments; 328 329 comments = this.editor.pages[this.editor.currentpage].comments; 330 for (i = 0; i < comments.length; i++) { 331 if (comments[i] === this) { 332 comments.splice(i, 1); 333 this.drawable.erase(); 334 this.editor.save_current_page(); 335 return; 336 } 337 } 338 }; 339 340 /** 341 * Event handler to remove a comment from the users quicklist. 342 * 343 * @protected 344 * @method remove_from_quicklist 345 */ 346 this.remove_from_quicklist = function(e, quickcomment) { 347 e.preventDefault(); 348 349 this.menu.hide(); 350 351 this.editor.quicklist.remove(quickcomment); 352 }; 353 354 /** 355 * A quick comment was selected in the list, update the active comment and redraw the page. 356 * 357 * @param Event e 358 * @protected 359 * @method set_from_quick_comment 360 */ 361 this.set_from_quick_comment = function(e, quickcomment) { 362 e.preventDefault(); 363 364 this.menu.hide(); 365 366 this.rawtext = quickcomment.rawtext; 367 this.width = quickcomment.width; 368 this.colour = quickcomment.colour; 369 370 this.editor.save_current_page(); 371 372 this.editor.redraw(); 373 }; 374 375 /** 376 * Event handler to add a comment to the users quicklist. 377 * 378 * @protected 379 * @method add_to_quicklist 380 */ 381 this.add_to_quicklist = function(e) { 382 e.preventDefault(); 383 this.menu.hide(); 384 this.editor.quicklist.add(this); 385 }; 386 387 /** 388 * Draw the in progress edit. 389 * 390 * @public 391 * @method draw_current_edit 392 * @param M.assignfeedback_editpdf.edit edit 393 */ 394 this.draw_current_edit = function(edit) { 395 var drawable = new M.assignfeedback_editpdf.drawable(this.editor), 396 shape, 397 bounds; 398 399 bounds = new M.assignfeedback_editpdf.rect(); 400 bounds.bound([edit.start, edit.end]); 401 402 // We will draw a box with the current background colour. 403 shape = this.editor.graphic.addShape({ 404 type: Y.Rect, 405 width: bounds.width, 406 height: bounds.height, 407 fill: { 408 color: COMMENTCOLOUR[edit.commentcolour] 409 }, 410 x: bounds.x, 411 y: bounds.y 412 }); 413 414 drawable.shapes.push(shape); 415 416 return drawable; 417 }; 418 419 /** 420 * Promote the current edit to a real comment. 421 * 422 * @public 423 * @method init_from_edit 424 * @param M.assignfeedback_editpdf.edit edit 425 * @return bool true if comment bound is more than min width/height, else false. 426 */ 427 this.init_from_edit = function(edit) { 428 var bounds = new M.assignfeedback_editpdf.rect(); 429 bounds.bound([edit.start, edit.end]); 430 431 // Minimum comment width. 432 if (bounds.width < 100) { 433 bounds.width = 100; 434 } 435 436 // Save the current edit to the server and the current page list. 437 438 this.gradeid = this.editor.get('gradeid'); 439 this.pageno = this.editor.currentpage; 440 this.x = bounds.x; 441 this.y = bounds.y; 442 this.width = bounds.width; 443 this.colour = edit.commentcolour; 444 this.rawtext = ''; 445 446 return (bounds.has_min_width() && bounds.has_min_height()); 447 }; 448 449 }; 450 451 M.assignfeedback_editpdf = M.assignfeedback_editpdf || {}; 452 M.assignfeedback_editpdf.comment = COMMENT;
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |