├── .gitignore
├── README.md
├── admin
├── add_form.php
└── tab_publish.php
├── code
├── FormGenerator.class.php
├── Forms.class.php
├── General.class.php
├── Module.class.php
├── Placeholders.class.php
├── Resources.class.php
├── TemplateSets.class.php
├── Templates.class.php
├── actions.php
└── index.html
├── css
├── builder.css
├── codemirror.css
├── edit_form.css
├── index.html
└── styles.css
├── default_template_sets
├── conformist-1.2.json
├── default-1.2.json
├── illuminate-1.1.json
├── prosimple-1.3.json
└── theme-default-1.1.json
├── form.php
├── form_resources
├── css.php
├── index.html
└── js.php
├── help.php
├── images
├── builder_logo.png
├── dialog_header_bg.png
├── dialog_option.png
├── dialog_selected_option.png
├── icon16.png
├── icon24.png
├── icon26.png
├── icon_form_builder.png
├── loading.gif
├── sidebar_section_loading.gif
└── tip.png
├── index.php
├── lang
├── en_us.php
└── index.html
├── library.php
├── module_config.php
├── preview.php
├── preview_form.php
├── published
└── index.html
├── schemas
├── README.md
└── template_set-1.0.0.json
├── scripts
├── builder.js
├── index.html
├── manage_forms.js
└── manage_template_sets.js
├── settings.php
├── share
└── index.html
├── smarty_plugins
├── eval.tpl
├── function.captcha.php
├── function.code_block.php
├── function.continue_block.php
├── function.display_placeholder_field_type.php
├── function.display_template_set_name.php
├── function.display_template_set_placeholders.php
├── function.display_template_set_templates.php
├── function.display_template_set_type.php
├── function.display_template_set_usage.php
├── function.display_template_type.php
├── function.display_template_usage.php
├── function.error_message.php
├── function.footer.php
├── function.form_builder_edit_link.php
├── function.header.php
├── function.navigation.php
├── function.page.php
├── function.template_sets.php
├── function.template_type_dropdown.php
├── function.template_types.php
├── modifier.in.php
├── placeholders_html.tpl
└── templates_html.tpl
├── tab_settings_form_offline.php
├── tab_settings_main.php
├── tab_settings_thanks.php
├── template_sets
├── index.php
├── tab_add_placeholder.php
├── tab_edit_placeholder.php
├── tab_edit_resource.php
├── tab_edit_template.php
├── tab_info.php
├── tab_placeholders.php
├── tab_resources.php
└── tab_templates.php
└── templates
├── admin
├── add_form.tpl
└── tab_publish.tpl
├── help.tpl
├── index.html
├── index.tpl
├── preview.tpl
├── settings.tpl
├── tab_settings_form_offline.tpl
├── tab_settings_main.tpl
├── tab_settings_thanks.tpl
└── template_sets
├── index.tpl
├── tab_add_placeholder.tpl
├── tab_edit_placeholder.tpl
├── tab_edit_resource.tpl
├── tab_edit_template.tpl
├── tab_info.tpl
├── tab_placeholders.tpl
├── tab_resources.tpl
└── tab_templates.tpl
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea*
2 | .DS_Store
3 | published/*
4 | !published/index.html
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Form Builder module
2 |
3 | The Form Builder lets you create actual forms on your website. Check out the documentation for more information.
4 |
5 |
6 | ### Documentation
7 |
8 | - [https://docs.formtools.org/modules/form_builder/](https://docs.formtools.org/modules/form_builder/)
9 |
10 |
11 | ### Other Links
12 |
13 | - [Available Form Tools modules](https://modules.formtools.org/)
14 | - [About Form Tools modules](https://docs.formtools.org/userdoc/modules/)
15 | - [Installation instructions](https://docs.formtools.org/userdoc/modules/installing/)
16 | - [Upgrading](https://docs.formtools.org/userdoc/modules/upgrading/)
17 |
--------------------------------------------------------------------------------
/admin/add_form.php:
--------------------------------------------------------------------------------
1 | getLangStrings();
12 | $LANG = Core::$L;
13 |
14 | if (isset($request["add_form"])) {
15 | list($g_success, $g_message, $new_form_id) = General::createForm($request);
16 | if ($g_success) {
17 | header("location: ../../../admin/forms/edit/?form_id={$new_form_id}&message=notify_form_builder_form_created");
18 | exit;
19 | }
20 | }
21 |
22 | $page_values = array(
23 | "page" => "add_form_internal",
24 | "page_url" => Pages::getPageUrl("add_form_internal"),
25 | "head_title" => "{$LANG['phrase_add_form']}",
26 | "L" => $L
27 | );
28 |
29 | $page_vars["head_js"] =<<< END
30 | ft.click([
31 | { el: "at1", targets: [{ el: "custom_clients", action: "hide" }] },
32 | { el: "at2", targets: [{ el: "custom_clients", action: "hide" }] },
33 | { el: "at3", targets: [{ el: "custom_clients", action: "show" }] }
34 | ]);
35 |
36 | $(function() {
37 | $("#form_name").focus();
38 | $("#create_internal_form").bind("submit",function(e) {
39 | var rules = [];
40 | rules.push("required,form_name,{$LANG["validation_no_form_name"]}");
41 | rules.push("required,num_fields,{$LANG["validation_no_num_form_fields"]}");
42 | rules.push("digits_only,num_fields,{$LANG["validation_invalid_num_form_fields"]}");
43 | rules.push("range<=1000,num_fields,{$LANG["validation_internal_form_too_many_fields"]}");
44 | rules.push("required,access_type,{$LANG["validation_no_access_type"]}");
45 | if (!rsv.validate(this, rules)) {
46 | e.preventDefault();
47 | }
48 | ft.select_all("selected_client_ids[]");
49 | });
50 | });
51 | END;
52 |
53 | $module->displayPage("../../modules/form_builder/templates/admin/add_form.tpl", $page_vars);
54 |
--------------------------------------------------------------------------------
/admin/tab_publish.php:
--------------------------------------------------------------------------------
1 | fb_display_publish_tab().
15 | */
16 |
17 | $settings = Settings::get();
18 | $module = Modules::getModuleInstance("form_builder");
19 | $L = $module->getLangStrings();
20 | $root_url = Core::getRootUrl();
21 |
22 | $success = true;
23 | $message = "";
24 | if (isset($_POST["set_as_form_builder"])) {
25 | list($success, $message) = Forms::convertFormToFormBuilderForm($form_id, $L);
26 | } else {
27 | if (isset($_GET["delete"])) {
28 | list($success, $message) = Forms::deleteFormConfiguration($form_id, $_GET["delete"], $L);
29 | } else {
30 | if (isset($_GET["delete_published_form"])) {
31 | $override = (isset($_GET["override"])) ? true : false;
32 | $published_form_id = $_GET["delete_published_form"];
33 | list($success, $message) = $module->deletePublishedForm($form_id, $published_form_id, $_GET["delete_form_config"], $L, $override);
34 | } else {
35 | if (isset($_POST["update_order"])) {
36 | list($success, $message) = Forms::updatePublishedFormOrder($form_id, $L, $_POST);
37 | }
38 | }
39 | }
40 | }
41 |
42 | $form_info = CoreForms::getForm($form_id);
43 |
44 | $module_settings = $module->getSettings();
45 | $width = $module_settings["form_builder_width"];
46 | $height = $module_settings["form_builder_height"];
47 |
48 | // compile the templates information
49 | $page_vars["g_success"] = $success;
50 | $page_vars["g_message"] = $message;
51 | $page_vars["page"] = "publish";
52 | $page_vars["page_url"] = Pages::getPageUrl("edit_form_main", array("form_id" => $form_id));
53 | $page_vars["head_title"] = "{$LANG["phrase_edit_form"]} - {$L["word_publish"]}";
54 | $page_vars["form_info"] = $form_info;
55 | $page_vars["js_messages"] = array(
56 | "word_cancel",
57 | "phrase_please_confirm",
58 | "word_yes",
59 | "word_no",
60 | "phrase_show_form",
61 | "word_close",
62 | "phrase_open_form_in_new_tab_or_win"
63 | );
64 |
65 | $page_vars["head_string"] = <<< END
66 |
67 |
68 |
69 |
70 | END;
71 |
72 | $default_timezone_offset = $settings["default_timezone_offset"];
73 | $server_time = CoreGeneral::getDate($default_timezone_offset, CoreGeneral::getCurrentDatetime(), "M jS, Y G:i:s A");
74 |
75 | $onload_js = "";
76 | if (isset($_GET["action"]) && $_GET["action"] == "auto_open" && isset($_GET["published_form_id"])) {
77 | $published_form_id = $_GET["published_form_id"];
78 | $onload_js = "dialog = window.open(\"$root_url/modules/form_builder/preview.php?form_id=$form_id&published_form_id=$published_form_id\", \"preview\", \"status=0,toolbar=0,location=0,menubar=0,height=$height,width=$width\");";
79 | }
80 |
81 | $page_vars["head_js"] = <<< END
82 | $(function() {
83 | var dialog = null;
84 | $("#publish_new_form").bind("click", function() {
85 | if (dialog == null || dialog.closed) {
86 | var dialog = window.open("$root_url/modules/form_builder/preview.php?form_id=$form_id", "preview", "status=0,toolbar=0,location=0,menubar=0,height=$height,width=$width");
87 | } else {
88 | dialog.focus();
89 | }
90 | });
91 |
92 | $("#form_builder_form_list .edit").bind("click", function() {
93 | if (dialog == null || dialog.closed) {
94 | var published_form_id = $(this).closest(".row_group").find(".sr_order").val();
95 | dialog = window.open("$root_url/modules/form_builder/preview.php?form_id=$form_id&published_form_id=" + published_form_id, "preview", "status=0,toolbar=0,location=0,menubar=0,height=$height,width=$width");
96 | } else {
97 | dialog.focus();
98 | }
99 | });
100 |
101 | ft.init_show_form_links();
102 | $onload_js
103 | });
104 |
105 | g.mod_messages = {
106 | confirm_delete_form_confirmation: "{$L["confirm_delete_form_confirmation"]}",
107 | phrase_form_offline_date: "{$L["phrase_form_offline_date"]}",
108 | notify_form_offline_message: "{$L["notify_form_offline_message"]}"
109 | }
110 | g.current_server_time = "$server_time";
111 |
112 | END;
113 |
114 | // N.B. the actual tab_publish.tpl is loaded via a hook
115 | Themes::displayPage("admin/forms/edit/index.tpl", $page_vars);
116 |
--------------------------------------------------------------------------------
/code/General.class.php:
--------------------------------------------------------------------------------
1 | setTemplateDir("$root_dir/themes/default");
56 | $smarty->setCompileDir("$root_dir/themes/default/cache/");
57 | $smarty->setUseSubDirs(Core::shouldUseSmartySubDirs());
58 | $smarty->left_delimiter = $left_delimiter;
59 | $smarty->right_delimiter = $right_delimiter;
60 | $smarty->addPluginsDir(array(
61 | "$root_dir/global/smarty_plugins",
62 | "$root_dir/modules/form_builder/smarty_plugins"
63 | ));
64 |
65 | return $smarty;
66 | }
67 |
68 |
69 | /**
70 | * Helper function to return a list of View tabs.
71 | *
72 | * @param array $view_info
73 | */
74 | public static function getViewTabsFromViewInfo($view_info)
75 | {
76 | $view_tabs = array();
77 |
78 | foreach ($view_info["tabs"] as $tab_info) {
79 | $tab_label = trim($tab_info["tab_label"]);
80 | if (!empty($tab_label)) {
81 | $view_tabs[] = array("tab_label" => $tab_label);
82 | }
83 | }
84 |
85 | if (empty($view_tabs)) {
86 | $view_tabs[] = array("tab_label" => "Form");
87 | }
88 |
89 | return $view_tabs;
90 | }
91 |
92 |
93 | /**
94 | * Creates a Form Builder form. Same as ft_create_internal_form(), except for the form type.
95 | *
96 | * @param $info array POST request containing the form name, number of fields and access type.
97 | */
98 | public static function createForm($request)
99 | {
100 | $db = Core::$db;
101 | $LANG = Core::$L;
102 |
103 | $rules = array();
104 | $rules[] = "required,form_name,{$LANG["validation_no_form_name"]}";
105 | $rules[] = "required,num_fields,{$LANG["validation_no_num_form_fields"]}";
106 | $rules[] = "digits_only,num_fields,{$LANG["validation_invalid_num_form_fields"]}";
107 | $rules[] = "required,access_type,{$LANG["validation_no_access_type"]}";
108 |
109 | $errors = validate_fields($request, $rules);
110 | if (!empty($errors)) {
111 | array_walk($errors, create_function('&$el','$el = "• " . $el;'));
112 | $message = join("
", $errors);
113 | return array(false, $message);
114 | }
115 |
116 | $config = array(
117 | "form_type" => "form_builder",
118 | "form_name" => $request["form_name"],
119 | "access_type" => $request["access_type"],
120 | "submission_type" => "code"
121 | );
122 |
123 | // set up the entry for the form
124 | list($success, $message, $new_form_id) = CoreForms::setupForm($config);
125 |
126 | $form_data = array(
127 | "form_tools_form_id" => $new_form_id,
128 | "form_tools_display_notification_page" => false
129 | );
130 |
131 | for ($i=1; $i<=$request["num_fields"]; $i++) {
132 | $form_data["field{$i}"] = $i;
133 | }
134 | CoreForms::initializeForm($form_data);
135 |
136 | $form_fields = Fields::getFormFields($new_form_id);
137 |
138 | $order = 1;
139 |
140 | // if the user just added a form with a lot of fields (over 50), the database row size will be too
141 | // large. Varchar fields (which with utf-8 equates to 1220 bytes) in a table can have a combined row
142 | // size of 65,535 bytes, so 53 is the max. The client-side validation limits the number of fields to
143 | // 1000. Any more will throw an error.
144 | $field_size_clause = ($request["num_fields"] > 50) ? ", field_size = 'small'" : "";
145 |
146 | foreach ($form_fields as $field_info) {
147 | if (preg_match("/field(\d+)/", $field_info["field_name"], $matches)) {
148 | $db->query("
149 | UPDATE {PREFIX}form_fields
150 | SET field_title = :field_title,
151 | col_name = :col_name
152 | $field_size_clause
153 | WHERE field_id = :field_id
154 | ");
155 | $db->bindAll(array(
156 | "field_title" => "{$LANG["word_field"]} $order",
157 | "col_name" => "col_$order",
158 | "field_id" => $field_info["field_id"]
159 | ));
160 | $db->execute();
161 | $order++;
162 | }
163 | }
164 |
165 | CoreForms::finalizeForm($new_form_id);
166 |
167 | // if the form has an access type of "private" add whatever client accounts the user selected
168 | if ($request["access_type"] == "private") {
169 | $selected_client_ids = $request["selected_client_ids"];
170 | $queries = array();
171 |
172 | foreach ($selected_client_ids as $client_id) {
173 | $queries[] = "($client_id, $new_form_id)";
174 | }
175 |
176 | if (!empty($queries)) {
177 | $insert_values = implode(",", $queries);
178 | $db->query("
179 | INSERT INTO {PREFIX}client_forms (account_id, form_id)
180 | VALUES $insert_values
181 | ");
182 | }
183 | }
184 |
185 | // now apply a few simple changes to the View we just created, to simplify things for the
186 | $views = Views::getFormViews($new_form_id);
187 | $view_id = $views[0]["view_id"];
188 |
189 | // 1. Change the View name to "Form Builder View"
190 | $db->query("UPDATE {PREFIX}views SET view_name = 'Form Builder View' WHERE view_id = :view_id");
191 | $db->bind("view_id", $view_id);
192 | $db->execute();
193 |
194 | // 2. Change the View's first tab (the only one defined!) to be called "Page 1"
195 | $db->query("UPDATE {PREFIX}view_tabs SET tab_label = 'Page 1' WHERE view_id = :view_id AND tab_number = 1 LIMIT 1");
196 | $db->bind("view_id", $view_id);
197 | $db->execute();
198 |
199 | // 3. Change the View Field Group label to "Fields" instead of "DATA"
200 | $db->query("UPDATE {PREFIX}list_groups SET group_name = 'Fields' WHERE group_type = :group_type LIMIT 1");
201 | $db->bind("group_type", "view_fields_{$view_id}");
202 | $db->execute();
203 |
204 | return array(true, $LANG["notify_internal_form_created"], $new_form_id);
205 | }
206 |
207 |
208 | /**
209 | * What a beautiful function name. This largely duplicates some Core JS code, but it's necessary + a good idea for later on when
210 | * we want to offer different ways to display validation errors.
211 | *
212 | * @return string
213 | */
214 | public static function getFormValidationCustomErrorHandlerJs()
215 | {
216 | $LANG = Core::$L;
217 |
218 | $js =<<< END
219 | function fb_validate(f, error_info) {
220 | if (!error_info.length) {
221 | return true;
222 | }
223 | var first_el = null;
224 | var error_str = "
\n | \n \n\n \n \n {{$page_name}} \n\n {{error_message}}\n\n \n\n | \n
\n | \n \n\n \n \n {{$review_page_title}} \n\n \n\n | \n
\n | \n \n\n \n {{$thankyou_page_content}} \n \n | \n
29 | This form is unavailable. 30 |
31 | 32 | 33 | END; 34 | exit; 35 | } 36 | 37 | $module = Modules::getModuleInstance("form_builder"); 38 | $namespace = "form_builder_{$published_form_id}"; 39 | 40 | // find out about the page: form / review / thanks. That determines what values we pass to processFormBuilderPage 41 | $config = Forms::getFormConfiguration($published_form_id); 42 | 43 | $form_id = $config["form_id"]; 44 | $view_id = $config["view_id"]; 45 | 46 | FormGenerator::deleteUnfinalizedSubmissions($form_id); 47 | 48 | // check that we have all the info we need (configured form, View etc) 49 | $error_code = FormGenerator::checkLiveFormConditions($config); 50 | if (!empty($error_code)) { 51 | $config["error_code"] = $error_code; 52 | FormGenerator::generateFormPage($config); 53 | exit; 54 | } 55 | 56 | if (isset($_GET["clear"])) { 57 | FormGenerator::clearFormBuilderFormSessions($namespace); 58 | header("location: $filename"); 59 | } 60 | 61 | // check the form shouldn't be taken offline. This does some special logic to override the is_online == "no" 62 | // for cases where submissions have been started but the form is now offline 63 | $is_online = FormGenerator::checkFormOffline($config, $namespace); 64 | $config["is_online"] = ($is_online) ? "yes" : "no"; 65 | 66 | // set up sessions and retrieve the field data already submitted 67 | list($new_session, $fields) = FormGenerator::initFormBuilderPage($form_id, $view_id, $namespace); 68 | 69 | // get the current submission ID 70 | $submission_id = isset($_SESSION[$namespace]["form_tools_submission_id"]) ? $_SESSION[$namespace]["form_tools_submission_id"] : ""; 71 | 72 | // get an ordered list of the pages in this published form 73 | $page_params = array( 74 | "view_tabs" => ViewTabs::getViewTabs($view_id, true), 75 | "include_review_page" => ($config["include_review_page"] == "yes") ? true : false, 76 | "include_thanks_page_in_nav" => ($config["include_thanks_page_in_nav"] == "yes") ? true : false, 77 | "review_page_title" => $config["review_page_title"], 78 | "thankyou_page_title" => $config["thankyou_page_title"] 79 | ); 80 | 81 | $all_pages = Forms::getAllFormPages($page_params); 82 | $page = CoreGeneral::loadField("page", "{$namespace}_form_page", 1, $namespace); // TODO... 83 | 84 | // one additional check: make sure the page they're attempting to look at is permitted. They have to pass 85 | // through each page in order to prevent people bypassing any field validation 86 | $page = FormGenerator::verifyPageNumber($page, $all_pages, $namespace); 87 | 88 | $next_page = $page + 1; 89 | $page_info = $all_pages[$page - 1]; 90 | $page_type = $page_info["page_type"]; 91 | 92 | 93 | $post_values = array(); 94 | $params = array(); 95 | if ($page_type == "thanks") { 96 | FormGenerator::clearFormBuilderFormSessions($namespace); 97 | } else { 98 | $params = array( 99 | "namespace" => $namespace, 100 | "published_form_id" => $published_form_id, 101 | "submission_id" => $submission_id, 102 | "config" => $config, 103 | "page" => $page, 104 | "page_type" => $page_type, 105 | "form_id" => $form_id, 106 | "view_id" => $view_id, 107 | "submit_button" => "form_tools_continue", 108 | "next_page" => "$filename?page=$next_page", 109 | "form_data" => $_POST, 110 | "file_data" => $_FILES, 111 | "no_sessions_url" => "$filename?page=1" 112 | ); 113 | 114 | // we need to finalize the submission on the penultimate page. This can mean either the Review page or 115 | // the final form page if there's no Review page 116 | $num_pages = count($all_pages); 117 | if ($page_type == "review" || ($page >= $num_pages - 1)) { 118 | $params["finalize"] = true; 119 | } 120 | 121 | // just in case 122 | if ($page == $num_pages && isset($params["form_data"]["form_tools_continue"])) { 123 | $params["next_page"] = ""; 124 | } 125 | 126 | list($g_success, $g_message) = FormGenerator::processFormBuilderPage($params); 127 | 128 | // if there were any validation errors, pass the error along to the page. It'll use it to know not to 129 | // redirecting and to show the error message 130 | if (!$g_success) { 131 | $config["validation_error"] = $g_message; 132 | } 133 | } 134 | 135 | // now generate and display the form 136 | FormGenerator::generateFormPage($config, $page, $submission_id); 137 | -------------------------------------------------------------------------------- /form_resources/css.php: -------------------------------------------------------------------------------- 1 | false)); 21 | Modules::includeModule("form_builder"); 22 | 23 | $resource_id = $_GET["resource_id"]; 24 | $source = (isset($_GET["source"]) && $_GET["source"] == "sessions") ? "sessions" : "database"; 25 | 26 | $resource_info = Resources::getResource($resource_id); 27 | $set_id = $resource_info["template_set_id"]; 28 | $css = $resource_info["content"]; 29 | 30 | $placeholders = Placeholders::getPlaceholders($set_id); 31 | $placeholder_hash = array(); 32 | foreach ($placeholders as $placeholder_info) { 33 | $placeholder_hash[$placeholder_info["placeholder_id"]] = $placeholder_info["placeholder"]; 34 | } 35 | 36 | $config = array(); 37 | $smarty = General::createNewSmartyInstance(); 38 | 39 | $P = array(); 40 | if ($source == "sessions") { 41 | if (Core::getSessionType() == "database") { 42 | $sess = new DatabaseSessions(Core::$db, Core::getSessionSavePath()); 43 | } 44 | if (!empty($g_session_save_path)) { 45 | session_save_path($g_session_save_path); 46 | } 47 | 48 | session_start(); 49 | header("Cache-control: private"); 50 | header("Content-Type: text/html; charset=utf-8"); 51 | 52 | $placeholder_id_to_values = $_SESSION["ft"]["form_builder"]["placeholders"]; 53 | 54 | foreach ($placeholder_id_to_values as $placeholder_id => $value) { 55 | if (!isset($placeholder_hash[$placeholder_id])) { 56 | continue; 57 | } 58 | $placeholder = $placeholder_hash[$placeholder_id]; 59 | 60 | // TODO multi-select + checkboxes... 61 | $P[$placeholder] = $value; 62 | } 63 | } else { 64 | $config = Forms::getFormConfiguration($_GET["published_form_id"]); 65 | foreach ($config["placeholders"] as $placeholder_info) { 66 | $curr_placeholder_id = $placeholder_info["placeholder_id"]; 67 | $val = $placeholder_info["placeholder_value"]; 68 | 69 | if (!isset($placeholder_hash[$curr_placeholder_id])) { 70 | continue; 71 | } 72 | 73 | $placeholder = $placeholder_hash[$curr_placeholder_id]; 74 | $P[$placeholder] = $val; 75 | } 76 | } 77 | 78 | $smarty->assign("P", $P); 79 | $smarty->assign("eval_str", $css); 80 | 81 | header("Content-Type: text/css"); 82 | header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); 83 | 84 | echo $smarty->fetch("../../modules/form_builder/smarty_plugins/eval.tpl"); 85 | -------------------------------------------------------------------------------- /form_resources/index.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /form_resources/js.php: -------------------------------------------------------------------------------- 1 | false)); 20 | Modules::includeModule("form_builder"); 21 | 22 | $resource_id = $_GET["resource_id"]; 23 | $source = (isset($_GET["source"]) && $_GET["source"] == "sessions") ? "sessions" : "database"; 24 | 25 | $resource_info = Resources::getResource($resource_id); 26 | $set_id = $resource_info["template_set_id"]; 27 | $css = $resource_info["content"]; 28 | 29 | $placeholders = Placeholders::getPlaceholders($set_id); 30 | $placeholder_hash = array(); 31 | foreach ($placeholders as $placeholder_info) { 32 | $placeholder_hash[$placeholder_info["placeholder_id"]] = $placeholder_info["placeholder"]; 33 | } 34 | 35 | $config = array(); 36 | $smarty = General::createNewSmartyInstance(); 37 | 38 | $P = array(); 39 | if ($source == "sessions") { 40 | if (Core::getSessionType() == "database") { 41 | $sess = new DatabaseSessions(Core::$db, Core::getSessionSavePath()); 42 | } 43 | if (!empty($g_session_save_path)) { 44 | session_save_path($g_session_save_path); 45 | } 46 | 47 | session_start(); 48 | header("Cache-control: private"); 49 | header("Content-Type: text/html; charset=utf-8"); 50 | 51 | $placeholder_id_to_values = $_SESSION["ft"]["form_builder"]["placeholders"]; 52 | 53 | foreach ($placeholder_id_to_values as $placeholder_id => $value) { 54 | if (!isset($placeholder_hash[$placeholder_id])) { 55 | continue; 56 | } 57 | $placeholder = $placeholder_hash[$placeholder_id]; 58 | 59 | // TODO multi-select + checkboxes... 60 | $P[$placeholder] = $value; 61 | } 62 | } else { 63 | $config = Forms::getFormConfiguration($_GET["published_form_id"]); 64 | foreach ($config["placeholders"] as $placeholder_info) { 65 | $curr_placeholder_id = $placeholder_info["placeholder_id"]; 66 | $val = $placeholder_info["placeholder_value"]; 67 | 68 | if (!isset($placeholder_hash[$curr_placeholder_id])) { 69 | continue; 70 | } 71 | 72 | $placeholder = $placeholder_hash[$curr_placeholder_id]; 73 | $P[$placeholder] = $val; 74 | } 75 | } 76 | 77 | $smarty->assign("P", $P); 78 | $smarty->assign("eval_str", $css); 79 | 80 | header("Content-Type: text/javascript"); 81 | header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); 82 | 83 | echo $smarty->fetch("../../modules/form_builder/smarty_plugins/eval.tpl"); 84 | -------------------------------------------------------------------------------- /help.php: -------------------------------------------------------------------------------- 1 | displayPage("templates/help.tpl"); 8 | -------------------------------------------------------------------------------- /images/builder_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formtools/module-form_builder/df2a9a70a7af6057783d2e3b748017fe5a48c84d/images/builder_logo.png -------------------------------------------------------------------------------- /images/dialog_header_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formtools/module-form_builder/df2a9a70a7af6057783d2e3b748017fe5a48c84d/images/dialog_header_bg.png -------------------------------------------------------------------------------- /images/dialog_option.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formtools/module-form_builder/df2a9a70a7af6057783d2e3b748017fe5a48c84d/images/dialog_option.png -------------------------------------------------------------------------------- /images/dialog_selected_option.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formtools/module-form_builder/df2a9a70a7af6057783d2e3b748017fe5a48c84d/images/dialog_selected_option.png -------------------------------------------------------------------------------- /images/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formtools/module-form_builder/df2a9a70a7af6057783d2e3b748017fe5a48c84d/images/icon16.png -------------------------------------------------------------------------------- /images/icon24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formtools/module-form_builder/df2a9a70a7af6057783d2e3b748017fe5a48c84d/images/icon24.png -------------------------------------------------------------------------------- /images/icon26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formtools/module-form_builder/df2a9a70a7af6057783d2e3b748017fe5a48c84d/images/icon26.png -------------------------------------------------------------------------------- /images/icon_form_builder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formtools/module-form_builder/df2a9a70a7af6057783d2e3b748017fe5a48c84d/images/icon_form_builder.png -------------------------------------------------------------------------------- /images/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formtools/module-form_builder/df2a9a70a7af6057783d2e3b748017fe5a48c84d/images/loading.gif -------------------------------------------------------------------------------- /images/sidebar_section_loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formtools/module-form_builder/df2a9a70a7af6057783d2e3b748017fe5a48c84d/images/sidebar_section_loading.gif -------------------------------------------------------------------------------- /images/tip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formtools/module-form_builder/df2a9a70a7af6057783d2e3b748017fe5a48c84d/images/tip.png -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | getLangStrings(); 11 | $LANG = Core::$L; 12 | $root_url = Core::getRootUrl(); 13 | 14 | $sortable_id = "template_set_table"; 15 | 16 | // hidden feature, used for development only 17 | if (isset($_GET["generate"])) { 18 | echo TemplateSets::createDefaultTemplateSetFile(); 19 | exit; 20 | } 21 | 22 | if (isset($_GET["export"]) && is_numeric($_GET["export"])) { 23 | echo TemplateSets::generateTemplateSetExportFile($_GET["export"]); 24 | exit; 25 | } 26 | 27 | $success = true; 28 | $message = ""; 29 | if (isset($_GET["import"])) { 30 | list($success, $message) = TemplateSets::importTemplateSet($_GET["import"], $L); 31 | } 32 | if (isset($_GET["delete"])) { 33 | list($success, $message) = TemplateSets::deleteTemplateSet($_GET["delete"], $L); 34 | } 35 | if (isset($request["update_order"])) { 36 | $request["sortable_id"] = $sortable_id; 37 | list($success, $message) = TemplateSets::updateTemplateSetOrder($request, $L); 38 | } 39 | 40 | $template_sets = TemplateSets::getTemplateSets(false); 41 | 42 | // shame, but needed for the markup 43 | $updated_template_sets = array(); 44 | foreach ($template_sets as $template_set_info) { 45 | $set_id = $template_set_info["set_id"]; 46 | $template_set_info["usage"] = TemplateSets::getTemplateSetUsage($set_id); 47 | $updated_template_sets[] = $template_set_info; 48 | } 49 | 50 | $module_settings = $module->getSettings(); 51 | 52 | $page_vars = array( 53 | "g_success" => $success, 54 | "g_message" => $message, 55 | "sortable_id" => $sortable_id, 56 | "template_sets" => $updated_template_sets, 57 | "module_settings" => $module_settings, 58 | "js_messages" => array( 59 | "word_close", "word_yes", "word_no", "phrase_please_confirm" 60 | ), 61 | "module_js_messages" => array( 62 | "phrase_create_new_template_set", "validation_no_template_set_name", 63 | "confirm_delete_template_set", "confirm_delete_template_set" 64 | ) 65 | ); 66 | 67 | $page_vars["head_js"] =<<< END 68 | $(function() { 69 | fb_ns.init_create_new_template_set_dialog(); 70 | $(".info").bind("click", function() { 71 | ft.create_dialog({ 72 | title: "{$L["phrase_delete_template_set"]}", 73 | content: "{$L["text_delete_template_in_use"]}", 74 | popup_type: "info", 75 | width: 460, 76 | buttons: [{ 77 | text: "{$LANG["word_close"]}", 78 | click: function() { 79 | $(this).dialog("close"); 80 | } 81 | }] 82 | }); 83 | }); 84 | }); 85 | END; 86 | 87 | $module->displayPage("templates/index.tpl", $page_vars); 88 | -------------------------------------------------------------------------------- /lang/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /library.php: -------------------------------------------------------------------------------- 1 | getSettings(); 25 | 26 | $selected_templates = array(); 27 | $config_info = array(); 28 | $include_review_page = "yes"; 29 | $include_thanks_page_in_nav = "yes"; 30 | $is_online = "yes"; 31 | $is_published = "no"; 32 | $view_id = ""; 33 | $thankyou_page_content = $module_settings["default_thankyou_page_content"]; 34 | $form_offline_page_content = $module_settings["default_form_offline_page_content"]; 35 | $published_filename = ""; 36 | $published_folder_url = $module_settings["default_published_folder_url"]; 37 | $published_folder_path = $module_settings["default_published_folder_path"]; 38 | $review_page_title = $module_settings["review_page_title"]; 39 | $thankyou_page_title = $module_settings["thankyou_page_title"]; 40 | $offline_date = ""; 41 | 42 | // if we're editing an existing configuration, override all the defaults with whatever's been saved 43 | if (!empty($published_form_id)) { 44 | $config_info = Forms::getFormConfiguration($published_form_id); 45 | $is_published = $config_info["is_published"]; 46 | $is_online = $config_info["is_online"]; 47 | $set_id = $config_info["set_id"]; 48 | $view_id = $config_info["view_id"]; 49 | $include_review_page = $config_info["include_review_page"]; 50 | $include_thanks_page_in_nav = $config_info["include_thanks_page_in_nav"]; 51 | $thankyou_page_content = $config_info["thankyou_page_content"]; 52 | $form_offline_page_content = $config_info["form_offline_page_content"]; 53 | 54 | foreach ($config_info["templates"] as $template_info) { 55 | $selected_templates[$template_info["template_type"]] = $template_info["template_id"]; 56 | } 57 | $published_filename = preg_replace("/\.php$/", "", $config_info["filename"]); 58 | $published_folder_url = $config_info["folder_url"]; 59 | $published_folder_path = $config_info["folder_path"]; 60 | 61 | if (!is_null($config_info["offline_date"])) { 62 | // convert the datetime to a friendlier format 63 | list($date, $time) = explode(" ", $config_info["offline_date"]); 64 | list($year, $month, $day) = explode("-", $date); 65 | list($hours, $mins, $seconds) = explode(":", $time); 66 | $offline_date = "{$month}/{$day}/{$year} $hours:$mins"; 67 | } 68 | 69 | $review_page_title = $config_info["review_page_title"]; 70 | $thankyou_page_title = $config_info["thankyou_page_title"]; 71 | } else { 72 | // here, the admin is publishing a new form. There are no templates or other settings specified yet, so 73 | // we just pick the first set ID 74 | $set_id = TemplateSets::getFirstTemplateSetId(); 75 | if (empty($set_id)) { 76 | $major_error = $L["notify_no_complete_template"]; 77 | } 78 | 79 | $views = Views::getFormViews($form_id); 80 | if (!empty($views)) { 81 | $view_id = $views[0]["view_id"]; 82 | } 83 | } 84 | 85 | if (!Views::checkViewExists($view_id)) { 86 | $major_error = "Sorry, the View that was assigned to this form no longer exists. You will need to delete this form configuration and publish a new form."; 87 | } 88 | 89 | // calculate the page element heights and widths 90 | $default_width = $module_settings["form_builder_width"]; 91 | $default_height = $module_settings["form_builder_height"]; 92 | $sidebar_width = 260; 93 | $header_height = 34; 94 | $footer_height = 30; 95 | $iframe_header_height = 30; 96 | $iframe_width = $default_width - $sidebar_width; 97 | $content_height = $default_height - ($header_height + $footer_height); 98 | 99 | $page_vars = array(); 100 | $page_vars["allow_url_fopen"] = (ini_get("allow_url_fopen") == "1"); 101 | $page_vars["major_error"] = $major_error; 102 | $page_vars["published_form_id"] = $published_form_id; // 103 | $page_vars["include_review_page"] = $include_review_page; 104 | $page_vars["include_thanks_page_in_nav"] = $include_thanks_page_in_nav; 105 | $page_vars["is_published"] = $is_published; 106 | $page_vars["is_online"] = $is_online; 107 | $page_vars["thankyou_page_content"] = $thankyou_page_content; 108 | $page_vars["form_offline_page_content"] = $form_offline_page_content; 109 | $page_vars["module_settings"] = $module_settings; 110 | $page_vars["header_height"] = $header_height; 111 | $page_vars["footer_height"] = $footer_height; 112 | $page_vars["content_height"] = $content_height; 113 | $page_vars["sidebar_width"] = $sidebar_width; 114 | $page_vars["iframe_width"] = $iframe_width; 115 | $page_vars["iframe_header_height"] = $iframe_header_height; 116 | $page_vars["published_filename"] = $published_filename; 117 | $page_vars["published_folder_url"] = $published_folder_url; 118 | $page_vars["published_folder_path"] = $published_folder_path; 119 | $page_vars["offline_date"] = $offline_date; 120 | $page_vars["review_page_title"] = $review_page_title; 121 | $page_vars["thankyou_page_title"] = $thankyou_page_title; 122 | 123 | if (empty($major_error)) { 124 | $placeholders = Placeholders::getPlaceholders($set_id); 125 | $page_vars["form_id"] = $form_id; 126 | $page_vars["view_id"] = $view_id; 127 | $page_vars["set_id"] = $set_id; 128 | $page_vars["selected_templates"] = $selected_templates; 129 | $page_vars["placeholders"] = $placeholders; 130 | $page_vars["js"] = "g.view_tabs = [" . General::getNumViewTabsJs($form_id) . "];"; 131 | 132 | $placeholder_hash = array(); 133 | if (empty($config_info)) { 134 | foreach ($placeholders as $placeholder_info) { 135 | $placeholder_hash[$placeholder_info["placeholder_id"]] = $placeholder_info["default_value"]; 136 | } 137 | } else { 138 | foreach ($config_info["placeholders"] as $placeholder_info) { 139 | $placeholder_hash[$placeholder_info["placeholder_id"]] = $placeholder_info["placeholder_value"]; 140 | } 141 | } 142 | 143 | $page_vars["placeholder_hash"] = $placeholder_hash; 144 | } 145 | 146 | $module->displayPage("templates/preview.tpl", $page_vars); 147 | -------------------------------------------------------------------------------- /preview_form.php: -------------------------------------------------------------------------------- 1 | false)); 20 | } 21 | 22 | // convert the placeholder info in the request into a simple hash of placeholder_id => value 23 | $placeholders = array(); 24 | $placeholder_ids = isset($request["placeholder_ids"]) ? $request["placeholder_ids"] : array(); 25 | foreach ($placeholder_ids as $placeholder_id) { 26 | // note: this will either store a string or an array (checkboxes / multi-select) 27 | $placeholders[$placeholder_id] = (isset($request["placeholder_{$placeholder_id}"])) ? $request["placeholder_{$placeholder_id}"] : ""; 28 | } 29 | 30 | // we store the placeholders in sessions so that any resources (CSS/JS) in Smarty format can access the info. Normally it's just 31 | // pulled from the database 32 | $_SESSION["ft"]["form_builder"]["placeholders"] = $placeholders; 33 | 34 | // creating a new array here isn't strictly needed, since we COULD just tweak and pass along the POST request, 35 | // but it helps to see precisely what info is being sent 36 | $settings = array( 37 | 38 | // used by the generate function for things like overriding the default form submit, and 39 | // other functionality when in preview mode 40 | "mode" => "preview", // "preview" / "live" 41 | 42 | // main info 43 | "form_id" => $request["form_id"], 44 | "view_id" => $request["view_id"], 45 | "submission_id" => "", // N/A during the form building process 46 | "template_set_id" => $request["template_set_id"], 47 | "page" => $request["page"], 48 | "include_review_page" => isset($request["include_review_page"]) ? true : false, 49 | "include_thanks_page_in_nav" => isset($request["include_thanks_page_in_nav"]) ? true : false, 50 | "is_online" => isset($request["is_online"]) ? true : false, 51 | 52 | // the thankyou and form offline page content 53 | "thankyou_page_content" => $request["thankyou_page_content"], 54 | "form_offline_page_content" => $request["form_offline_page_content"], 55 | 56 | // other 57 | "offline_date" => $request["offline_date"], 58 | "review_page_title" => $request["review_page_title"], 59 | "thankyou_page_title" => $request["thankyou_page_title"], 60 | 61 | // templates 62 | "page_layout_template_id" => $request["page_layout_template_id"], 63 | "header_template_id" => $request["header_template_id"], 64 | "footer_template_id" => $request["footer_template_id"], 65 | "navigation_template_id" => $request["navigation_template_id"], 66 | "continue_block_template_id" => $request["continue_block_template_id"], 67 | "error_message_template_id" => $request["error_message_template_id"], 68 | "form_page_template_id" => $request["form_page_template_id"], 69 | "form_offline_page_template_id" => $request["form_offline_page_template_id"], 70 | "review_page_template_id" => $request["review_page_template_id"], 71 | "thankyou_page_template_id" => $request["thankyou_page_template_id"], 72 | 73 | // placeholders 74 | "placeholders" => $placeholders, 75 | ); 76 | 77 | echo FormGenerator::generateForm($settings); 78 | 79 | -------------------------------------------------------------------------------- /published/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /schemas/README.md: -------------------------------------------------------------------------------- 1 | ## Template Set Schema 2 | 3 | As of Form Builder 2.0.0, the source data for the Template Sets have been moved to standalone JSON files, found in the 4 | `[FT Root]/modules/form_builder/default_template_sets/` folder. The structure of these files is now determined by the 5 | `schema.json` file found in this folder. It's a standardized format, defined by [json-schema.org](http://json-schema.org/). 6 | 7 | These files each contain a single, complete Template Set (i.e. the contents of a Form Builder template, allowing you to 8 | generate forms out of it that use its styles and appearance). 9 | 10 | ### Purpose of Schema Files 11 | 12 | The long term goal of Form Tools is to be able to share _configurations_ of all forms, Option Lists, View configurations, 13 | user configs, email templates - _everything and anything_. This will allow users to install not just Form Tools and the 14 | modules but any pre-existing data configuration, significantly cutting down on configuration time and promoting sharing 15 | of great-looking forms. 16 | 17 | In order to do that all data has to be well defined in known structures so validation may be performed to confirm 18 | data integrity. That's the purpose of these schema files. 19 | 20 | 21 | ### Example Template Set Schema 22 | 23 | N.B. I've annotated this to explain each property. Note that valid JSON cannot contain comments! 24 | 25 | ```javascript 26 | { 27 | // the schema version that this JSON file adheres to. If the format of the file fails to match the schema version 28 | // specified here, the Form Builder will complain when it attempts to import the Template Set. Over time, if we need 29 | // to add/remove content to Template Sets the structure of the document may change, and this value would need to be 30 | // updated to match the appropriate structure. 31 | "schema_version": "1.0.0", 32 | 33 | // whatever human-friendly name you want to give you Template Set 34 | "template_set_name": "Template set Name", 35 | 36 | // the Template Set version. Any changes to the content of the Template Set JSON file should always mean this 37 | // value gets incremented. Also rename the file to include the version there as well (it just removed any ambiguity) 38 | "template_set_version": "1.0.0", 39 | 40 | // a description of the template set to give users a rough idea of what to expect 41 | "description": "blurb here", 42 | 43 | // the time the file was last updated 44 | "last_updated": "2017-11-18 12:00:00", 45 | 46 | // this contains all the templates used in generating the template set. The property names are all required and must 47 | // contain at least one template in each. When a particular template type has > 1 option, the user is presented 48 | // with the option to choose what they want via the UI. Otherwise it's just prescribed for them. Note that the arrays 49 | // of each template type are ordered: the first item is the template type that will be selected by default when 50 | // creating new Form Builder forms. The structure of the content is the same for each section, so I've omitted 51 | // the details for brevity 52 | "templates": { 53 | "header": [ 54 | { 55 | "template_name": "Name of header template", 56 | "content": "smarty content here" 57 | }, 58 | { 59 | "template_name": "Name of second header template", 60 | "content": "smarty content here" 61 | } 62 | ], 63 | "footer": [ 64 | // ... 65 | ], 66 | "form_page": [ 67 | // ... 68 | ], 69 | "review_page": [ 70 | // ... 71 | ], 72 | "thankyou_page": [ 73 | // ... 74 | ], 75 | "form_offline_page": [ 76 | // ... 77 | ], 78 | "continue_block": [ 79 | // ... 80 | ], 81 | "navigation": [ 82 | // ... 83 | ], 84 | "error_message": [ 85 | // ... 86 | ] 87 | }, 88 | "resources": { 89 | "css": [ 90 | { 91 | "resource_name": "More styles", 92 | "placeholder": "styles", 93 | "content": "CSS here" 94 | } 95 | ], 96 | "js": [ 97 | { 98 | "resource_name": "Javascript", 99 | "placeholder": "js", 100 | "content": "JS here..." 101 | } 102 | ] 103 | }, 104 | "placeholders": [ 105 | { 106 | "placeholder_label": "Colour", 107 | "placeholder": "colour", 108 | "field_type": "select", 109 | "field_orientation": "na", 110 | "default_value": "Red", 111 | "options": [ 112 | { 113 | "option_text": "Red" 114 | }, 115 | { 116 | "option_text": "Blue" 117 | } 118 | ] 119 | } 120 | ] 121 | } 122 | ``` 123 | -------------------------------------------------------------------------------- /schemas/template_set-1.0.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Template Set Schemas", 3 | "schema_version": "1.0.0", 4 | "$schema": "http://json-schema.org/draft-04/schema#", 5 | "type": "object", 6 | "properties": { 7 | "schema_version": { 8 | "type": "string", 9 | "oneOf": [ 10 | { 11 | "type": "string", 12 | "enum": ["1.0.0"] 13 | } 14 | ] 15 | }, 16 | "template_set_name": { 17 | "type": "string" 18 | }, 19 | "template_set_version": { 20 | "type": "string" 21 | }, 22 | "description": { 23 | "type": "string" 24 | }, 25 | "last_updated": { 26 | "type": "string" 27 | }, 28 | "templates": { 29 | "type": "object", 30 | "properties": { 31 | "page_layout": { 32 | "type": "array", 33 | "items": { 34 | "$ref": "#/definitions/template" 35 | } 36 | }, 37 | "header": { 38 | "type": "array", 39 | "items": { 40 | "$ref": "#/definitions/template" 41 | } 42 | }, 43 | "footer": { 44 | "type": "array", 45 | "items": { 46 | "$ref": "#/definitions/template" 47 | } 48 | }, 49 | "form_page": { 50 | "type": "array", 51 | "items": { 52 | "$ref": "#/definitions/template" 53 | } 54 | }, 55 | "review_page": { 56 | "type": "array", 57 | "items": { 58 | "$ref": "#/definitions/template" 59 | } 60 | }, 61 | "thankyou_page": { 62 | "type": "array", 63 | "items": { 64 | "$ref": "#/definitions/template" 65 | } 66 | }, 67 | "form_offline_page": { 68 | "type": "array", 69 | "items": { 70 | "$ref": "#/definitions/template" 71 | } 72 | }, 73 | "continue_block": { 74 | "type": "array", 75 | "items": { 76 | "$ref": "#/definitions/template" 77 | } 78 | }, 79 | "navigation": { 80 | "type": "array", 81 | "items": { 82 | "$ref": "#/definitions/template" 83 | } 84 | }, 85 | "error_message": { 86 | "type": "array", 87 | "items": { 88 | "$ref": "#/definitions/template" 89 | } 90 | } 91 | }, 92 | "required": [ 93 | "page_layout", 94 | "header", 95 | "footer", 96 | "form_page", 97 | "review_page", 98 | "thankyou_page", 99 | "form_offline_page", 100 | "continue_block", 101 | "navigation", 102 | "error_message" 103 | ] 104 | }, 105 | 106 | "resources": { 107 | "type": "object", 108 | "properties": { 109 | "css": { 110 | "type": "array" 111 | }, 112 | "js": { 113 | "type": "array" 114 | } 115 | } 116 | }, 117 | "placeholders": { 118 | "type": "array", 119 | "items": { 120 | "type": "object", 121 | "properties": { 122 | "placeholder_label": { 123 | "type": "string" 124 | }, 125 | "placeholder": { 126 | "type": "string" 127 | }, 128 | "field_type": { 129 | "type": "string", 130 | "enum": ["textbox", "textarea", "radios", "checkboxes", "select", "multi-select"] 131 | }, 132 | "field_orientation": { 133 | "type": "string", 134 | "enum": ["na", "horizontal", "vertical"] 135 | }, 136 | "default_value": { 137 | "type": "string" 138 | }, 139 | "options": { 140 | "type": "array", 141 | "items": { 142 | "type": "object", 143 | "properties": { 144 | "option_text": { 145 | "type": "string" 146 | } 147 | } 148 | } 149 | } 150 | }, 151 | "required": [ 152 | "placeholder_label", 153 | "placeholder", 154 | "field_type", 155 | "field_orientation", 156 | "default_value" 157 | ] 158 | } 159 | } 160 | }, 161 | "definitions": { 162 | "template": { 163 | "type": "object", 164 | "properties": { 165 | "template_name": { 166 | "type": "string" 167 | }, 168 | "content": { 169 | "type": "string" 170 | } 171 | }, 172 | "required": [ 173 | "template_name", 174 | "content" 175 | ] 176 | } 177 | }, 178 | "required": [ 179 | "schema_version", 180 | "template_set_name", 181 | "template_set_version", 182 | "description", 183 | "last_updated", 184 | "templates" 185 | ] 186 | } 187 | -------------------------------------------------------------------------------- /scripts/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/manage_forms.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | $(".publish_tab_offline_date").bind("click", function() { 3 | var content = g.mod_messages.notify_form_offline_message.replace(/%offline_time%/, this.innerHTML); 4 | content = content.replace(/%current_time%/, g.current_server_time); 5 | 6 | ft.create_dialog({ 7 | title: g.mod_messages.phrase_form_offline_date, 8 | content: content, 9 | width: 460, 10 | buttons: [{ 11 | text: g.messages["word_close"], 12 | click: function() { $(this).dialog("close"); } 13 | }] 14 | }); 15 | }); 16 | }); 17 | 18 | var fb_ns = {}; 19 | fb_ns.delete_form_configuration_dialog = $(""); 20 | 21 | 22 | /** 23 | * Called when the user selects a form from one of the dropdowns in the first column. It shows 24 | * the appropriate View content in the second column. 25 | */ 26 | fb_ns.select_form = function(form_id) { 27 | if (form_id == "") { 28 | $("#view_id")[0].options.length = 0; 29 | $("#view_id")[0].options[0] = new Option(g.messages["phrase_please_select_form"], ""); 30 | $("#view_id").attr("disabled", "disabled"); 31 | return false; 32 | } else { 33 | $("#view_id").attr("disabled", ""); 34 | fb_ns.populate_view_dropdown("view_id", form_id); 35 | } 36 | return false; 37 | } 38 | 39 | 40 | /** 41 | * Populates a dropdown element with a list of Views including a "Please Select" default 42 | * option. 43 | */ 44 | fb_ns.populate_view_dropdown = function(element_id, form_id) { 45 | var form_index = null; 46 | for (var i=0; i![]() |
7 | 8 | {$LANG.word_forms} » 9 | {$LANG.phrase_add_form} » 10 | {$L.module_name} 11 | | 12 |