=============================
Jam.py documentation contents
=============================
.. toctree::
:hidden:
index
.. toctree::
:maxdepth: 3
intro/index
programming/index
faq/index
how_to/index
admin/index
refs/index
releases/index
jampy-design-doco/contents
=========
Version 4
=========
In Version 4 the server side was reworked. Web.py library was replaced with
werkzeug. Session support was added.
.. toctree::
:maxdepth: 1
version_4_0_70
version_4_0_71
version_4_0_74
version_4_0_78
version_4_0_79
version_4_0_81
version_4_0_84
version_4_0_88
# Jam.py
## Docs
- [Jam.py documentation contents](https://jampy-docs-v7.readthedocs.io/en/latest/contents.html)
- [Jam.py V7 documentation](https://jampy-docs-v7.readthedocs.io/en/latest/index.html)
- [Getting started](https://jampy-docs-v7.readthedocs.io/en/latest/intro/index.html)
- [Installation](https://jampy-docs-v7.readthedocs.io/en/latest/intro/install.html)
- [Understanding admin.sqlite](https://jampy-docs-v7.readthedocs.io/en/latest/intro/admin.html)
- [Demo project](https://jampy-docs-v7.readthedocs.io/en/latest/intro/demo_project.html)
- [Deployment](https://jampy-docs-v7.readthedocs.io/en/latest/intro/deployment.html)
- [Creating a project](https://jampy-docs-v7.readthedocs.io/en/latest/intro/new_project.html)
- [Customizing Forms](https://jampy-docs-v7.readthedocs.io/en/latest/intro/tutorial01/customizing_forms.html)
- [Filters](https://jampy-docs-v7.readthedocs.io/en/latest/intro/tutorial01/filters.html)
- [Tutorial. Part 1. First project](https://jampy-docs-v7.readthedocs.io/en/latest/intro/tutorial01/index.html)
- [New project](https://jampy-docs-v7.readthedocs.io/en/latest/intro/tutorial01/new_project.html)
- [New catalog](https://jampy-docs-v7.readthedocs.io/en/latest/intro/tutorial01/new_catalog.html)
- [Lookup fields](https://jampy-docs-v7.readthedocs.io/en/latest/intro/tutorial01/lookup_fields.html)
- [Lookup lists](https://jampy-docs-v7.readthedocs.io/en/latest/intro/tutorial01/lookup_list.html)
- [Indexes](https://jampy-docs-v7.readthedocs.io/en/latest/intro/tutorial01/indexes.html)
- [Tutorial. Part 2. File and image fields](https://jampy-docs-v7.readthedocs.io/en/latest/intro/tutorial02/index.html)
- [Tutorial. Part 3. Details](https://jampy-docs-v7.readthedocs.io/en/latest/intro/tutorial03/index.html)
- [Jam.py programming](https://jampy-docs-v7.readthedocs.io/en/latest/programming/index.html)
- [Task tree](https://jampy-docs-v7.readthedocs.io/en/latest/programming/task_tree.html)
- [Common fields](https://jampy-docs-v7.readthedocs.io/en/latest/programming/data/common_fields.html)
- [Dataset](https://jampy-docs-v7.readthedocs.io/en/latest/programming/data/dataset.html)
- [Details](https://jampy-docs-v7.readthedocs.io/en/latest/programming/data/details.html)
- [Fields](https://jampy-docs-v7.readthedocs.io/en/latest/programming/data/fields.html)
- [Filtering records](https://jampy-docs-v7.readthedocs.io/en/latest/programming/data/filtering_records.html)
- [Filters](https://jampy-docs-v7.readthedocs.io/en/latest/programming/data/filters.html)
- [Data programming](https://jampy-docs-v7.readthedocs.io/en/latest/programming/data/index.html)
- [Navigating datasets](https://jampy-docs-v7.readthedocs.io/en/latest/programming/data/navigating_datasets.html)
- [Lookup fields](https://jampy-docs-v7.readthedocs.io/en/latest/programming/data/lookup_fields.html)
- [Modifying datasets](https://jampy-docs-v7.readthedocs.io/en/latest/programming/data/modifying_datasets.html)
- [Data-aware controls](https://jampy-docs-v7.readthedocs.io/en/latest/programming/interface/data_controls.html)
- [Close query events](https://jampy-docs-v7.readthedocs.io/en/latest/programming/interface/form_events.html)
- [Form examples](https://jampy-docs-v7.readthedocs.io/en/latest/programming/interface/form_examples.html)
- [Form options](https://jampy-docs-v7.readthedocs.io/en/latest/programming/interface/form_options.html)
- [Form templates](https://jampy-docs-v7.readthedocs.io/en/latest/programming/interface/form_templates.html)
- [Forms](https://jampy-docs-v7.readthedocs.io/en/latest/programming/interface/forms.html)
- [Client side programming](https://jampy-docs-v7.readthedocs.io/en/latest/programming/interface/index.html)
- [Index.html](https://jampy-docs-v7.readthedocs.io/en/latest/programming/interface/index_html.html)
- [Initializing application](https://jampy-docs-v7.readthedocs.io/en/latest/programming/interface/initializing_application.html)
- [Working with modules](https://jampy-docs-v7.readthedocs.io/en/latest/programming/modules.html)
- [Client-side report programming](https://jampy-docs-v7.readthedocs.io/en/latest/programming/reports/client_side_programming.html)
- [Creating a report](https://jampy-docs-v7.readthedocs.io/en/latest/programming/reports/creating_report.html)
- [Programming reports](https://jampy-docs-v7.readthedocs.io/en/latest/programming/reports/index.html)
- [Report templates](https://jampy-docs-v7.readthedocs.io/en/latest/programming/reports/templates.html)
- [Report parameters](https://jampy-docs-v7.readthedocs.io/en/latest/programming/reports/report_parameters.html)
- [Server-side report programming](https://jampy-docs-v7.readthedocs.io/en/latest/programming/reports/server_side_programming.html)
- [Reserved words](https://jampy-docs-v7.readthedocs.io/en/latest/programming/reserved.html)
- [Server side programming](https://jampy-docs-v7.readthedocs.io/en/latest/programming/server/index.html)
- [on_apply events](https://jampy-docs-v7.readthedocs.io/en/latest/programming/server/on_apply_events.html)
- [on_open_events](https://jampy-docs-v7.readthedocs.io/en/latest/programming/server/on_open_events.html)
- [Workflow](https://jampy-docs-v7.readthedocs.io/en/latest/programming/workflow.html)
- [Jam.py FAQ](https://jampy-docs-v7.readthedocs.io/en/latest/faq/index.html)
- [What is the difference between catalogs and journals](https://jampy-docs-v7.readthedocs.io/en/latest/faq/faq_catalogs_vs_journals.html)
- [What are foreign keys used for?](https://jampy-docs-v7.readthedocs.io/en/latest/faq/faq_foreign_keys.html)
- [How to upgrade an already created project to a new version of jampy?](https://jampy-docs-v7.readthedocs.io/en/latest/faq/faq_howto_upgrade_existing_project.html)
- [When printing a report I get an ods file instead of pdf](https://jampy-docs-v7.readthedocs.io/en/latest/faq/faq_print_ods_pdf.html)
- [Can I use other libraries in my application](https://jampy-docs-v7.readthedocs.io/en/latest/faq/faq_using_other_libraries.html)
- [How to](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/index.html)
- [How to install Jam.py on Windows](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_install_on_windows.html)
- [How to give user ability to change the password](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/authentication/how_give_user_ability_to_change_password.html)
- [How to authenticate from custom users table](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/authentication/how_to_authenticate_from_custom_users_table.html)
- [How to create registration form](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/authentication/how_to_create_registration_form.html)
- [Authentication](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/authentication/index.html)
- [A step-by-step guide to deploy a Jam.py on the AWS](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/deploy/a_step-by-step_guide_to_deploy_a_jam_py_on_the_aws.html)
- [How to deploy project on PythonAnywhere](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/deploy/how_to_deploy_project_on_pythonanywhere.html)
- [How to deploy jam-py app at Linux Apache http server?](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/deploy/how_to_deploy_to_linux_apache.html)
- [How to do with Nginx with Gunicorn?](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/deploy/how_to_do_with_gunicorn.html)
- [How to deploy](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/deploy/index.html)
- [Export to / import from csv files](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/export_import_csv_files.html)
- [How do I write functions which have a global scope](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/global_scripts.html)
- [How change field value of selected records](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_change_field_value_of_selected_records.html)
- [How to add a button to a form](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_add_a_button_to_a_form.html)
- [How can I perform calculations in the background](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_calculations_in_the_background.html)
- [How to change style and attributes of form elements](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_change_style_and_attributes_of_elements.html)
- [How to create a custom menu](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_create_a_custom_menu.html)
- [How can I use data from other database tables](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_data_from_other_database_tables.html)
- [Is it supported to have details inside details?](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_details_inside_details.html)
- [How to execute script from client](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_execute_script_from_client.html)
- [How to implement a many-to-many relationship](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_implement_a_many-to-many_relationship.html)
- [How to link two tables](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_link_two_tables.html)
- [How to migrate development to production](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_migrate_development_to_production.html)
- [How to migrate to another database](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_migrate_to_another_database.html)
- [How to migrate v5 project to v7](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_migrate_to_v7.html)
- [How to implement some sort of basic multi-tenancy? For example, to have users with separate data.](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_multitenancy.html)
- [How to prevent duplicate values in a table field](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_prevent_duplicate_values.html)
- [How to prohibit changing record](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_prohibit_changing_record.html)
- [How I can process a request or get some data from other application or service](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_request_from_other_application.html)
- [How to save changes to two tables in same transaction on the server](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_save_changes_to_two_tables_in_same_transaction.html)
- [How to save edit form without closing it](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_save_edit_form_without_closing_it.html)
- [Can I use Jam.py with existing database](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_use_jam_py_with_existing_database.html)
- [How to validate field value](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/how_to_validate_field_value.html)
- [How to append a record using an edit form without opening a view form?](https://jampy-docs-v7.readthedocs.io/en/latest/how_to/to_append_a_record_without_view_form.html)
- [Business application builder](https://jampy-docs-v7.readthedocs.io/en/latest/admin/index.html)
- [Project management](https://jampy-docs-v7.readthedocs.io/en/latest/admin/project/index.html)
- [Parameters](https://jampy-docs-v7.readthedocs.io/en/latest/admin/project/parameters.html)
- [Database](https://jampy-docs-v7.readthedocs.io/en/latest/admin/project/database.html)
- [Export](https://jampy-docs-v7.readthedocs.io/en/latest/admin/project/export.html)
- [Find](https://jampy-docs-v7.readthedocs.io/en/latest/admin/project/find.html)
- [Import](https://jampy-docs-v7.readthedocs.io/en/latest/admin/project/import.html)
- [Export/import metadata](https://jampy-docs-v7.readthedocs.io/en/latest/admin/project/metadata_file.html)
- [Print](https://jampy-docs-v7.readthedocs.io/en/latest/admin/project/print.html)
- [Roles](https://jampy-docs-v7.readthedocs.io/en/latest/admin/roles.html)
- [Users](https://jampy-docs-v7.readthedocs.io/en/latest/admin/users.html)
- [Code editor](https://jampy-docs-v7.readthedocs.io/en/latest/admin/code_editor.html)
- [Task](https://jampy-docs-v7.readthedocs.io/en/latest/admin/task.html)
- [Groups](https://jampy-docs-v7.readthedocs.io/en/latest/admin/groups/index.html)
- [Item Group Editor](https://jampy-docs-v7.readthedocs.io/en/latest/admin/groups/item_group_editor.html)
- [Report Group Editor](https://jampy-docs-v7.readthedocs.io/en/latest/admin/groups/report_group_editor.html)
- [Detail Group Editor](https://jampy-docs-v7.readthedocs.io/en/latest/admin/groups/table_group_editor.html)
- [Items](https://jampy-docs-v7.readthedocs.io/en/latest/admin/items/index.html)
- [Item Editor Dialog](https://jampy-docs-v7.readthedocs.io/en/latest/admin/items/item_editor_dialog.html)
- [Field Editor Dialog](https://jampy-docs-v7.readthedocs.io/en/latest/admin/items/field_editor_dialog.html)
- [Edit Form Dialog](https://jampy-docs-v7.readthedocs.io/en/latest/admin/items/edit_form_dialog.html)
- [View Form Dialog](https://jampy-docs-v7.readthedocs.io/en/latest/admin/items/view_form_dialog.html)
- [Filters Dialog](https://jampy-docs-v7.readthedocs.io/en/latest/admin/items/filters_dialog.html)
- [Details Dialog](https://jampy-docs-v7.readthedocs.io/en/latest/admin/items/details_dialog.html)
- [Order Dialog](https://jampy-docs-v7.readthedocs.io/en/latest/admin/items/order_dialog.html)
- [Indices Dialog](https://jampy-docs-v7.readthedocs.io/en/latest/admin/items/indices_dialog.html)
- [Reports Dialog](https://jampy-docs-v7.readthedocs.io/en/latest/admin/items/reports_dialog.html)
- [Details](https://jampy-docs-v7.readthedocs.io/en/latest/admin/details.html)
- [Lookup List Dialog](https://jampy-docs-v7.readthedocs.io/en/latest/admin/lookup_lists.html)
- [Importing existing database tables](https://jampy-docs-v7.readthedocs.io/en/latest/admin/integration_with_existing_database.html)
- [Saving audit trail/change history made by users](https://jampy-docs-v7.readthedocs.io/en/latest/admin/saving_history.html)
- [Record locking](https://jampy-docs-v7.readthedocs.io/en/latest/admin/record_locking.html)
- [Language support](https://jampy-docs-v7.readthedocs.io/en/latest/admin/language_support.html)
- [Language translation](https://jampy-docs-v7.readthedocs.io/en/latest/admin/language_translation.html)
- [Accept string](https://jampy-docs-v7.readthedocs.io/en/latest/admin/accept_string.html)
- [Foreign Keys Dialog](https://jampy-docs-v7.readthedocs.io/en/latest/admin/items/foreign_keys_dialog.html)
- [Routing](https://jampy-docs-v7.readthedocs.io/en/latest/admin/routing.html)
- [Sanitizing](https://jampy-docs-v7.readthedocs.io/en/latest/admin/sanitizing.html)
- [Jam.py class reference](https://jampy-docs-v7.readthedocs.io/en/latest/refs/index.html)
- [Client side (javascript) class reference](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/index.html)
- [AbstractItem class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstractitem_api.html)
- [ID](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/at_id.html)
- [item_caption](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/at_item_caption.html)
- [item_name](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/at_item_name.html)
- [item_type](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/at_item_type.html)
- [items](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/at_items.html)
- [owner](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/at_owner.html)
- [task](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/at_task.html)
- [abort](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/m_abort.html)
- [alert](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/m_alert.html)
- [can_view](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/m_can_view.html)
- [each_item](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/m_each_item.html)
- [hide_message](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/m_hide_message.html)
- [item_by_ID](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/m_item_by_id.html)
- [load_module](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/m_load_module.html)
- [load_modules](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/m_load_modules.html)
- [load_script](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/m_load_script.html)
- [message](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/m_message.html)
- [question](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/m_question.html)
- [server](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/m_server.html)
- [warning](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/m_warn.html)
- [yes_no_cancel](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/abstr_item/m_yes_no_cancel.html)
- [Task class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task_api.html)
- [forms_container](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/at_forms_container.html)
- [forms_in_tabs](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/at_forms_in_tabs.html)
- [safe_mode](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/at_safe_mode.html)
- [templates](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/at_templates.html)
- [user_info](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/at_user_info.html)
- [add_tab](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/m_add_tab.html)
- [close_tab](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/m_close_tab.html)
- [create_menu](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/m_create_menu.html)
- [init_tabs](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/m_init_tabs.html)
- [load](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/m_load.html)
- [login](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/m_login.html)
- [logout](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/m_logout.html)
- [set_forms_container](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/m_set_forms_container.html)
- [upload](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/m_upload.html)
- [on_edit_form_close_query](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_edit_form_close_query.html)
- [on_edit_form_created](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_edit_form_created.html)
- [on_edit_form_keydown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_edit_form_keydown.html)
- [on_edit_form_keyup](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_edit_form_keyup.html)
- [on_edit_form_shown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_edit_form_shown.html)
- [on_filter_form_close_query](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_filter_form_close_query.html)
- [on_filter_form_created](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_filter_form_created.html)
- [on_filter_form_shown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_filter_form_shown.html)
- [on_page_loaded](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_page_loaded.html)
- [on_param_form_close_query](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_param_form_close_query.html)
- [on_param_form_created](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_param_form_created.html)
- [on_param_form_shown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_param_form_shown.html)
- [on_view_form_close_query](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_view_form_close_query.html)
- [on_view_form_created](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_view_form_created.html)
- [on_view_form_keydown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_view_form_keydown.html)
- [on_view_form_keyup](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_view_form_keyup.html)
- [on_view_form_shown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/task/on_view_form_shown.html)
- [Group class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item_group_api.html)
- [on_edit_form_close_query](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/group/on_edit_form_close_query.html)
- [on_edit_form_created](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/group/on_edit_form_created.html)
- [on_edit_form_keydown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/group/on_edit_form_keydown.html)
- [on_edit_form_keyup](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/group/on_edit_form_keyup.html)
- [on_edit_form_shown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/group/on_edit_form_shown.html)
- [on_filter_form_close_query](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/group/on_filter_form_close_query.html)
- [on_filter_form_created](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/group/on_filter_form_created.html)
- [on_filter_form_shown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/group/on_filter_form_shown.html)
- [on_view_form_close_query](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/group/on_view_form_close_query.html)
- [on_view_form_created](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/group/on_view_form_created.html)
- [on_view_form_keydown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/group/on_view_form_keydown.html)
- [on_view_form_keyup](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/group/on_view_form_keyup.html)
- [on_view_form_shown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/group/on_view_form_shown.html)
- [Item class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item_api.html)
- [active](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_active.html)
- [can_modify](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_can_modify.html)
- [details](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_details.html)
- [edit_form](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_edit_form.html)
- [edit_options](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_edit_options.html)
- [fields](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_fields.html)
- [filter_form](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_filter_form.html)
- [filter_options](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_filter_options.html)
- [Filtered](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_filtered.html)
- [filters](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_filters.html)
- [item_state](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_item_state.html)
- [log_changes](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_log_changes.html)
- [lookup_field](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_lookup_field.html)
- [paginate](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_paginate.html)
- [permissions](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_permissions.html)
- [read_only](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_read_only.html)
- [rec_count](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_rec_count.html)
- [rec_no](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_rec_no.html)
- [selections](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_selections.html)
- [table_options](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_table_options.html)
- [view_form](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_view_form.html)
- [view_options](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_view_options.html)
- [virtual_table](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/at_virtual_table.html)
- [add_edit_button](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_add_edit_button.html)
- [add_view_button](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_add_view_button.html)
- [append](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_append.html)
- [append_record](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_append_record.html)
- [apply](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_apply.html)
- [apply_record](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_apply_record.html)
- [assign_filters](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_assign_filters.html)
- [bof](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_bof.html)
- [calc_summary](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_calc_summary.html)
- [can_create](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_can_create.html)
- [can_delete](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_can_delete.html)
- [can_edit](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_can_edit.html)
- [cancel](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_cancel.html)
- [cancel_edit](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_cancel_edit.html)
- [clear_filters](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_clear_filters.html)
- [clone](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_clone.html)
- [close](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_close.html)
- [close_edit_form](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_close_edit_form.html)
- [close_filter_form](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_close_filter_form.html)
- [close_view_form](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_close_view_form.html)
- [copy](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_copy.html)
- [create_detail_views](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_create_detail_views.html)
- [create_edit_form](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_create_edit_form.html)
- [create_filter_form](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_create_filter_form.html)
- [create_filter_inputs](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_create_filter_inputs.html)
- [create_inputs](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_create_inputs.html)
- [create_table](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_create_table.html)
- [create_view_form](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_create_view_form.html)
- [delete](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_delete.html)
- [delete_record](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_delete_record.html)
- [disable_controls](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_disable_controls.html)
- [disable_edit_form](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_disable_edit_form.html)
- [each](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_each.html)
- [each_detail](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_each_detail.html)
- [each_field](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_each_field.html)
- [each_filter](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_each_filter.html)
- [edit](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_edit.html)
- [edit_record](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_edit_record.html)
- [enable_controls](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_enable_controls.html)
- [enable_edit_form](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_enable_edit_form.html)
- [eof](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_eof.html)
- [field_by_name](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_field_by_name.html)
- [filter_by_name](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_filter_by_name.html)
- [first](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_first.html)
- [insert](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_insert.html)
- [insert_record](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_insert_record.html)
- [is_changing](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_is_changing.html)
- [is_edited](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_is_editing.html)
- [is_modified](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_is_modified.html)
- [is_new](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_is_new.html)
- [last](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_last.html)
- [locate](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_locate.html)
- [next](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_next.html)
- [open](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_open.html)
- [post](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_post.html)
- [prior](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_prior.html)
- [record_count](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_record_count.html)
- [refresh_page](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_refresh_page.html)
- [refresh_record](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_refresh_record.html)
- [search](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_search.html)
- [select_records](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_select_records.html)
- [set_fields](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_set_fields.html)
- [set_order_by](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_set_order_by.html)
- [set_where](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_set_where.html)
- [show_history](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_show_history.html)
- [update_controls](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_update_controls.html)
- [view](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/m_view.html)
- [on_after_append](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_after_append.html)
- [on_after_apply](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_after_apply.html)
- [on_after_cancel](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_after_cancel.html)
- [on_after_delete](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_after_delete.html)
- [on_after_edit](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_after_edit.html)
- [on_after_open](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_after_open.html)
- [on_after_post](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_after_post.html)
- [on_after_scroll](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_after_scroll.html)
- [on_before_append](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_before_append.html)
- [on_before_apply](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_before_apply.html)
- [on_before_cancel](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_before_cancel.html)
- [on_before_delete](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_before_delete.html)
- [on_before_edit](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_before_edit.html)
- [on_before_field_changed](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_before_field_changed.html)
- [on_before_open](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_before_open.html)
- [on_before_post](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_before_post.html)
- [on_before_scroll](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_before_scroll.html)
- [on_detail_changed](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_detail_changed.html)
- [on_edit_form_close_query](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_edit_form_close_query.html)
- [on_edit_form_created](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_edit_form_created.html)
- [on_edit_form_keydown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_edit_form_keydown.html)
- [on_edit_form_keyup](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_edit_form_keyup.html)
- [on_edit_form_shown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_edit_form_shown.html)
- [on_field_changed](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_field_changed.html)
- [on_field_get_html](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_field_get_html.html)
- [on_field_select_value](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_field_select_value.html)
- [on_field_validate](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_field_validate.html)
- [on_filter_changed](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_filter_changed.html)
- [on_filter_form_close_query](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_filter_form_close_query.html)
- [on_filter_form_created](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_filter_form_created.html)
- [on_filter_form_shown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_filter_form_shown.html)
- [on_filter_record](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_filter_record.html)
- [on_filters_applied](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_filters_applied.html)
- [on_field_get_text](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_get_field_text.html)
- [on_view_form_close_query](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_view_form_close_query.html)
- [on_view_form_created](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_view_form_created.html)
- [on_view_form_keydown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_view_form_keydown.html)
- [on_view_form_keyup](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_view_form_keyup.html)
- [on_view_form_shown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/item/on_view_form_shown.html)
- [Detail class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/detail_api.html)
- [master](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/detail/at_master.html)
- [Reports class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/report_group_api.html)
- [on_before_print_report](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/reports/on_before_print_report.html)
- [on_open_report](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/reports/on_open_report.html)
- [on_param_form_close_query](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/reports/on_param_form_close_query.html)
- [on_param_form_created](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/reports/on_param_form_created.html)
- [on_param_form_shown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/reports/on_param_form_shown.html)
- [Report class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/report_api.html)
- [extension](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/report/at_extension.html)
- [param_form](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/report/at_param_form.html)
- [param_options](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/report/at_param_options.html)
- [close_param_form](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/report/m_close_param_form.html)
- [create_param_form](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/report/m_create_param_form.html)
- [create_param_inputs](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/report/m_create_param_inputs.html)
- [print](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/report/m_print.html)
- [process_report](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/report/m_process_report.html)
- [on_before_print_report](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/report/on_before_print_report.html)
- [on_open_report](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/report/on_open_report.html)
- [on_param_form_close_query](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/report/on_param_form_close_query.html)
- [on_param_form_created](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/report/on_param_form_created.html)
- [on_param_form_shown](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/report/on_param_form_shown.html)
- [Field class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field_api.html)
- [display_text](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/at_display_text.html)
- [field_caption](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/at_field_caption.html)
- [field_mask](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/at_field_mask.html)
- [field_name](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/at_field_name.html)
- [field_size](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/at_field_size.html)
- [field_type](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/at_field_type.html)
- [lookup_text](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/at_lookup_text.html)
- [lookup_type](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/at_lookup_type.html)
- [lookup_value](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/at_lookup_value.html)
- [owner](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/at_owner.html)
- [raw_value](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/at_raw_value.html)
- [Field read_only](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/at_read_only.html)
- [required](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/at_required.html)
- [text](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/at_text.html)
- [value](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/at_value.html)
- [download](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/m_download.html)
- [open](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/field/m_open.html)
- [Filter class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/filter_api.html)
- [filter_caption](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/filter/at_filter_caption.html)
- [filter_name](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/filter/at_filter_name.html)
- [owner](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/filter/at_owner.html)
- [value](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/filter/at_value.html)
- [visible](https://jampy-docs-v7.readthedocs.io/en/latest/refs/client/filter/at_visible.html)
- [Server side (python) class reference](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/index.html)
- [App class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/app_api.html)
- [admin](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/app/at_admin.html)
- [task](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/app/at_task.html)
- [AbstractItem class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/abstractitem_api.html)
- [environ](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/abstr_item/at_environ.html)
- [ID](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/abstr_item/at_id.html)
- [item_caption](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/abstr_item/at_item_caption.html)
- [item_name](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/abstr_item/at_item_name.html)
- [item_type](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/abstr_item/at_item_type.html)
- [items](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/abstr_item/at_items.html)
- [owner](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/abstr_item/at_owner.html)
- [session](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/abstr_item/at_session.html)
- [task](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/abstr_item/at_task.html)
- [can_view](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/abstr_item/m_can_view.html)
- [item_by_ID](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/abstr_item/m_item_by_id.html)
- [Task class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task_api.html)
- [app](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/at_app.html)
- [work_dir](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/at_work_dir.html)
- [check_password_hash](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/m_check_password_hash.html)
- [connect](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/m_connect.html)
- [copy_database](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/m_copy_database.html)
- [create_connection](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/m_create_connection.html)
- [create_connection_ex](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/m_create_connection_ex.html)
- [execute](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/m_execute.html)
- [generate_password_hash](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/m_generate_password_hash.html)
- [lock](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/m_lock.html)
- [redirect](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/m_redirect.html)
- [select](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/m_select.html)
- [serve_page](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/m_serve_page.html)
- [on_created](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/on_created.html)
- [on_ext_request](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/on_ext_request.html)
- [on_login](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/on_login.html)
- [on_request](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/task/on_request.html)
- [Group class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item_group_api.html)
- [master](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/detail/at_master.html)
- [Detail class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/detail_api.html)
- [display_text](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/field/at_display_text.html)
- [field_caption](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/field/at_field_caption.html)
- [field_name](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/field/at_field_name.html)
- [field_size](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/field/at_field_size.html)
- [field_type](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/field/at_field_type.html)
- [lookup_text](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/field/at_lookup_text.html)
- [lookup_value](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/field/at_lookup_value.html)
- [owner](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/field/at_owner.html)
- [raw_value](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/field/at_raw_value.html)
- [read_only](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/field/at_read_only.html)
- [required](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/field/at_required.html)
- [text](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/field/at_text.html)
- [value](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/field/at_value.html)
- [Field class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/field_api.html)
- [filter_name](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/filter/at_filter_name.html)
- [owner](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/filter/at_owner.html)
- [value](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/filter/at_value.html)
- [Filter class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/filter_api.html)
- [active](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/at_active.html)
- [details](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/at_details.html)
- [fields](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/at_fields.html)
- [filters](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/at_filters.html)
- [item_state](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/at_item_state.html)
- [log_changes](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/at_log_changes.html)
- [rec_no](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/at_rec_no.html)
- [table_name](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/at_table_name.html)
- [virtual_table](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/at_virtual_table.html)
- [append](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_append.html)
- [apply](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_apply.html)
- [bof](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_bof.html)
- [can_create](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_can_create.html)
- [can_delete](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_can_delete.html)
- [can_edit](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_can_edit.html)
- [cancel](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_cancel.html)
- [clear_filters](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_clear_filters.html)
- [close](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_close.html)
- [copy](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_copy.html)
- [delete](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_delete.html)
- [edit](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_edit.html)
- [eof](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_eof.html)
- [field_by_name](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_field_by_name.html)
- [filter_by_name](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_filter_by_name.html)
- [first](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_first.html)
- [insert](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_insert.html)
- [is_changing](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_is_changing.html)
- [is_edited](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_is_editing.html)
- [is_modified](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_is_modified.html)
- [is_new](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_is_new.html)
- [last](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_last.html)
- [locate](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_locate.html)
- [next](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_next.html)
- [open](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_open.html)
- [post](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_post.html)
- [prior](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_prior.html)
- [record_count](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_record_count.html)
- [set_fields](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_set_fields.html)
- [set_order_by](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_set_order_by.html)
- [set_where](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/m_set_where.html)
- [on_apply](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/on_apply.html)
- [on_open](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item/on_open.html)
- [Item class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/item_api.html)
- [report_filename](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/report/at_report_filename.html)
- [report_url](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/report/at_report_url.html)
- [template](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/report/at_template.html)
- [generate](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/report/m_generate.html)
- [hide_columns](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/report/m_hide_columns.html)
- [print_band](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/report/m_print_band.html)
- [on_after_generate](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/report/on_after_generate.html)
- [on_before_generate](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/report/on_before_generate.html)
- [on_generate](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/report/on_generate.html)
- [on_parsed](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/report/on_parsed.html)
- [Report class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/report_api.html)
- [Reports class](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/report_group_api.html)
- [on_convert_report](https://jampy-docs-v7.readthedocs.io/en/latest/refs/server/reports/on_convert_report.html)
- [Release notes](https://jampy-docs-v7.readthedocs.io/en/latest/releases/index.html)
- [Version 1](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version_1.html)
- [Jam.py roadmap](https://jampy-docs-v7.readthedocs.io/en/latest/releases/roadmap.html)
- [Version 5](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/index.html)
- [Version 5.0.1](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_0_1.html)
- [Version 5.1.1](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_1_1.html)
- [Version 5.2.1](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_2_1.html)
- [Version 5.3.1](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_3_1.html)
- [Version 5.3.3](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_3_3.html)
- [Version 5.4.1](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_1.html)
- [Version 5.4.109](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_109.html)
- [Version 5.4.11](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_11.html)
- [Version 5.4.14](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_14.html)
- [Version 5.4.15](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_15.html)
- [Version 5.4.21](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_21.html)
- [Version 5.4.22](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_22.html)
- [Version 5.4.23](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_23.html)
- [Version 5.4.24](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_24.html)
- [Version 5.4.27](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_27.html)
- [Version 5.4.29](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_29.html)
- [Version 5.4.30](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_30.html)
- [Version 5.4.31](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_31.html)
- [Version 5.4.36](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_36.html)
- [Version 5.4.37](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_37.html)
- [Version 5.4.40](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_40.html)
- [Version 5.4.53](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_53.html)
- [Version 5.4.54](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_54.html)
- [Version 5.4.56](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_56.html)
- [Version 5.4.57](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_57.html)
- [Version 5.4.60](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_60.html)
- [Version 5.4.61](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_61.html)
- [Version 5.4.69](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_4_69.html)
- [Version 5.5.4](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version 5/version_5_5_1.html)
- [Version 2](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version_2.html)
- [Version 3](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version_3.html)
- [Version 4](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version_4/index.html)
- [Version 4.0.70](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version_4/version_4_0_70.html)
- [Version 4.0.71](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version_4/version_4_0_71.html)
- [Version 4.0.74](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version_4/version_4_0_74.html)
- [Version 4.0.78](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version_4/version_4_0_78.html)
- [Version 4.0.79](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version_4/version_4_0_79.html)
- [Version 4.0.81](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version_4/version_4_0_81.html)
- [Version 4.0.84](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version_4/version_4_0_84.html)
- [Version 4.0.88](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version_4/version_4_0_88.html)
- [Version 7](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version_7/index.html)
- [Version 7.0.39](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version_7/version_7_0_39.html)
- [Version 7.0.50](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version_7/version_7_0_50.html)
- [Version 7.0.53](https://jampy-docs-v7.readthedocs.io/en/latest/releases/version_7/version_7_0_53.html)
==================================================
A step-by-step guide to deploy a Jam.py on the AWS
==================================================
This is adapted from
https://devops.profitbricks.com/tutorials/install-and-configure-mod_wsgi-on-ubuntu-1604-1/
I hope someone finds it useful.
* Create an AWS account and login
* Go to EC2, create an instance (in this case an Ubuntu 16.04 t2.micro)
* Download the private key when prompted
* Convert pem to ppk using Puttygen (see: https://stackoverflow.com/questions/3190667/convert-pem-to-ppk-file-format)
* Get EC2 instance public DNS from AWS dashboard
* SSH into EC2 instance using Putty (pointed to the Public DNS and your ppk)
* Username is ubuntu
* Refresh package library:
.. code-block:: console
sudo apt-get update
* Install pip:
.. code-block:: console
sudo apt-get install python3-pip
* Install jam.py:
.. code-block:: console
sudo pip3 install jam.py
* Install Apache:
.. code-block:: console
sudo apt-get install apache2 apache2-utils libexpat1 ssl-cert
* Install mod-wsgi:
.. code-block:: console
sudo apt-get install libapache2-mod-wsgi-py3
* Restart Apache:
.. code-block:: console
sudo /etc/init.d/apache2 restart
* Move here:
.. code-block:: console
cd /var/www/html/
* Create directory:
.. code-block:: console
sudo mkdir [appname]
* Move here:
.. code-block:: console
cd [appname]
* Create app:
.. code-block:: console
sudo jam-project.py
* Check it's there:
.. code-block:: console
ls
* Create the config:
.. code-block:: console
sudo nano /etc/apache2/conf-available/wsgi.conf
* Paste the following
.. code-block:: apache
WSGIScriptAlias / /var/www/html/[appname]/wsgi.py
WSGIPythonPath /var/www/html/[appname]
Require all granted
Alias /static/ /var/www/html/[appname]/static/
Require all granted
* Exit and save
* Give file permissions to apache:
.. code-block:: console
sudo chmod 777 /var/www/html/[appname]
* Give ownership to apache:
.. code-block:: console
sudo chown -R www-data:www-data /var/www
* Enable wsgi:
.. code-block:: console
sudo a2enconf wsgi
* Restart apache:
.. code-block:: console
sudo /etc/init.d/apache2 restart
* Create security group on AWS to allow you to connect HTTP on port 80
* Assign instance to security group
* Test
* If it's not working, check the error logs to see what's going on:
.. code-block:: console
nano /var/log/apache2/error.log
*This was initially published by Simon Cox on*
https://groups.google.com/forum/#!msg/jam-py/Zv5JfkLRFy4/22tolZ-hAQAJ
==================
AbstractItem class
==================
.. py:class:: AbstractItem
**domain**: server
**language**: python
AbstractItem class is the ancestor for all item objects of the
:doc:`task tree `
Below the attributes and methods of the class are listed.
Attributes
==========
.. toctree::
:maxdepth: 1
:glob:
abstr_item/at_*
Methods
=======
.. toctree::
:maxdepth: 1
:glob:
abstr_item/m_*
=============
Accept string
=============
An accept string can be a combination of the following values,
separated by comma.
============== ===========
Value Description
============== ===========
file_extension Specify the file extension(s) (e.g: .gif, .jpg, .png, .doc)
audio/* All sound files
video/* All video files
image/* All image files
============== ===========
For example::
.pdf,.xls
image/*,.pdf,.xls
audio/*
audio/*,video/*
Understanding admin.sqlite
==========================
The Mind Map for Jam.py V7 admin.sqlite database describes the Jam.py database engine schema. The intention was to quickly find the information needed, as well as the code.
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/image.png
:target: ../_static/Jam.py.html_files/image.png
.. raw:: html
:file: ../_static/Jam.py.html
=========
App class
=========
.. py:class:: App
**domain**: server
**language**: python
App class is used to create a WSGI application
Below the attributes of the class are listed.
.. toctree::
:maxdepth: 1
:glob:
app/at_*
======
active
======
.. py:attribute:: active
**domain**: server
**language**: python
**class** :doc:`Item class `
Description
===========
Specifies whether or not an item dataset is open.
Use ``active`` read only property to determine whether an item dataset is open.
The
:doc:`open `
method changes the value of ``active`` to ``true``. The
:doc:`close ` method sets it to ``false``.
When the dataset is
open its records can be navigated and its data can be modified and the changes
saved in the item database table.
See also
========
:doc:`Dataset `
:doc:`Navigating datasets `
:doc:`Modifying datasets `
=====
admin
=====
.. py:attribute:: admin
**domain**: server
**language**: python
**class**: :doc:`App class `
Description
===========
Returns a reference to the Application builder task tree
See also
========
:doc:`Workflow `
:doc:`Task tree `
===
app
===
.. py:attribute:: app
**domain**: server
**language**: python
**class**: :doc:`Task class `
Description
===========
Returns a reference to WSGI
:doc:`application object `.
The Framework uses Werkzeug_ WSGI Utility Library.
.. _Werkzeug: http://werkzeug.pocoo.org/
See also
========
:doc:`Workflow `
==========
can_modify
==========
.. js:attribute:: active
**domain**: client
**language**: javascript
**class** :doc:`Item class `
Description
===========
Set the ``can_modify`` property to false if you need to prohibit changing
of the item in the visual controls.
When ``can_modify`` is true the
:doc:`can_create `,
:doc:`can_edit `,
:doc:`can_delete `
methods return false.
By default the ``can_modify`` property is true.
=======
details
=======
.. py:attribute:: details
**domain**: server
**language**: python
**class** :doc:`Item class `
Description
===========
Lists all
:doc:`detail `
objects of the item.
See also
========
:doc:`Details `
============
display_text
============
.. py:attribute:: display_text
**domain**: server
**language**: python
:doc:`Field class `
Description
===========
Represents the field's value as a string.
``Display_text`` property is a read-only string representation of a field's value
to display it to users. If an
:doc:`on_get_field_text `
event handler is assigned, **display_text** is the value returned by this event
handler. Otherwise, display_text is the value of the
:doc:`lookup_text `
property for
:doc:`lookup fields `
and
:doc:`text `
property converted according to the
:doc:`language locale `
settings
for other fields.
``Display_text`` is the string representation of the field's value property when
it is not being edited. When the field is being edited, the
:doc:`text `
property is used.
Example
=======
.. code-block:: py
def on_generate(report):
cust = report.task.customers.copy()
cust.open()
report.print_band('title')
for c in cust:
firstname = c.firstname.display_text
lastname = c.lastname.display_text
company = c.company.display_text
country = c.country.display_text
address = c.address.display_text
phone = c.phone.display_text
email = c.email.display_text
report.print_band('detail', locals())
See also
========
:doc:`Fields `
:doc:`Lookup fields `
:doc:`on_get_field_text `
:doc:`text `
:doc:`lookup_text `
=========
edit_form
=========
.. js:attribute:: edit_form
**domain**: client
**language**: javascript
**class** :doc:`Item class `
Description
===========
Use ``edit_form`` attribute to get access to a Jquery object representing the
edit form of the item.
It is created by the
:doc:`create_edit_form `
method.
The
:doc:`close_edit_form `
method sets the ``edit_form`` value to undefined.
Example
=======
In the following example the button defined in the item edit html template is
assigned a click event:
.. code-block:: js
item.edit_form.find("#ok-btn").on('click.task',
function() {
item.apply_record();
}
);
See also
========
:doc:`Forms `
:doc:`create_edit_form `
:doc:`close_edit_form `
============
edit_options
============
.. js:attribute:: edit_options
**domain**: client
**language**: javascript
**class** :doc:`Item class `
Description
===========
The ``edit_options`` attribute is a set of options that determine how the edit
form will be displayed on the browser page.
These options are set in the
:doc:`Edit Form Dialog `
in Application Builder.
You can change ``edit options`` in the
:doc:`on_edit_form_created `
event handler of the item. See example.
``edit_options`` is an object that has the following attributes:
=================== ============================================================
Option Description
=================== ============================================================
width the width of the modal form, the default value is 600 px,
title the title of the form, the default value is the value of a
:doc:`item_caption `
attribute,
form_border if true, the border will be displayed around the form
form_header if true, the form header will be created and displayed
containing form title and various buttons
history_button if true and
:doc:`saving change history is enabled `,
the history button will be displayed in the form header
close_button if true, the close button will be created in the upper-right
corner of the form
close_on_escape if true, pressing on the Escape key will execute the
:doc:`close_edit_form `
method to close the form
edit_details the list of the detail names, that will be available for
editing in the edit form, if edit form template contains the
div with class 'edit-detail' (the default edit form template
have this div)
detail_height the height of the detail displayed in the view form,
if not specified the height of the detail table is 200px
fields specify the list of field names that the
:doc:`create_inputs `
method will use, if fields attribute of its options
parameter is not specified
template_class if specified, the div with this class will be searched in
the task
:doc:`templates `
attribute and used as a form html template when creating a
form. This attribute must be set before creating the form
modeless if set the edit forms will be created modeless, otherwise -
modal
=================== ============================================================
Example
=======
.. code-block:: js
function on_edit_form_created(item) {
item.edit_options.width = 800;
item.edit_options.close_on_escape = false;
}
See also
========
:doc:`Forms `
:doc:`create_edit_form `
:doc:`close_edit_form `
=======
environ
=======
.. py:attribute:: environ
**domain**: server
**language**: python
**class** :doc:`AbstractItem class `
Description
===========
Specifies the WSGI environment dictionary of the current request from the client.
See also
========
:doc:`Server side programming `
:doc:`session `
=========
extension
=========
.. js:attribute:: extension
**domain**: client
**language**: javascript
**class** :doc:`Report class `
Description
===========
Use ``extension`` attribute to specify a report type. The server, based on the
report template, first generates **ods** file. And if report extension is other
that **ods** performs conversion using the LibreOffice.
The attribute value can be any extension that LibreOffice supports conversion to.
Example
=======
.. code-block:: js
function on_before_print_report(report) {
report.extension = 'html';
}
See also
========
:doc:`Client-side report programming `
:doc:`Server-side report programming `
:doc:`print `
:doc:`create_param_form `
:doc:`on_before_print_report `
=============
field_caption
=============
.. py:attribute:: field_caption
**domain**: server
**language**: python
:doc:`Field class `
Description
===========
``Field_caption`` attribute specifies the name of the field that appears to
users.
See also
========
:doc:`Dataset `
:doc:`Fields `
:doc:`field_name `
==========
field_mask
==========
.. js:attribute:: field_mask
**domain**: client
**language**: javascript
**class** :doc:`Field class `
Description
===========
You can use **field_mask** attribute to specify the name of the field that appears to
The mask allows a user to more easily enter fixed width input where you would
like them to enter the data in a certain format (dates,phone numbers, etc).
A mask is defined by a format made up of mask literals and mask definitions.
Any character not in the definitions list below is considered a mask literal.
Mask literals will be automatically entered for the user as they type and will
not be able to be removed by the user.The following mask definitions are predefined:
* a - Represents an alpha character (A-Z,a-z)
* 9 - Represents a numeric character (0-9)
* `*` - Represents an alphanumeric character (A-Z,a-z,0-9)
Example
=======
.. code-block:: js
function on_edit_form_created(item) {
item.phone.field_mask = '999-99-99';
}
==========
field_name
==========
.. py:attribute:: field_name
**domain**: server
**language**: python
:doc:`Field class `
Description
===========
Specifies the name of the field as referenced in code.
Use ``field_name`` to refer to the field in code.
See also
========
:doc:`Dataset `
:doc:`Fields `
:doc:`field_caption `
==========
field_size
==========
.. py:attribute:: field_size
**domain**: server
**language**: python
:doc:`Field class `
Description
===========
Identifies the size of the text field object.
See also
========
:doc:`Dataset `
:doc:`Fields `
==========
field_type
==========
.. py:attribute:: field_type
**domain**: server
**language**: python
:doc:`Field class `
Description
===========
Identifies the data type of the field object.
Use the ``field_type`` attribute to learn the type of the data the field contains.
It is one of the following values:
* "text",
* "integer",
* "float",
* "currency",
* "date",
* "datetime",
* "boolean",
* "blob"
See also
========
:doc:`Dataset `
:doc:`Fields `
======
fields
======
.. py:attribute:: fields
**domain**: server
**language**: python
**class** :doc:`Item class `
Description
===========
Lists all
:doc:`field `
objects of the item dataset.
Example
=======
.. code-block:: py
def customer_fields(customers):
customers.open(limit=1)
for f in customers.fields:
print f.field_caption, f.display_text
See also
========
:doc:`Fields `
:doc:`Field class `
==============
filter_caption
==============
.. js:attribute:: filter_caption
**domain**: client
**language**: javascript
**class** :doc:`Filter class `
Description
===========
**Filter_caption** attribute specifies the name of the filter that appears to
users.
See also
========
:doc:`Filters `
:doc:`filter_name `
:doc:`Dataset `
===========
filter_form
===========
.. js:attribute:: filter_form
**domain**: client
**language**: javascript
**class** :doc:`Item class `
Description
===========
Use ``filter_form`` attribute to get access to a Jquery object representing the
filter form of the item.
It is created by the
:doc:`create_filter_form `
method.
The
:doc:`close_filter_form `
method sets the ``filter_form`` value to undefined.
Example
=======
In the following example the button defined in the item filter html template is
assigned a click event:
.. code-block:: js
item.filter_form.find("#cancel-btn").on('click',
function() {
item.close_filter()
}
);
See also
========
:doc:`Forms `
:doc:`create_filter_form `
:doc:`close_filter_form `
===========
filter_name
===========
.. py:attribute:: filter_name
**domain**: server
**language**: python
**class** :doc:`Filter class `
Description
===========
Specifies the name of the filter as referenced in code.
Use ``filter_name`` to refer to the field in code.
See also
========
:doc:`Filters `
:doc:`Dataset `
==============
filter_options
==============
.. js:attribute:: filter_options
**domain**: client
**language**: javascript
**class** :doc:`Item class `
Description
===========
Use the ``filter_options`` attribute to specify parameters of the modal filter form.
``filter_options`` is an object that has the following attributes:
* ``width`` - the width of the modal form, the default value is 560 px,
* ``title`` - use it to get or set the title of the filter form,
* ``close_button`` - if true, the close button will be created in the upper-right
corner of the form, the default value is true,
* ``close_caption`` - if true and close_button is true, will display 'Close - [Esc]'
near the button
* ``close_on_escape`` - if true, pressing on the Escape key will trigger the
:doc:`close_filter_form `
method.
* ``close_focusout`` - if true, the
:doc:`close_filter_form `
method will be called when a form loses focus
* ``template_class`` - if specified, the div with this class will be searched in
the task
:doc:`templates `
attribute and used as a form html template when creating a form
Example
=======
.. code-block:: js
function on_filter_form_created(item) {
item.filter_options.width = 700;
}
See also
========
:doc:`Forms `
:doc:`create_filter_form `
:doc:`close_filter_form `
========
Filtered
========
.. js:attribute:: filtered
**domain**: client
**language**: javascript
**class** :doc:`Item class `
Description
===========
Specifies whether or not filtering is active for a dataset.
Check ``filtered`` to determine whether or not local dataset filtering is in
effect. If ``filtered`` is ``true``, then filtering is active. To apply filter
conditions specified in the
:doc:`on_filter_record `
event handler, set ``filtered`` to ``true``.
See also
========
:doc:`on_filter_record `
=======
filters
=======
.. py:attribute:: filters
**domain**: server
**language**: python
**class** :doc:`Item class `
Description
===========
Lists all
:doc:`filter `
objects of the item dataset.
Example
=======
.. code-block:: py
def invoices_filters(invoices):
for f in invoices.filters:
print f.filter_name, f.value
See also
========
:doc:`Filters `
:doc:`Filter class `
===============
forms_container
===============
.. js:attribute:: forms_container
**domain**: client
**language**: javascript
**class** :doc:`Task `
Description
===========
The ``forms_container`` is a JQuery object in which the application will create
forms.
To initialize ``forms_container`` use the
:doc:`set_forms_container ` method or the
:doc:`create_menu ` method.
The default code uses the :doc:`create_menu ` method.
See also
========
:doc:`forms_in_tabs `
:doc:`create_menu `
:doc:`set_forms_container `
=============
forms_in_tabs
=============
.. js:attribute:: forms_in_tabs
**domain**: client
**language**: javascript
**class** :doc:`Task `
Description
===========
If the ``forms_in_tabs`` attribute is set and
:doc:`forms_container ` is specified the application will
create forms in tabs.
This attribute can be set in the **Interface** tab of
:doc:`Parameters `.
==
ID
==
.. py:attribute:: ID
**domain**: server
**language**: python
**class** :doc:`AbstractItem class `
Description
===========
The ``ID`` attribute is the unique in the framework id of the item
The ``ID`` attribute is most useful when referring to the item by number rather than
name. It is also used internally.
See also
========
:doc:`Task tree `
============
item_caption
============
.. py:attribute:: item_caption
**domain**: server
**language**: python
**class** :doc:`AbstractItem class `
Description
===========
Specifies the name of the item that appears to users
See also
========
:doc:`Task tree `
=========
item_name
=========
.. py:attribute:: item_name
**domain**: server
**language**: python
**class** :doc:`AbstractItem class `
Description
===========
Specifies the name of the item as referenced in code.
Use ``item_name`` to refer to the item in code.
See also
========
:doc:`Task tree `
==========
item_state
==========
.. py:attribute:: item_state
**domain**: server
**language**: python
**class** :doc:`Item class `
Description
===========
Examine ``item_state`` to determine the current operating mode of the item.
Item_state determines what can be done with data in an item dataset, such as
editing existing records or inserting new ones. The ``item_state`` constantly
changes as an application processes data.
Opening a item changes state from inactive to browse. An application can call
:doc:`edit `
to put an item into edit state, or call
:doc:`insert `
or
:doc:`append `
to put an item into
insert state.
Posting or cancelling edits, insertions, or deletions, changes ``item_state``
from its current state to browse. Closing a dataset changes its state to
inactive.
To check item_state value use the following methods:
* :doc:`is_new ` - indicates whether the item is in insert state
* :doc:`is_edited ` - indicates whether the item is in edit state
* :doc:`is_changing ` - indicates whether the item is in edit or
insert state
item_state value can be:
* 0 - inactive state,
* 1 - browse state,
* 2 - insert state,
* 3 - edit state,
* 4 - delete state
item :doc:`task ` attribute have consts object
that defines following attributes:
* "STATE_INACTIVE": 0,
* "STATE_BROWSE": 1,
* "STATE_INSERT": 2,
* "STATE_EDIT": 3,
* "STATE_DELETE": 4
so if the item is in edit state can be checked the following way:
::
item.item_state == 2
or::
item.item_state == item.task.consts.STATE_INSERT
or::
item.is_new()
See also
========
:doc:`Modifying datasets `
=========
item_type
=========
.. py:attribute:: item_type
**domain**: server
**language**: python
**class**: :doc:`AbstractItem class `
Description
===========
Specifies the type of the item.
Use the ``item_type`` attribute to get the type of the item. It can have one of the
following values
* “task”,
* “items”,
* “details”,
* “reports”,
* “item”,
* “detail_item”,
* “report”,
* “detail”
See also
========
:doc:`Task tree `
=====
items
=====
.. py:attribute:: items
**domain**: server
**language**: python
**class** :doc:`AbstractItem class `
Description
===========
Lists all items owned by the item.
Use ``items`` to access any of the item owned by this object.
See also
========
:doc:`Task tree `
===========
log_changes
===========
.. py:attribute:: log_changes
**domain**: server
**language**: python
**class** :doc:`Item class `
Description
===========
Indicates whether to log data changes.
Use ``log_changes`` to control whether or not changes made to the data in an
item dataset are recorded. When ``log_changes`` is ``true`` (the default), all
changes are recorded. They can later be applied to an application server by
calling the
:doc:`apply `
method. When ``log_changes`` is ``false``, data changes are not recorded and cannot
be applied to an application server.
See also
========
:doc:`Modifying datasets `
:doc:`apply `
============
lookup_field
============
.. js:attribute:: lookup_field
**domain**: client
**language**: javascript
**class** :doc:`Item class `
Description
===========
Use ``lookup_field`` to check if the item was created to select a value for
the lookup field. See :doc:`Lookup fields `
Example
=======
.. code-block:: js
function on_view_form_created(item) {
item.table_options.multiselect = false;
if (!item.lookup_field) {
var print_btn = item.add_view_button('Print', {image: 'icon-print'}),
email_btn = item.add_view_button('Send email', {image: 'icon-pencil'});
email_btn.click(function() { send_email() });
print_btn.click(function() { print(item) });
item.table_options.multiselect = true;
}
}
===========
lookup_text
===========
.. py:attribute:: lookup_text
**domain**: server
**language**: python
:doc:`Field class `
Description
===========
Use ``lookup_text`` property to get the lookup value of the
:doc:`lookup field ` converted to string.
If the field is
:doc:`lookup field `
gives its lookup text,
otherwise gives the value of the
:doc:`text `
property
See also
========
:doc:`Fields `
:doc:`Lookup fields `
:doc:`lookup_value `
:doc:`text `
===========
lookup_type
===========
.. js:attribute:: lookup_type
**domain**: client
**language**: javascript
**class** :doc:`Field class `
Description
===========
For
:doc:`lookup fields `
identifies the type of the
:doc:`lookup_value `,
otherwise returns the value of
:doc:`field_type `
attribute.
See also
========
:doc:`Dataset `
:doc:`Fields `
============
lookup_value
============
.. py:attribute:: lookup_value
**domain**: server
**language**: python
:doc:`Field class `
Description
===========
Use ``lookup_value`` property to get the lookup value of the
:doc:`lookup field `
If the field is
:doc:`lookup field `
gives its lookup value,
otherwise gives the value of the
:doc:`value `
property
See also
========
:doc:`Fields `
:doc:`Lookup fields `
:doc:`lookup_value `
:doc:`lookup_text `
======
master
======
.. py:attribute:: master
**domain**: server
**language**: python
**class** :doc:`Detail class `
Description
===========
Use ``master`` attribute to get reference to the master of the detail.
See also
========
:doc:`Details `
=====
owner
=====
.. js:attribute:: owner
**domain**: server
**language**: python
**class** :doc:`Filter class `
Description
===========
Identifies the item to which a filter object belongs.
Check the value of the owner attribute to determine the item that uses the filter
object to represent one of its filters.
========
paginate
========
.. js:attribute:: paginate
**domain**: client
**language**: javascript
**class** :doc:`Item class `
Description
===========
The ``paginate`` attribute determines the behavior of a table created by the
:doc:`create_table `
method
When ``paginate`` is set to ``true``, a paginator is created, and the table
calculates the number of the rows displayed, based on its height. The table will
internally manipulate the
``limit`` and ``offset`` parameters of the
:doc:`open `
method, depending on its height and current page, reopening the dataset when
page changes.
If ``paginate`` value is ``false``, the table will displays all available
records of the dataset.
See also
========
:doc:`create_table `
:doc:`open `
==========
param_form
==========
.. js:attribute:: param_form
**domain**: client
**language**: javascript
**class** :doc:`Report class `
Description
===========
Use ``param_form`` attribute to get access to a Jquery object representing the
param form of the report.
It is created by the
:doc:`create_param_form `
method, that, usually, is called by then
:doc:`print `
method.
The
:doc:`close_param_form `
method sets the ``param_form`` value to undefined.
Example
=======
.. code-block:: js
function on_param_form_created(report) {
report.create_param_inputs(report.param_form.find(".edit-body"));
report.param_form.find("#cancel-btn").on('click.task', function() {
report.close_param_form();
});
report.param_form.find("#ok-btn").on('click.task', function() {
report.process_report()
});
}
See also
========
:doc:`Forms `
:doc:`print `
:doc:`create_param_form `
:doc:`close_param_form `
=============
param_options
=============
.. js:attribute:: param_options
**domain**: client
**language**: javascript
**class** :doc:`Report class `
Description
===========
Use the ``param_options`` attribute to specify parameters of the modal param form.
``param_options`` is an object that has the following attributes:
* ``width`` - the width of the modal form, the default value is 560 px,
* ``title`` - the title of the modal form, the default value is the value of a
:doc:`report_caption `
attribute,
* ``close_button`` - if true, the close button will be created in the upper-right
corner of the form, the default value is true,
* ``close_caption`` - if true and close_button is true, will display 'Close - [Esc]'
near the button
* ``close_on_escape`` - if true, pressing on the Escape key will trigger the
:doc:`close_param_form `
method.
* ``close_focusout`` - if true, the
:doc:`close_param_form `
method will be called when a form loses focus
* ``template_class`` - if specified, the div with this class will be searched in
the task
:doc:`templates `
attribute and used as a form html template when creating a form
Example
=======
.. code-block:: js
function on_param_form_created(report) {
report.param_options.width = 800;
report.param_options.close_button = false;
report.param_options.close_on_escape = false;
}
See also
========
:doc:`Forms `
:doc:`print `
:doc:`create_param_form `
:doc:`close_param_form `
===========
permissions
===========
.. js:attribute:: permissions
**domain**: client
**language**: javascript
**class** :doc:`Item class `
Description
===========
Set the ``permissions`` property attributes to prohibit changing of the item in
the visual controls.
The ``permissions`` property is an object that has the following attributes:
* can_create
* can_edit
* can_delete
By default theses attributes are set to true.
When these attributes are set to false the corresponding
* :doc:`can_create `,
* :doc:`can_edit `,
* :doc:`can_delete `
methods return false.
See also
========
:doc:`How to prohibit changing record `
=========
raw_value
=========
.. py:attribute:: raw_value
**domain**: server
**language**: python
:doc:`Field class `
Description
===========
Represents the data in a field object.
Use ``raw_value`` read only property to read data directly from the item dataset.
Other properties such as
:doc:`value `
and
:doc:`text `
use conversion.
So the
:doc:`value `
property converts the ``null`` value to ``0`` for the numeric fields.
See also
========
:doc:`Fields `
:doc:`value `
:doc:`text `
=========
read_only
=========
.. py:attribute:: read_only
**domain**: server
**language**: python
:doc:`Field class `
Description
===========
Determines whether the field can be modified in data-aware controls.
Set ``read_only`` to ``true`` to prevent a field from being modified in
data-aware controls.
See also
========
:doc:`Fields `
:doc:`required `
=========
rec_count
=========
.. js:attribute:: rec_count
**domain**: client
**language**: javascript
**class** :doc:`Item class `
Description
===========
Read the ``rec_count`` property to get the number of records owned by
the item's dataset.
If the module declares an
:doc:`on_filter_record `
event handler and the
:doc:`Filtered `
attribute is set, this property calculates the
number of records that satisfy this filter, otherwise the
:doc:`record_count `
method is used to calculate the number of records.
See also
========
:doc:`record_count `
Example
=======
.. code-block:: js
function edit_invoice(invoice_id) {
var invoices = task.invoices.copy();
invoices.open({ where: {id: invoice_id} }, function() {
if (invoices.rec_count) {
invoices.edit_record();
}
else {
invoices.alert_error('Invoices: record not found.');
}
});
}
======
rec_no
======
.. py:attribute:: rec_no
**domain**: server
**language**: python
**class** :doc:`Item class `
Description
===========
Examine the ``rec_no`` property to determine the record number of the current
record in the item dataset.
``rec_no`` can be set to a specific record number to position the cursor on that
record.
See also
========
:doc:`Dataset `
:doc:`Navigating datasets `
===============
report_filename
===============
.. py:attribute:: report_filename
**domain**: client
**language**: python
**class** :doc:`Report class `
Description
===========
When the
:doc:`template `
attribute of the report is specified, the
:doc:`generate `
method saves the content of the generated report to a file in a report folder
of the static directory and set the value of the
**report_filename** attribute to the name of the saved file.
Its value can be used in the
:doc:`on_after_generate `
event handler.
See also
========
:doc:`Server-side report programming `
:doc:`generate `
==========
report_url
==========
.. py:attribute:: report_url
**domain**: client
**language**: python
**class** :doc:`Report class `
Description
===========
The
:doc:`generate `
method sends to the client the value that is stored in this attribute as url of
the generated file.
When the
:doc:`template `
attribute of the report is specified, this value is set by the
:doc:`generate `
method after it save generated content. Otherwise a developer must set it
himself.
See also
========
:doc:`Server-side report programming `
:doc:`generate `
========
required
========
.. py:attribute:: required
**domain**: server
**language**: python
:doc:`Field class `
Description
===========
Specifies whether a not empty value for a field is required.
Use ``required`` to find out if a field requires a value or if the field can be
blank. When ``required`` property is set to true, trying to post a null value
will cause an exception to be raised.
See also
========
:doc:`Fields `
:doc:`read_only `
=========
safe_mode
=========
.. js:attribute:: safe_mode
**domain**: client
**language**: javascript
**class** :doc:`Task `
Description
===========
Check the ``safe_mode`` attribute to determine if the
:doc:`safe mode `
parameter of the project is set.
Example
=======
.. code-block:: js
function on_page_loaded(task) {
$("#title").html(task.item_caption);
if (task.safe_mode) {
$("#user-info").text(task.user_info.role_name + ' ' + task.user_info.user_name);
$('#log-out')
.show()
.click(function(e) {
e.preventDefault();
task.logout();
});
}
task.tasks.view($("#content"));
}
See also
========
:doc:`Parameters `
:doc:`user_info `
:doc:`on_page_loaded `
==========
selections
==========
.. js:attribute:: selections
**domain**: client
**language**: javascript
**class** :doc:`Item class `
Description
===========
The ``selections`` attribute stores a list of a primary key field values.
When a **Multiple selection** check box is checked on the
**Layout** tab in the
:doc:`View Form Dialog ` or
multiselect attribute of the
:doc:`table_options ` is set programmatically,
the check box in the leftmost column of the table appears and
each time a user clicks on the check box, the ``selections`` attribute changes.
It can also be changed programmatically by using ``add`` or ``remove`` methods
or assigning an array.
Example
=======
In this example, the ``send_email`` function, on the client, uses **Customers** selection
attribute to get array of primary key field values selected by users and send them
to the ``send_email`` function defined in the server module of the item using
the
:doc:`server `
method
.. code-block:: js
function send_email(subject, message) {
var selected = task.customers.selections;
if (!selected.length) {
selected.add(task.customers.id.value);
}
item.server('send_email', [selected, subject, message],
function(result, err) {
if (err) {
item.alert('Failed to send the mail: ' + err);
}
else {
item.alert('Successfully sent the mail');
}
}
);
}
On the server, this array is used to retrieve information about selected customers
using
:doc:`open `
method
.. code-block:: py
import smtplib
def send_email(item, selected, subject, mess):
cust = item.task.customers.copy()
cust.set_where(id__in=selected)
cust.open()
to = []
for c in cust:
to.append(c.email.value)
# code that sends email
=======
session
=======
.. py:attribute:: session
**domain**: server
**language**: python
**class** :doc:`AbstractItem class `
Description
===========
Use the ``session`` property to get access to session object of the current
request from the client.
The session is a dictionary that has the following items:
* ``ip`` - ip address of the user
* ``user_info`` - dictionary containing information about the user
* ``user_id`` - id identifying the user
* ``user_name`` - name of the user
* ``role_id`` - id of user role
* ``role_name`` - name of user role
Example
=======
.. code-block:: py
def on_open(item, params):
user_id = item.session['user_info']['user_id']
if user_id:
params['__filters'].append(['user_id', item.task.consts.FILTER_EQ, user_id])
def on_apply(item, delta, params):
user_id = item.session['user_info']['user_id']
if user_id:
for d in delta:
d.edit()
d.user_id.value = user_id
d.post()
See also
========
:doc:`Server side programming `
:doc:`environ `
==========
table_name
==========
.. py:attribute:: table_name
**domain**: server
**language**: python
**class** :doc:`Item class `
Description
===========
Read this property to get the name of the corresponding table in the project
database.
=============
table_options
=============
.. js:attribute:: table_options
**domain**: client
**language**: javascript
**class** :doc:`Item class `
Description
===========
The ``table_options`` attribute is a set of options that determine how the table
of the view form of will be displayed. Options defined in it are used by the
:doc:`create_table `
method if its options parameter don't override corresponding option.
These options are set in the **Layout** tab of the
:doc:`View Form Dialog `
in Application Builder.
You can change ``table_options`` in the
:doc:`on_view_form_created `
event handler of the item. See example.
The ``table_options`` parameter is an object that may have the following attributes:
=================== ============================================================
Option Description
=================== ============================================================
row_count specifies the number of rows displayed by the table
height if row_count is not specified, it determines the height of
the table, the default value is 480. The table at creation
calculates the number of rows displayed (row_count),
based on the value of this parameter.
fields a list of field names. If specified, a column will be
created for each field whose name is in this list, if not
specified (the default) then the fields attribute of an
:doc:`view_options `
will be used
title_line_count specifies the number of lines of text displayed in a
title row, if it is 0, the height of the row is determined
by the contents of the title cells
row_line_count specifies the number of lines of text displayed in a
table row, if it is 0, the height of the row is determined
by the contents of the cells
expand_selected_row if row_line_count is set and expand_selected_row is
greater that 0, it specifies the minimal number of lines of
text displayed in the selected row of the table
title_word_wrap specifies if the column title text can be wrapped.
column_width the width of the columns are calculated by a Web Browser.
You can use this option to force the width of columns. The option is an
object, key values of which are field names, the values are column widths
as CSS units
editable_fields the list of field names could be edited in the table.
selected_field if editable_fields are set, specifies the name of the
field whose column will be selected, when the selected row
is changed.
sortable if this option is specified, it is possible to sort the
records by clicking on the table column header. When a
sort_fields option is not specified (default), a user can
sort records on any field, otherwise, only on the fields
whose names are listed in this option.
sort_fields the list of field names on which the table can be sorted,
by clicking on the corresponding table column header.
If an item is a detail the operation is performed on the
client, otherwise sorting is performed on the server (the
:doc:`open `
method is used internally).
summary_fields a list of field names. When it is specified, the table
calculates sums for numeric fields and displays them in the
table footer, for not numeric fields it displays the number
of records.
freeze_count an integer value. If it is greater than 0, it specifies
number of first columns that become frozen - they will not
scroll when the table is scrolled horizontally.
show_hints if true, the tooltip will be displayed when the user hovers
the mouse over a table cell, and the cell text does not fit
in the cell size. The default value is true.
hint_fields a list of field names. If it is specified, the tooltip will
be displayed only for fields from this list, regardless of
the value of show_hints option value.
on_click specifies the function, that will be executed when a user
click on a table row. The item will be passed as a parameter
to the function.
on_dblclick specifies the function, that will be executed when a user
double click on a table row. The item will be passed as a
parameter to the function.
dblclick_edit if the value of the option is set to true and the
on_dblclick option is not set, the edit form will be shown
when a user double click on a table row.
multiselect if this option is set, a leftmost column with check-boxes
will be created to select records. So, that when a user
clicks on the check-box, the value of the primary key field
of the record will be added to or deleted from the
:doc:`selections ` attribute.
select_all if true, the menu will appear in the leftmost column of
the table header, which will allow the user selects all
records that match the current filters and the search value.
row_callback the callback functions called each time fields of the record
are changed. Two parameters are passed to the function -
item, whose record has changed and JQuery object of the
corresponding row of the table. Please be careful - the
item passed to the function can be not item itself, but its
clone that share the same dataset.
=================== ============================================================
Example
=======
.. code-block:: js
function on_view_form_created(item) {
item.table_options.row_line_count = 2;
item.table_options.expand_selected_row = 3;
}
The code in the following two examples does the same:
.. code-block:: js
item.invoice_table.create_table(item.view_form.find('.view-detail'), {
height: 200,
summary_fields: ['date', 'total'],
});
.. code-block:: js
item.invoice_table.table_options.height = 200;
item.invoice_table.table_options.summary_fields = ['date', 'total'];
item.invoice_table.create_table(item.view_form.find('.view-detail'));
See also
========
:doc:`View Form Dialog `
:doc:`on_view_form_created `
:doc:`create_table `
====
task
====
.. py:attribute:: task
**domain**: server
**language**: python
**class**: :doc:`App class `
Description
===========
Returns a reference to the Project task tree
See also
========
:doc:`Workflow `
:doc:`Task tree `
========
template
========
.. py:attribute:: template
**domain**: client
**language**: python
**class** :doc:`Report class `
Description
===========
The **report_filename** attribute stores a file name of the report template. Usually it
is set in the Application builder when the report is created. But it can be changed
dynamically on the server in the
:doc:`on_before_generate `
event handler or be empty, if it's necessary to create, for example, some **txt**
file.
See also
========
:doc:`Report templates `
:doc:`Creating a report `
:doc:`Server-side report programming `
=========
templates
=========
.. js:attribute:: templates
**domain**: client
**language**: javascript
**class** :doc:`Task `
Description
===========
The ``templates`` attribute stores the form templates of the project.
See also
========
:doc:`Form templates `
:doc:`Forms `
====
text
====
.. py:attribute:: text
**domain**: server
**language**: python
:doc:`Field class `
Description
===========
Use ``text`` property to get or set the text value of the field.
Getting text property value
---------------------------
Gets the value of the
:doc:`value `
property and converts it to text.
Setting text property value
---------------------------
Converts the text to the type of the field and assigns its :doc:`value `
property to this value
See also
========
:doc:`Fields `
:doc:`Lookup fields `
:doc:`lookup_value `
:doc:`text `
:doc:`lookup_text `
=========
user_info
=========
.. js:attribute:: user_info
**domain**: client
**language**: javascript
**class** :doc:`Task `
Description
===========
Use ``user_info`` attribute to get user information when project
:doc:`Safe mode parameter `
is set.
``user_info`` is an object that has the following attributes:
* ``user_id`` - the user id
* ``user_name`` - the user name
* ``role_id`` - user role id
* ``role_name`` - the role assigned to the user
* ``admin`` - if true the user can work in the Application builder
If safe mode is false the ``user_info`` attribute is an empty
object.
Example
=======
.. code-block:: js
function on_page_loaded(task) {
$("#title").html('Jam.py demo application');
if (task.safe_mode) {
$("#user-info").text(task.user_info.role_name + ' ' + task.user_info.user_name);
$('#log-out')
.show()
.click(function(e) {
e.preventDefault();
task.logout();
});
}
// some initalization code
}
See also
========
:doc:`load `
:doc:`login `
:doc:`logout `
:doc:`Users `
:doc:`Roles `
=====
value
=====
.. py:attribute:: value
**domain**: server
**language**: python
**class** :doc:`Filter class `
Description
===========
Use ``value`` property to get or set the value of the filter.
Example
=======
.. code-block:: js
function on_view_form_created(item) {
item.filters.invoicedate1.value = new Date(new Date().setYear(new Date().getFullYear() - 1));
}
See also
========
:doc:`Filters `
:doc:`Dataset `
=========
view_form
=========
.. js:attribute:: view_form
**domain**: client
**language**: javascript
**class** :doc:`Item class `
Description
===========
Use ``view_form`` attribute to get access to a Jquery object representing the
view form of the item.
It is created by the
:doc:`view `
method.
The
:doc:`close_view_form `
method sets the ``view_form`` value to undefined.
Example
=======
In the following example the button defined in the item html template is assigned
a click event:
.. code-block:: js
item.view_form.find("#new-btn").on('click',
function() {
item.insert_record();
}
);
See also
========
:doc:`Forms `
:doc:`view `
:doc:`create_view_form `
:doc:`close_view_form `
============
view_options
============
.. js:attribute:: view_options
**domain**: client
**language**: javascript
**class** :doc:`Item class `
Description
===========
The ``view_options`` attribute is a set of options that determine how the view
form of will be displayed on the browser page.
These options are set in the
:doc:`View Form Dialog `
in Application Builder.
You can change view options in the
:doc:`on_view_form_created `
event handler of the item. See example.
``view_options`` is an object that has the following attributes:
=================== ============================================================
Option Description
=================== ============================================================
width the width of the modal form, the default value is 600 px
title the title of the form, the default value is the value of a
:doc:`item_caption `
attribute,
form_border if true, the border will be displayed around the form
form_header if true, the form header will be created and displayed
containing form title and various buttons
history_button if true and
:doc:`saving change history is enabled `,
the history button will be displayed in the form header
refresh_button if true, the refresh button will be created in the form
header, that will allow users to refresh the page by sending
request to the server
enable_search if true, the search input will be created in the form header
search_field the name of the field that will be the default search field
enable_filters if true and there are visible filters, the filter button will
be created in the form header
close_button if true, the close button will be created in the upper-right
corner of the form
close_on_escape if true, pressing on the Escape key will execute the
:doc:`close_view_form `
method to close the form
view_details the list of detail names, that will be displayed
in the view form, if view form template contains the div
with class 'view-detail' (the default view form template have
this div)
detail_height the height of the details displayed in the view form,
if not specified the height of the detail table is 200px
modeless if true, the form will be displayed as modeless
template_class if specified, the div with this class will be searched in
the task
:doc:`templates `
attribute and used as a form html template when creating a
form. This attribute must be set before the form is created
=================== ============================================================
Example
=======
.. code-block:: js
function on_view_form_created(item) {
item.view_options.width = 800;
item.view_options.close_button = false;
item.view_options.close_on_escape = false;
}
See also
========
:doc:`Forms `
:doc:`view `
=============
virtual_table
=============
.. py:attribute:: virtual_table
**domain**: server
**language**: python
**class** :doc:`Item class `
Description
===========
Use the read-only ``virtual_table`` property to find out if the item has a
corresponding table in the project database.
If ``virtual_table`` is ``True`` there is no corresponding table in the project
database. You can use these items to work with in-memory dataset or use its
modules to write code.
Calling the
:doc:`open `
method creates an empty data set, and calling the
:doc:`apply `
method does nothing.
=======
visible
=======
.. js:attribute:: visible
**domain**: client
**language**: javascript
**class** :doc:`Filter class `
Description
===========
If the value of this property is **true** the input control for this filter will
be created by the
:doc:`create_filter_inputs `
method, if the **filters** option in not specified.
See also
========
:doc:`Filters `
:doc:`value `
:doc:`Dataset `
========
work_dir
========
.. py:attribute:: work_dir
**domain**: server
**language**: python
**class**: :doc:`Task class `
Description
===========
Returns the real absolute path to the project directory.
See also
========
:doc:`Workflow `
==============================
Client-side report programming
==============================
To print a report on the client use the
:doc:`print `
method.
As a result of calling this function, the client calls
:doc:`create_param_form `
method to create a form for editing the report parameters, based on the html
template defined in the index.html file
(see :doc:`Forms `).
This method, after creating the form, triggers the following events:
* :doc:`on_param_form_created `
of the task.
* :doc:`on_param_form_created `
of the report group that owns the report, if one is defined
* :doc:`on_param_form_created `
of the report, if one is defined.
The default code has the
:doc:`on_param_form_created `
event handler, defined for the task. In this event, the click on the **Print**
button is connected to the report's
:doc:`process_report `
method.
.. code-block:: js
function on_param_form_created(item) {
item.create_param_inputs(item.param_form.find(".edit-body"));
item.param_form.find("#ok-btn").on('click.task', function() {
item.process_report()
});
item.param_form.find("#cancel-btn").on('click.task', function() {
item.close_param_form()
});
}
In its turn the
:doc:`process_report `
method triggers
* :doc:`on_before_print_report `
event handler of the report group
* :doc:`on_before_print_report `
event handler of the report
In this event handlers developer can define some common (report group
event handler) or specific (report event handler) attributes of the report.
For example, in the default code, there is the on_before_print_report event
handler of the report group, in which report's
:doc:`extension `
attribute is defined:
.. code-block:: js
function on_before_print_report(report) {
var select;
report.extension = 'pdf';
if (report.param_form) {
select = report.param_form.find('select');
if (select && select.val()) {
report.extension = select.val();
}
}
}
In the following event handler, defined in the client module of the
**invoice** report of the Demo application, the value of the report
**id** parameter is set:
.. code-block:: js
function on_before_print_report(report) {
report.id.value = report.task.invoices.id.value;
}
After that the
:doc:`process_report `
method sends asynchronous request to the server to generate the report
(see :doc:`Server-side programming `).
The server returns to the method an url to a file with generated report.
The method then checks if the
:doc:`on_open_report ` event handler of
the report group is defined. If this events handler if defined calls it,
otherwise checks the
:doc:`on_open_report ` of the report. If it
is defined then calls it.
If none of this events are defined, it (depending on the report
:doc:`extension `
attribute) opens the report in the browser or saves it to disc.
===========
Code editor
===========
For every item of the project :doc:`task tree ` there
are two buttons in the upper-right corner of the
:doc:`Application builder `
: ``Client module [F7]``
and ``Server module[F8]``.
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/item_btns_jampy.png
:align: center
:alt: Invoke code editor buttons
By clicking on these buttons the Code Editor for the client or server
module of the item will be opened.
(See :doc:`Working with modules `)
To the left of the **Editor** there is an information pane with four tabs:
* **Module** - this tab displays all events and functions defined in the editor,
double-click on one of them to move the cursor to the proper function.
* **Events** - displays all the published event of the item, double-click to
add a wrapper for the event at the current cursor position (see the
on_before_post event on the figure above).
* **Task** - the
:doc:`task tree `,
double-click on the node to enter the item_name at the current cursor position.
* **Fields** - the field list of the current item, double-click on one of the
fields to enter the field_name at the current cursor position.
To save changes click the **OK** button or press Ctrl-S.
To search the project modules, click the **Find in project** button or press
Alt-F to display the
:doc:`Find in project Dialog `
Jam.py uses the `ace editor`_ editor to implement its code editor.
`Here are keyboard shortcuts for the ace editor`_.
.. _ace editor: https://ace.c9.io
.. _Here are Keyboard Shortcuts for the ace editor: https://github.com/ajaxorg/ace/wiki/Default-Keyboard-Shortcuts
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/editor_jampy.png
:align: center
:alt: code editor
=============
Common fields
=============
Items that have access to the database data can have common fields. They are
defined in the group they belong to:
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/common_fields_jampy.png
:align: center
:alt: Common fields
Here two fields are defined: **id** and **deleted**.
The **id** field is set as a primary key and will store a unique identifier
for each record in the database table. This value is automatically generated by
the framework when inserting a new record into the table.
The **deleted** field is set as a deletion flag. When the 'Soft delete'
check-box is checked in the
:doc:`Item Editor Dialog `,
the delete method does not erase a record physically from the table, but uses
this field to mark the record as deleted. The open method takes this into
account when an SQL query is generated to get records from the database table.
The **Record version** field is used for :doc:`Record locking `.
=================
Creating a report
=================
To add a new report to Jam.py project, choose the Reports node in the project
tree, the click the New button and fill in the caption, name and the template file
name of the report.
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/new_report_jampy.png
:align: center
:alt: Creating a report
If a **visible** checkbox is set, the default code adds the report to the
**Reports** menu of the project.
=================
Customizing Forms
=================
When we refresh the project page, we see that fields in the table and
in the edit form of the "Contacts" journal are displayed in the order in which
they were created.
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/contacts_new_jampy.png
:scale: 50%
:align: center
:alt: Contacts new record
To change how fields are displayed in the table, click the **View Form**
button to open the
:doc:`View Form Dialog `.
Let's change the displayed fields using **left**, **right**, **up**
and **down** buttons.
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/view_contacts1_jampy.png
:scale: 50%
:align: center
:alt: View contacts1
In the example above, we have hidden the "firstname" field by selecting it and
pressing the **right** arrow button, and we have moved the "notes" field to be
last by selecting it and pressing the **down** button.
We can also change which fields can be used for sorting the table.
To do this, click on the button right to the **Sort fields** input and select the
corresponding column header of the table. Then save all changes by pressing **OK**.
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/view_contacts_order_by_jampy.png
:scale: 50%
:align: center
:alt: view_contacts_order_by_jampy.png
To change the way the fields are displayed in the edit form, click the **Edit Form**
button to open the
:doc:`Edit Form Dialog `.
This works in a very similar way to the **View Form** above.
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/edit_contacts2_jampy.png
:scale: 50%
:align: center
:alt: Edit contacts2
To see the result of our work, go to the project page, refresh it and click
the **New** button.
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/contacts_view_jampy.png
:scale: 50%
:align: center
:alt: Contacts view
===================
Data-aware controls
===================
To create a table to display an item's dataset use
:doc:`create_table `
method:
.. code-block:: js
item.create_table(item.view_form.find(".view-table"), table_options);
To create data controls to edit fields of the of the dataset use
:doc:`create_inputs `
method:
.. code-block:: js
item.create_inputs(item.edit_form.find(".edit-body"), input_options);
These methods have two parameters - **container** and **options**. The first
parameter is a JQuery container in which the controls will be placed. The second
- options, satisfying the way the data will be displayed. For detailed
information see their API reference.
The methods are usually used in the **on_view_form_created** and
**on_edit_form_created** event handlers.
All visual controls (tables, inputs, checkboxes), created by this methods
are data-aware. This means that they immediately reflect any changes of the
item dataset.
Sometimes it is necessary to disable this interaction. To do so use the
:doc:`disable_controls `
and
:doc:`enable_controls `
methods respectively.
Videos
======
`Data aware controls`_
.. _`Data aware controls`: https://youtu.be/fMTq8P4XdGw
========
Database
========
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/database_jampy.png
:scale: 50%
:align: center
:alt: Database dialog
In this dialog project database parameters are displayed. When they have been
changed and OK button is clicked, the Application builder will check connection
to the database and if it failed to connect an error will be displayed.
.. note::
When any **Database** parameter is changed, except **DB manual update**,
the server application must be restarted for changes to take effect.
If **DB manual update** checkbox is unchecked (default), then when changes to an
item, that have an associated database table, are saved, this database table is
automatically modified. For example, if we add a new field to some item in the
:doc:`Item Editor Dialog `
, the new field will be added to the associated database table. If this checkbox
is checked, no modifications to the database tables are made.
The **DB manual update** was renamed to **DB manual mode** in more recent version.
.. note::
Please be very careful when using this option.
Examples of database setups
===========================
.. admonition:: Adapted from `Jam.py Design Tips`_
Jam.py supports many different database servers. For example PostgreSQL_, MariaDB_, MySQL_, MSSQL_, Oracle_, Firebird_, IBM_, SQLite_ and SQLite with SQLCipher_.
If you are developing a small project or something you don't plan to deploy in
a production environment, SQLite is generally the best option as it doesn't
require running a separate server. However, SQLite has many differences from
other databases, so if you are working on something substantial, it's
recommended to develop with the same database that you plan on using in
production.
In addition to a database backend, we need to make sure the Python
database bindings are installed.
* If using PostgreSQL, the ``psycopg2`` or ``psycopg2-binary`` package is needed.
* If using MySQL or MariaDB, the ``MySQLdb`` for Python 2.x is needed. For Python 3.x, the ``mysql-connector-python`` and ``mysqlclient`` package is needed, as well as database client development files.
* If using MSSQL, the ``pymssql`` is needed.
* If using Oracle, the `cx_Oracle`_ is needed, as well as Python headers (development files).
* If using SQLCipher_, ``sqlcipher3-binary`` package is needed for Linux. There is a standalone DLL for Windows available.
* If using IBM_, ``ibm_db`` and ``ibm_db_dbi`` package is needed.
* If using Firebird, ``fdb`` package is needed.
.. _Jam.py Design Tips: https://jampy-application-design-tips.readthedocs.io/
.. _PostgreSQL: https://www.postgresql.org/
.. _MariaDB: https://mariadb.org/
.. _MySQL: https://www.mysql.com/
.. _psycopg2: https://www.psycopg.org/
.. _SQLite: https://www.sqlite.org/
.. _cx_Oracle: https://oracle.github.io/python-cx_Oracle/
.. _Oracle: https://www.oracle.com/
.. _MSSQL: https://www.microsoft.com/en-au/sql-server/sql-server-downloads
.. _Firebird: https://firebirdsql.org/
.. _SQLCipher: https://github.com/sqlcipher
.. _IBM: https://www.ibm.com/support/pages/downloading-ibm-db2-version-115-linux-unix-and-windows
Using MySQL on Windows is supported, please visit `MySQL deployment on Windows`_.
Even though Jam.py supports all databases from the above, there is no guarantee
that some specific and/or propriety database functionality is supported.
Here we name a few tested databases:
.. _MySQL deployment on Windows: https://www.radishlogic.com/coding/python-3/installing-mysqldb-for-python-3-in-windows/
SQLite
------
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/SQLite_setup_jampy.png
:scale: 50%
:align: center
:alt: SQLite setup
PostgreSQL
----------
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/postgres_setup_jampy.png
:scale: 50%
:align: center
:alt: PostgreSQL setup
MySql
-----
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/MySql_setup_jampy.png
:scale: 50%
:align: center
:alt: MySql setup
FireBird
--------
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/firebird_setup_jampy.png
:scale: 50%
:align: center
:alt: FireBird setup
MSSQL
-----
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/mssql_setup_jampy.png
:scale: 50%
:align: center
:alt: MSSQL setup
Oracle
------
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/oracle_setup_jampy.png
:scale: 50%
:align: center
:alt: Oracle setup
=======
Dataset
=======
Jam.py framework uses a dataset concept that is very close to
datasets of `Embarcadero Delphi`_.
.. _Embarcadero Delphi: https://en.wikipedia.org/wiki/Delphi_(programming_language)
.. note::
There are other ways to read and modify the database data. You can use the
:doc:`connect `
method of the task to get a connection from the connection pool and use
the connection to get access to the database using Python Database API.
All items with ``item_type`` "item" or "table" as well as their details (see
:doc:`Task tree `)
can access data from associated tables from the project database and write
changes to it. They all are objects of
the Item class
* :doc:`Item class ` (on the client)
* :doc:`Item class ` (on the server)
Both of these classes have the same attributes, methods, and events associated
with the data handling.
To get a dataset (a set of records) from the project dataset table, use the open
method. This method, based on parameters, generates an SQL query to get a
dataset.
After dataset is opened, the application can navigate it, change its records or
insert new ones and write changes to the item's database table.
For example, the following functions will set *support_rep_id* field values to
the values of the *id* field on the client and server respectively:
.. code-block:: js
function set_support_id(customers) {
customers.open();
while (!customers.eof()) {
customers.edit();
customers.support_rep_id.value = customers.id.value;
customers.post();
customers.next();
}
customers.apply();
}
.. code-block:: py
def set_support_id(customers):
customers.open()
while not customers.eof():
customers.edit()
customers.support_rep_id.value = customers.id.value
customers.post()
customers.next()
customers.apply();
These functions get the **customers** item as a parameter. Then the *open*
method is used to get a list of records from the customers table and each
record is modified. In the end the changes are saved in the database table, using
the apply method (see
:doc:`Modifying datasets `
).
.. note::
There is a shorter way to navigate a dataset (see
:doc:`Navigating datasets `
). For example, in python, the following loops are equivalent:
.. code-block:: py
while not customers.eof():
print customers.firstname.value
customers.next()
for c in customers:
print c.firstname.value
Videos
======
`Datasets`_ and `Datasets Part 2`_ demonstrate almost all methods of working with
datasets on specific examples
.. _`Datasets`: https://youtu.be/gHTYj7h9ljI
.. _`Datasets Part 2`: https://youtu.be/1bUGmgBfrNw
============
Demo project
============
The framework has a full fledged demo application that demonstrates programming
techniques used in the framework.
The demo is located in the demo folder of the Jam.py package downloaded from Github. There is also a stand alone or an
portable application for Windows x64 provided `here `_.
The portable application depends on LibreOffice for Reports and nothing more. Just run it and point the browser as per below.
To start the demo application go to the demo folder and run *server.py* script.
.. code-block:: console
$ ./server.py
Open a Web browser and enter
.. code-block:: console
127.0.0.1:8080
in the address bar.
To see the
:doc:`Application builder `,
open a new page in a browser and enter
.. code-block:: console
127.0.0.1:8080/builder.html
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/demo_jampy.png
:scale: 70 %
:align: center
:alt: Demo application
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/demo_admin_jampy.png
:scale: 70 %
:align: center
:alt: Application builder of demo project
===========
Deployment
===========
Jam.py deployment with Apache and mod_wsgi
==========================================
Once you’ve got ``mod_wsgi`` installed and activated, edit your Apache server’s
httpd.conf file and add the following. If you are using a version of Apache older
than 2.4, replace **Require all granted** with **Allow from all** and also add
the line **Order deny,allow** above it.
.. code-block:: apache
WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
WSGIPythonPath /path/to/mysite.com
Require all granted
Alias /static/ /path/to/mysite.com/static/
Require all granted
The first bit in the ``WSGIScriptAlias`` line is the base URL path you want to
serve your application at (``/`` indicates the root url), and the second is the
location of a "WSGI file" -- see below -- on your system, usually inside of
your project package (``mysite`` in this example). This tells Apache to serve
any request below the given URL using the WSGI application defined in that
file.
The ``WSGIPythonPath`` line ensures that your project package is available for
import on the Python path; in other words, that ``import mysite`` works.
The ```` piece just ensures that Apache can access your
:file:`wsgi.py` file.
The next lines ensure that anything in the ``/static/`` URL space is explicitly
served as a static files.
See also
========
See the additional information on the deployment in the
:doc:`How to deploy `
============
Detail class
============
.. py:class:: Detail
**domain**: server
**language**: python
Detail class inherits attributes, methods and events of
:doc:`Item class `
Attributes
==========
.. toctree::
:maxdepth: 1
:glob:
detail/at_*
=======
Details
=======
Details are used in the framework to work with tabular data, pertaining to a record
in an item's table.
For example, the **Invoices** journal in the Demo application has the
**InvoiceTable** detail, which keeps a list of tracks in an customer's invoice.
Details and detail items share the same underlying database table.
To create a detail, you must first create a detail item (select Details group of
the project tree and click on New button) and then use the
:doc:`Details Dialog `
(select item in the project tree and click on Details button)
to add a detail to an item.
For example the following code
.. code-block:: py
def on_created(task):
task.invoice_table.open()
print task.invoice_table.record_count()
task.invoices.open(limit=1)
task.invoices.invoice_table.open()
print task.invoices.invoice_table.record_count()
will print::
2259
6
Details have two
:doc:`common fields ` -
``master_id`` and ``master_rec_id``, that are used to store information about the
``ID`` of the master (each item have its own unique ID) and the value of the primary
field of the record of its master. This way each table can be linked to several
items. As well as each item can have several details. To get access to details of
an item use its ``details`` attribute. To get access to the master of the detail
use its ``master`` attribute.
Detail class, used to create details, is an ancestor of the Item class and
inherits all its attributes, methods and events.
.. note::
The ``apply`` method of the Detail class does nothing. To write changes made
to a detail use ``apply`` method of its master.
To work with a detail its muster must be active
To make any changes to a detail its master must be in an edit or insert mode
Examples
========
In this example from the client module of the **Invoices** item of
:doc:`Demo project `, the **Invoice_table** detail is
reopened every time the cursor of its master moves to another record.
.. code-block:: js
var ScrollTimeOut;
function on_after_scroll(item) {
clearTimeout(ScrollTimeOut);
ScrollTimeOut = setTimeout(
function() {
item.invoice_table.open(function() {});
},
100
);
}
And just as an example:
.. code-block:: py
from datetime import datetime, timedelta
def on_created(task):
invoices = task.invoices.copy()
invoices.set_where(invoicedate__gt=datetime.now()-timedelta(days=1))
invoices.open()
for i in invoices:
i.invoice_table.open()
i.edit()
for t in i.invoice_table:
t.edit()
t.sales_id.value = '101010'
t.post()
i.post()
invoices.apply()
The same code on the client will be as follows:
.. code-block:: js
function on_page_loaded(task) {
var date = new Date(),
invoices = task.invoices.copy();
invoices.set_where({invoicedate__gt: date.setDate(date.getDate() - 1)});
invoices.open();
invoices.each(function(i) {
i.invoice_table.open();
i.edit();
i.invoice_table.each(function(t) {
t.edit();
t.sales_id.value = '101010';
t.post();
});
i.post();
});
invoices.apply();
}
==============
Details Dialog
==============
Use this dialog to setup details of an item. See
:doc:`Details `.
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/details_dialog_jampy.png
:align: center
:alt: Details Dialog
The **Details Dialog** has two panels. The left panel lists details that
have been added. The right panel has available detail items that could be added
as details.
To add a detail item as detail, select it in the right panel and use the **Left arrow**
button in the center or press **Space** key on a keyboard.
To remove a detail, select it in the left panel and use the **Right arrow**
button in the center or press **Space** key on a keyboard.
Click the **OK** button to save to result or **Cancel** to cancel the operation.
================
Edit Form Dialog
================
The **Edit Fields Dialog** opens when a developer selects the item in the
Application builder and clicks the **Edit Form** button.
It has two tabs **Layout** and **Form**, as well as button ``Desktop`` and ``device``.
The button ``Desktop`` is a default and ``device`` can be used for **tablet** and/or
**mobile phone** inclusion. Each option is independent to each other.
Layout tab
==========
On the **Layout** tab, you can specify the fields that the user can edit,
their order, create tabs and bands for grouping field inputs.
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/edit_form_layout_jampy.png
:align: center
:alt: Edit Fields Dialog
The **Layout** tab has two lists of fields. The left list contains the fields
that were selected for editing. In the right list there are available fields
that you can select.
To select a field, select it in the right list and use the **Left arrow**
button in the center or press **Space** key on a keyboard.
To unselect a field, select it in the left list and use the **Right arrow**
button in the center or press **Space** key on a keyboard.
To order the selected fields use the buttons that located below left list.
On the right side of the "Layout" tab are the controls that you can use to
specify the display options for the fields selected for editing on the form.
* **Columns** - the number of columns that will be created for field inputs
* **Label size** - select a value that determines the size of the labels
displayed to the right of the field input:
* xSmall
* Small
* Medium
* Large
* xLarge
* **In panel** - if set, the div containing the inputs will have an inset effect
You can create tabs and bands and customize fields that you can edit on each
tab or band.
On the right side of the tab there are three buttons for adding,
editing or deleting tabs of the edit form.
On the left side of the tab there are two buttons for adding and
deleting of bands.
Each tab can have several bands.
After creating tabs and bands, you can use field lists and controls on the right
to customize the fields that will be edited on each tab and band.
Form tab
========
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/edit_form_form_jampy.png
:align: center
:alt: Edit Form layout tab
On this tab are the controls that you can use to specify the options of the
edit form
* **Form border** - if set, the border will be displayed around the form
* **Form header** - if set, the form header will be created and displayed
containing form title and various buttons
* **History** - if set and
:doc:`saving change history is enabled `, the history
button will be displayed in the form header
* **Close button** - if set, the close button will be created in the upper-right
corner of the form
* **Close on escape** - - if set, pressing on the Escape key will close the form
* **Width** - an integer, the width of the modal form, if not set the value is
600 px
* **Edit details** - click the button to the right of the input field to select
details, that will be available for editing in the edit form
* **Detail height** - an integer, the height of the details displayed in the
edit form, if not set, the height of the detail table is 262px
* **Buttons on top** - if this check box is checked the buttons are displayed on
the top of the view form, when form has a default form template
* **Modeless form** - if this check box is checked the form will be modeless,
otherwise - modal.
Click the **OK** button to save to result or **Cancel** to cancel the operation.
After saving, you can see the changes by refreshing the project page.
======
Export
======
Press this button to export project
:doc:`metadata `
to zip file.
See also
========
:doc:`Import `
:doc:`Metadata file `
:doc:`How to migrate development to production `
=================================
Export to / import from csv files
=================================
First, in the client module of the item we create two buttons that execute the
corresponding functions when you click on them:
.. code-block:: js
function on_view_form_created(item) {
var csv_import_btn = item.add_view_button('Import csv file'),
csv_export_btn = item.add_view_button('Export csv file');
csv_import_btn.click(function() { csv_import(item) });
csv_export_btn.click(function() { csv_export(item) });
}
function csv_export(item) {
item.server('export_scv', function(file_name, error) {
if (error) {
item.alert_error(error);
}
else {
var url = [location.protocol, '//', location.host, location.pathname].join('');
url += 'static/files/' + file_name;
window.open(encodeURI(url));
}
});
}
function csv_import(item) {
task.upload('static/files', {accept: '.csv', callback: function(file_name) {
item.server('import_scv', [file_name], function(error) {
if (error) {
item.warning(error);
}
item.refresh_page(true);
});
}});
}
These functions execute the following functions defined in the server module.
In this module we use the Python csv module. We do not export system fields -
primary key field and deletion flag field.
Below is the code for Python 3:
.. code-block:: py
import os
import csv
def export_scv(item):
copy = item.copy()
copy.open()
file_name = item.item_name + '.csv'
path = os.path.join(item.task.work_dir, 'static', 'files', file_name)
with open(path, 'w', encoding='utf-8') as csvfile:
fieldnames = []
for field in copy.fields:
if not field.system_field():
fieldnames.append(field.field_name)
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for c in copy:
dic = {}
for field in copy.fields:
if not field.system_field():
dic[field.field_name] = field.text
writer.writerow(dic)
return file_name
def import_scv(item, file_name):
copy = item.copy()
path = os.path.join(item.task.work_dir, 'static', 'files', file_name)
with open(path, 'r', encoding='utf-8') as csvfile:
copy.open(open_empty=True)
reader = csv.DictReader(csvfile)
for row in reader:
print(row)
copy.append()
for field in copy.fields:
if not field.system_field():
field.text = row[field.field_name]
copy.post()
copy.apply()
For Python 2, this code looks like this:
.. code-block:: py
import os
import csv
def export_scv2(item):
copy = item.copy()
copy.open()
file_name = item.item_name + '.csv'
path = os.path.join(item.task.work_dir, 'static', 'files', file_name)
with open(path, 'wb') as csvfile:
fieldnames = []
for field in copy.fields:
if not field.system_field():
fieldnames.append(field.field_name.encode('utf8'))
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for c in copy:
dic = {}
for field in copy.fields:
if not field.system_field():
dic[field.field_name.encode('utf8')] = field.text.encode('utf8')
writer.writerow(dic)
return file_name
def import_scv2(item, file_name):
copy = item.copy()
path = os.path.join(item.task.work_dir, 'static', 'files', file_name)
with open(path, 'rb') as csvfile:
item.task.execute('delete from %s' % item.table_name)
copy.open(open_empty=True)
reader = csv.DictReader(csvfile)
for row in reader:
print(row)
copy.append()
for field in copy.fields:
if not field.system_field():
field.text = row[field.field_name.encode('utf8')].decode('utf8')
copy.post()
copy.apply()
====================================================
What is the difference between catalogs and journals
====================================================
When a new project is created, its
:doc:`task tree `
has the following groups:
**Catalogs**, **Journals**, **Details** and **Reports**.
**Catalogs** and **Journals** belong to the Item Group type and have the same
functional purpose. See :doc:`Groups `.
We created them to distinguish between two types of data items:
* data items that contain information of catalog type
such as customers, organizations, tracks, etc. - **Catalogs**
* data items that store information about events
recorded in some documents, such as invoices, purchase orders, etc. - **Journals**
===============================
What are foreign keys used for?
===============================
Foreign keys that you can create in the Application Builder prevent deletion
of a record in the lookup table if a reference to it is stored in the lookup field.
For example, when a foreign key is created on the "Customer" field for "Invoices"
item, user won't be able to delete a customer in "Customers" catalog if a
reference to it is stored in "Invoices".
The soft delete attribute of the lookup item must be set to false (see
:doc:`Item Editor Dialog `
) for the lookup field to appear in the
:doc:`Foreign Keys Dialog `
====================================================================
How to upgrade an already created project to a new version of jampy?
====================================================================
To upgrade an existing V7 project to a new package you must update the package.
You can do it using pip.
If you're using Linux, Mac OS X or some other flavour of Unix, enter the
command:
.. code-block:: console
sudo pip install --upgrade jam.py-v7
If you're using Windows, start a command shell with administrator privileges
and run the command
.. code-block:: console
pip install --upgrade jam.py-v7
To migrate v5 project to v7 project, please see
:doc:`How to migrate v5 project to v7`
=======================================================
When printing a report I get an ods file instead of pdf
=======================================================
When a report is generated the server application first creates an ods file.
If
:doc:`extension `
attribute of the report is set to 'pdf' or any other format except 'ods', the
application first creates an ods file and then uses LibreOffice
in "headless" mode to convert the ods file to that format.
If LibreOffice is currently running on the server this conversion
may not happen. You must close LibreOffice on the server for
the conversion to take place.
===========================================
Can I use other libraries in my application
===========================================
You can add javascript libraries to use them for programming on the client side.
It is better to place them in the *js* folders of the *static* directory of the
project. And refer to them using the src attribute in the
On the server side you can import python libraries to your modules.
For example the mail item server module import smtplib library to send emails:
.. code-block:: py
import smtplib
===========
Field class
===========
.. py:class:: Field
**domain**: server
**language**: python
Attributes and properties
=========================
.. toctree::
:maxdepth: 1
:glob:
field/at_*
===================
Field Editor Dialog
===================
Use the **Field Editor Dialog** to create a new or modify an existing field.
.. note::
For some operations, the :doc:`DB manual mode ` must be set to true.
For example, changing the field type. Since the database is in "Manual Mode", changing the type
will not reflect within the database structure. Use this with caution.
The dialog has following tabs: **Field**, **Lookup**, **Interface** and **Calculation**.
Field tab
=========
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/fields_editr_field_jampy.png
:align: center
:alt: fields_editr_field_jampy.png
The **Field** tab have the following fields:
* **Caption** - the field name that appears to users.
* **Name** - the name of the field that will be used in programming code to
get access to the field object. It should be a valid python identifier.
* **Type** - type of the field — one of the following values:
* **TEXT**
* **INTEGER**
* **FLOAT**
* **CURRENCY**
* **DATE**
* **DATETIME**
* **BOOLEAN**
* **LONGTEXT**
* **FILE**
* **IMAGE**
* **Size** - the size of the field for text fields.
* **Default value** - the default value of the field, for boolean fields use
0 or 1
* **Required** - if this checkbox is checked, the post method will raise an
exception if this field is empty. See
:doc:`Modifying datasets `.
* **Read only** - this checkbox is checked, the field value can not be changed
in the interface controls created by the
:doc:`create_inputs `
method on the client.
Lookup tab
==========
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/fields_editr_lookup_jampy.png
:align: center
:alt: fields_editr_lookup_jampy.png
* **Lookup item** - the lookup item for
:doc:`Lookup fields `
* **Lookup field** - the lookup field for
:doc:`Lookup fields `
* **Lookup field 2** - the lookup field 2 for
:doc:`Lookup fields `
* **Lookup field 3** - the lookup field 3 for
:doc:`Lookup fields `
* **Master field** - the master field for
:doc:`Lookup fields `
* **Typeahead** - if this checkbox is checked, typeahead is enabled for the
lookup field
* **Lookup value list** - use it to specify a
:doc:`lookup list `
for an integer field
Interface tab
=============
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/fields_editr_interface_jampy.png
:align: center
:alt: fields_editr_interface_jampy.png
* **Mask** - use this attribute to specify the
:doc:`field_mask `
* **TextArea** - for text fields if this attribute is set the textarea element
will be created for these fields in the :doc:`Edit Form Dialog `
* **Do not sanitize** - set this attribute to prevent default sanitizing of the
field value, see :doc:`Sanitizing `
* **Alignment** - determines the alignment of text in the controls that display
this field.
* **Placeholder** - use this attribute to specify the placeholder that will be
displayed by the field input.
* **Help** - if any text / html-message is specified, a question mark will be
displayed to the right of the input, so when the user moves the mouse pointer
over this mark, a pop-up window appears displaying this message.
Interface tab for FILE field
============================
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/fields_editr_file_interface_jampy.png
:align: center
:alt: fields_editr_file_interface_jampy.png
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/file_btns_jampy.png
:align: center
:alt: file_btns_jampy.png
* **Download btn** - uncheck the box to hide the download button (middle)
* **Open btn** - uncheck the box to hide the open button (right)
* **Accept** - the attribute specifies the types of files that can be loaded.
This is an :doc:`Accept string `.
.. note::
Please note that **Accept** attribute is required.
Uploaded files are checked on the server against this attribute.
Interface tab for Image field
=============================
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/fields_editr_image_interface_jampy.png
:align: center
:alt: fields_editr_image_interface_jampy.png
* **View width** - specifies the width of an image in pixels when it is displayed
in the table of the view form. If it not specified, the width is auto
* **View height** - specifies the height of an image in pixels when it is displayed
in the table of the view form. If it not specified, the height is auto
* **Edit width** - specifies the width of an image in pixels when it is displayed
in the edit form. If it not specified, the width is auto
* **Edit height** - specifies the height of an image in pixels when it is displayed
in the edit form. If it not specified, the height is auto
* **Capture from camera** - if this checkbox is set, the user will be able to
capture image from camera by double-click. The image is automatically uploded
to the server,
providing the ".png" is added on Parameters :doc:`Accept string `.
* **Placeholder image** - double-click the image to set the placeholder image,
that will be displayed when field image is not set.
Hold Ctrl key and double-click the image to clear the placeholder image.
Calculation tab
===============
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/fields_editr_calc_jampy.png
:align: center
:alt: fields_editr_calc_jampy.png
* **Calc. object** - specifies the :doc:`Details ` table.
* **Lookup field** - specifies the
:doc:`Lookup field `. For example, the Details table *invoice_table*, *tracks* field,
which is a lookup field to *Name* field on table *Tracks*.
* **Calc. field** - specifies on which field the calculation is performing on.
* **Function** - specifies the server side functions (SUM, COUNT, MIN, MAX, AVG).
======
Fields
======
All items, working with database table data have a
:doc:`fields `
attribute - a list of field objects, which are used to represent fields in item's
table records.
Every field have the following attributes:
.. csv-table::
:header: Client, Server, Description
:widths: 10, 10, 80
:doc:`owner `, :doc:`owner `, "The item that owns this field."
:doc:`field_name `, :doc:`field_name `, "The name of the field that will be used in programming code to get access to the field object."
:doc:`field_caption `, :doc:`field_caption `, "The name of the field that appears to users."
:doc:`field_type `, :doc:`field_type `, "Type of the field, one of the following values: **text**, **integer**, **float**, **currency**, **date**, **datetime**, **boolean**, **blob**."
:doc:`field_size `, :doc:`field_size `, "A size of the field with type **text**"
:doc:`required `, :doc:`required `, "Specifies whether a nonblank value for a field is required."
To get access to the item dataset data, the Field class have the following properties:
.. csv-table::
:header: Client, Server, Description
:widths: 10, 10, 80
:doc:`value `, :doc:`value `, "Use this property to get or set the field's value of the current record. When reading the value is converted to the type of the field. So for fields of type integer, float and currency, if value for this field in database table record is NULL, value of this property is 0. To get unconverted value use the raw_value property."
:doc:`text `, :doc:`text `, "Use this property to get or set the value of the field as text."
:doc:`lookup_value `, :doc:`lookup_value `, "Use this property to get or set lookup value, see :doc:`Lookup fields `."
:doc:`lookup_text `, :doc:`lookup_text `, "Use this property to get or set the lookup value of the field as text, see :doc:`Lookup fields `."
:doc:`display_text `, :doc:`display_text `, "Represents the field's value as it is displayed in data-aware controls. When the field is a lookup field it's value is the lookup_text value, otherwise it is the text value, with regard of project locale parameters. This behavior can be overridden by the :doc:`on_field_get_text ` event handler of the item that owns the field."
:doc:`raw_value `, :doc:`raw_value `, "Use this property to get field value of the current record as it is stored in database. No conversion is used."
In addition every field is an attribute of the item that owns it. So, to get
access to a field of an item use the following syntax: ``item.field_name``
.. code-block:: js
invoices.total.value
``invoices.total`` is the reference to the
**Total** field of the **Invoices** item and the
``invoices.total.value`` is the value of this field
Below are the values of the attributes of the fields of the **invoices** item in the
:doc:`Demo project `
::
customer integer
value: 2
text: 2
lookup_value: Köhler
lookup_text: Köhler
display_text: Leonie Köhler
firstname integer
value: 2
text: 2
lookup_value: Leonie
lookup_text: Leonie
display_text: Leonie
billing_address integer
value: 2
text: 2
lookup_value: Theodor-Heuss-Straße 34
lookup_text: Theodor-Heuss-Straße 34
display_text: Theodor-Heuss-Straße 34
id integer
value: 1
text: 1
lookup_value: None
lookup_text:
display_text: 1
date date
value: 2014-01-01
text: 01/01/2014
lookup_value: None
lookup_text:
display_text: 01/01/2014
total currency
value: 2.08
text: $2.08
lookup_value: None
lookup_text:
display_text: $2.08
============
Filter class
============
.. py:class:: Filter
**domain**: server
**language**: python
Attributes and properties
=========================
.. toctree::
:maxdepth: 1
:glob:
filter/at_*
=================
Filtering records
=================
There are three ways to define what records an item
:doc:`dataset `
will get from the database table
when the ``open`` method is called:
* to specify ``where`` parameter (option) of the ``open`` method,
* call the ``set_where`` method, before calling the ``open`` method,
* or use
:doc:`filters `.
When ``where`` parameter is specified, it is always used even if the ``set_where``
method was called or item has filters whose values have been set.
When ``where`` parameter is omitted the parameter passed to the ``set_where``
method are used.
For example on the client in the following code in the first call of the ``open``
method the ``where`` option will be used to filter records,
in the second call the parameters passed to ``set_where`` and only the third
time the value of ``invoicedate1`` filter will be used
.. code-block:: js
function test(invoices) {
var date = new Date(new Date().setYear(new Date().getFullYear() - 1));
invoices.clear_filters();
invoices.filters.invoicedate1.value = date;
invoices.open({where: {invoicedate__ge: date}});
invoices.set_where({invoicedate__ge: date});
invoices.open();
invoices.open();
}
date = datetime.datetime.now() - datetime.timedelta(days=3*365)
The same code on the server looks the following way:
.. code-block:: py
from datetime import datetime
def test(invoices):
date = datetime.now()
date = date.replace(year=date.year-1)
invoices.clear_filters()
invoices.filters.invoicedate1.value = date
invoices.open(where={'invoicedate__ge': date})
invoices.set_where(invoicedate__ge=date)
invoices.open()
invoices.open()
In the framework, the following symbols and corresponding constants are defined
to filter records:
.. csv-table::
:header: Filter type, Filter symbol, Constant, SQL Operator
:widths: 20, 15, 10, 70
``EQ``, 'eq', ``FILTER_EQ``, ``=``
``NE``, 'ne', ``FILTER_NE``, ``<>``
``LT``, 'lt', ``FILTER_LT``, ``<``
``LE``, 'le', ``FILTER_LE``, ``<=``
``GT``, 'gt', ``FILTER_GT``, ``>``
``GE``, 'ge', ``FILTER_GE``, ``>=``
``IN``, 'in', ``FILTER_IN``, ``IN``
``NOT IN``, 'not_in', ``FILTER_NOT_IN``, ``NOT IN``
``RANGE``, 'range', ``FILTER_RANGE``, ``BETWEEN``
``ISNULL``, 'isnull', ``FILTER_ISNULL``, ``IS NULL``
``EXACT``, 'exact', ``FILTER_EXACT``, ``=``
``CONTAINS``, 'contains', ``FILTER_CONTAINS``, uses ``LIKE`` with the "%" sign to find records where field value contains a search string
``STARTWITH``, 'startwith', ``FILTER_STARTWITH``, uses ``LIKE`` with the "%" sign to find records where field value starts with a search string
``ENDWITH``, 'endwith', ``FILTER_ENDWITH``, uses ``LIKE`` with the "%" sign to find records where field value ends with a search string
``CONTAINS ALL``, 'contains_all', ``FILTER_CONTAINS_ALL``, uses ``LIKE`` with the "%" sign to find records where field value contains all words of a search string
The ``where`` the parameter of the ``open`` method is a dictionary, whose keys
are the names of the fields that are followed, after double underscore, by a
filter symbol. For ``EQ`` filter the filtering symbol '__eq' can be omitted.
For example ``{'id': 100}`` is equivalent to ``{'id__eq': 100}``.
See also
========
:doc:`Dataset `
:doc:`Filters `
Client
------
:doc:`open `
:doc:`set_where `
Server
------
:doc:`open `
:doc:`set_where `
=======
Filters
=======
:doc:`Filters `
are used to select records from the database table according to the specified criteria.
Click the **Filters** button to open the
:doc:`Filters Dialog `.
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/filters_dlg_jampy.png
:scale: 50%
:align: center
:alt: Filters dialog
Now click the **New** button and fill out the following form:
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/new_filter_jampy.png
:scale: 50%
:align: center
:alt: New filter
Similarly, create a few other filters:
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/all_filters_jampy.png
:scale: 50%
:align: center
:alt: All filters
When we refresh the project page, the **Filters** button appears in the
header of the "Contacts" form. Clicking this button opens the "Filters" dialog box:
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/contacts_filters_jampy.png
:scale: 50%
:align: center
:alt: Contacts filters
==============
Filters Dialog
==============
Use **Filters Dialog** to create and modify item filters. See
:doc:`Filters `
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/filters_dialog_jampy.png
:align: center
:alt: Filters Dialog
To add or edit a filter click on the appropriate button on the form. The
following form will appear:
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/filter_editor_jampy.png
:align: center
:alt: Filter Editor
Fill in the following fields:
* **Field** - the field which will be used to filter records.
* **Caption** - the filter name that appears to users.
* **Name** - the name of the filter that will be used in programming code to
get access to the filter object. It should be a valid python identifier.
* **Filter type** - select filter type.
* **Placeholder** - use this attribute to specify the placeholder that will be
displayed by the field input.
* **Help** - if any text / html-message is specified, a question mark will be
displayed to the right of the input, so when the user moves the mouse pointer
over this mark, a pop-up window appears displaying this message.
Help - if any text / html-message is specified, a question mark will be displayed to the right of the input,
so when the user moves the mouse pointer over this label, a pop-up window appears displaying this message.
* **Visible** - if this checkbox is not checked, this filter will not be displayed
in the item Filters dialog.
Use the up and down arrows to place the filters in the order in which they will
be displayed. See
:doc:`create_filter_inputs `
====
Find
====
Press this button to to search for the character string in all modules of
the project.
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/find_jampy.png
:align: center
:alt: Find in project dialog
===================
Foreign Keys Dialog
===================
If an item has a lookup field, and in the definition of lookup item the soft
delete attribute is not set, in order to maintain the integrity of the data,
we can create a foreign key. See
:doc:`Foreign keys topic ` in FAQ
.. image:: https://jampy-docs-v7.readthedocs.io/en/latest/_images/foreign_keys_dialog_jampy.png
:align: center
:alt: Foreign Keys Dialog
To do so click the **New** button, select the field and click **OK**.
/===========
Form events
===========
After the form is created and the HTML form template is added to the DOM,
the application triggers the following form events during the life cycle of
the form:
* ``on_view_form_created`` - the event is triggered when the form has been created but not shown yet
* ``on_view_form_shown`` -the event is triggered when the the form has been shown
* ``on_view_form_close_query`` - the event is triggered when an attempt is made to close the form
* ``on_view_form_closed`` - the event is triggered when the form has been closed
* ``on_view_form_keydown`` - the event is triggered when the keydown event occurs for the form
* ``on_view_form_keyup`` - the event is triggered when the keyup event occurs for the form
For other form types - edit, filter and param, replace 'view' with the form type,
for example ``on_edit_form_created`` for edit form.
We will first explain how to use the ``on_view_form_created`` event.
When the user clicks on menu item the application executes the
:doc:`view `
method of corresponding task tree item, this method creates a form using its HTML
form template and triggers first the
:doc:`on_view_form_created ` event of
the task.
When you create a new project, the task client module already contains the
code, including the
:doc:`on_view_form_created `
event handler. This event handler is executed each time the view form is created
and defines the default behavior of view forms.
You can open the task client module to see this event handler.
If you need to change the default behavior for all view forms of the project,
you should do it here.
Below we describe the major steps it performs:
* Initializes the
:doc:`view_form `
and
:doc:`table_options `
that are used by some methods when view form and table are created.
* Assigns JQuery event handlers for default buttons to methods of the item,
depending on the user rights. In the example below the delete button is.
Initialized:
.. code-block:: js
if (item.can_delete()) {
item.view_form.find("#delete-btn").on('click.task', function(e) {
e.preventDefault();
item.delete_record();
});
}
else {
item.view_form.find("#delete-btn").prop("disabled", true);
}
* Executes the
:doc:`on_view_form_created `
event handler of the item group and.
:doc:`on_view_form_created `
of the item if they are defined:
.. code-block:: js
if (!item.master && item.owner.on_view_form_created) {
item.owner.on_view_form_created(item);
}
if (item.on_view_form_created) {
item.on_view_form_created(item);
}
* Creates a table to display the item data and tables for details if they have
been specified by calling ``create_view_tables`` method
* Executes
:doc:`open `
method, that gets the item dataset from the server.
* Finally returns true to prevent calling of the ``on_view_form_created`` of the
owner group and the item because the were already called see the
``_process_event`` method below.
After we initialized buttons and before creating tables we call the
``on_view_form_created`` event handler of the item itself.
For example, in the client module of the tracks item of the demo app
the following
:doc:`on_view_form_created `
event handler is defined. In it we
change the height attribute of the
:doc:`table_options `
, create the copy of the
invoice_table set its attributes and call its
:doc:`create_table `
method that creates a table to display its data.
.. code-block:: js
function on_view_form_created(item) {
item.table_options.height -= 200;
item.invoice_table = task.invoice_table.copy();
item.invoice_table.paginate = false;
item.invoice_table.create_table(item.view_form.find('.view-detail'), {
height: 200,
summary_fields: ['date', 'total'],
});
item.alert('Double-click the record in the bottom table to see track sales.');
}
The module also has the
:doc:`on_after_scroll `
event handler that will be executed when
the user moves to the other track and will get the sales of this track.
This example explains the principle of form events usage.
The order of triggering of events depends on the type of event.
The order in which events are generated depends on the type of event.
Close query events
==================
When user tries to close the form the on_close_query event is first triggered
(if defined) for the item.
If the event handler returns true the application closes the form,
else if the event handler returns false the application leaves the form open,
otherwise the on_close_query event is triggered (if defined) the same way
for the item group and then for the task.
For example, by default there is the
:doc:`on_edit_form_close_query `
event handler in the task client module:
.. code-block:: js
function on_edit_form_close_query(item) {
var result = true;
if (!item.virtual_table && item.is_changing()) {
if (item.is_modified()) {
item.yes_no_cancel(task.language.save_changes,
function() {
item.apply_record();
},
function() {
item.cancel_edit();
}
);
result = false;
}
else {
item.cancel_edit();
}
}
return result;
}
This code checks whether the record has been modified and then opens
"Yes No Cancel" dialog.
If we want to close the form without this dialog we can defined the following
event handler in the client module of the item:
.. code-block:: js
function on_edit_form_close_query(item) {
item.cancel()
return true;
}
Keydown, keyup events
=====================
These events are triggered the same way as Close query events, starting from the item,
but if the event handler returns true, the event handlers of the group and task
are not executed.
For example, by default there is the
:doc:`on_edit_form_keyup `
event handler in the task client module:
.. code-block:: js
function on_edit_form_keyup(item, event) {
if (event.keyCode === 13 && event.ctrlKey === true){
item.edit_form.find("#ok-btn").focus();
item.apply_record();
}
}
This code saves the changes of the record to the database table when user
presses Ctrl+Enter.
Suppose we want to save the changes when user presses Enter. Then we write the
following event handler in the item client module:
.. code-block:: js
function on_edit_form_keyup(item, event) {
if (event.keyCode === 13){
item.edit_form.find("#ok-btn").focus();
item.apply_record();
return true;
}
}
In this case the event handler of the task won't be called when the user press
Enter.
All other events
================
For other events, the event handler of the task is called first, if it doesn't
return true, the event handler of the group is executed if it doesn't
return true the event handler of the item is called.
This mechanism is implemented the ``_process_event`` method of the Item class in
the *jam.js* module.
.. code-block:: js
_process_event: function(form_type, event_type, e) {
var event = 'on_' + form_type + '_form_' + event_type,
can_close;
if (event_type === 'close_query') {
if (this[event]) {
can_close = this[event].call(this, this);
}
if (!this.master && can_close === undefined && this.owner[event]) {
can_close = this.owner[event].call(this, this);
}
if (can_close === undefined && this.task[event]) {
can_close = this.task[event].call(this, this);
}
return can_close;
}
else if (event_type === 'keyup' || event_type === 'keydown') {
if (this[event]) {
if (this[event].call(this, this, e)) return;
}
if (!this.master && this.owner[event]) {
if (this.owner[event].call(this, this, e)) return;
}
if (this.task[event]) {
if (this.task[event].call(this, this, e)) return;
}
}
else {
if (this.task[event]) {
if (this.task[event].call(this, this)) return;
}
if (!this.master && this.owner[event]) {
if (this.owner[event].call(this, this)) return;
}
if (this[event]) {
if (this[event].call(this, this)) return;
}
}
}
=============
Form examples
=============
Currently, the Framework uses `Bootstrap 5`_ with a simple and easy to use grid
system that uses 12 columns and allows you to create any kind of layouts.
It is responsive and have many components, such as dropdowns,
dropdown buttons, button groups, navs, navbars, tabs, breadcrumbs, badges,
progress bars, etc.
.. _`Bootstrap 5`: https://getbootstrap.com/docs/5.0/
Default edit form template
--------------------------
This template is used for creating edit forms, if an item and its owner don't
have their own edit form template
.. code-block:: html