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