diff --git a/src/ecmascript/spidermonkey/element.c b/src/ecmascript/spidermonkey/element.c
index 72b582d04..585e29381 100644
--- a/src/ecmascript/spidermonkey/element.c
+++ b/src/ecmascript/spidermonkey/element.c
@@ -73,6 +73,7 @@ static bool element_get_property_nextElementSibling(JSContext *ctx, unsigned int
 static bool element_get_property_nextSibling(JSContext *ctx, unsigned int argc, JS::Value *vp);
 static bool element_get_property_outerHtml(JSContext *ctx, unsigned int argc, JS::Value *vp);
 static bool element_set_property_outerHtml(JSContext *ctx, unsigned int argc, JS::Value *vp);
+static bool element_get_property_parentElement(JSContext *ctx, unsigned int argc, JS::Value *vp);
 static bool element_get_property_parentNode(JSContext *ctx, unsigned int argc, JS::Value *vp);
 static bool element_get_property_previousElementSibling(JSContext *ctx, unsigned int argc, JS::Value *vp);
 static bool element_get_property_previousSibling(JSContext *ctx, unsigned int argc, JS::Value *vp);
@@ -109,6 +110,7 @@ JSPropertySpec element_props[] = {
 	JS_PSG("nextElementSibling",	element_get_property_nextElementSibling, JSPROP_ENUMERATE),
 	JS_PSG("nextSibling",	element_get_property_nextSibling, JSPROP_ENUMERATE),
 	JS_PSGS("outerHTML",	element_get_property_outerHtml, element_set_property_outerHtml, JSPROP_ENUMERATE),
+	JS_PSG("parentElement",	element_get_property_parentElement, JSPROP_ENUMERATE),
 	JS_PSG("parentNode",	element_get_property_parentNode, JSPROP_ENUMERATE),
 	JS_PSG("previousElementSibling",	element_get_property_previousElementSibling, JSPROP_ENUMERATE),
 	JS_PSG("previousSibling",	element_get_property_previousSibling, JSPROP_ENUMERATE),
@@ -666,6 +668,52 @@ element_get_property_nextSibling(JSContext *ctx, unsigned int argc, JS::Value *v
 	return true;
 }
 
+static bool
+element_get_property_parentElement(JSContext *ctx, unsigned int argc, JS::Value *vp)
+{
+	JS::CallArgs args = CallArgsFromVp(argc, vp);
+	JS::RootedObject hobj(ctx, &args.thisv().toObject());
+
+	struct view_state *vs;
+	JSCompartment *comp = js::GetContextCompartment(ctx);
+
+	if (!comp) {
+		return false;
+	}
+
+	struct ecmascript_interpreter *interpreter = JS_GetCompartmentPrivate(comp);
+
+	/* This can be called if @obj if not itself an instance of the
+	 * appropriate class but has one in its prototype chain.  Fail
+	 * such calls.  */
+	if (!JS_InstanceOf(ctx, hobj, &element_class, NULL))
+		return false;
+
+	vs = interpreter->vs;
+	if (!vs) {
+		return false;
+	}
+
+	xmlpp::Element *el = JS_GetPrivate(hobj);
+
+	if (!el) {
+		args.rval().setNull();
+		return true;
+	}
+
+	auto node = dynamic_cast<xmlpp::Element*>(el->get_parent());
+
+	if (!node) {
+		args.rval().setNull();
+		return true;
+	}
+
+	JSObject *elem = getElement(ctx, node);
+	args.rval().setObject(*elem);
+
+	return true;
+}
+
 static bool
 element_get_property_parentNode(JSContext *ctx, unsigned int argc, JS::Value *vp)
 {
diff --git a/test/ecmascript/parentElement.html b/test/ecmascript/parentElement.html
new file mode 100644
index 000000000..1a080558b
--- /dev/null
+++ b/test/ecmascript/parentElement.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<body>
+
+<p>Example list:</p>
+
+<ul>
+  <li id="myLI">Coffee</li>
+  <li>Tea</li>
+</ul>
+
+<p>Click the button to get the node name of the parent node of the li element in the list.</p>
+
+<button onclick="myFunction()">Try it</button>
+
+<p id="demo"></p>
+
+<script>
+function myFunction() {
+  var x = document.getElementById("myLI").parentElement.tagName;
+  alert(x);
+}
+</script>
+
+</body>
+</html>
\ No newline at end of file