javascript - HTML5/webcomponents: Call prototype function from template code -
i'm making tests using (or not) web components in single page app i'm creating.
here's example problem:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> </head> <body> <template id="atemplate"> <div style="border:1px solid red"> <p>text <input type="text"></p> <button>clickme</button> </div> </template> <script> var proto = object.create(htmlelement.prototype); proto.createdcallback = function () { var t = document.queryselector('#atemplate'); var clone = document.importnode(t.content, true); this.createshadowroot().appendchild(clone); }; proto.afunction = function() { alert("proto " + "text value?"); } document.registerelement('x-proto', {prototype: proto}); var protochild = object.create(proto); protochild.createdcallback = function () { proto.createdcallback.call(this) }; protochild.afunction = function() { alert("child " + "text value?"); } document.registerelement('x-proto-child', { prototype: proto }); </script> <x-proto></x-proto> <x-proto-child></x-proto-child> </body>
the problem cannot find way set "onclick" handler in button (inside template) calls method "afunction" in object created using prototype. method should called in correct object instance, access internal dom components, , attributes , functions in prototype.
i've tried lot of things, (binding event after construction, using js or jquery, using created/attached callbacks, ) i'm out of ideas.
thanks in advance.
edit:
thanks minusfour answer. line:
clone.queryselector('button').addeventlistener('click', this.afunction);
in trying do, anyway, resulted in (same jquery, testing compatibilitiy):
$(this.showbutton).on("click", this.afunction.bind(this));
the "bind" makes 'this' aka container, complete component, available in js code, needed.
here's completed final example, may find helpful:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <script src="http://code.jquery.com/jquery-2.1.4.min.js"></script> </head> <body> <template id="atemplate"> <div style="border:1px solid darkgray;padding:10px;margin: 10px;"> <h2 class="thecaption"></h2> <p>text <input class="thetext" type="text"></p> <button class="showbutton">show val</button> <button class="closebutton">close</button> </div> </template> <script> // .bind method prototype.js if (!function.prototype.bind) { // check if native implementation available function.prototype.bind = function () { var fn = this, args = array.prototype.slice.call(arguments), object = args.shift(); return function () { return fn.apply(object, args.concat(array.prototype.slice.call(arguments))); }; }; } function createproto() { $("#spawnpoint").append("<x-proto x-caption='proto'></x-proto>"); } function createchild() { $("#spawnpoint").append("<x-proto-child x-caption='a child of proto'></x-proto-child>"); } var proto = object.create(htmlelement.prototype); object.defineproperty(proto, "x-caption", {value: "no caption"}); proto.createdcallback = function () { var t = document.queryselector('#atemplate'); var clone = document.importnode(t.content, true); this.shadowroot = this.createshadowroot(); this.shadowroot.appendchild(clone); $(clone).children("div").append("<p>ssss</p>") this.showbutton = this.shadowroot.queryselector('.showbutton'); this.closebutton = this.shadowroot.queryselector('.closebutton'); this.shadowroot.queryselector('.thecaption').textcontent = $(this).attr("x-caption"); this.thetext = this.shadowroot.queryselector('.thetext'); $(this.showbutton).on("click", this.afunction.bind(this)); $(this.closebutton).on("click", this.close.bind(this)); }; proto.afunction = function () { alert("in proto = " + $(this.thetext).val()); } proto.close = function () { $(this).detach(); } document.registerelement('x-proto', {prototype: proto}); var protochild = object.create(proto); protochild.createdcallback = function () { proto.createdcallback.call(this); }; protochild.afunction = function () { alert("overrided in child = " + $(this.thetext).val()); } document.registerelement('x-proto-child', { prototype: protochild }); </script> <button onclick="javascript:createproto()">create proto</button> <button onclick="javascript:createchild()">create child</button> <div id="spawnpoint"> </div> </body>
i believe add listener importednode
(clone
in case).
clone.queryselector('button').addeventlistener('click', function(){ //code logic here });
you meant:
document.registerelement('x-proto-child', { prototype: protochild });
here's how like:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> </head> <body> <template id="atemplate"> <div style="border:1px solid red"> <p>text <input type="text"></p> <button>clickme</button> </div> </template> <script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/0.7.14/webcomponents.min.js"></script> <script> var proto = object.create(htmlelement.prototype); proto.createdcallback = function () { var t = document.queryselector('#atemplate'); var clone = document.importnode(t.content, true); clone.queryselector('button').addeventlistener('click', this.afunction); this.createshadowroot().appendchild(clone); }; proto.afunction = function() { alert("proto " + "text value?"); } document.registerelement('x-proto', {prototype: proto}); var protochild = object.create(proto); protochild.createdcallback = function () { proto.createdcallback.call(this); console.log(this.template); /*this.template.queryselector('button').addeventlistener('click', function(){ console.log('child'); });*/ }; protochild.afunction = function() { alert("child " + "text value?"); } document.registerelement('x-proto-child', { prototype: protochild }); </script> <x-proto></x-proto> <x-proto-child></x-proto-child> </body>
Comments
Post a Comment