The Widget Tutorial
WebMacro manual:tutorials.widget.Page
Source
<div class="container" data-widget="tutorials.SyncWidget"> <div class="row"> <div class="col-xs-12"> <h1>Ikona Panther Widgets</h1> <a href="/manual/content/tutorials.doc.WidgetTutorial" target="_blank">Widget Tutorial</a> <hr> </div> </div> <div class="row"> <div class="col-sm-6" data-widget="tutorials.FormWidget"> <h4>Register new email</h4> <hr> <div> <input type="text" value="" class="form-control" data-form="EmailInput" placeholder="Enter email address"> </div> <hr> <button class="btn btn-success" data-form="SubmitEmailButton">Store Email</button> </div> <div class="col-sm-6" data-widget="tutorials.ListWidget" data-list-element-class="email-element"> <h4>Registered emails</h4> <hr> <p> <span data-list="EmailsCountLabel"></span> registered emails</p> <button class="btn btn-danger" data-list="EmptyEmailsButton">Empty emails</button> <hr> <ul class="nav nav-stacked nav-pills well" data-list="EmailsList"></ul> </div> </div> <div class="row"> <div class="col-xs-12"> <hr> <div class="hidden alert alert-success" data-sync="StatusOk"> Update from server successful </div> <div class="hidden alert alert-danger" data-sync="StatusErrorEmailAlreadyExists"> The email was already in the list </div> <hr> </div> </div> </div> <script> //this code should usually be included in the main css //it is just here to show how to get panther widgets started //after page load $(function () { //global debug options var debug = true; //global is window in clients var global = window; //set scope to panther var scope = panther = global.panther = {}; /* include panther.ClientLib */ #{ panther.ClientLib } //set scope to tutorials scope = global.tutorials = {}; //create new widgets singleton for test page var widgets = scope.widgets = new panther.widgets.Widgets(); /* include tutorials.widget.SyncWidget */ #{ tutorials.widget.SyncWidget } /* include tutorials.widget.FormWidget */ #{ tutorials.widget.FormWidget } /* include tutorials.widget.ListWidget */ #{ tutorials.widget.ListWidget } //add global error handler scope.widgets.on("Error", function handleErrors(type, error) { if (console.error) { console.error(error); } else { console.log(error); if (error.stack) { console.log(error.stack); } } }); //intialized the existing widgets on this page widgets.init(); //print all widgets console.log("There are " + widgets.size() + " widgets in this page", widgets.list()); }); </script>
WebMacro manual:tutorials.widget.FormWidget
Source
scope.FormWidget = (function (panther) { panther.widgets.AbstractWidget.extend(FormWidget); //load universal for validation var scope = FormWidget; #{ tutorials.widget.ValidateEmail } function FormWidget() { FormWidget.prototype.super.constructor.call(this); } FormWidget.prototype.init = function (element) { FormWidget.prototype.super.init.call(this, element); this.updateElements(); this.emailInput.focus(); }; FormWidget.prototype.initEmailInput = function (emailInput) { this.emailInput = $(emailInput); var self = this; this.emailInput.on("keyup", function () { self.updateElements(); }); this.emailInput.on("change", function () { self.submitEmail(); }); }; FormWidget.prototype.initSubmitEmailButton = function (submitEmailButton) { this.submitEmailButton = $(submitEmailButton); var self = this; this.submitEmailButton.on('click', function () { self.submitEmail(); }); }; FormWidget.prototype.triggerAddEmail = function (email) { }; FormWidget.prototype.submitEmail = function () { if (this.updateElements()) { this.triggerAddEmail(this.emailInput.val()); this.emailInput.val(""); this.updateElements(); } }; FormWidget.prototype.updateElements = function () { //valid mail if (FormWidget.validateEmail(this.emailInput.val())) { this.emailInput.parent().removeClass("has-error"); this.submitEmailButton.removeClass("disabled"); return true; } //invalid mail else { this.emailInput.parent().addClass("has-error"); this.submitEmailButton.addClass("disabled"); return false; } }; return FormWidget; })(panther);
WebMacro manual:tutorials.widget.ListWidget
Source
scope.ListWidget = (function (panther) { panther.widgets.AbstractWidget.extend(ListWidget); function ListWidget() { ListWidget.prototype.super.constructor.call(this); } ListWidget.prototype.init = function (element) { ListWidget.prototype.super.init.call(this, element); this.emailListElementClass = this.element.data("listElementClass") || ""; this.updateElements([]); }; ListWidget.prototype.initEmailsCountLabel = function (emailsCountLabel) { this.emailsCountLabel = $(emailsCountLabel); }; ListWidget.prototype.initEmptyEmailsButton = function (emptyEmailsButton) { this.emptyEmailsButton = $(emptyEmailsButton); var self = this; //delete all item from list this.emptyEmailsButton.on("click", function () { self.triggerRemoveAllEmails(); }); }; ListWidget.prototype.initEmailsList = function (emailsList) { this.emailsList = $(emailsList); var self = this; //delete one item from list this.emailsList.on("click", "a[data-list='EmailListElement']", function (evt) { evt.preventDefault(); self.triggerRemoveEmail($(this).text()); }); }; ListWidget.prototype.triggerRemoveAllEmails = function () { }; ListWidget.prototype.triggerRemoveEmail = function (email) { }; ListWidget.prototype.onUpdateEmails = function (emails) { this.updateElements(emails); }; ListWidget.prototype.updateElements = function (emails) { //set label to email conunt this.emailsCountLabel.text(emails.length); //update list this.emailsList.empty(); for (var i = 0; i < emails.length; i++) { this.emailsList.append( $("<li>") .addClass(this.emailListElementClass) .append( $("<a>") .attr("href", "#") .attr("data-list", "EmailListElement") .text(emails[i]) ) ); } }; return ListWidget; })(panther);
WebMacro manual:tutorials.widget.SyncWidget
Source
scope.SyncWidget = (function (panther) { panther.widgets.AbstractWidget.extend(SyncWidget); function SyncWidget() { SyncWidget.prototype.super.constructor.call(this); this.apiUrl = "#{content.home('tutorials.widget.Api')}"; } SyncWidget.prototype.initStatusOk = function (statusOk) { this.statusOk = $(statusOk); }; SyncWidget.prototype.initStatusErrorEmailAlreadyExists = function (statusErrorEmailAlreadyExists) { this.statusErrorEmailAlreadyExists = $(statusErrorEmailAlreadyExists); }; SyncWidget.prototype.triggerUpdateEmails = function (emails) { }; SyncWidget.prototype.onAddEmail = function (email) { updateEmailsWithServer.call(this, { ac: "add", email: email }); }; SyncWidget.prototype.onRemoveEmail = function (email) { updateEmailsWithServer.call(this, { ac: "remove", email: email }); }; SyncWidget.prototype.onRemoveAllEmails = function () { updateEmailsWithServer.call(this, { ac: "removeAll" }); }; SyncWidget.prototype.onWidgetsInitSuccess = function () { updateEmailsWithServer.call(this, { ac: "list" }); }; SyncWidget.prototype.updateStatus = function (data) { if (data.status === "OK") { this.statusOk.removeClass("hidden"); this.statusErrorEmailAlreadyExists.addClass("hidden"); } else if (data.status === "EMAIL_ALREADY_EXISTS") { this.statusOk.addClass("hidden"); this.statusErrorEmailAlreadyExists.removeClass("hidden"); } }; function updateEmailsWithServer(data) { var self = this; $.ajax(this.apiUrl, { type: "post", cache: false, dataType: "json", data: data, success: function (data) { self.updateStatus(data); self.triggerUpdateEmails(data.emails); }, error: function (data) { self.updateStatus(data.responseJSON); throw new Error("Invalid update from server " + JSON.stringify(data)); } }); } return SyncWidget; })(panther);
WebMacro manual:tutorials.widget.Api
Source
require("request"); require("response"); require("session"); this.EmailApi = (function () { var SESSION_KEY = "tutorials.widget.emails"; //load universal for validation this.scope = EmailApi; load("tutorials.widget.ValidateEmail"); function EmailApi() {} EmailApi.prototype.handle = function (action) { if (!action) { throw new Error("ERROR_UNDEFINED_ACTION"); } if (action.length > 50) { throw new Error("ERROR_INVALID_ACTION"); } var actionName = "do" + action[0].toUpperCase() + action.slice(1); if (typeof (this[actionName]) === "function") { return this[actionName](); } else { throw new Error("ERROR_UNKNOWN_ACTION"); } }; EmailApi.prototype.doList = function () { var result = {}; result.status = "OK"; result.emails = getEmails(); return result; }; EmailApi.prototype.doAdd = function () { var result = {}; result.status = "OK"; var emails = getEmails(); var email = request.parameter("email"); //just allow to add valid emails if (!EmailApi.validateEmail(email)) { throw new Error("EMAIL_INVALID"); } //dont alow to add the same email multiple times var index = emails.indexOf(email); if (index > -1) { throw new Error("EMAIL_ALREADY_EXISTS"); } emails.push(email); setEmails(emails); result.emails = emails; return result; }; EmailApi.prototype.doRemove = function () { var result = {}; result.status = "OK"; var emails = getEmails(); var email = request.parameter("email"); var index = emails.indexOf(email); if (index > -1) { emails.splice(index, 1); } else { throw new Error("EMAIL_DOES_NOT_EXIST"); } setEmails(emails); result.emails = emails; return result; }; EmailApi.prototype.doRemoveAll = function () { var result = {}; result.status = "OK"; setEmails([]); result.emails = []; return result; }; function getEmails() { return JSON.parse(session.get(SESSION_KEY) || "[]"); } function setEmails(emails) { if (Array.isArray(emails)) { session.set(SESSION_KEY, JSON.stringify(emails)); } } return EmailApi; })(); function main() { try { var action = request.parameter("ac"); var emailApi = new EmailApi(); return JSON.stringify(emailApi.handle(action)); } catch (ex) { response.sendError(400, JSON.stringify({ status: ex.message })); } }
WebMacro manual:tutorials.widget.ValidateEmail
Source
(function ValidateEmail(scope) { scope.validateEmail = function (email) { return /^[a-z0-9\-_]?[a-z0-9.\-_]+[a-z0-9\-_]?@[a-z.-]+\.[a-z]{2,3}$/i.test(email); }; })(scope);