MDL-42023 assign: Edit PDF plugin - Jerome's contributions
authorJerome Mouneyrac <jerome@mouneyrac.com>
Fri, 27 Sep 2013 06:47:12 +0000 (14:47 +0800)
committerDamyon Wiese <damyon@moodle.com>
Thu, 3 Oct 2013 01:29:54 +0000 (09:29 +0800)
mod/assign/feedback/editpdf/yui/src/editor/js/annotationline.js [new file with mode: 0644]
mod/assign/feedback/editpdf/yui/src/editor/js/annotationoval.js [new file with mode: 0644]
mod/assign/feedback/editpdf/yui/src/editor/js/annotationpen.js [new file with mode: 0644]
mod/assign/feedback/editpdf/yui/src/editor/js/annotationrectangle.js [new file with mode: 0644]
mod/assign/feedback/editpdf/yui/src/editor/js/annotationstamp.js [new file with mode: 0644]
mod/assign/feedback/editpdf/yui/src/editor/js/stamppicker.js [new file with mode: 0644]

diff --git a/mod/assign/feedback/editpdf/yui/src/editor/js/annotationline.js b/mod/assign/feedback/editpdf/yui/src/editor/js/annotationline.js
new file mode 100644 (file)
index 0000000..407e3e3
--- /dev/null
@@ -0,0 +1,112 @@
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Class representing a line.
+ *
+ * @namespace M.assignfeedback_editpdf
+ * @class annotationline
+ * @extends annotation
+ * @module moodle-assignfeedback_editpdf-editor
+ */
+ANNOTATIONLINE = function(config) {
+    ANNOTATIONLINE.superclass.constructor.apply(this, [config]);
+};
+
+ANNOTATIONLINE.NAME = "annotationline";
+ANNOTATIONLINE.ATTRS = {};
+
+Y.extend(ANNOTATIONLINE, M.assignfeedback_editpdf.annotation, {
+    /**
+     * Draw a line annotation
+     * @protected
+     * @method draw
+     * @return M.assignfeedback_editpdf.drawable
+     */
+    draw : function() {
+        var drawable,
+            shape;
+
+        drawable = new M.assignfeedback_editpdf.drawable(this.editor);
+
+        shape = this.editor.graphic.addShape({
+        type: Y.Path,
+            fill: false,
+            stroke: {
+                weight: STROKEWEIGHT,
+                color: ANNOTATIONCOLOUR[this.colour]
+            }
+        });
+
+        shape.moveTo(this.x, this.y);
+        shape.lineTo(this.endx, this.endy);
+        shape.end();
+        drawable.shapes.push(shape);
+        this.drawable = drawable;
+
+        return ANNOTATIONLINE.superclass.draw.apply(this);
+    },
+
+    /**
+     * Draw the in progress edit.
+     *
+     * @public
+     * @method draw_current_edit
+     * @param M.assignfeedback_editpdf.edit edit
+     */
+    draw_current_edit : function(edit) {
+        var drawable = new M.assignfeedback_editpdf.drawable(this.editor),
+            shape;
+
+        shape = this.editor.graphic.addShape({
+           type: Y.Path,
+            fill: false,
+            stroke: {
+                weight: STROKEWEIGHT,
+                color: ANNOTATIONCOLOUR[edit.annotationcolour]
+            }
+        });
+
+        shape.moveTo(edit.start.x, edit.start.y);
+        shape.lineTo(edit.end.x, edit.end.y);
+        shape.end();
+
+        drawable.shapes.push(shape);
+
+        return drawable;
+    },
+
+    /**
+     * Promote the current edit to a real annotation.
+     *
+     * @public
+     * @method init_from_edit
+     * @param M.assignfeedback_editpdf.edit edit
+     */
+    init_from_edit : function(edit) {
+        this.gradeid = this.editor.get('gradeid');
+        this.pageno = this.editor.currentpage;
+        this.x = edit.start.x;
+        this.y = edit.start.y;
+        this.endx = edit.end.x;
+        this.endy = edit.end.y;
+        this.colour = edit.annotationcolour;
+        this.path = '';
+    }
+
+});
+
+M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
+M.assignfeedback_editpdf.annotationline = ANNOTATIONLINE;
diff --git a/mod/assign/feedback/editpdf/yui/src/editor/js/annotationoval.js b/mod/assign/feedback/editpdf/yui/src/editor/js/annotationoval.js
new file mode 100644 (file)
index 0000000..dcca29f
--- /dev/null
@@ -0,0 +1,100 @@
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Class representing a oval.
+ *
+ * @namespace M.assignfeedback_editpdf
+ * @class annotationoval
+ * @extends annotation
+ * @module moodle-assignfeedback_editpdf-editor
+ */
+ANNOTATIONOVAL = function(config) {
+    ANNOTATIONOVAL.superclass.constructor.apply(this, [config]);
+};
+
+ANNOTATIONOVAL.NAME = "annotationoval";
+ANNOTATIONOVAL.ATTRS = {};
+
+Y.extend(ANNOTATIONOVAL, M.assignfeedback_editpdf.annotation, {
+    /**
+     * Draw a oval annotation
+     * @protected
+     * @method draw
+     * @return M.assignfeedback_editpdf.drawable
+     */
+    draw : function() {
+        var drawable,
+            shape;
+
+        drawable = new M.assignfeedback_editpdf.drawable(this.editor);
+
+        bounds = new M.assignfeedback_editpdf.rect();
+        bounds.bound([new M.assignfeedback_editpdf.point(this.x, this.y),
+                      new M.assignfeedback_editpdf.point(this.endx, this.endy)]);
+
+        shape = this.editor.graphic.addShape({
+            type: Y.Ellipse,
+            width: bounds.width,
+            height: bounds.height,
+            stroke: {
+               weight: STROKEWEIGHT,
+               color: ANNOTATIONCOLOUR[this.colour]
+            },
+            x: bounds.x,
+            y: bounds.y
+        });
+        drawable.shapes.push(shape);
+        this.drawable = drawable;
+
+        return ANNOTATIONOVAL.superclass.draw.apply(this);
+    },
+
+    /**
+     * Draw the in progress edit.
+     *
+     * @public
+     * @method draw_current_edit
+     * @param M.assignfeedback_editpdf.edit edit
+     */
+    draw_current_edit : function(edit) {
+        var drawable = new M.assignfeedback_editpdf.drawable(this.editor),
+            shape,
+            bounds;
+
+        bounds = new M.assignfeedback_editpdf.rect();
+        bounds.bound([new M.assignfeedback_editpdf.point(edit.start.x, edit.start.y),
+                      new M.assignfeedback_editpdf.point(edit.end.x, edit.end.y)]);
+
+        shape = this.editor.graphic.addShape({
+            type: Y.Ellipse,
+            width: bounds.width,
+            height: bounds.height,
+            stroke: {
+               weight: STROKEWEIGHT,
+               color: ANNOTATIONCOLOUR[edit.annotationcolour]
+            },
+            x: bounds.x,
+            y: bounds.y
+        });
+
+        drawable.shapes.push(shape);
+
+        return drawable;
+    }
+});
+
+M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
+M.assignfeedback_editpdf.annotationoval = ANNOTATIONOVAL;
diff --git a/mod/assign/feedback/editpdf/yui/src/editor/js/annotationpen.js b/mod/assign/feedback/editpdf/yui/src/editor/js/annotationpen.js
new file mode 100644 (file)
index 0000000..9915a52
--- /dev/null
@@ -0,0 +1,152 @@
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Class representing a pen.
+ *
+ * @namespace M.assignfeedback_editpdf
+ * @class annotationpen
+ * @extends annotation
+ * @module moodle-assignfeedback_editpdf-editor
+ */
+ANNOTATIONPEN = function(config) {
+    ANNOTATIONPEN.superclass.constructor.apply(this, [config]);
+};
+
+ANNOTATIONPEN.NAME = "annotationpen";
+ANNOTATIONPEN.ATTRS = {};
+
+Y.extend(ANNOTATIONPEN, M.assignfeedback_editpdf.annotation, {
+    /**
+     * Draw a pen annotation
+     * @protected
+     * @method draw
+     * @return M.assignfeedback_editpdf.drawable
+     */
+    draw : function() {
+        var drawable,
+            shape,
+            first,
+            positions,
+            xy;
+
+        drawable = new M.assignfeedback_editpdf.drawable(this.editor);
+
+        shape = this.editor.graphic.addShape({
+           type: Y.Path,
+            fill: false,
+            stroke: {
+                weight: STROKEWEIGHT,
+                color: ANNOTATIONCOLOUR[this.colour]
+            }
+        });
+
+        first = true;
+        // Recreate the pen path array.
+        positions = this.path.split(':');
+        // Redraw all the lines.
+        Y.each(positions, function(position) {
+            xy = position.split(',');
+            if (first) {
+                shape.moveTo(xy[0], xy[1]);
+                first = false;
+            } else {
+                shape.lineTo(xy[0], xy[1]);
+            }
+        }, this);
+
+        shape.end();
+
+        drawable.shapes.push(shape);
+        this.drawable = drawable;
+
+        return ANNOTATIONPEN.superclass.draw.apply(this);
+    },
+
+    /**
+     * Draw the in progress edit.
+     *
+     * @public
+     * @method draw_current_edit
+     * @param M.assignfeedback_editpdf.edit edit
+     */
+    draw_current_edit : function(edit) {
+        var drawable = new M.assignfeedback_editpdf.drawable(this.editor),
+            shape,
+            first;
+
+        shape = this.editor.graphic.addShape({
+           type: Y.Path,
+            fill: false,
+            stroke: {
+                weight: STROKEWEIGHT,
+                color: ANNOTATIONCOLOUR[edit.annotationcolour]
+            }
+        });
+
+        first = true;
+        // Recreate the pen path array.
+        // Redraw all the lines.
+        Y.each(edit.path, function(position) {
+            if (first) {
+                shape.moveTo(position.x, position.y);
+                first = false;
+            } else {
+                shape.lineTo(position.x, position.y);
+            }
+        }, this);
+
+        shape.end();
+
+        drawable.shapes.push(shape);
+
+        return drawable;
+    },
+
+
+    /**
+     * Promote the current edit to a real annotation.
+     *
+     * @public
+     * @method init_from_edit
+     * @param M.assignfeedback_editpdf.edit edit
+     */
+    init_from_edit : function(edit) {
+        var bounds = new M.assignfeedback_editpdf.rect(),
+            pathlist = [],
+            i = 0;
+
+        // This will get the boundaries of all points in the path.
+        bounds.bound(edit.path);
+
+        for (i = 0; i < edit.path.length; i++) {
+            pathlist.push(parseInt(edit.path[i].x, 10) + ',' + parseInt(edit.path[i].y, 10));
+        }
+
+        this.gradeid = this.editor.get('gradeid');
+        this.pageno = this.editor.currentpage;
+        this.x = bounds.x;
+        this.y = bounds.y;
+        this.endx = bounds.x + bounds.width;
+        this.endy = bounds.y + bounds.height;
+        this.colour = edit.annotationcolour;
+        this.path = pathlist.join(':');
+    }
+
+
+});
+
+M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
+M.assignfeedback_editpdf.annotationpen = ANNOTATIONPEN;
diff --git a/mod/assign/feedback/editpdf/yui/src/editor/js/annotationrectangle.js b/mod/assign/feedback/editpdf/yui/src/editor/js/annotationrectangle.js
new file mode 100644 (file)
index 0000000..368a74c
--- /dev/null
@@ -0,0 +1,100 @@
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Class representing a rectangle.
+ *
+ * @namespace M.assignfeedback_editpdf
+ * @class annotationrectangle
+ * @extends annotation
+ * @module moodle-assignfeedback_editpdf-editor
+ */
+ANNOTATIONRECTANGLE = function(config) {
+    ANNOTATIONRECTANGLE.superclass.constructor.apply(this, [config]);
+};
+
+ANNOTATIONRECTANGLE.NAME = "annotationrectangle";
+ANNOTATIONRECTANGLE.ATTRS = {};
+
+Y.extend(ANNOTATIONRECTANGLE, M.assignfeedback_editpdf.annotation, {
+    /**
+     * Draw a rectangle annotation
+     * @protected
+     * @method draw
+     * @return M.assignfeedback_editpdf.drawable
+     */
+    draw : function() {
+        var drawable,
+            shape;
+
+        drawable = new M.assignfeedback_editpdf.drawable(this.editor);
+
+        bounds = new M.assignfeedback_editpdf.rect();
+        bounds.bound([new M.assignfeedback_editpdf.point(this.x, this.y),
+                      new M.assignfeedback_editpdf.point(this.endx, this.endy)]);
+
+        shape = this.editor.graphic.addShape({
+            type: Y.Rect,
+            width: bounds.width,
+            height: bounds.height,
+            stroke: {
+               weight: STROKEWEIGHT,
+               color: ANNOTATIONCOLOUR[this.colour]
+            },
+            x: bounds.x,
+            y: bounds.y
+        });
+        drawable.shapes.push(shape);
+        this.drawable = drawable;
+
+        return ANNOTATIONRECTANGLE.superclass.draw.apply(this);
+    },
+
+    /**
+     * Draw the in progress edit.
+     *
+     * @public
+     * @method draw_current_edit
+     * @param M.assignfeedback_editpdf.edit edit
+     */
+    draw_current_edit : function(edit) {
+        var drawable = new M.assignfeedback_editpdf.drawable(this.editor),
+            shape,
+            bounds;
+
+        bounds = new M.assignfeedback_editpdf.rect();
+        bounds.bound([new M.assignfeedback_editpdf.point(edit.start.x, edit.start.y),
+                      new M.assignfeedback_editpdf.point(edit.end.x, edit.end.y)]);
+
+        shape = this.editor.graphic.addShape({
+            type: Y.Rect,
+            width: bounds.width,
+            height: bounds.height,
+            stroke: {
+               weight: STROKEWEIGHT,
+               color: ANNOTATIONCOLOUR[edit.annotationcolour]
+            },
+            x: bounds.x,
+            y: bounds.y
+        });
+
+        drawable.shapes.push(shape);
+
+        return drawable;
+    }
+});
+
+M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
+M.assignfeedback_editpdf.annotationrectangle = ANNOTATIONRECTANGLE;
diff --git a/mod/assign/feedback/editpdf/yui/src/editor/js/annotationstamp.js b/mod/assign/feedback/editpdf/yui/src/editor/js/annotationstamp.js
new file mode 100644 (file)
index 0000000..5b816f5
--- /dev/null
@@ -0,0 +1,158 @@
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Class representing a stamp.
+ *
+ * @namespace M.assignfeedback_editpdf
+ * @class annotationstamp
+ * @extends annotation
+ * @module moodle-assignfeedback_editpdf-editor
+ */
+ANNOTATIONSTAMP = function(config) {
+    ANNOTATIONSTAMP.superclass.constructor.apply(this, [config]);
+};
+
+ANNOTATIONSTAMP.NAME = "annotationstamp";
+ANNOTATIONSTAMP.ATTRS = {};
+
+Y.extend(ANNOTATIONSTAMP, M.assignfeedback_editpdf.annotation, {
+    /**
+     * Draw a stamp annotation
+     * @protected
+     * @method draw
+     * @return M.assignfeedback_editpdf.drawable
+     */
+    draw : function() {
+        var drawable = new M.assignfeedback_editpdf.drawable(this.editor),
+            drawingregion = Y.one(SELECTOR.DRAWINGREGION),
+            node,
+            position;
+
+        position = this.editor.get_window_coordinates(new M.assignfeedback_editpdf.point(this.x, this.y));
+        node = Y.Node.create('<div/>');
+        node.setStyles({
+            'display': 'inline-block',
+            'backgroundImage': 'url(' + this.path + ')',
+            'width': (this.endx - this.x),
+            'height': (this.endy - this.y),
+            'backgroundSize': '100%',
+            'zIndex': 50
+        });
+
+        drawingregion.append(node);
+        node.setX(position.x);
+        node.setY(position.y);
+
+        // Pass throught the event handlers on the div.
+        node.on('gesturemovestart', this.editor.edit_start, null, this.editor);
+        node.on('gesturemove', this.editor.edit_move, null, this.editor);
+        node.on('gesturemoveend', this.editor.edit_end, null, this.editor);
+
+        drawable.nodes.push(node);
+
+        this.drawable = drawable;
+        return ANNOTATIONSTAMP.superclass.draw.apply(this);
+    },
+
+    /**
+     * Draw the in progress edit.
+     *
+     * @public
+     * @method draw_current_edit
+     * @param M.assignfeedback_editpdf.edit edit
+     */
+    draw_current_edit : function(edit) {
+        var bounds = new M.assignfeedback_editpdf.rect(),
+            drawable = new M.assignfeedback_editpdf.drawable(this.editor),
+            drawingregion = Y.one(SELECTOR.DRAWINGREGION),
+            node,
+            position;
+
+        bounds.bound([edit.start, edit.end]);
+        position = this.editor.get_window_coordinates(new M.assignfeedback_editpdf.point(bounds.x, bounds.y));
+
+        node = Y.Node.create('<div/>');
+        node.setStyles({
+            'display': 'inline-block',
+            'backgroundImage': 'url(' + edit.stamp + ')',
+            'width': bounds.width,
+            'height': bounds.height,
+            'backgroundSize': '100%',
+            'zIndex': 50
+        });
+
+        drawingregion.append(node);
+        node.setX(position.x);
+        node.setY(position.y);
+
+        drawable.nodes.push(node);
+
+        return drawable;
+    },
+
+    /**
+     * Promote the current edit to a real annotation.
+     *
+     * @public
+     * @method init_from_edit
+     * @param M.assignfeedback_editpdf.edit edit
+     */
+    init_from_edit : function(edit) {
+        var bounds = new M.assignfeedback_editpdf.rect();
+        bounds.bound([edit.start, edit.end]);
+
+        if (bounds.width < 40) {
+            bounds.width = 40;
+        }
+        if (bounds.height < 40) {
+            bounds.height = 40;
+        }
+        this.gradeid = this.editor.get('gradeid');
+        this.pageno = this.editor.currentpage;
+        this.x = bounds.x;
+        this.y = bounds.y;
+        this.endx = bounds.x + bounds.width;
+        this.endy = bounds.y + bounds.height;
+        this.colour = edit.annotationcolour;
+        this.path = edit.stamp;
+    },
+
+    /**
+     * Move an annotation to a new location.
+     * @public
+     * @param int newx
+     * @param int newy
+     * @method move_annotation
+     */
+    move : function(newx, newy) {
+        var diffx = newx - this.x,
+            diffy = newy - this.y;
+
+        this.x += diffx;
+        this.y += diffy;
+        this.endx += diffx;
+        this.endy += diffy;
+
+        if (this.drawable) {
+            this.drawable.erase();
+        }
+        this.editor.drawables.push(this.draw());
+    }
+
+});
+
+M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
+M.assignfeedback_editpdf.annotationstamp = ANNOTATIONSTAMP;
diff --git a/mod/assign/feedback/editpdf/yui/src/editor/js/stamppicker.js b/mod/assign/feedback/editpdf/yui/src/editor/js/stamppicker.js
new file mode 100644 (file)
index 0000000..71aad62
--- /dev/null
@@ -0,0 +1,105 @@
+var STAMPPICKER_NAME = "Colourpicker",
+    STAMPPICKER;
+
+/**
+ * STAMPPICKER
+ * This is a drop down list of stamps.
+ *
+ * @namespace M.assignfeedback_editpdf.stamppicker
+ * @class dropdown
+ * @constructor
+ * @extends Y.Base
+ */
+STAMPPICKER = function(config) {
+    STAMPPICKER.superclass.constructor.apply(this, [config]);
+};
+
+Y.extend(STAMPPICKER, M.assignfeedback_editpdf.dropdown, {
+
+    /**
+     * Initialise the menu.
+     *
+     * @method initializer
+     * @return void
+     */
+    initializer : function(config) {
+        var stamplist = Y.Node.create('<ul role="menu" class="assignfeedback_editpdf_menu"/>');
+
+        // Build a list of stamped buttons.
+        Y.each(this.get('stamps'), function(stamp) {
+            var button, listitem, title;
+
+            title = M.util.get_string('stamp', 'assignfeedback_editpdf');
+            button = Y.Node.create('<button><img height="40" alt="' + title + '" src="' + stamp + '"/></button>');
+            button.setAttribute('data-stamp', stamp);
+            button.setStyle('backgroundImage', 'none');
+            listitem = Y.Node.create('<li/>');
+            listitem.append(button);
+            stamplist.append(listitem);
+        }, this);
+
+
+        // Set the call back.
+        stamplist.delegate('click', this.callback_handler, 'button', this);
+        stamplist.delegate('key', this.callback_handler, 'down:13', 'button', this);
+
+        // Set the accessible header text.
+        this.set('headerText', M.util.get_string('stamppicker', 'assignfeedback_editpdf'));
+
+        // Set the body content.
+        this.set('bodyContent', stamplist);
+
+        STAMPPICKER.superclass.initializer.call(this, config);
+    },
+    callback_handler : function(e) {
+        var callback = this.get('callback'),
+            callbackcontext = this.get('context'),
+            bind;
+
+        this.hide();
+
+        // Call the callback with the specified context.
+        bind = Y.bind(callback, callbackcontext, e);
+
+        bind();
+    }
+}, {
+    NAME : STAMPPICKER_NAME,
+    ATTRS : {
+        /**
+         * The list of stamps this stamp picker supports.
+         *
+         * @attribute stamps
+         * @type String[] - the stamp filenames.
+         * @default {}
+         */
+        stamps : {
+            value : []
+        },
+
+        /**
+         * The function called when a new stamp is chosen.
+         *
+         * @attribute callback
+         * @type function
+         * @default null
+         */
+        callback : {
+            value : null
+        },
+
+        /**
+         * The context passed to the callback when a stamp is chosen.
+         *
+         * @attribute context
+         * @type Y.Node
+         * @default null
+         */
+        context : {
+            value : null
+        }
+    }
+});
+
+M.assignfeedback_editpdf = M.assignfeedback_editpdf || {};
+M.assignfeedback_editpdf.stamppicker = STAMPPICKER;