wlxml: edumed - order exercise
authorAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Tue, 5 Aug 2014 08:48:07 +0000 (10:48 +0200)
committerAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Thu, 14 Aug 2014 14:26:13 +0000 (16:26 +0200)
karma.conf.js
src/wlxml/extensions/edumed/edumed.js [new file with mode: 0644]
src/wlxml/extensions/edumed/edumed.test.js [new file with mode: 0644]
src/wlxml/extensions/edumed/order.xml [new file with mode: 0644]
src/wlxml/wlxml.js

index 9f84f89..913c295 100644 (file)
@@ -9,6 +9,7 @@ files = [
   {pattern: 'libs/*.js', included: false},
   {pattern: 'src/**/*.js', included: false},
   {pattern: 'src/**/*.html', included: false},
+  {pattern: 'src/**/*.xml', included: false},
   'tests/main.js',
 ];
 
diff --git a/src/wlxml/extensions/edumed/edumed.js b/src/wlxml/extensions/edumed/edumed.js
new file mode 100644 (file)
index 0000000..3176ae0
--- /dev/null
@@ -0,0 +1,163 @@
+define(function(require) {
+    
+'use strict';
+
+var _ = require('libs/underscore'),
+    orderExerciseTemplate = require('libs/text!./order.xml');
+
+var Item = function(node, exerciseNode) {
+    Object.defineProperty(this, 'text', {
+        get: function() {
+            /* globals Node */
+            var firstNode = node.contents()[0];
+            if(firstNode && firstNode.nodeType === Node.TEXT_NODE) {
+                return firstNode.getText();
+            }
+            return '';
+        }
+    });
+    this.node = node;
+    this.exerciseNode = exerciseNode;
+};
+_.extend(Item.prototype, {
+    setText: function(text) {
+        /* globals Node */
+        var contents = this.node.contents();
+        if(contents.length === 1 && contents[0].nodeType === Node.TEXT_NODE) {
+            contents[0].setText(text);
+        } else {
+            contents.forEach(function(childNode) {
+                childNode.detach();
+            });
+            contents.append({text: text});
+        }
+    },
+    remove: function() {
+        this.node.detach();
+    },
+    getAnswer: function() {
+        var toret = parseInt(this.node.getAttr('answer'), 10);
+        if(_.isNaN(toret)) {
+            toret = 1;
+        }
+        return toret;
+    },
+    setAnswer: function(answer) {
+        answer = parseInt(answer, 10);
+        var prev = answer;
+        if(!_.isNumber(answer)) {
+            return;
+        }
+        
+        this.exerciseNode.object.getItems()
+            .sort(function(item1, item2) {
+                if(item1.getAnswer() > item2.getAnswer()) {
+                    return 1;
+                }
+                return -1;
+            })
+            .some(function(item) {
+                if(item.getAnswer() === prev && !item.node.sameNode(this.node)) {
+                    item.node.setAttr('answer', prev+1);
+                    prev = prev + 1;
+                }
+            }.bind(this));
+        this.node.setAttr('answer', answer);
+        
+    }
+});
+
+var isItemsList = function(node) {
+    return node.is('list.orderable');
+};
+
+
+var extension = {wlxmlClass: {'exercise.order': {
+    methods: {
+        isContextRoot: function(node) {
+            return this.object.isItemNode(node) || this.sameNode(node);
+        },
+        getItems: function() {
+            var toret = [],
+                exerciseNode = this;
+
+            this.contents().some(function(node) {
+                if(isItemsList(node)) {
+                    node.contents()
+                        .filter(function(node) {
+                            return node.is('item.answer');
+                        })
+                        .forEach(function(node) {
+                            toret.push(new Item(node, exerciseNode));
+                        });
+                    return true;
+                }
+            });
+            return toret;
+        },
+        isItemNode: function(node) {
+            var list;
+            if(!node) {
+                return;
+            }
+            this.contents().some(function(node) {
+                if(isItemsList(node)) {
+                    list = node;
+                    return true;
+                }
+            });
+            return list && list.sameNode(node.parent());
+        },
+        getDescription: function() {
+            var toret = [];
+            this.contents().some(function(node) {
+                if(isItemsList(node)) {
+                   return true;
+                }
+                toret.push(node);
+            });
+            return toret;
+        }
+    },
+    transformations: {
+        addItem: function(text) {
+            var toret;
+            this.contents().some(function(node) {
+                if(isItemsList(node)) {
+                    var itemNode = this.document.createDocumentNode({tagName: 'div', attrs: {'class': 'item.answer', answer: this.object.getItems().length+1}});
+                    toret = itemNode.append({text: text});
+                    node.append(itemNode);
+                    return true;
+                }
+            }.bind(this));
+            return toret;
+        },
+        setDescription: function(text) {
+            this.contents().some(function(node) {
+                var textNode;
+                if(node.is('p')) {
+                    textNode = node.contents()[0];
+                    if(!(textNode && textNode.nodeType === Node.TEXT_NODE)) {
+                        node.prepend({text:text});
+                    } else {
+                        textNode.setText(text);
+                    }
+                    return true;
+                }
+            });
+        }
+    }
+}}};
+
+extension.document = {
+    methods: {
+         edumedCreateExerciseNode: function(klass) {
+            void(klass);
+            return this.createDocumentNode(orderExerciseTemplate);
+         }
+    }
+};
+
+return extension;
+
+});
\ No newline at end of file
diff --git a/src/wlxml/extensions/edumed/edumed.test.js b/src/wlxml/extensions/edumed/edumed.test.js
new file mode 100644 (file)
index 0000000..c039f0d
--- /dev/null
@@ -0,0 +1,70 @@
+define(function(require) {
+    
+'use strict';
+/* globals describe, it */
+
+var chai = require('libs/chai'),
+    wlxml = require('wlxml/wlxml');
+    //edumedExtension = require('./edumed.js');
+
+var expect = chai.expect;
+
+
+var getDocumentFromXML = function(xml, options) {
+    var doc = wlxml.WLXMLDocumentFromXML(xml, options || {});
+    //doc.registerExtension(edumedExtension);
+    return doc;
+};
+
+
+describe('Setting answer', function() {
+    it('sets answer (1)', function() {
+        /* jshint multistr:true */
+        var doc = getDocumentFromXML('\
+                <div class="exercise.order">\
+                    <div class="list.orderable">\
+                        <div class="item.answer" answer="3">Element 3</div>\
+                        <div class="item.answer" answer="1">Element 1</div>\
+                        <div class="item.answer" answer="2">Element 2</div>\
+                    </div>\
+                </div>');
+
+        doc.root.object.getItems()[2].setAnswer(1);
+
+        var items = doc.root.object.getItems();
+
+        expect(items[0].getAnswer()).to.equal(3);
+        expect(items[1].getAnswer()).to.equal(2);
+        expect(items[2].getAnswer()).to.equal(1);
+
+    });
+    it('sets answer (2)', function() {
+        /* jshint multistr:true */
+        var doc = getDocumentFromXML('\
+                <div class="exercise.order">\
+                    <div class="list.orderable">\
+                        <div class="item.answer" answer="1">Element 1</div>\
+                        <div class="item.answer" answer="2">Element 2</div>\
+                        <div class="item.answer" answer="3">Element 3</div>\
+                    </div>\
+                </div>');
+        doc.transaction(function() {
+            doc.root.object.getItems()[2].setAnswer(2);
+        }, {
+            error: function(e) { throw e;}
+        });
+        
+
+        var items = doc.root.object.getItems();
+
+        expect(items[0].getAnswer()).to.equal(1);
+        expect(items[1].getAnswer()).to.equal(3);
+        expect(items[2].getAnswer()).to.equal(2);
+
+    });
+});
+
+
+
+
+});
\ No newline at end of file
diff --git a/src/wlxml/extensions/edumed/order.xml b/src/wlxml/extensions/edumed/order.xml
new file mode 100644 (file)
index 0000000..167e981
--- /dev/null
@@ -0,0 +1,5 @@
+<div class="exercise.order">
+  <div class="p"></div>
+  <div class="list.orderable">
+  </div>
+</div>
\ No newline at end of file
index 262004c..cb43f07 100644 (file)
@@ -4,8 +4,9 @@ define([
     'smartxml/smartxml',
     'smartxml/transformations',
     'wlxml/extensions/metadata/metadata',
-    'wlxml/extensions/comments/comments'
-], function($, _, smartxml, transformations, metadataExtension, commentExtension) {
+    'wlxml/extensions/comments/comments',
+    'wlxml/extensions/edumed/edumed'
+], function($, _, smartxml, transformations, metadataExtension, commentExtension, edumedExtension) {
     
 'use strict';
 
@@ -184,7 +185,7 @@ $.extend(WLXMLTextNode.prototype, WLXMLDocumentNodeMethods, {
 var WLXMLDocument = function(xml, options) {
     this.classMethods = {};
     this.classTransformations = {};
-    smartxml.Document.call(this, xml, [metadataExtension, commentExtension]);
+    smartxml.Document.call(this, xml, [metadataExtension, commentExtension, edumedExtension]);
     this.options = options;
 };