/* Part of SWISH Author: Jan Wielemaker E-mail: J.Wielemaker@cs.vu.nl WWW: http://www.swi-prolog.org Copyright (C): 2014-2017, VU University Amsterdam CWI Amsterdam All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @fileOverview * * RequireJS module providing some general support methods for handling * forms and functions to build Bootstrap forms easily. * * @version 0.1.0 * @author Jan Wielemaker, J.Wielemaker@vu.nl * @requires jquery */ define([ "jquery", "config", "modal", "laconic", "tagmanager" ], function($, config, modal) { var LABELWIDTH = 3; var form = { /** * Serialize a form as an object. The following normalizations are * performed: * - Form fields that have an empty string are ignored unless * `ignore_empty` is `true` * - The value from a ``is converted * into a JavaScript boolean. * - The value of a tag-list is converted into a list of strings. * @returns {Object} holding the name/value pairs of the form */ serializeAsObject: function(form, ignore_empty) { var arr = form.serializeArray(); var inset = []; var obj = {}; // get arrays of checkboxes form.find("div.checkboxes.array").each(function() { var elem = $(this); var set = []; elem.find("input:checked").each(function() { var name = $(this).attr("name"); set.push(name); }); elem.find("input").each(function() { var name = $(this).attr("name"); inset.push(name); }); obj[elem.attr("name")] = set; }); for(var i=0; i 0 ) { var group = input.closest(".form-group"); if ( input.parent().hasClass("input-group") ) input = input.parent(); group.addClass("has-error"); input.after($.el.p({class:"help-block with-errors"}, msg)); } else { alert("Missing value for "+field); } }, showDialog: function(data) { $(".swish-event-receiver").trigger("dialog", data); }, /** * Invoke the central broadcasting of SWISH * @param {String} event is the event name * @param {any} [data] is the associated data */ formBroadcast: function(event, data) { $(".swish-event-receiver").trigger(event, data); }, dyn_clear: function(form, onclear) { form.find('.has-clear input[type="text"]').on('input propertychange', function() { var $this = $(this); var visible = Boolean($this.val()); $this.siblings('.form-control-clear').toggleClass('hidden', !visible); }).trigger('propertychange'); form.find('.form-control-clear').click(function() { var input = $(this).siblings('input[type="text"]'); input.val('').trigger('propertychange').focus(); if ( onclear ) onclear.call(input); }); }, fields: { fileName: function(name, public, example, disabled) { var labeltext; var empty = "(leave empty for generated random name)" var fork, input; var community_examples = config.swish.community_examples && example != undefined; if ( community_examples ) labeltext = "Public | Example | name"; else labeltext = "Public | name"; var elem = $.el.div({class:"form-group"}, label("name", labeltext), $.el.div({class:valgridw()}, $.el.div({class:"input-group"}, $.el.span({class:"input-group-addon", title:"If checked, other users can find this program" }, checkbox("public", { checked: public })), community_examples ? $.el.span({class:"input-group-addon", title:"If checked, add to examples menu" }, checkbox("example", { checked: example })) : undefined, input = textInput("name", {placeholder:"Name " + empty, title:"Public name of your program", value:name, disabled:disabled}), name ? fork = $.el.span({class:"input-group-btn" }, $.el.button({ class: "btn btn-success", type: "button" }, "Fork")) : undefined ))); if ( fork ) { $(fork).on("click", function() { var btn = $(input).closest("form").find(".btn.btn-primary"); $(input).attr("placeholder", "Fork as " + empty); $(input).val(""); btn.text(btn.text().replace("Update", "Fork")); }); } return elem; }, title: function(title) { var elem = $.el.div({class:"form-group"}, label("title", "Title"), $.el.div({class:valgridw()}, textInput("title", {placeholder:"Descriptive title", value:title}))); return elem; }, /** * @param {String} [identity] if provided, this indicates that the * author cannot be changed. */ author: function(author, identity) { var options = { placeholder:"Your name", value:author }; if ( author && identity ) { options.readonly = true; options.title = "Verified author name"; } var elem = $.el.div({class:"form-group"}, label("author", "Author"), $.el.div({class:valgridw()}, textInput("author", options))); return elem; }, link: function(link) { var options = { readonly: true, title: "Permalink", value: link }; var elem = $.el.div({class:"form-group"}, label("link", "Link"), $.el.div({class:valgridw()}, textInput("link", options))); return elem; }, date: function(stamp, labels, name) { name = name||label; var elem = $.el.div({class:"form-group"}, label(name, labels), $.el.div({class:valgridw()}, textInput(name, {disabled: true, value:new Date(stamp*1000).toLocaleString() }))); return elem; }, description: function(description) { var elem = $.el.div({class:"form-group"}, label("description", "Description"), $.el.div({class:valgridw()}, textarea("description", {value:description}))); return elem; }, commit_message: function(msg) { var elem = $.el.div({class:"form-group"}, label("commit_message", "Changes"), $.el.div({class:valgridw()}, textarea("commit_message", { value:msg, placeholder:"Describe your changes here" }))); return elem; }, description: function(msg) { var elem = $.el.div({class:"form-group"}, label("description", "Description"), $.el.div({class:valgridw()}, textarea("description", { value:msg, placeholder:"Description" }))); return elem; }, tags: function(tags) { var elem = $.el.div({class:"form-group"}, label("tags", "Tags"), $.el.div({class:valgridw()}, tagInput("tags", "Tags help finding this code", tags))); return elem; }, /** * Provide checkboxes for determining who may save a new version * of this file */ modify: function(who, canmodify) { var fields = []; var opts = { name:"modify", label:"Can save new version", type:"array" }; function add(key, label) { fields.push({ name:key, label:label, value:who.indexOf(key) != -1, readonly: !canmodify }); } add("any", "Anyone"); add("login", "Logged in users"); add("owner", "Only me"); if ( !canmodify ) opts.title = "Only logged in users and owners can set permissions"; else opts.title = "Specify who can save an updated version of this file"; return form.fields.checkboxes(fields, opts); }, follow: function(email) { return form.fields.checkboxes( [ { name: "follow", label: "Follow this document", value:!!email, readonly:!email } ], { name:"options", label:"", title: "Notify about activity (updates, chat)\n"+ "Requires being logged in with valid email" }); }, projection: function(projection) { var elem = $.el.div({class:"form-group"}, label("projection", "Projection"), $.el.div({class:valgridw()}, textInput("projection", {placeholder:"Columns", value:projection}))); return elem; }, csvFormat: function(list, format) { var elem; list = list||["prolog"]; format = format||list[0]; if ( list.length == 1 ) { elem = $.el.input({type:"hidden", name:"format", value:list[0]}); } else { elem = $.el.div({class:"form-group"}, label("format", "Format"), $.el.div({class:valgridw()}, select("format", list, {value:format}))); } return elem; }, /** * Ask for limit and distinct to modify the solution set. * @param {Number} [limit] is the max number of solutions to * return * @param {Boolean} [distinct] requests only to return distinct * solutions. */ limit: function(limit, distinct) { var elem = $.el.div({class:"form-group"}, label("name", "Distinct | limit"), $.el.div({class:valgridw()}, $.el.div({class:"input-group"}, $.el.span({class:"input-group-addon", title:"If checked only return distinct results" }, checkbox("distinct", { checked: distinct })), textInput("limit", {placeholder:"Maximum result count (blank for unlimited)", title:"Limit results", value:limit})))); return elem; }, /** * @param {Array} boxes is a list of checkbox specifications. * Uses .name, .label, .value (Boolean) and .readonly */ checkboxes: function(boxes, options) { var boxel; options = $.extend({name:"options", label:"Options", col:LABELWIDTH}, options||{}); var dopts = { class: "checkboxes col-xs-"+(12-options.col), name: options.name }; if ( options.title ) dopts.title = options.title; if ( options.type ) dopts.class += " "+options.type; var elem = $.el.div({class:"form-group"}, label(options.name, options.label, options.col), boxel = $.el.div(dopts)); for(var k=0; k input[name=Name]").val(); * @param {String} name is the name of the radio button * @param {Array(Object)} buttons is an array of objects with * .active, .label and .value */ radio: function(name, buttons, type) { var elem = $.el.div({class:"btn-group", "data-toggle":"buttons"}); type = type||"radio" for(var i=0; i element from a list of options * @param {String} name is the name of the select element * @param {Array} from is an array of options. Each options is a * string or an object with keys `value` and `label`. * @param {Object} [options] * @param {Object} [options.value] If provided, the corresponding * option is selected */ function select(name, from, options) { var select = $($.el.select({class:"form-control", name:name})); options=options||{}; function addSelect(e) { if ( typeof(e) == "string" ) { if ( e == options.value ) { select.append($.el.option({selected:"selected"}, e)); } else { select.append($.el.option(e)); } } else { var opts = {value:e.value}; if ( e.value == options.value ) opts.selected = "selected"; select.append($.el.option(opts, e.label)); } } for(var i=0; i