You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by dh...@apache.org on 2026/10/06 10:00:50 UTC
(ranger) 01/01: RANGER-5268 : Remove Backbone JS code base from Ranger security-admin module
This is an automated email from the ASF dual-hosted git repository.
dhavaljrajpara pushed a commit to branch RANGER-5268-2.10
in repository https://gitbox.apache.org/repos/asf/ranger.git
commit 3e479be0890c8786735e8a367ef350d3e8bfbe51
Author: Mugdha Varadkar <mu...@apache.org>
AuthorDate: Tue Oct 6 15:29:58 2026 +0530
RANGER-5268 : Remove Backbone JS code base from Ranger security-admin module
---
.travis.yml | 3 +-
README.md | 17 +-
security-admin/pom.xml | 150 -
security-admin/src/main/webapp/backbone-index.html | 139 -
.../libs/bower/backbone-forms/css/bootstrap.css | 43 -
.../webapp/libs/bower/backbone-forms/css/old.css | 140 -
.../libs/bower/backbone-forms/js/backbone-forms.js | 2527 ---
.../bower/backbone-forms/js/backbone-forms.min.js | 1 -
.../libs/bower/backbone-forms/js/bootstrap.js | 83 -
.../webapp/libs/bower/backbone-forms/js/list.js | 658 -
.../libs/bower/backbone-forms/js/list.min.js | 1 -
.../webapp/libs/bower/backbone-forms/js/old.js | 99 -
.../backbone-pageable/js/backbone-pageable.js | 1327 --
.../backbone-pageable/js/backbone-pageable.min.js | 8 -
.../backbone.babysitter/js/backbone.babysitter.js | 178 -
.../js/backbone.babysitter.min.js | 10 -
.../js/backbone.bootstrap-modal.js | 291 -
.../backbone.localstorage/backbone.localStorage.js | 222 -
.../backbone.marionette/js/backbone.marionette.js | 1959 --
.../js/backbone.marionette.min.js | 20 -
.../libs/bower/backbone.wreqr/js/backbone.wreqr.js | 277 -
.../bower/backbone.wreqr/js/backbone.wreqr.min.js | 11 -
.../webapp/libs/bower/backbone/js/backbone-min.js | 2 -
.../main/webapp/libs/bower/backbone/js/backbone.js | 2096 --
.../bower/backgrid-filter/css/backgrid-filter.css | 149 -
.../bower/backgrid-filter/js/backgrid-filter.js | 463 -
.../backgrid-paginator/css/backgrid-paginator.css | 58 -
.../backgrid-paginator/js/backgrid-paginator.js | 366 -
.../webapp/libs/bower/bootprompt/bootprompt.js | 1138 --
.../bootstrap-notify/css/bootstrap-notify.css | 31 -
.../bower/bootstrap-notify/js/bootstrap-notify.js | 366 -
.../webapp/libs/bower/bootstrap/js/bootstrap.js | 7033 -------
.../libs/bower/bootstrap/js/bootstrap.min.js | 7 -
.../src/main/webapp/libs/bower/esprima/esprima.js | 5599 ------
.../main/webapp/libs/bower/globalize/.bower.json | 15 -
.../main/webapp/libs/bower/globalize/.gitignore | 9 -
.../main/webapp/libs/bower/globalize/.npmignore | 1 -
.../webapp/libs/bower/globalize/lib/globalize.js | 1586 --
.../libs/bower/jquery-toggles/css/toggles.css | 22 -
.../libs/bower/jquery-toggles/js/toggles.min.js | 11 -
.../moment/js/moment-timezone-with-data.min.js | 1 -
.../bower/moment/js/moment-with-locales.min.js | 2 -
.../require-handlebars-plugin/js/Handlebars.js | 6026 ------
.../libs/bower/require-handlebars-plugin/js/hbs.js | 653 -
.../main/webapp/libs/bower/requirejs/js/require.js | 2146 ---
.../libs/bower/select2/select2-bootstrap4.css | 175 -
.../webapp/libs/bower/select2/select2-spinner.gif | Bin 1849 -> 0 bytes
.../src/main/webapp/libs/bower/select2/select2.css | 615 -
.../src/main/webapp/libs/bower/select2/select2.js | 3219 ----
.../src/main/webapp/libs/bower/select2/select2.png | Bin 613 -> 0 bytes
.../main/webapp/libs/bower/select2/select2x2.png | Bin 845 -> 0 bytes
.../webapp/libs/bower/tag-it/css/jquery.tagit.css | 69 -
.../src/main/webapp/libs/bower/tag-it/js/tag-it.js | 589 -
.../main/webapp/libs/bower/tag-it/js/tag-it.min.js | 17 -
.../webapp/libs/bower/underscore/js/underscore.js | 2079 --
.../bower/x-editable/css/bootstrap-editable.css | 674 -
.../webapp/libs/bower/x-editable/img/clear.png | Bin 509 -> 0 bytes
.../webapp/libs/bower/x-editable/img/loading.gif | Bin 1849 -> 0 bytes
.../libs/bower/x-editable/js/bootstrap-editable.js | 6636 -------
.../main/webapp/libs/fsOverrides/BBFOverrides.js | 370 -
.../main/webapp/libs/other/backbone.fetch-cache.js | 326 -
.../Backgrid.ColumnManager.css | 114 -
.../Backgrid.ColumnManager.min.js | 971 -
.../main/webapp/libs/other/backgrid/backgrid.css | 258 -
.../main/webapp/libs/other/backgrid/backgrid.js | 2946 ---
.../libs/other/datepicker/css/datepicker.css | 224 -
.../other/datepicker/js/bootstrap-datepicker.js | 834 -
.../libs/other/datepicker/less/datepicker.less | 122 -
.../other/daterangepicker/css/daterangepicker.css | 410 -
.../other/daterangepicker/js/daterangepicker.js | 1578 --
.../jquery-ui/css/images/animated-overlay.gif | Bin 1738 -> 0 bytes
.../ui-bg_diagonals-thick_18_b81900_40x40.png | Bin 528 -> 0 bytes
.../ui-bg_diagonals-thick_20_666666_40x40.png | Bin 436 -> 0 bytes
.../css/images/ui-bg_flat_10_000000_40x100.png | Bin 205 -> 0 bytes
.../css/images/ui-bg_glass_100_f6f6f6_1x400.png | Bin 376 -> 0 bytes
.../css/images/ui-bg_glass_100_fdf5ce_1x400.png | Bin 458 -> 0 bytes
.../css/images/ui-bg_glass_65_ffffff_1x400.png | Bin 317 -> 0 bytes
.../images/ui-bg_gloss-wave_35_f6a828_500x100.png | Bin 5925 -> 0 bytes
.../ui-bg_highlight-soft_100_eeeeee_1x100.png | Bin 394 -> 0 bytes
.../ui-bg_highlight-soft_75_ffe45c_1x100.png | Bin 438 -> 0 bytes
.../css/images/ui-icons_222222_256x240.png | Bin 7077 -> 0 bytes
.../css/images/ui-icons_228ef1_256x240.png | Bin 4670 -> 0 bytes
.../css/images/ui-icons_444444_256x240.png | Bin 6992 -> 0 bytes
.../css/images/ui-icons_555555_256x240.png | Bin 6988 -> 0 bytes
.../css/images/ui-icons_777620_256x240.png | Bin 4549 -> 0 bytes
.../css/images/ui-icons_777777_256x240.png | Bin 6999 -> 0 bytes
.../css/images/ui-icons_cc0000_256x240.png | Bin 4549 -> 0 bytes
.../css/images/ui-icons_ef8c08_256x240.png | Bin 4670 -> 0 bytes
.../css/images/ui-icons_ffd27a_256x240.png | Bin 4670 -> 0 bytes
.../css/images/ui-icons_ffffff_256x240.png | Bin 6539 -> 0 bytes
.../webapp/libs/other/jquery-ui/css/jquery-ui.css | 1314 --
.../libs/other/jquery-ui/css/jquery-ui.min.css | 7 -
.../other/jquery-ui/js/jquery-ui-1.13.1.custom.js | 19062 -------------------
.../libs/other/jquery-ui/js/jquery-ui.min.js | 6 -
.../webapp/libs/other/visualsearch/.bower.json | 45 -
.../webapp/libs/other/visualsearch/css/icons.css | 19 -
.../libs/other/visualsearch/css/workspace.css | 290 -
.../images/embed/icons/cancel_search.png | Bin 541 -> 0 bytes
.../images/embed/icons/search_glyph.png | Bin 420 -> 0 bytes
.../libs/other/visualsearch/js/visualsearch.js | 1969 --
security-admin/src/main/webapp/minify.build.js | 27 -
security-admin/src/main/webapp/package-lock.json | 36 -
security-admin/src/main/webapp/package.json | 10 -
.../react-webapp/src/views/SideBar/SideBarBody.jsx | 13 -
security-admin/src/main/webapp/scripts/App.js | 65 -
security-admin/src/main/webapp/scripts/Init.js | 155 -
security-admin/src/main/webapp/scripts/Main.js | 76 -
.../src/main/webapp/scripts/RegionManager.js | 65 -
.../collection_bases/RangerPolicyListBase.js | 60 -
.../RangerPolicyResourceListBase.js | 66 -
.../collection_bases/RangerServiceDefListBase.js | 65 -
.../collection_bases/RangerServiceListBase.js | 60 -
.../scripts/collection_bases/RangerZoneListBase.js | 58 -
.../collection_bases/UserPermissionListBase.js | 64 -
.../collection_bases/VXAccessAuditListBase.js | 60 -
.../scripts/collection_bases/VXAssetListBase.js | 60 -
.../scripts/collection_bases/VXAuditMapListBase.js | 59 -
.../collection_bases/VXAuthSessionListBase.js | 64 -
.../scripts/collection_bases/VXGroupListBase.js | 101 -
.../scripts/collection_bases/VXKmsKeyListBase.js | 68 -
.../collection_bases/VXModuleDefListBase.js | 64 -
.../scripts/collection_bases/VXPermMapListBase.js | 59 -
.../VXPolicyExportAuditListBase.js | 61 -
.../collection_bases/VXPortalUserListBase.js | 59 -
.../scripts/collection_bases/VXResourceListBase.js | 60 -
.../scripts/collection_bases/VXRoleListBase.js | 99 -
.../scripts/collection_bases/VXTrxLogListBase.js | 74 -
.../scripts/collection_bases/VXUserListBase.js | 110 -
.../webapp/scripts/collections/RangerPolicyList.js | 34 -
.../collections/RangerPolicyResourceList.js | 34 -
.../scripts/collections/RangerServiceDefList.js | 36 -
.../scripts/collections/RangerServiceList.js | 36 -
.../webapp/scripts/collections/RangerZoneList.js | 34 -
.../scripts/collections/UserPermissionList.js | 34 -
.../scripts/collections/VXAccessAuditList.js | 36 -
.../main/webapp/scripts/collections/VXAssetList.js | 36 -
.../webapp/scripts/collections/VXAuditMapList.js | 36 -
.../scripts/collections/VXAuthSessionList.js | 36 -
.../main/webapp/scripts/collections/VXGroupList.js | 36 -
.../webapp/scripts/collections/VXKmsKeyList.js | 36 -
.../webapp/scripts/collections/VXModuleDefList.js | 34 -
.../webapp/scripts/collections/VXPermMapList.js | 36 -
.../scripts/collections/VXPolicyExportAuditList.js | 36 -
.../webapp/scripts/collections/VXPortalUserList.js | 36 -
.../webapp/scripts/collections/VXResourceList.js | 36 -
.../main/webapp/scripts/collections/VXRoleList.js | 34 -
.../webapp/scripts/collections/VXTrxLogList.js | 36 -
.../main/webapp/scripts/collections/VXUserList.js | 36 -
.../webapp/scripts/collections/XABaseCollection.js | 147 -
.../src/main/webapp/scripts/communicator.js | 43 -
.../main/webapp/scripts/controllers/Controller.js | 650 -
.../main/webapp/scripts/controllers/NController.js | 651 -
.../src/main/webapp/scripts/mgrs/SessionMgr.js | 151 -
.../webapp/scripts/model_bases/RangerPolicyBase.js | 90 -
.../model_bases/RangerPolicyResourceBase.js | 90 -
.../scripts/model_bases/RangerServiceBase.js | 101 -
.../scripts/model_bases/RangerServiceDefBase.js | 105 -
.../webapp/scripts/model_bases/RangerZoneBase.js | 56 -
.../scripts/model_bases/UserPermissionBase.js | 59 -
.../scripts/model_bases/VXAccessAuditBase.js | 111 -
.../main/webapp/scripts/model_bases/VXAssetBase.js | 131 -
.../webapp/scripts/model_bases/VXAuditMapBase.js | 100 -
.../scripts/model_bases/VXAuthSessionBase.js | 54 -
.../main/webapp/scripts/model_bases/VXGroupBase.js | 108 -
.../webapp/scripts/model_bases/VXKmsKeyBase.js | 103 -
.../webapp/scripts/model_bases/VXModuleDefBase.js | 59 -
.../scripts/model_bases/VXPasswordChangeBase.js | 33 -
.../webapp/scripts/model_bases/VXPermMapBase.js | 105 -
.../scripts/model_bases/VXPolicyExportAuditBase.js | 99 -
.../webapp/scripts/model_bases/VXPortalUserBase.js | 135 -
.../webapp/scripts/model_bases/VXResourceBase.js | 125 -
.../main/webapp/scripts/model_bases/VXRoleBase.js | 62 -
.../webapp/scripts/model_bases/VXTrxLogBase.js | 99 -
.../main/webapp/scripts/model_bases/VXUserBase.js | 61 -
.../webapp/scripts/models/BackboneFormDataType.js | 297 -
.../src/main/webapp/scripts/models/RangerPolicy.js | 213 -
.../webapp/scripts/models/RangerPolicyResource.js | 66 -
.../main/webapp/scripts/models/RangerService.js | 72 -
.../main/webapp/scripts/models/RangerServiceDef.js | 162 -
.../src/main/webapp/scripts/models/RangerZone.js | 243 -
.../main/webapp/scripts/models/UserPermission.js | 70 -
.../src/main/webapp/scripts/models/VAppState.js | 43 -
.../main/webapp/scripts/models/VXAccessAudit.js | 52 -
.../src/main/webapp/scripts/models/VXAsset.js | 134 -
.../src/main/webapp/scripts/models/VXAuditMap.js | 53 -
.../main/webapp/scripts/models/VXAuthSession.js | 52 -
.../src/main/webapp/scripts/models/VXGroup.js | 95 -
.../src/main/webapp/scripts/models/VXKmsKey.js | 54 -
.../src/main/webapp/scripts/models/VXModuleDef.js | 70 -
.../main/webapp/scripts/models/VXPasswordChange.js | 27 -
.../src/main/webapp/scripts/models/VXPermMap.js | 54 -
.../webapp/scripts/models/VXPolicyExportAudit.js | 59 -
.../src/main/webapp/scripts/models/VXPortalUser.js | 121 -
.../src/main/webapp/scripts/models/VXResource.js | 53 -
.../src/main/webapp/scripts/models/VXRole.js | 92 -
.../src/main/webapp/scripts/models/VXTrxLog.js | 53 -
.../src/main/webapp/scripts/models/VXUser.js | 81 -
.../src/main/webapp/scripts/models/XABaseModel.js | 113 -
.../src/main/webapp/scripts/modules/RestCsrf.js | 114 -
.../src/main/webapp/scripts/modules/Vent.js | 26 -
.../src/main/webapp/scripts/modules/XALinks.js | 370 -
.../src/main/webapp/scripts/modules/XAOverrides.js | 1731 --
.../webapp/scripts/modules/globalize/message/en.js | 578 -
.../src/main/webapp/scripts/routers/Router.js | 131 -
.../src/main/webapp/scripts/utils/XAEnums.js | 399 -
.../src/main/webapp/scripts/utils/XAGlobals.js | 97 -
.../src/main/webapp/scripts/utils/XALangSupport.js | 94 -
.../src/main/webapp/scripts/utils/XAUtils.js | 2041 --
.../src/main/webapp/scripts/utils/XAViewUtils.js | 151 -
.../webapp/scripts/views/DownloadServicePolicy.js | 172 -
.../webapp/scripts/views/UploadServicePolicy.js | 432 -
.../main/webapp/scripts/views/common/AddGroup.js | 212 -
.../webapp/scripts/views/common/BreadCrumbs.js | 67 -
.../webapp/scripts/views/common/CustomSubgrid.js | 199 -
.../webapp/scripts/views/common/DashboardLayout.js | 80 -
.../main/webapp/scripts/views/common/ErrorView.js | 121 -
.../src/main/webapp/scripts/views/common/Footer.js | 81 -
.../main/webapp/scripts/views/common/ProfileBar.js | 172 -
.../main/webapp/scripts/views/common/Spinner.js | 90 -
.../src/main/webapp/scripts/views/common/TopNav.js | 131 -
.../scripts/views/common/UserPermissionList.js | 393 -
.../main/webapp/scripts/views/common/XABackgrid.js | 387 -
.../webapp/scripts/views/common/XATableLayout.js | 231 -
.../webapp/scripts/views/kms/KMSTableLayout.js | 413 -
.../main/webapp/scripts/views/kms/KmsKeyCreate.js | 185 -
.../main/webapp/scripts/views/kms/KmsKeyForm.js | 108 -
.../views/permissions/ModulePermissionCreate.js | 146 -
.../views/permissions/ModulePermissionForm.js | 380 -
.../views/permissions/ModulePermsTableLayout.js | 268 -
.../views/policies/NRangerPolicyTableLayout.js | 767 -
.../scripts/views/policies/PermissionList.js | 1146 --
.../scripts/views/policies/PolicyTimeList.js | 194 -
.../views/policies/RangerPolicyConditions.js | 114 -
.../scripts/views/policies/RangerPolicyCreate.js | 340 -
.../scripts/views/policies/RangerPolicyForm.js | 649 -
.../scripts/views/policies/RangerPolicyRO.js | 351 -
.../views/policies/RangerPolicyTableLayout.js | 586 -
.../webapp/scripts/views/policies/ResourceList.js | 171 -
.../scripts/views/policymanager/NServiceLayout.js | 88 -
.../scripts/views/policymanager/ServiceLayout.js | 406 -
.../views/policymanager/ServiceLayoutSidebar.js | 599 -
.../views/reports/AuditAccessLogDetailView.js | 141 -
.../webapp/scripts/views/reports/AuditLayout.js | 2340 ---
.../scripts/views/reports/LoginSessionDetail.js | 100 -
.../scripts/views/reports/OperationDiffDetail.js | 397 -
.../views/reports/PlugableServiceDiffDetail.js | 461 -
.../scripts/views/reports/UserAccessLayout.js | 1215 --
.../scripts/views/security_zone/SecurityZone.js | 343 -
.../views/security_zone/ZoneAdministration.js | 89 -
.../scripts/views/security_zone/ZoneCreate.js | 202 -
.../scripts/views/security_zone/ZoneCreateForm.js | 293 -
.../views/security_zone/ZoneResourceForm.js | 499 -
.../scripts/views/security_zone/zoneResource.js | 222 -
.../scripts/views/service/AuditFilterConfig.js | 568 -
.../scripts/views/service/ConfigurationList.js | 111 -
.../views/service/RangerServiceViewDetail.js | 106 -
.../views/service/ServiceAuditFilterResources.js | 483 -
.../webapp/scripts/views/service/ServiceCreate.js | 314 -
.../webapp/scripts/views/service/ServiceForm.js | 321 -
.../main/webapp/scripts/views/user/UserProfile.js | 218 -
.../webapp/scripts/views/user/UserProfileForm.js | 159 -
.../scripts/views/users/AddUsersOrGroupsList.js | 156 -
.../main/webapp/scripts/views/users/GroupCreate.js | 161 -
.../main/webapp/scripts/views/users/GroupForm.js | 82 -
.../main/webapp/scripts/views/users/RoleCreate.js | 161 -
.../main/webapp/scripts/views/users/RoleForm.js | 140 -
.../main/webapp/scripts/views/users/UserCreate.js | 216 -
.../main/webapp/scripts/views/users/UserForm.js | 292 -
.../main/webapp/scripts/views/users/UserInfo.js | 107 -
.../webapp/scripts/views/users/UserTableLayout.js | 1205 --
security-admin/src/main/webapp/styles/app-font.css | 64 -
.../webapp/templates/common/AddGroup_tmpl.html | 31 -
.../webapp/templates/common/ErrorView_tmpl.html | 36 -
.../main/webapp/templates/common/Footer_tmpl.html | 28 -
.../webapp/templates/common/ProfileBar_tmpl.html | 31 -
.../common/ServiceManagerLayout_tmpl.html | 101 -
.../common/ServiceManagerSidebarLayout_tmpl.html | 276 -
.../templates/common/ServiceMappingItem.html | 28 -
.../main/webapp/templates/common/TopNav_tmpl.html | 114 -
.../templates/common/UserPermissionItem.html | 51 -
.../templates/common/UserPermissionList.html | 41 -
.../templates/common/XATableLayout_tmpl.html | 22 -
.../main/webapp/templates/common/breadcrumbs.html | 29 -
.../common/downloadservicepolicy_tmpl.html | 34 -
.../main/webapp/templates/common/loading_tmpl.html | 45 -
.../templates/common/uploadservicepolicy_tmpl.html | 69 -
.../templates/dashboard/DashboardLayout_tmpl.html | 19 -
.../src/main/webapp/templates/helpers/XAHelpers.js | 627 -
.../webapp/templates/kms/KmsKeyCreate_tmpl.html | 26 -
.../main/webapp/templates/kms/KmsKeyForm_tmpl.html | 20 -
.../webapp/templates/kms/KmsTableLayout_tmpl.html | 42 -
.../permissions/ModulePermissionCreate_tmpl.html | 26 -
.../permissions/ModulePermissionForm_tmpl.html | 72 -
.../permissions/ModulePermsTableLayout_tmpl.html | 29 -
.../webapp/templates/policies/PermissionItem.html | 62 -
.../webapp/templates/policies/PermissionList.html | 41 -
.../policies/PolicyConditionsItem_tmpl.html | 20 -
.../templates/policies/PolicyTimeItem_tmpl.html | 46 -
.../templates/policies/PolicyTimeList_tmpl.html | 42 -
.../policies/RangerPolicyCreate_tmpl.html | 56 -
.../templates/policies/RangerPolicyForm_tmpl.html | 156 -
.../templates/policies/RangerPolicyRO_tmpl.html | 332 -
.../policies/RangerPolicyTableLayout_tmpl.html | 71 -
.../templates/policies/ResourceItem_tmpl.html | 26 -
.../templates/policies/ResourceList_tmpl.html | 37 -
.../templates/reports/AssetOperationDiff_tmpl.html | 134 -
.../reports/AssetUpdateOperationDiff_tmpl.html | 112 -
.../reports/AuditAccessLogDetail_tmpl.html | 285 -
.../webapp/templates/reports/AuditLayout_tmpl.html | 78 -
.../templates/reports/GroupOperationDiff_tmpl.html | 79 -
.../reports/GroupUpdateOperationDiff_tmpl.html | 74 -
.../templates/reports/LoginSessionDetail_tmpl.html | 47 -
.../PlugableServicePolicyDeleteDiff_tmpl.html | 417 -
.../reports/PlugableServicePolicyDiff_tmpl.html | 394 -
.../PlugableServicePolicyUpdateDiff_tmpl.html | 831 -
.../templates/reports/RoleOperationDiff_tmpl.html | 129 -
.../reports/RoleUpdateOperationDiff_tmpl.html | 133 -
.../templates/reports/UserAccessLayout_tmpl.html | 149 -
.../templates/reports/UserOperationDiff_tmpl.html | 102 -
.../templates/reports/UserSyncInfo_tmpl.html | 34 -
.../reports/UserUpdateOperationDiff_tmpl.html | 120 -
.../templates/reports/ZoneOperationDiff_tmpl.html | 135 -
.../reports/ZoneUpdateOperationDiff_tmpl.html | 125 -
.../templates/security_zone/SecurityZone_tmpl.html | 106 -
.../security_zone/ZoneAdministration_tmpl.html | 90 -
.../security_zone/ZoneCreateForm_tmpl.html | 86 -
.../templates/security_zone/ZoneCreate_tmpl.html | 30 -
.../security_zone/ZoneResourceForm_tmpl.html | 17 -
.../security_zone/ZoneResourceItem_tmpl.html | 29 -
.../security_zone/ZoneResourceList_tmpl.html | 18 -
.../security_zone/ZoneResourcesForm_tmpl.html | 21 -
.../security_zone/ZoneResources_tmpl.html | 15 -
.../templates/service/AuditFilterItem_tmpl.html | 70 -
.../templates/service/AuditFilterList_tmpl.html | 50 -
.../templates/service/ConfigurationItem_tmpl.html | 23 -
.../templates/service/ConfigurationList_tmpl.html | 38 -
.../service/RangerServiceViewDetail_tmpl.html | 229 -
.../ServiceAuditFilterResourcesForm_tmpl.html | 17 -
.../templates/service/ServiceCreate_tmpl.html | 29 -
.../webapp/templates/service/ServiceForm_tmpl.html | 62 -
.../templates/service/ServiceTableLayout_tmpl.html | 26 -
.../templates/user/UserProfileForm_tmpl.html | 25 -
.../webapp/templates/user/UserProfile_tmpl.html | 40 -
.../templates/users/AddUserOrGroupsItem_tmpl.html | 27 -
.../templates/users/AddUserOrGroupsList_tmpl.html | 41 -
.../webapp/templates/users/GroupCreate_tmpl.html | 26 -
.../webapp/templates/users/GroupForm_tmpl.html | 45 -
.../webapp/templates/users/RoleCreate_tmpl.html | 26 -
.../main/webapp/templates/users/RoleForm_tmpl.html | 44 -
.../webapp/templates/users/UserCreate_tmpl.html | 34 -
.../main/webapp/templates/users/UserForm_tmpl.html | 55 -
.../main/webapp/templates/users/UserInfo_tmpl.html | 98 -
.../templates/users/UserTableLayout_tmpl.html | 62 -
.../src/test/javascript/karma-common.conf.js | 98 -
.../src/test/javascript/karma-dev.conf.js | 25 -
.../src/test/javascript/karma-prd.conf.js | 26 -
.../src/test/javascript/package-lock.json | 3595 ----
security-admin/src/test/javascript/package.json | 14 -
security-admin/src/test/javascript/test-main.js | 45 -
.../src/test/javascript/tests/main-test.js | 37 -
360 files changed, 7 insertions(+), 127218 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 711794b08..8c1fbdfa6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,7 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-
sudo: false
dist: bionic
language: generic
@@ -42,7 +41,7 @@ jobs:
group: edge
env:
- JDK_VERSION=11
- - MAVEN_ARGS="-DskipJSTests=true -P!all"
+ - MAVEN_ARGS=" -P!all"
before_install:
- export MAVEN_OPTS="-Xmx1200M -XX:MaxPermSize=768m -Xms512m"
diff --git a/README.md b/README.md
index 0566da892..bbc76b58f 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,7 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
+
# Apache Ranger
[](https://www.apache.org/licenses/LICENSE-2.0.txt)
@@ -21,13 +22,12 @@ under the License.
[](https://ranger.apache.org)
[](https://cwiki.apache.org/confluence/display/RANGER/Index)
-
#### NOTE
+
Apache Ranger allows contributions via pull requests (PRs) on GitHub.
Alternatively, use [this](https://reviews.apache.org) to submit changes for review using the Review Board.
Also create a [ranger jira](https://issues.apache.org/jira/browse/RANGER) to go along with the review and mention it in the review board review.
-
## Building Ranger in Docker (Sandbox Install)
Ranger is built using [Apache Maven](https://maven.apache.org/). To run Ranger:
@@ -45,6 +45,7 @@ Ranger is built using [Apache Maven](https://maven.apache.org/). To run Ranger:
`./ranger_in_docker up`
6. After successful completion of the above command, you should be able to view Ranger Admin Console by using URL:
+
```
http://<hostname-of-system>:6080/
@@ -62,10 +63,6 @@ Ranger is built using [Apache Maven](https://maven.apache.org/). To run Ranger:
`mvn eclipse:eclipse`
- Ranger Admin UI tests depend on PhantomJS. If the build fails with npm or Karma errors you can either:
- - install PhantomJS dependencies for your platform (bzip2 and fontconfig)
- - skip JavaScript test execution: mvn -DskipJSTests ...
-
3. After the above build command execution, you should see the following TAR files in the target folder:
```
ranger-<version>-admin.tar.gz
@@ -95,12 +92,11 @@ Ranger is built using [Apache Maven](https://maven.apache.org/). To run Ranger:
2. Import maven project from the root directory where ranger source code is downloaded (and build)
-
## Deployment Process
-
### Installation Host Information
-1. Ranger Admin Tool Component (ranger-<version-number>-admin.tar.gz) should be installed on a host where Policy Admin Tool web application runs on port 6080 (default).
+
+1. Ranger Admin Tool Component (ranger-<version-number>-admin.tar.gz) should be installed on a host where Policy Admin Tool web application runs on port 6080 (default).
2. Ranger User Synchronization Component (ranger-<version-number>-usersync.tar.gz) should be installed on a host to synchronize the external user/group information into Ranger database via Ranger Admin Tool.
3. Ranger Component plugin should be installed on the component boxes:
- HDFS Plugin needs to be installed on Name Node hosts.
@@ -122,8 +118,7 @@ Ranger is built using [Apache Maven](https://maven.apache.org/). To run Ranger:
3. Go to the component name under the expanded folder (e.g. /usr/lib/ranger/ranger-<version-number>-admin/)
-4. Modify the install.properties file with appropriate variables
+4. Modify the install.properties file with appropriate variables
5. - If the module has setup.sh, execute ./setup.sh
- If the install.sh file does not exists, execute ./enable-<component>-plugin.sh
-
diff --git a/security-admin/pom.xml b/security-admin/pom.xml
index 3929423c5..bfaf5b531 100644
--- a/security-admin/pom.xml
+++ b/security-admin/pom.xml
@@ -29,7 +29,6 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<skipJSCoverage>true</skipJSCoverage>
- <skipJSTests>false</skipJSTests>
</properties>
<dependencies>
<dependency>
@@ -183,7 +182,6 @@
</exclusion>
</exclusions>
</dependency>
-
<dependency>
<groupId>com.webcohesion.enunciate</groupId>
<artifactId>enunciate-core-annotations</artifactId>
@@ -892,40 +890,6 @@
</execution>
</executions>
</plugin>
- <plugin>
- <groupId>com.google.code.maven-replacer-plugin</groupId>
- <artifactId>replacer</artifactId>
- <version>1.5.3</version>
- <executions>
- <execution>
- <goals>
- <goal>replace</goal>
- </goals>
- <phase>prepare-package</phase>
- <configuration>
- <basedir>${project.build.directory}/${project.build.finalName}</basedir>
- <includes>
- <include>backbone-index.html</include>
- <include>scripts/Init.js</include>
- </includes>
- <replacements>
- <replacement>
- <token>build.version</token>
- <value>${project.version}</value>
- </replacement>
- <replacement>
- <token>(?m)\<\!-- *dev *--\>(.*)$</token>
- <value>\<\!-- dev $1 --\></value>
- </replacement>
- <replacement>
- <token>\<\!-- *prod *(.*) *--\></token>
- <value>\<\!-- prod --\>$1</value>
- </replacement>
- </replacements>
- </configuration>
- </execution>
- </executions>
- </plugin>
<plugin>
<groupId>com.webcohesion.enunciate</groupId>
<artifactId>enunciate-maven-plugin</artifactId>
@@ -951,44 +915,6 @@
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
- <execution>
- <id>copy-resources</id>
- <goals>
- <goal>copy-resources</goal>
- </goals>
- <phase>validate</phase>
- <configuration>
- <outputDirectory>${project.build.directory}/jsmain</outputDirectory>
- <resources>
- <resource>
- <directory>${basedir}/src/main/webapp</directory>
- <includes>
- <include>package.json</include>
- <include>package-lock.json</include>
- </includes>
- </resource>
- </resources>
- </configuration>
- </execution>
- <execution>
- <id>copy-js-test-resources</id>
- <goals>
- <goal>copy-resources</goal>
- </goals>
- <phase>validate</phase>
- <configuration>
- <outputDirectory>${project.build.directory}/jstest</outputDirectory>
- <resources>
- <resource>
- <directory>${basedir}/src/test/javascript</directory>
- <includes>
- <include>package.json</include>
- <include>package-lock.json</include>
- </includes>
- </resource>
- </resources>
- </configuration>
- </execution>
<!-- react-webapp copy-resources execution start -->
<execution>
<id>copy-resources-react-webapp</id>
@@ -1091,82 +1017,6 @@
<installDirectory>${project.build.directory}</installDirectory>
</configuration>
<executions>
- <execution>
- <id>install node and npm</id>
- <goals>
- <goal>install-node-and-npm</goal>
- </goals>
- <phase>process-resources</phase>
- <configuration>
- <nodeVersion>v8.12.0</nodeVersion>
- <npmVersion>6.4.1</npmVersion>
- </configuration>
- </execution>
- <execution>
- <id>npm install for packaging</id>
- <goals>
- <goal>npm</goal>
- </goals>
- <phase>prepare-package</phase>
- <configuration>
- <workingDirectory>${project.build.directory}/jsmain</workingDirectory>
- <arguments>install</arguments>
- </configuration>
- </execution>
- <execution>
- <id>npm run r.js</id>
- <goals>
- <goal>npm</goal>
- </goals>
- <phase>prepare-package</phase>
- <configuration>
- <workingDirectory>${project.build.directory}/jsmain</workingDirectory>
- <arguments>run r.js -- -o ../${project.build.finalName}/minify.build.js</arguments>
- </configuration>
- </execution>
- <execution>
- <id>npm install for tests</id>
- <goals>
- <goal>npm</goal>
- </goals>
- <phase>test</phase>
- <configuration>
- <skip>${skipJSTests}</skip>
- <workingDirectory>${project.build.directory}/jstest</workingDirectory>
- <arguments>install</arguments>
- </configuration>
- </execution>
- <execution>
- <id>karma dev</id>
- <goals>
- <goal>karma</goal>
- </goals>
- <phase>test</phase>
- <configuration>
- <environmentVariables>
- <OPENSSL_CONF>/etc/ssl/</OPENSSL_CONF>
- </environmentVariables>
- <skip>${skipJSTests}</skip>
- <workingDirectory>${project.build.directory}/jstest</workingDirectory>
- <karmaConfPath>../../src/test/javascript/karma-dev.conf.js</karmaConfPath>
- </configuration>
- </execution>
- <execution>
- <id>karma prd</id>
- <goals>
- <goal>karma</goal>
- </goals>
- <phase>integration-test</phase>
- <configuration>
- <environmentVariables>
- <buildDir>${project.build.finalName}</buildDir>
- <OPENSSL_CONF>/etc/ssl/</OPENSSL_CONF>
- </environmentVariables>
- <skip>${skipJSTests}</skip>
- <workingDirectory>${project.build.directory}/jstest</workingDirectory>
- <karmaConfPath>../../src/test/javascript/karma-prd.conf.js</karmaConfPath>
- </configuration>
- </execution>
<!-- react-webapp frontend-maven-plugin start -->
<execution>
<id>install node and npm for react-webapp</id>
diff --git a/security-admin/src/main/webapp/backbone-index.html b/security-admin/src/main/webapp/backbone-index.html
deleted file mode 100644
index bc006cd75..000000000
--- a/security-admin/src/main/webapp/backbone-index.html
+++ /dev/null
@@ -1,139 +0,0 @@
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!doctype html>
-<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
-<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
-<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
-<!--[if gt IE 8]> <html class="ie"> <![endif]-->
-<html class="no-js">
- <!--<![endif]-->
- <head>
- <meta charset="utf-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
- <title>Ranger</title>
- <meta name="description" content="">
- <meta name="viewport" content="width=device-width">
- <!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
- <link rel="shortcut icon" href="images/favicon.ico">
- <link rel="stylesheet" href="styles/app-font.css">
- <link rel="stylesheet" href="styles/font-awesome.min.css">
- <link href="styles/bootstrap.min.css" media="all" rel="stylesheet" type="text/css" id="bootstrap-css">
- <link href="libs/other/jquery-ui/css/jquery-ui.min.css" media="all" rel="stylesheet" type="text/css">
- <link href="libs/other/backgrid/backgrid.css" media="all" rel="stylesheet" type="text/css">
- <link href="libs/other/backgrid-column-manager/Backgrid.ColumnManager.css" media="all" rel="stylesheet" type="text/css">
- <link href="libs/bower/backgrid-paginator/css/backgrid-paginator.css" media="all" rel="stylesheet" type="text/css">
- <link href="libs/bower/backgrid-filter/css/backgrid-filter.css" media="all" rel="stylesheet" type="text/css">
- <link href="libs/bower/select2/select2.css" media="all" rel="stylesheet" type="text/css">
- <link href="libs/bower/select2/select2-bootstrap4.css" media="all" rel="stylesheet" type="text/css">
- <link href="libs/bower/bootstrap-notify/css/bootstrap-notify.css" rel="stylesheet">
- <link href="libs/bower/tag-it/css/jquery.tagit.css" rel="stylesheet">
- <link href="libs/other/datepicker/css/datepicker.css" media="all" rel="stylesheet" type="text/css">
- <link href="libs/bower/x-editable/css/bootstrap-editable.css" media="all" rel="stylesheet" type="text/css">
- <link href="libs/other/daterangepicker/css/daterangepicker.css" media="all" rel="stylesheet" type="text/css">
- <link href="libs/other/visualsearch/css/workspace.css" rel="stylesheet">
- <link href="libs/other/visualsearch/css/icons.css" rel="stylesheet">
- <link href="styles/xa.css" media="all" rel="stylesheet" type="text/css">
- </head>
-
- <body class="container-fluid service-layout" id="contentBody">
- <!-- Main navigation bar
- ================================================== -->
- <header class="navbar fixed-top navbar-expand-lg ranger-nav" id="top-navbar">
- <div class="navbar-inner">
- <div class="container-fluid">
- <a class="navbar-brand logo" href="#"><img alt="Af_logo" src="images/ranger_logo.png"></a>
- <a class="btn nav-button collapsed" data-toggle="collapse" data-target=".navbar-collapse"> <span class="fa fw fa fa-reorder"></span> </a>
- <div id="r_topNav" style="margin-right: auto;"></div>
- <div id="r_topProfileBar"></div>
- </div>
- </div>
- </header>
- <!-- / Main navigation bar -->
- <!-- Page content
- ================================================== -->
- <section id="r_sidebar"></section>
- <section class="container-fluid">
- <div class="headerBreadcrumbs">
- <section id="r_breadcrumbs" class="r_breadcrumbs"></section>
- <div class="latestResponse"></div>
- </div>
- <div class="notifications top-right ranger-notifications"></div>
- <section id="r_content" style="min-height: 450px;">
- <div class="loading-img">
- <div id="center">
- <div class="letter_container_1">
- <span>L</span>
- </div>
- <div class="letter_container_2">
- <span>O</span>
- </div>
- <div class="letter_container_3">
- <span>A</span>
- </div>
- <div class="letter_container_4">
- <span>D</span>
- </div>
- <div class="letter_container_5">
- <span>I</span>
- </div>
- <div class="letter_container_6">
- <span>N</span>
- </div>
- <div class="letter_container_7">
- <span>G</span>
- </div>
- <div class="letter_container_8">
- <span>..</span>
- </div>
- </div>
- </div>
- </section><!-- r_content -->
-
- <!-- Page footer
- ================================================== -->
- <footer class="clearBoth" id="r_footer">
-
- </footer>
- <!-- / Page footer -->
- </section>
- <!-- Page content ends
- ================================================== -->
-
- <a href="#" class="btn-top _allowNav" id="back-top" title="Scroll to top">
- <i class="fa fa-arrow-up bigger-120 _allowNav"></i>
- </a>
- <script src="libs/bower/requirejs/js/require.js"></script>
-
- <!--
- the script tags below are commented/uncommented during the packaging phase.
- (see the replacer configuration in POM)
- -->
- <!-- dev --><script src="scripts/Init.js?ver=build.version"></script>
- <!-- prod <script src="scripts/Main.min.js?ver=build.version"></script> -->
-
- <script type="text/javascript">
- require.config({
- waitSeconds : 0
- });
- if (!window.console) window.console = {};
- if (!window.console.log) window.console.log = function () { };
- require(['Main'], function(){
- //nothing to do, loading Main already triggers the app
- });
- </script>
- </body>
-</html>
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/libs/bower/backbone-forms/css/bootstrap.css b/security-admin/src/main/webapp/libs/bower/backbone-forms/css/bootstrap.css
deleted file mode 100644
index 667c6f40a..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone-forms/css/bootstrap.css
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Date */
-.bbf-date .bbf-date {
- width: 4em
-}
-
-.bbf-date .bbf-month {
- width: 9em;
-}
-
-.bbf-date .bbf-year {
- width: 5em;
-}
-
-
-/* DateTime */
-.bbf-datetime select {
- width: 4em;
-}
-
-
-/* List */
-.bbf-list .bbf-add {
- margin-top: -10px
-}
-
-.bbf-list li {
- margin-bottom: 5px
-}
-
-.bbf-list .bbf-del {
- margin-left: 4px
-}
-
-
-/* List.Modal */
-.bbf-list-modal {
- cursor: pointer;
- border: 1px solid #ccc;
- width: 208px;
- border-radius: 3px;
- padding: 4px;
- color: #555;
-}
diff --git a/security-admin/src/main/webapp/libs/bower/backbone-forms/css/old.css b/security-admin/src/main/webapp/libs/bower/backbone-forms/css/old.css
deleted file mode 100644
index 79261ea54..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone-forms/css/old.css
+++ /dev/null
@@ -1,140 +0,0 @@
-/* Form */
-.bbf-form {
- margin: 0;
- padding: 0;
- border: none;
-}
-
-
-/* Field */
-.bbf-field {
- margin: 1em 0;
- list-style-type: none;
- position: relative;
- clear: both;
-}
-
- .bbf-field label {
- float: left;
- width: 25%;
- }
-
- .bbf-field .bbf-editor {
- margin-left: 25%;
- width: 74%;
- }
-
- .bbf-field input, .bbf-field textarea, .bbf-field select {
- width: 100%;
- }
-
- .bbf-field .bbf-help {
- margin-left: 25%;
- width: 74%;
- color: #999;
- }
-
- .bbf-field .bbf-error {
- margin-left: 25%;
- width: 74%;
- color: red;
- }
-
- .bbf-field.bbf-error .bbf-editor {
- outline: 1px solid red;
- }
-
-
-/* Radio */
-.bbf-radio {
- list-style-type: none;
-}
-
- .bbf-radio input {
- width: auto;
- }
-
- .bbf-radio label {
- float: none;
- }
-
-
-/* Checkboxes */
-.bbf-checkboxes {
- list-style-type: none;
-}
-
- .bbf-checkboxes input {
- width: auto;
- }
-
- .bbf-checkboxes label {
- float: none;
- }
-
-
-/* List */
-.bbf-list ul {
- list-style-type: none;
- margin: 0;
- padding: 0;
-}
-
- .bbf-list .bbf-error {
- border: 1px solid red;
- }
-
- .bbf-list li {
- clear: both;
- width: 100%;
- }
-
- .bbf-list li .bbf-editor-container {
- margin-right: 2em;
- }
-
- .bbf-list li .bbf-remove {
- float: right;
- width: 2em;
- }
-
-.bbf-list .bbf-actions {
- text-align: center;
- clear: both;
-}
-
-/* List.Modal */
-.bbf-list-modal {
- cursor: pointer;
- border: 1px solid #ccc;
- width: 208px;
- border-radius: 3px;
- padding: 4px;
- color: #555;
-}
-
-
-
-/* Date */
-.bbf-date .bbf-date {
- width: 4em;
-}
-
-.bbf-date .bbf-month {
- width: 9em;
-}
-
-.bbf-date .bbf-year {
- width: 6em;
-}
-
-
-/* DateTime */
-.bbf-datetime .bbf-date-container {
- float: left;
- margin-right: 1em;
-}
-
-.bbf-datetime select {
- width: 4em;
-}
diff --git a/security-admin/src/main/webapp/libs/bower/backbone-forms/js/backbone-forms.js b/security-admin/src/main/webapp/libs/bower/backbone-forms/js/backbone-forms.js
deleted file mode 100644
index bb16c684a..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone-forms/js/backbone-forms.js
+++ /dev/null
@@ -1,2527 +0,0 @@
-/**
- * Backbone Forms v0.14.1
- *
- * NOTE:
- * This version is for use with RequireJS
- * If using regular <script> tags to include your files, use backbone-forms.min.js
- *
- * Copyright (c) 2013 Charles Davison, Pow Media Ltd
- *
- * License and more information at:
- * http://github.com/powmedia/backbone-forms
- */
-define(['jquery', 'underscore', 'backbone'], function($, _, Backbone) {
-
- //==================================================================================================
-//FORM
-//==================================================================================================
-
-var Form = Backbone.View.extend({
-
- events: {
- 'submit': function(event) {
- this.trigger('submit', event);
- }
- },
-
- /**
- * Constructor
- *
- * @param {Object} [options.schema]
- * @param {Backbone.Model} [options.model]
- * @param {Object} [options.data]
- * @param {String[]|Object[]} [options.fieldsets]
- * @param {String[]} [options.fields]
- * @param {String} [options.idPrefix]
- * @param {Form.Field} [options.Field]
- * @param {Form.Fieldset} [options.Fieldset]
- * @param {Function} [options.template]
- * @param {Boolean|String} [options.submitButton]
- */
- initialize: function(options) {
- var self = this;
-
- //Merge default options
- options = this.options = _.extend({
- submitButton: false
- }, options);
-
- //Find the schema to use
- var schema = this.schema = (function() {
- //Prefer schema from options
- if (options.schema) return _.result(options, 'schema');
-
- //Then schema on model
- var model = options.model;
- if (model && model.schema) return _.result(model, 'schema');
-
- //Then built-in schema
- if (self.schema) return _.result(self, 'schema');
-
- //Fallback to empty schema
- return {};
- })();
-
- //Store important data
- _.extend(this, _.pick(options, 'model', 'data', 'idPrefix', 'templateData'));
-
- //Override defaults
- var constructor = this.constructor;
- this.template = options.template || this.template || constructor.template;
- this.Fieldset = options.Fieldset || this.Fieldset || constructor.Fieldset;
- this.Field = options.Field || this.Field || constructor.Field;
- this.NestedField = options.NestedField || this.NestedField || constructor.NestedField;
-
- //Check which fields will be included (defaults to all)
- var selectedFields = this.selectedFields = options.fields || _.keys(schema);
-
- //Create fields
- var fields = this.fields = {};
-
- _.each(selectedFields, function(key) {
- var fieldSchema = schema[key];
- fields[key] = this.createField(key, fieldSchema);
- }, this);
-
- //Create fieldsets
- var fieldsetSchema = options.fieldsets || _.result(this, 'fieldsets') || [selectedFields],
- fieldsets = this.fieldsets = [];
-
- _.each(fieldsetSchema, function(itemSchema) {
- this.fieldsets.push(this.createFieldset(itemSchema));
- }, this);
- },
-
- /**
- * Creates a Fieldset instance
- *
- * @param {String[]|Object[]} schema Fieldset schema
- *
- * @return {Form.Fieldset}
- */
- createFieldset: function(schema) {
- var options = {
- schema: schema,
- fields: this.fields
- };
-
- return new this.Fieldset(options);
- },
-
- /**
- * Creates a Field instance
- *
- * @param {String} key
- * @param {Object} schema Field schema
- *
- * @return {Form.Field}
- */
- createField: function(key, schema) {
- var options = {
- form: this,
- key: key,
- schema: schema,
- idPrefix: this.idPrefix
- };
-
- if (this.model) {
- options.model = this.model;
- } else if (this.data) {
- options.value = this.data[key];
- } else {
- options.value = null;
- }
-
- var field = new this.Field(options);
-
- this.listenTo(field.editor, 'all', this.handleEditorEvent);
-
- return field;
- },
-
- /**
- * Callback for when an editor event is fired.
- * Re-triggers events on the form as key:event and triggers additional form-level events
- *
- * @param {String} event
- * @param {Editor} editor
- */
- handleEditorEvent: function(event, editor) {
- //Re-trigger editor events on the form
- var formEvent = editor.key+':'+event;
-
- this.trigger.call(this, formEvent, this, editor, Array.prototype.slice.call(arguments, 2));
-
- //Trigger additional events
- switch (event) {
- case 'change':
- this.trigger('change', this);
- break;
-
- case 'focus':
- if (!this.hasFocus) this.trigger('focus', this);
- break;
-
- case 'blur':
- if (this.hasFocus) {
- //TODO: Is the timeout etc needed?
- var self = this;
- setTimeout(function() {
- var focusedField = _.find(self.fields, function(field) {
- return field.editor.hasFocus;
- });
-
- if (!focusedField) self.trigger('blur', self);
- }, 0);
- }
- break;
- }
- },
-
- templateData: function() {
- var options = this.options;
-
- return {
- submitButton: options.submitButton
- }
- },
-
- render: function() {
- var self = this,
- fields = this.fields,
- $ = Backbone.$;
-
- //Render form
- var $form = $($.trim(this.template(_.result(this, 'templateData'))));
-
- //Render standalone editors
- $form.find('[data-editors]').add($form).each(function(i, el) {
- var $container = $(el),
- selection = $container.attr('data-editors');
-
- if (_.isUndefined(selection)) return;
-
- //Work out which fields to include
- var keys = (selection == '*')
- ? self.selectedFields || _.keys(fields)
- : selection.split(',');
-
- //Add them
- _.each(keys, function(key) {
- var field = fields[key];
-
- $container.append(field.editor.render().el);
- });
- });
-
- //Render standalone fields
- $form.find('[data-fields]').add($form).each(function(i, el) {
- var $container = $(el),
- selection = $container.attr('data-fields');
-
- if (_.isUndefined(selection)) return;
-
- //Work out which fields to include
- var keys = (selection == '*')
- ? self.selectedFields || _.keys(fields)
- : selection.split(',');
-
- //Add them
- _.each(keys, function(key) {
- var field = fields[key];
-
- $container.append(field.render().el);
- });
- });
-
- //Render fieldsets
- $form.find('[data-fieldsets]').add($form).each(function(i, el) {
- var $container = $(el),
- selection = $container.attr('data-fieldsets');
-
- if (_.isUndefined(selection)) return;
-
- _.each(self.fieldsets, function(fieldset) {
- $container.append(fieldset.render().el);
- });
- });
-
- //Set the main element
- this.setElement($form);
-
- //Set class
- $form.addClass(this.className);
-
- return this;
- },
-
- /**
- * Validate the data
- *
- * @return {Object} Validation errors
- */
- validate: function(options) {
- var self = this,
- fields = this.fields,
- model = this.model,
- errors = {};
-
- options = options || {};
-
- //Collect errors from schema validation
- _.each(fields, function(field) {
- var error = field.validate();
- if (error) {
- errors[field.key] = error;
- }
- });
-
- //Get errors from default Backbone model validator
- if (!options.skipModelValidate && model && model.validate) {
- var modelErrors = model.validate(this.getValue());
-
- if (modelErrors) {
- var isDictionary = _.isObject(modelErrors) && !_.isArray(modelErrors);
-
- //If errors are not in object form then just store on the error object
- if (!isDictionary) {
- errors._others = errors._others || [];
- errors._others.push(modelErrors);
- }
-
- //Merge programmatic errors (requires model.validate() to return an object e.g. { fieldKey: 'error' })
- if (isDictionary) {
- _.each(modelErrors, function(val, key) {
- //Set error on field if there isn't one already
- if (fields[key] && !errors[key]) {
- fields[key].setError(val);
- errors[key] = val;
- }
-
- else {
- //Otherwise add to '_others' key
- errors._others = errors._others || [];
- var tmpErr = {};
- tmpErr[key] = val;
- errors._others.push(tmpErr);
- }
- });
- }
- }
- }
-
- return _.isEmpty(errors) ? null : errors;
- },
-
- /**
- * Update the model with all latest values.
- *
- * @param {Object} [options] Options to pass to Model#set (e.g. { silent: true })
- *
- * @return {Object} Validation errors
- */
- commit: function(options) {
- //Validate
- options = options || {};
-
- var validateOptions = {
- skipModelValidate: !options.validate
- };
-
- var errors = this.validate(validateOptions);
- //custom property
- if (errors){
- var vFirstField = this.fields[_.keys(errors)[0]];
- if(vFirstField){
- $("html, body").animate({
- scrollTop: vFirstField.$el.position().top-100
- }, 1100, function(){
- if(options.focusFirstField) vFirstField.editor.$el.focus();
- });
- }
- return errors;
- }
-
- //Commit
- var modelError;
-
- var setOptions = _.extend({
- error: function(model, e) {
- modelError = e;
- }
- }, options);
-
- this.model.set(this.getValue(), setOptions);
-
- if (modelError) return modelError;
- },
-
- /**
- * Get all the field values as an object.
- * Use this method when passing data instead of objects
- *
- * @param {String} [key] Specific field value to get
- */
- getValue: function(key) {
- //Return only given key if specified
- if (key) return this.fields[key].getValue();
-
- //Otherwise return entire form
- var values = {};
- _.each(this.fields, function(field) {
- values[field.key] = field.getValue();
- });
-
- return values;
- },
-
- /**
- * Update field values, referenced by key
- *
- * @param {Object|String} key New values to set, or property to set
- * @param val Value to set
- */
- setValue: function(prop, val) {
- var data = {};
- if (typeof prop === 'string') {
- data[prop] = val;
- } else {
- data = prop;
- }
-
- var key;
- for (key in this.schema) {
- if (data[key] !== undefined) {
- this.fields[key].setValue(data[key]);
- }
- }
- },
-
- /**
- * Returns the editor for a given field key
- *
- * @param {String} key
- *
- * @return {Editor}
- */
- getEditor: function(key) {
- var field = this.fields[key];
- if (!field) throw new Error('Field not found: '+key);
-
- return field.editor;
- },
-
- /**
- * Gives the first editor in the form focus
- */
- focus: function() {
- if (this.hasFocus) return;
-
- //Get the first field
- var fieldset = this.fieldsets[0],
- field = fieldset.getFieldAt(0);
-
- if (!field) return;
-
- //Set focus
- field.editor.focus();
- },
-
- /**
- * Removes focus from the currently focused editor
- */
- blur: function() {
- if (!this.hasFocus) return;
-
- var focusedField = _.find(this.fields, function(field) {
- return field.editor.hasFocus;
- });
-
- if (focusedField) focusedField.editor.blur();
- },
-
- /**
- * Manages the hasFocus property
- *
- * @param {String} event
- */
- trigger: function(event) {
- if (event === 'focus') {
- this.hasFocus = true;
- }
- else if (event === 'blur') {
- this.hasFocus = false;
- }
-
- return Backbone.View.prototype.trigger.apply(this, arguments);
- },
-
- /**
- * Override default remove function in order to remove embedded views
- *
- * TODO: If editors are included directly with data-editors="x", they need to be removed
- * May be best to use XView to manage adding/removing views
- */
- remove: function() {
- _.each(this.fieldsets, function(fieldset) {
- fieldset.remove();
- });
-
- _.each(this.fields, function(field) {
- field.remove();
- });
-
- return Backbone.View.prototype.remove.apply(this, arguments);
- }
-
-}, {
-
- //STATICS
- template: _.template('\
- <form>\
- <div data-fieldsets></div>\
- <% if (submitButton) { %>\
- <button type="submit"><%= submitButton %></button>\
- <% } %>\
- </form>\
- ', null, this.templateSettings),
-
- templateSettings: {
- evaluate: /<%([\s\S]+?)%>/g,
- interpolate: /<%=([\s\S]+?)%>/g,
- escape: /<%-([\s\S]+?)%>/g
- },
-
- editors: {}
-
-});
-
-
-//==================================================================================================
-//VALIDATORS
-//==================================================================================================
-
-Form.validators = (function() {
-
- var validators = {};
-
- validators.errMessages = {
- required: 'Required',
- regexp: 'Invalid',
- number: 'Must be a number',
- email: 'Invalid email address',
- url: 'Invalid URL',
- match: _.template('Must match field "<%= field %>"', null, Form.templateSettings)
- };
-
- validators.required = function(options) {
- options = _.extend({
- type: 'required',
- message: this.errMessages.required
- }, options);
-
- return function required(value) {
- options.value = value;
-
- var err = {
- type: options.type,
- message: _.isFunction(options.message) ? options.message(options) : options.message
- };
-
- if (value === null || value === undefined || value === false || value === '') return err;
- };
- };
-
- validators.regexp = function(options) {
- if (!options.regexp) throw new Error('Missing required "regexp" option for "regexp" validator');
-
- options = _.extend({
- type: 'regexp',
- match: true,
- message: this.errMessages.regexp
- }, options);
-
- return function regexp(value) {
- options.value = value;
-
- var err = {
- type: options.type,
- message: _.isFunction(options.message) ? options.message(options) : options.message
- };
-
- //Don't check empty values (add a 'required' validator for this)
- if (value === null || value === undefined || value === '') return;
-
- //Create RegExp from string if it's valid
- if ('string' === typeof options.regexp) options.regexp = new RegExp(options.regexp, options.flags);
-
- if ((options.match) ? !options.regexp.test(value) : options.regexp.test(value)) return err;
- };
- };
-
- validators.number = function(options) {
- options = _.extend({
- type: 'number',
- message: this.errMessages.number,
- regexp: /^[0-9]*\.?[0-9]*?$/
- }, options);
-
- return validators.regexp(options);
- };
-
- validators.email = function(options) {
- options = _.extend({
- type: 'email',
- message: this.errMessages.email,
- regexp: /^[\w\-]{1,}([\w\-\+.]{1,1}[\w\-]{1,}){0,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/
- }, options);
-
- return validators.regexp(options);
- };
-
- validators.url = function(options) {
- options = _.extend({
- type: 'url',
- message: this.errMessages.url,
- regexp: /^(http|https):\/\/(([A-Z0-9][A-Z0-9_\-]*)(\.[A-Z0-9][A-Z0-9_\-]*)+)(:(\d+))?\/?/i
- }, options);
-
- return validators.regexp(options);
- };
-
- validators.match = function(options) {
- if (!options.field) throw new Error('Missing required "field" options for "match" validator');
-
- options = _.extend({
- type: 'match',
- message: this.errMessages.match
- }, options);
-
- return function match(value, attrs) {
- options.value = value;
-
- var err = {
- type: options.type,
- message: _.isFunction(options.message) ? options.message(options) : options.message
- };
-
- //Don't check empty values (add a 'required' validator for this)
- if (value === null || value === undefined || value === '') return;
-
- if (value !== attrs[options.field]) return err;
- };
- };
-
-
- return validators;
-
-})();
-
-
-//==================================================================================================
-//FIELDSET
-//==================================================================================================
-
-Form.Fieldset = Backbone.View.extend({
-
- /**
- * Constructor
- *
- * Valid fieldset schemas:
- * ['field1', 'field2']
- * { legend: 'Some Fieldset', fields: ['field1', 'field2'] }
- *
- * @param {String[]|Object[]} options.schema Fieldset schema
- * @param {Object} options.fields Form fields
- */
- initialize: function(options) {
- options = options || {};
-
- //Create the full fieldset schema, merging defaults etc.
- var schema = this.schema = this.createSchema(options.schema);
-
- //Store the fields for this fieldset
- this.fields = _.pick(options.fields, schema.fields);
-
- //Override defaults
- this.template = options.template || schema.template || this.template || this.constructor.template;
- },
-
- /**
- * Creates the full fieldset schema, normalising, merging defaults etc.
- *
- * @param {String[]|Object[]} schema
- *
- * @return {Object}
- */
- createSchema: function(schema) {
- //Normalise to object
- if (_.isArray(schema)) {
- schema = { fields: schema };
- }
-
- //Add null legend to prevent template error
- schema.legend = schema.legend || null;
-
- return schema;
- },
-
- /**
- * Returns the field for a given index
- *
- * @param {Number} index
- *
- * @return {Field}
- */
- getFieldAt: function(index) {
- var key = this.schema.fields[index];
-
- return this.fields[key];
- },
-
- /**
- * Returns data to pass to template
- *
- * @return {Object}
- */
- templateData: function() {
- return this.schema;
- },
-
- /**
- * Renders the fieldset and fields
- *
- * @return {Fieldset} this
- */
- render: function() {
- var schema = this.schema,
- fields = this.fields,
- $ = Backbone.$;
-
- //Render fieldset
- var $fieldset = $($.trim(this.template(_.result(this, 'templateData'))));
-
- //Render fields
- $fieldset.find('[data-fields]').add($fieldset).each(function(i, el) {
- var $container = $(el),
- selection = $container.attr('data-fields');
-
- if (_.isUndefined(selection)) return;
-
- _.each(fields, function(field) {
- $container.append(field.render().el);
- });
- });
-
- this.setElement($fieldset);
-
- return this;
- },
-
- /**
- * Remove embedded views then self
- */
- remove: function() {
- _.each(this.fields, function(field) {
- field.remove();
- });
-
- Backbone.View.prototype.remove.call(this);
- }
-
-}, {
- //STATICS
-
- template: _.template('\
- <fieldset data-fields>\
- <% if (legend) { %>\
- <legend><%= legend %></legend>\
- <% } %>\
- </fieldset>\
- ', null, Form.templateSettings)
-
-});
-
-
-//==================================================================================================
-//FIELD
-//==================================================================================================
-
-Form.Field = Backbone.View.extend({
-
- /**
- * Constructor
- *
- * @param {Object} options.key
- * @param {Object} options.form
- * @param {Object} [options.schema]
- * @param {Function} [options.schema.template]
- * @param {Backbone.Model} [options.model]
- * @param {Object} [options.value]
- * @param {String} [options.idPrefix]
- * @param {Function} [options.template]
- * @param {Function} [options.errorClassName]
- */
- initialize: function(options) {
- options = options || {};
-
- //Store important data
- _.extend(this, _.pick(options, 'form', 'key', 'model', 'value', 'idPrefix'));
-
- //Create the full field schema, merging defaults etc.
- var schema = this.schema = this.createSchema(options.schema);
-
- //Override defaults
- this.template = options.template || schema.template || this.template || this.constructor.template;
- this.errorClassName = options.errorClassName || this.errorClassName || this.constructor.errorClassName;
-
- //Create editor
- this.editor = this.createEditor();
- },
-
- /**
- * Creates the full field schema, merging defaults etc.
- *
- * @param {Object|String} schema
- *
- * @return {Object}
- */
- createSchema: function(schema) {
- if (_.isString(schema)) schema = { type: schema };
-
- //Set defaults
- schema = _.extend({
- type: 'Text',
- title: this.createTitle()
- }, schema);
-
- //Get the real constructor function i.e. if type is a string such as 'Text'
- schema.type = (_.isString(schema.type)) ? Form.editors[schema.type] : schema.type;
-
- return schema;
- },
-
- /**
- * Creates the editor specified in the schema; either an editor string name or
- * a constructor function
- *
- * @return {View}
- */
- createEditor: function() {
- var options = _.extend(
- _.pick(this, 'schema', 'form', 'key', 'model', 'value'),
- { id: this.createEditorId() }
- );
-
- var constructorFn = this.schema.type;
-
- return new constructorFn(options);
- },
-
- /**
- * Creates the ID that will be assigned to the editor
- *
- * @return {String}
- */
- createEditorId: function() {
- var prefix = this.idPrefix,
- id = this.key;
-
- //Replace periods with underscores (e.g. for when using paths)
- id = id.replace(/\./g, '_');
-
- //If a specific ID prefix is set, use it
- if (_.isString(prefix) || _.isNumber(prefix)) return prefix + id;
- if (_.isNull(prefix)) return id;
-
- //Otherwise, if there is a model use it's CID to avoid conflicts when multiple forms are on the page
- if (this.model) return this.model.cid + '_' + id;
-
- return id;
- },
-
- /**
- * Create the default field title (label text) from the key name.
- * (Converts 'camelCase' to 'Camel Case')
- *
- * @return {String}
- */
- createTitle: function() {
- var str = this.key;
-
- //Add spaces
- str = str.replace(/([A-Z])/g, ' $1');
-
- //Uppercase first character
- str = str.replace(/^./, function(str) { return str.toUpperCase(); });
-
- return str;
- },
-
- /**
- * Returns the data to be passed to the template
- *
- * @return {Object}
- */
- templateData: function() {
- var schema = this.schema;
-
- return {
- help: schema.help || '',
- title: schema.title,
- fieldAttrs: schema.fieldAttrs,
- editorAttrs: schema.editorAttrs,
- key: this.key,
- editorId: this.editor.id
- };
- },
-
- /**
- * Render the field and editor
- *
- * @return {Field} self
- */
- render: function() {
- var schema = this.schema,
- editor = this.editor,
- $ = Backbone.$;
-
- //Only render the editor if Hidden
- if (schema.type == Form.editors.Hidden) {
- return this.setElement(editor.render().el);
- }
-
- //Render field
- var $field = $($.trim(this.template(_.result(this, 'templateData'))));
-
- if (schema.fieldClass) $field.addClass(schema.fieldClass);
- if (schema.fieldAttrs) $field.attr(schema.fieldAttrs);
-
- //Render editor
- $field.find('[data-editor]').add($field).each(function(i, el) {
- var $container = $(el),
- selection = $container.attr('data-editor');
-
- if (_.isUndefined(selection)) return;
-
- $container.append(editor.render().el);
- });
-
- this.setElement($field);
-
- return this;
- },
-
- /**
- * Check the validity of the field
- *
- * @return {String}
- */
- validate: function() {
- var error = this.editor.validate();
-
- if (error) {
- this.setError(error.message);
- } else {
- this.clearError();
- }
-
- return error;
- },
-
- /**
- * Set the field into an error state, adding the error class and setting the error message
- *
- * @param {String} msg Error message
- */
- setError: function(msg) {
- //Nested form editors (e.g. Object) set their errors internally
- if (this.editor.hasNestedForm) return;
-
- //Add error CSS class
- this.$el.addClass(this.errorClassName);
-
- //Set error message
- this.$('[data-error]').html(msg);
- },
-
- /**
- * Clear the error state and reset the help message
- */
- clearError: function() {
- //Remove error CSS class
- this.$el.removeClass(this.errorClassName);
-
- //Clear error message
- this.$('[data-error]').empty();
- },
-
- /**
- * Update the model with the new value from the editor
- *
- * @return {Mixed}
- */
- commit: function() {
- return this.editor.commit();
- },
-
- /**
- * Get the value from the editor
- *
- * @return {Mixed}
- */
- getValue: function() {
- return this.editor.getValue();
- },
-
- /**
- * Set/change the value of the editor
- *
- * @param {Mixed} value
- */
- setValue: function(value) {
- this.editor.setValue(value);
- },
-
- /**
- * Give the editor focus
- */
- focus: function() {
- this.editor.focus();
- },
-
- /**
- * Remove focus from the editor
- */
- blur: function() {
- this.editor.blur();
- },
-
- /**
- * Remove the field and editor views
- */
- remove: function() {
- this.editor.remove();
-
- Backbone.View.prototype.remove.call(this);
- }
-
-}, {
- //STATICS
-
- template: _.template('\
- <div>\
- <label for="<%= editorId %>"><%= title %></label>\
- <div>\
- <span data-editor></span>\
- <div data-error></div>\
- <div><%= help %></div>\
- </div>\
- </div>\
- ', null, Form.templateSettings),
-
- /**
- * CSS class name added to the field when there is a validation error
- */
- errorClassName: 'error'
-
-});
-
-
-//==================================================================================================
-//NESTEDFIELD
-//==================================================================================================
-
-Form.NestedField = Form.Field.extend({
-
- template: _.template('\
- <div>\
- <span data-editor></span>\
- <% if (help) { %>\
- <div><%= help %></div>\
- <% } %>\
- <div data-error></div>\
- </div>\
- ', null, Form.templateSettings)
-
-});
-
-/**
- * Base editor (interface). To be extended, not used directly
- *
- * @param {Object} options
- * @param {String} [options.id] Editor ID
- * @param {Model} [options.model] Use instead of value, and use commit()
- * @param {String} [options.key] The model attribute key. Required when using 'model'
- * @param {Mixed} [options.value] When not using a model. If neither provided, defaultValue will be used
- * @param {Object} [options.schema] Field schema; may be required by some editors
- * @param {Object} [options.validators] Validators; falls back to those stored on schema
- * @param {Object} [options.form] The form
- */
-Form.Editor = Form.editors.Base = Backbone.View.extend({
-
- defaultValue: null,
-
- hasFocus: false,
-
- initialize: function(options) {
- var options = options || {};
-
- //Set initial value
- if (options.model) {
- if (!options.key) throw new Error("Missing option: 'key'");
-
- this.model = options.model;
-
- this.value = this.model.get(options.key);
- }
- else if (options.value !== undefined) {
- this.value = options.value;
- }
-
- if (this.value === undefined) this.value = this.defaultValue;
-
- //Store important data
- _.extend(this, _.pick(options, 'key', 'form'));
-
- var schema = this.schema = options.schema || {};
-
- this.validators = options.validators || schema.validators;
-
- //Main attributes
- this.$el.attr('id', this.id);
- this.$el.attr('name', this.getName());
- if (schema.editorClass) this.$el.addClass(schema.editorClass);
- if (schema.editorAttrs) this.$el.attr(schema.editorAttrs);
- },
-
- /**
- * Get the value for the form input 'name' attribute
- *
- * @return {String}
- *
- * @api private
- */
- getName: function() {
- var key = this.key || '';
-
- //Replace periods with underscores (e.g. for when using paths)
- return key.replace(/\./g, '_');
- },
-
- /**
- * Get editor value
- * Extend and override this method to reflect changes in the DOM
- *
- * @return {Mixed}
- */
- getValue: function() {
- return this.value;
- },
-
- /**
- * Set editor value
- * Extend and override this method to reflect changes in the DOM
- *
- * @param {Mixed} value
- */
- setValue: function(value) {
- this.value = value;
- },
-
- /**
- * Give the editor focus
- * Extend and override this method
- */
- focus: function() {
- throw new Error('Not implemented');
- },
-
- /**
- * Remove focus from the editor
- * Extend and override this method
- */
- blur: function() {
- throw new Error('Not implemented');
- },
-
- /**
- * Update the model with the current value
- *
- * @param {Object} [options] Options to pass to model.set()
- * @param {Boolean} [options.validate] Set to true to trigger built-in model validation
- *
- * @return {Mixed} error
- */
- commit: function(options) {
- var error = this.validate();
- if (error) return error;
-
- this.listenTo(this.model, 'invalid', function(model, e) {
- error = e;
- });
- this.model.set(this.key, this.getValue(), options);
-
- if (error) return error;
- },
-
- /**
- * Check validity
- *
- * @return {Object|Undefined}
- */
- validate: function() {
- var $el = this.$el,
- error = null,
- value = this.getValue(),
- formValues = this.form ? this.form.getValue() : {},
- validators = this.validators,
- getValidator = this.getValidator;
-
- if (validators) {
- //Run through validators until an error is found
- _.every(validators, function(validator) {
- error = getValidator(validator)(value, formValues);
-
- return error ? false : true;
- });
- }
-
- return error;
- },
-
- /**
- * Set this.hasFocus, or call parent trigger()
- *
- * @param {String} event
- */
- trigger: function(event) {
- if (event === 'focus') {
- this.hasFocus = true;
- }
- else if (event === 'blur') {
- this.hasFocus = false;
- }
-
- return Backbone.View.prototype.trigger.apply(this, arguments);
- },
-
- /**
- * Returns a validation function based on the type defined in the schema
- *
- * @param {RegExp|String|Function} validator
- * @return {Function}
- */
- getValidator: function(validator) {
- var validators = Form.validators;
-
- //Convert regular expressions to validators
- if (_.isRegExp(validator)) {
- return validators.regexp({ regexp: validator });
- }
-
- //Use a built-in validator if given a string
- if (_.isString(validator)) {
- if (!validators[validator]) throw new Error('Validator "'+validator+'" not found');
-
- return validators[validator]();
- }
-
- //Functions can be used directly
- if (_.isFunction(validator)) return validator;
-
- //Use a customised built-in validator if given an object
- if (_.isObject(validator) && validator.type) {
- var config = validator;
-
- return validators[config.type](config);
- }
-
- //Unkown validator type
- throw new Error('Invalid validator: ' + validator);
- }
-});
-
-/**
- * Text
- *
- * Text input with focus, blur and change events
- */
-Form.editors.Text = Form.Editor.extend({
-
- tagName: 'input',
-
- defaultValue: '',
-
- previousValue: '',
-
- events: {
- 'keyup': 'determineChange',
- 'keypress': function(event) {
- var self = this;
- setTimeout(function() {
- self.determineChange();
- }, 0);
- },
- 'select': function(event) {
- this.trigger('select', this);
- },
- 'focus': function(event) {
- this.trigger('focus', this);
- },
- 'blur': function(event) {
- var trimmedVal = $.trim(this.$el.val());
- this.$el.val(trimmedVal);
- this.trigger('blur', this);
- }
- },
-
- initialize: function(options) {
- Form.editors.Base.prototype.initialize.call(this, options);
-
- var schema = this.schema;
-
- //Allow customising text type (email, phone etc.) for HTML5 browsers
- var type = 'text';
-
- if (schema && schema.editorAttrs && schema.editorAttrs.type) type = schema.editorAttrs.type;
- if (schema && schema.dataType) type = schema.dataType;
-
- this.$el.attr('type', type);
- },
-
- /**
- * Adds the editor to the DOM
- */
- render: function() {
- this.setValue(this.value);
-
- return this;
- },
-
- determineChange: function(event) {
- var currentValue = this.$el.val();
- var changed = (currentValue !== this.previousValue);
-
- if (changed) {
- this.previousValue = currentValue;
-
- this.trigger('change', this);
- }
- },
-
- /**
- * Returns the current editor value
- * @return {String}
- */
- getValue: function() {
- return this.$el.val();
- },
-
- /**
- * Sets the value of the form element
- * @param {String}
- */
- setValue: function(value) {
- this.$el.val(value);
- },
-
- focus: function() {
- if (this.hasFocus) return;
-
- this.$el.focus();
- },
-
- blur: function() {
- if (!this.hasFocus) return;
-
- this.$el.blur();
- },
-
- select: function() {
- this.$el.select();
- }
-
-});
-
-/**
- * TextArea editor
- */
-Form.editors.TextArea = Form.editors.Text.extend({
-
- tagName: 'textarea',
-
- /**
- * Override Text constructor so type property isn't set (issue #261)
- */
- initialize: function(options) {
- Form.editors.Base.prototype.initialize.call(this, options);
- }
-
-});
-
-/**
- * Password editor
- */
-Form.editors.Password = Form.editors.Text.extend({
-
- initialize: function(options) {
- Form.editors.Text.prototype.initialize.call(this, options);
-
- this.$el.attr('type', 'password');
- }
-
-});
-
-/**
- * NUMBER
- *
- * Normal text input that only allows a number. Letters etc. are not entered.
- */
-Form.editors.Number = Form.editors.Text.extend({
-
- defaultValue: 0,
-
- events: _.extend({}, Form.editors.Text.prototype.events, {
- 'keypress': 'onKeyPress',
- 'change': 'onKeyPress'
- }),
-
- initialize: function(options) {
- Form.editors.Text.prototype.initialize.call(this, options);
-
- var schema = this.schema;
-
- this.$el.attr('type', 'number');
-
- if (!schema || !schema.editorAttrs || !schema.editorAttrs.step) {
- // provide a default for `step` attr,
- // but don't overwrite if already specified
- this.$el.attr('step', 'any');
- }
- },
-
- /**
- * Check value is numeric
- */
- onKeyPress: function(event) {
- var self = this,
- delayedDetermineChange = function() {
- setTimeout(function() {
- self.determineChange();
- }, 0);
- };
-
- //Allow backspace
- if (event.charCode === 0) {
- delayedDetermineChange();
- return;
- }
-
- //Get the whole new value so that we can prevent things like double decimals points etc.
- var newVal = this.$el.val()
- if( event.charCode != undefined ) {
- newVal = newVal + String.fromCharCode(event.charCode);
- }
-
- var numeric = /^[0-9]*\.?[0-9]*?$/.test(newVal);
-
- if (numeric) {
- delayedDetermineChange();
- }
- else {
- event.preventDefault();
- }
- },
-
- getValue: function() {
- var value = this.$el.val();
-
- return value === "" ? null : parseFloat(value, 10);
- },
-
- setValue: function(value) {
- value = (function() {
- if (_.isNumber(value)) return value;
-
- if (_.isString(value) && value !== '') return parseFloat(value, 10);
-
- return null;
- })();
-
- if (_.isNaN(value)) value = null;
-
- Form.editors.Text.prototype.setValue.call(this, value);
- }
-
-});
-
-/**
- * Hidden editor
- */
-Form.editors.Hidden = Form.editors.Text.extend({
-
- defaultValue: '',
-
- initialize: function(options) {
- Form.editors.Text.prototype.initialize.call(this, options);
-
- this.$el.attr('type', 'hidden');
- },
-
- focus: function() {
-
- },
-
- blur: function() {
-
- }
-
-});
-
-/**
- * Checkbox editor
- *
- * Creates a single checkbox, i.e. boolean value
- */
-Form.editors.Checkbox = Form.editors.Base.extend({
-
- defaultValue: false,
-
- tagName: 'input',
-
- events: {
- 'click': function(event) {
- this.trigger('change', this);
- },
- 'focus': function(event) {
- this.trigger('focus', this);
- },
- 'blur': function(event) {
- this.trigger('blur', this);
- }
- },
-
- initialize: function(options) {
- Form.editors.Base.prototype.initialize.call(this, options);
-
- this.$el.attr('type', 'checkbox');
- },
-
- /**
- * Adds the editor to the DOM
- */
- render: function() {
- this.setValue(this.value);
-
- return this;
- },
-
- getValue: function() {
- return this.$el.prop('checked');
- },
-
- setValue: function(value) {
- if (value) {
- this.$el.prop('checked', true);
- }else{
- this.$el.prop('checked', false);
- }
- },
-
- focus: function() {
- if (this.hasFocus) return;
-
- this.$el.focus();
- },
-
- blur: function() {
- if (!this.hasFocus) return;
-
- this.$el.blur();
- }
-
-});
-
-/**
- * Select editor
- *
- * Renders a <select> with given options
- *
- * Requires an 'options' value on the schema.
- * Can be an array of options, a function that calls back with the array of options, a string of HTML
- * or a Backbone collection. If a collection, the models must implement a toString() method
- */
-Form.editors.Select = Form.editors.Base.extend({
-
- tagName: 'select',
-
- previousValue: '',
-
- events: {
- 'keyup': 'determineChange',
- 'keypress': function(event) {
- var self = this;
- setTimeout(function() {
- self.determineChange();
- }, 0);
- },
- 'change': function(event) {
- this.trigger('change', this);
- },
- 'focus': function(event) {
- this.trigger('focus', this);
- },
- 'blur': function(event) {
- this.trigger('blur', this);
- }
- },
-
- initialize: function(options) {
- Form.editors.Base.prototype.initialize.call(this, options);
-
- if (!this.schema || !this.schema.options) throw new Error("Missing required 'schema.options'");
- },
-
- render: function() {
- this.setOptions(this.schema.options);
-
- return this;
- },
-
- /**
- * Sets the options that populate the <select>
- *
- * @param {Mixed} options
- */
- setOptions: function(options) {
- var self = this;
-
- //If a collection was passed, check if it needs fetching
- if (options instanceof Backbone.Collection) {
- var collection = options;
-
- //Don't do the fetch if it's already populated
- if (collection.length > 0) {
- this.renderOptions(options);
- } else {
- collection.fetch({
- success: function(collection) {
- self.renderOptions(options);
- }
- });
- }
- }
-
- //If a function was passed, run it to get the options
- else if (_.isFunction(options)) {
- options(function(result) {
- self.renderOptions(result);
- }, self);
- }
-
- //Otherwise, ready to go straight to renderOptions
- else {
- this.renderOptions(options);
- }
- },
-
- /**
- * Adds the <option> html to the DOM
- * @param {Mixed} Options as a simple array e.g. ['option1', 'option2']
- * or as an array of objects e.g. [{val: 543, label: 'Title for object 543'}]
- * or as a string of <option> HTML to insert into the <select>
- * or any object
- */
- renderOptions: function(options) {
- var $select = this.$el,
- html;
-
- html = this._getOptionsHtml(options);
-
- //Insert options
- $select.html(html);
-
- //Select correct option
- this.setValue(this.value);
- },
-
- _getOptionsHtml: function(options) {
- var html;
- //Accept string of HTML
- if (_.isString(options)) {
- html = options;
- }
-
- //Or array
- else if (_.isArray(options)) {
- html = this._arrayToHtml(options);
- }
-
- //Or Backbone collection
- else if (options instanceof Backbone.Collection) {
- html = this._collectionToHtml(options);
- }
-
- else if (_.isFunction(options)) {
- var newOptions;
-
- options(function(opts) {
- newOptions = opts;
- }, this);
-
- html = this._getOptionsHtml(newOptions);
- //Or any object
- }else{
- html=this._objectToHtml(options);
- }
-
- return html;
- },
-
- determineChange: function(event) {
- var currentValue = this.getValue();
- var changed = (currentValue !== this.previousValue);
-
- if (changed) {
- this.previousValue = currentValue;
-
- this.trigger('change', this);
- }
- },
-
- getValue: function() {
- return this.$el.val();
- },
-
- setValue: function(value) {
- this.$el.val(value);
- },
-
- focus: function() {
- if (this.hasFocus) return;
-
- this.$el.focus();
- },
-
- blur: function() {
- if (!this.hasFocus) return;
-
- this.$el.blur();
- },
-
- /**
- * Transforms a collection into HTML ready to use in the renderOptions method
- * @param {Backbone.Collection}
- * @return {String}
- */
- _collectionToHtml: function(collection) {
- //Convert collection to array first
- var array = [];
- collection.each(function(model) {
- array.push({ val: model.id, label: model.toString() });
- });
-
- //Now convert to HTML
- var html = this._arrayToHtml(array);
-
- return html;
- },
- /**
- * Transforms an object into HTML ready to use in the renderOptions method
- * @param {Object}
- * @return {String}
- */
- _objectToHtml: function(obj) {
- //Convert object to array first
- var array = [];
- for(var key in obj){
- if( obj.hasOwnProperty( key ) ) {
- array.push({ val: key, label: obj[key] });
- }
- }
-
- //Now convert to HTML
- var html = this._arrayToHtml(array);
-
- return html;
- },
-
-
-
- /**
- * Create the <option> HTML
- * @param {Array} Options as a simple array e.g. ['option1', 'option2']
- * or as an array of objects e.g. [{val: 543, label: 'Title for object 543'}]
- * @return {String} HTML
- */
- _arrayToHtml: function(array) {
- var html = [];
-
- //Generate HTML
- _.each(array, function(option) {
- if (_.isObject(option)) {
- if (option.group) {
- html.push('<optgroup label="'+option.group+'">');
- html.push(this._getOptionsHtml(option.options))
- html.push('</optgroup>');
- } else {
- var val = (option.val || option.val === 0) ? option.val : '';
- html.push('<option value="'+val+'">'+option.label+'</option>');
- }
- }
- else {
- html.push('<option>'+option+'</option>');
- }
- }, this);
-
- return html.join('');
- }
-
-});
-
-/**
- * Radio editor
- *
- * Renders a <ul> with given options represented as <li> objects containing radio buttons
- *
- * Requires an 'options' value on the schema.
- * Can be an array of options, a function that calls back with the array of options, a string of HTML
- * or a Backbone collection. If a collection, the models must implement a toString() method
- */
-Form.editors.Radio = Form.editors.Select.extend({
-
- tagName: 'div',
-
- events: {
- 'change input[type=radio]': function() {
- this.trigger('change', this);
- },
- 'focus input[type=radio]': function() {
- if (this.hasFocus) return;
- this.trigger('focus', this);
- },
- 'blur input[type=radio]': function() {
- if (!this.hasFocus) return;
- var self = this;
- setTimeout(function() {
- if (self.$('input[type=radio]:focus')[0]) return;
- self.trigger('blur', self);
- }, 0);
- }
- },
-
- /**
- * Returns the template. Override for custom templates
- *
- * @return {Function} Compiled template
- */
- getTemplate: function() {
- return this.schema.template || this.constructor.template;
- },
-
- getValue: function() {
- return this.$('input[type=radio]:checked').val();
- },
-
- setValue: function(value) {
- this.$('input[type=radio]').val([value]);
- },
-
- focus: function() {
- if (this.hasFocus) return;
-
- var checked = this.$('input[type=radio]:checked');
- if (checked[0]) {
- checked.focus();
- return;
- }
-
- this.$('input[type=radio]').first().focus();
- },
-
- blur: function() {
- if (!this.hasFocus) return;
-
- this.$('input[type=radio]:focus').blur();
- },
-
- /**
- * Create the radio list HTML
- * @param {Array} Options as a simple array e.g. ['option1', 'option2']
- * or as an array of objects e.g. [{val: 543, label: 'Title for object 543'}]
- * @return {String} HTML
- */
- _arrayToHtml: function (array) {
- var self = this;
-
- var template = this.getTemplate(),
- name = self.getName(),
- id = self.id;
-
- var items = _.map(array, function(option, index) {
- var item = {
- name: name,
- id: id + '-' + index
- }
-
- if (_.isObject(option)) {
- item.value = (option.val || option.val === 0) ? option.val : '';
- item.label = option.label;
- } else {
- item.value = option;
- item.label = option;
- }
-
- return item;
- });
-
- return template({ items: items });
- }
-
-}, {
-
- //STATICS
- template: _.template('\
- <% _.each(items, function(item) { %>\
- <div class="form-check form-check-inline">\
- <input class="form-check-input" type="radio" name="<%= item.name %>" value="<%= item.value %>" id="<%= item.id %>" />\
- <label class="form-check-label" for="<%= item.id %>"><%= item.label %></label>\
- </div>\
- <% }); %>\
- ', null, Form.templateSettings)
-
-});
-
-/**
- * Checkboxes editor
- *
- * Renders a <ul> with given options represented as <li> objects containing checkboxes
- *
- * Requires an 'options' value on the schema.
- * Can be an array of options, a function that calls back with the array of options, a string of HTML
- * or a Backbone collection. If a collection, the models must implement a toString() method
- */
-Form.editors.Checkboxes = Form.editors.Select.extend({
-
- tagName: 'ul',
-
- groupNumber: 0,
-
- events: {
- 'click input[type=checkbox]': function() {
- this.trigger('change', this);
- },
- 'focus input[type=checkbox]': function() {
- if (this.hasFocus) return;
- this.trigger('focus', this);
- },
- 'blur input[type=checkbox]': function() {
- if (!this.hasFocus) return;
- var self = this;
- setTimeout(function() {
- if (self.$('input[type=checkbox]:focus')[0]) return;
- self.trigger('blur', self);
- }, 0);
- }
- },
-
- getValue: function() {
- var values = [];
- this.$('input[type=checkbox]:checked').each(function() {
- values.push($(this).val());
- });
- return values;
- },
-
- setValue: function(values) {
- if (!_.isArray(values)) values = [values];
- this.$('input[type=checkbox]').val(values);
- },
-
- focus: function() {
- if (this.hasFocus) return;
-
- this.$('input[type=checkbox]').first().focus();
- },
-
- blur: function() {
- if (!this.hasFocus) return;
-
- this.$('input[type=checkbox]:focus').blur();
- },
-
- /**
- * Create the checkbox list HTML
- * @param {Array} Options as a simple array e.g. ['option1', 'option2']
- * or as an array of objects e.g. [{val: 543, label: 'Title for object 543'}]
- * @return {String} HTML
- */
- _arrayToHtml: function (array) {
- var html = [];
- var self = this;
-
- _.each(array, function(option, index) {
- var itemHtml = '<li>';
- var close = true;
- if (_.isObject(option)) {
- if (option.group) {
- var originalId = self.id;
- self.id += "-" + self.groupNumber++;
- itemHtml = ('<fieldset class="group"> <legend>'+option.group+'</legend>');
- itemHtml += (self._arrayToHtml(option.options));
- itemHtml += ('</fieldset>');
- self.id = originalId;
- close = false;
- }else{
- var val = (option.val || option.val === 0) ? option.val : '';
- itemHtml += ('<input type="checkbox" name="'+self.getName()+'" value="'+val+'" id="'+self.id+'-'+index+'" />');
- itemHtml += ('<label for="'+self.id+'-'+index+'">'+option.label+'</label>');
- }
- }
- else {
- itemHtml += ('<input type="checkbox" name="'+self.getName()+'" value="'+option+'" id="'+self.id+'-'+index+'" />');
- itemHtml += ('<label for="'+self.id+'-'+index+'">'+option+'</label>');
- }
- if(close){
- itemHtml += '</li>';
- }
- html.push(itemHtml);
- });
-
- return html.join('');
- }
-
-});
-
-/**
- * Object editor
- *
- * Creates a child form. For editing Javascript objects
- *
- * @param {Object} options
- * @param {Form} options.form The form this editor belongs to; used to determine the constructor for the nested form
- * @param {Object} options.schema The schema for the object
- * @param {Object} options.schema.subSchema The schema for the nested form
- */
-Form.editors.Object = Form.editors.Base.extend({
- //Prevent error classes being set on the main control; they are internally on the individual fields
- hasNestedForm: true,
-
- initialize: function(options) {
- //Set default value for the instance so it's not a shared object
- this.value = {};
-
- //Init
- Form.editors.Base.prototype.initialize.call(this, options);
-
- //Check required options
- if (!this.form) throw new Error('Missing required option "form"');
- if (!this.schema.subSchema) throw new Error("Missing required 'schema.subSchema' option for Object editor");
- },
-
- render: function() {
- //Get the constructor for creating the nested form; i.e. the same constructor as used by the parent form
- var NestedForm = this.form.constructor;
-
- //Create the nested form
- this.nestedForm = new NestedForm({
- schema: this.schema.subSchema,
- data: this.value,
- idPrefix: this.id + '_',
- Field: NestedForm.NestedField
- });
-
- this._observeFormEvents();
-
- this.$el.html(this.nestedForm.render().el);
-
- if (this.hasFocus) this.trigger('blur', this);
-
- return this;
- },
-
- getValue: function() {
- if (this.nestedForm) return this.nestedForm.getValue();
-
- return this.value;
- },
-
- setValue: function(value) {
- this.value = value;
-
- this.render();
- },
-
- focus: function() {
- if (this.hasFocus) return;
-
- this.nestedForm.focus();
- },
-
- blur: function() {
- if (!this.hasFocus) return;
-
- this.nestedForm.blur();
- },
-
- remove: function() {
- this.nestedForm.remove();
-
- Backbone.View.prototype.remove.call(this);
- },
-
- validate: function() {
- return this.nestedForm.validate();
- },
-
- _observeFormEvents: function() {
- if (!this.nestedForm) return;
-
- this.nestedForm.on('all', function() {
- // args = ["key:change", form, fieldEditor]
- var args = _.toArray(arguments);
- args[1] = this;
- // args = ["key:change", this=objectEditor, fieldEditor]
-
- this.trigger.apply(this, args);
- }, this);
- }
-
-});
-
-/**
- * NestedModel editor
- *
- * Creates a child form. For editing nested Backbone models
- *
- * Special options:
- * schema.model: Embedded model constructor
- */
-Form.editors.NestedModel = Form.editors.Object.extend({
- initialize: function(options) {
- Form.editors.Base.prototype.initialize.call(this, options);
-
- if (!this.form) throw new Error('Missing required option "form"');
- if (!options.schema.model) throw new Error('Missing required "schema.model" option for NestedModel editor');
- },
-
- render: function() {
- //Get the constructor for creating the nested form; i.e. the same constructor as used by the parent form
- var NestedForm = this.form.constructor;
-
- var data = this.value || {},
- key = this.key,
- nestedModel = this.schema.model;
-
- //Wrap the data in a model if it isn't already a model instance
- var modelInstance = (data.constructor === nestedModel) ? data : new nestedModel(data);
-
- this.nestedForm = new NestedForm({
- model: modelInstance,
- idPrefix: this.id + '_',
- fieldTemplate: 'nestedField'
- });
-
- this._observeFormEvents();
-
- //Render form
- this.$el.html(this.nestedForm.render().el);
-
- if (this.hasFocus) this.trigger('blur', this);
-
- return this;
- },
-
- /**
- * Update the embedded model, checking for nested validation errors and pass them up
- * Then update the main model if all OK
- *
- * @return {Error|null} Validation error or null
- */
- commit: function() {
- var error = this.nestedForm.commit();
- if (error) {
- this.$el.addClass('error');
- return error;
- }
-
- return Form.editors.Object.prototype.commit.call(this);
- }
-
-});
-
-/**
- * Date editor
- *
- * Schema options
- * @param {Number|String} [options.schema.yearStart] First year in list. Default: 100 years ago
- * @param {Number|String} [options.schema.yearEnd] Last year in list. Default: current year
- *
- * Config options (if not set, defaults to options stored on the main Date class)
- * @param {Boolean} [options.showMonthNames] Use month names instead of numbers. Default: true
- * @param {String[]} [options.monthNames] Month names. Default: Full English names
- */
-Form.editors.Date = Form.editors.Base.extend({
-
- events: {
- 'change select': function() {
- this.updateHidden();
- this.trigger('change', this);
- },
- 'focus select': function() {
- if (this.hasFocus) return;
- this.trigger('focus', this);
- },
- 'blur select': function() {
- if (!this.hasFocus) return;
- var self = this;
- setTimeout(function() {
- if (self.$('select:focus')[0]) return;
- self.trigger('blur', self);
- }, 0);
- }
- },
-
- initialize: function(options) {
- options = options || {};
-
- Form.editors.Base.prototype.initialize.call(this, options);
-
- var Self = Form.editors.Date,
- today = new Date();
-
- //Option defaults
- this.options = _.extend({
- monthNames: Self.monthNames,
- showMonthNames: Self.showMonthNames
- }, options);
-
- //Schema defaults
- this.schema = _.extend({
- yearStart: today.getFullYear() - 100,
- yearEnd: today.getFullYear()
- }, options.schema || {});
-
- //Cast to Date
- if (this.value && !_.isDate(this.value)) {
- this.value = new Date(this.value);
- }
-
- //Set default date
- if (!this.value) {
- var date = new Date();
- date.setSeconds(0);
- date.setMilliseconds(0);
-
- this.value = date;
- }
-
- //Template
- this.template = options.template || this.constructor.template;
- },
-
- render: function() {
- var options = this.options,
- schema = this.schema,
- $ = Backbone.$;
-
- var datesOptions = _.map(_.range(1, 32), function(date) {
- return '<option value="'+date+'">' + date + '</option>';
- });
-
- var monthsOptions = _.map(_.range(0, 12), function(month) {
- var value = (options.showMonthNames)
- ? options.monthNames[month]
- : (month + 1);
-
- return '<option value="'+month+'">' + value + '</option>';
- });
-
- var yearRange = (schema.yearStart < schema.yearEnd)
- ? _.range(schema.yearStart, schema.yearEnd + 1)
- : _.range(schema.yearStart, schema.yearEnd - 1, -1);
-
- var yearsOptions = _.map(yearRange, function(year) {
- return '<option value="'+year+'">' + year + '</option>';
- });
-
- //Render the selects
- var $el = $($.trim(this.template({
- dates: datesOptions.join(''),
- months: monthsOptions.join(''),
- years: yearsOptions.join('')
- })));
-
- //Store references to selects
- this.$date = $el.find('[data-type="date"]');
- this.$month = $el.find('[data-type="month"]');
- this.$year = $el.find('[data-type="year"]');
-
- //Create the hidden field to store values in case POSTed to server
- this.$hidden = $('<input type="hidden" name="'+this.key+'" />');
- $el.append(this.$hidden);
-
- //Set value on this and hidden field
- this.setValue(this.value);
-
- //Remove the wrapper tag
- this.setElement($el);
- this.$el.attr('id', this.id);
- this.$el.attr('name', this.getName());
-
- if (this.hasFocus) this.trigger('blur', this);
-
- return this;
- },
-
- /**
- * @return {Date} Selected date
- */
- getValue: function() {
- var year = this.$year.val(),
- month = this.$month.val(),
- date = this.$date.val();
-
- if (!year || !month || !date) return null;
-
- return new Date(year, month, date);
- },
-
- /**
- * @param {Date} date
- */
- setValue: function(date) {
- this.$date.val(date.getDate());
- this.$month.val(date.getMonth());
- this.$year.val(date.getFullYear());
-
- this.updateHidden();
- },
-
- focus: function() {
- if (this.hasFocus) return;
-
- this.$('select').first().focus();
- },
-
- blur: function() {
- if (!this.hasFocus) return;
-
- this.$('select:focus').blur();
- },
-
- /**
- * Update the hidden input which is maintained for when submitting a form
- * via a normal browser POST
- */
- updateHidden: function() {
- var val = this.getValue();
-
- if (_.isDate(val)) val = val.toISOString();
-
- this.$hidden.val(val);
- }
-
-}, {
- //STATICS
- template: _.template('\
- <div>\
- <select data-type="date"><%= dates %></select>\
- <select data-type="month"><%= months %></select>\
- <select data-type="year"><%= years %></select>\
- </div>\
- ', null, Form.templateSettings),
-
- //Whether to show month names instead of numbers
- showMonthNames: true,
-
- //Month names to use if showMonthNames is true
- //Replace for localisation, e.g. Form.editors.Date.monthNames = ['Janvier', 'Fevrier'...]
- monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
-});
-
-/**
- * DateTime editor
- *
- * @param {Editor} [options.DateEditor] Date editor view to use (not definition)
- * @param {Number} [options.schema.minsInterval] Interval between minutes. Default: 15
- */
-Form.editors.DateTime = Form.editors.Base.extend({
-
- events: {
- 'change select': function() {
- this.updateHidden();
- this.trigger('change', this);
- },
- 'focus select': function() {
- if (this.hasFocus) return;
- this.trigger('focus', this);
- },
- 'blur select': function() {
- if (!this.hasFocus) return;
- var self = this;
- setTimeout(function() {
- if (self.$('select:focus')[0]) return;
- self.trigger('blur', self);
- }, 0);
- }
- },
-
- initialize: function(options) {
- options = options || {};
-
- Form.editors.Base.prototype.initialize.call(this, options);
-
- //Option defaults
- this.options = _.extend({
- DateEditor: Form.editors.DateTime.DateEditor
- }, options);
-
- //Schema defaults
- this.schema = _.extend({
- minsInterval: 15
- }, options.schema || {});
-
- //Create embedded date editor
- this.dateEditor = new this.options.DateEditor(options);
-
- this.value = this.dateEditor.value;
-
- //Template
- this.template = options.template || this.constructor.template;
- },
-
- render: function() {
- function pad(n) {
- return n < 10 ? '0' + n : n;
- }
-
- var schema = this.schema,
- $ = Backbone.$;
-
- //Create options
- var hoursOptions = _.map(_.range(0, 24), function(hour) {
- return '<option value="'+hour+'">' + pad(hour) + '</option>';
- });
-
- var minsOptions = _.map(_.range(0, 60, schema.minsInterval), function(min) {
- return '<option value="'+min+'">' + pad(min) + '</option>';
- });
-
- //Render time selects
- var $el = $($.trim(this.template({
- hours: hoursOptions.join(),
- mins: minsOptions.join()
- })));
-
- //Include the date editor
- $el.find('[data-date]').append(this.dateEditor.render().el);
-
- //Store references to selects
- this.$hour = $el.find('select[data-type="hour"]');
- this.$min = $el.find('select[data-type="min"]');
-
- //Get the hidden date field to store values in case POSTed to server
- this.$hidden = $el.find('input[type="hidden"]');
-
- //Set time
- this.setValue(this.value);
-
- this.setElement($el);
- this.$el.attr('id', this.id);
- this.$el.attr('name', this.getName());
-
- if (this.hasFocus) this.trigger('blur', this);
-
- return this;
- },
-
- /**
- * @return {Date} Selected datetime
- */
- getValue: function() {
- var date = this.dateEditor.getValue();
-
- var hour = this.$hour.val(),
- min = this.$min.val();
-
- if (!date || !hour || !min) return null;
-
- date.setHours(hour);
- date.setMinutes(min);
-
- return date;
- },
-
- /**
- * @param {Date}
- */
- setValue: function(date) {
- if (!_.isDate(date)) date = new Date(date);
-
- this.dateEditor.setValue(date);
-
- this.$hour.val(date.getHours());
- this.$min.val(date.getMinutes());
-
- this.updateHidden();
- },
-
- focus: function() {
- if (this.hasFocus) return;
-
- this.$('select').first().focus();
- },
-
- blur: function() {
- if (!this.hasFocus) return;
-
- this.$('select:focus').blur();
- },
-
- /**
- * Update the hidden input which is maintained for when submitting a form
- * via a normal browser POST
- */
- updateHidden: function() {
- var val = this.getValue();
- if (_.isDate(val)) val = val.toISOString();
-
- this.$hidden.val(val);
- },
-
- /**
- * Remove the Date editor before removing self
- */
- remove: function() {
- this.dateEditor.remove();
-
- Form.editors.Base.prototype.remove.call(this);
- }
-
-}, {
- //STATICS
- template: _.template('\
- <div class="bbf-datetime">\
- <div class="bbf-date-container" data-date></div>\
- <select data-type="hour"><%= hours %></select>\
- :\
- <select data-type="min"><%= mins %></select>\
- </div>\
- ', null, Form.templateSettings),
-
- //The date editor to use (constructor function, not instance)
- DateEditor: Form.editors.Date
-});
-
-
-
- //Metadata
- Form.VERSION = '0.14.1';
-
- //Exports
- Backbone.Form = Form;
-
- return Form;
-});
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/libs/bower/backbone-forms/js/backbone-forms.min.js b/security-admin/src/main/webapp/libs/bower/backbone-forms/js/backbone-forms.min.js
deleted file mode 100644
index 40c9b0129..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone-forms/js/backbone-forms.min.js
+++ /dev/null
@@ -1 +0,0 @@
-define(["jquery","underscore","backbone"],function(e,t,n){var r=n.View.extend({events:{submit:function(e){this.trigger("submit",e)}},initialize:function(e){var n=this;e=this.options=t.extend({submitButton:!1},e);var r=this.schema=function(){if(e.schema)return t.result(e,"schema");var r=e.model;return r&&r.schema?t.result(r,"schema"):n.schema?t.result(n,"schema"):{}}();t.extend(this,t.pick(e,"model","data","idPrefix","templateData"));var i=this.constructor;this.template=e.template||this.t [...]
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/libs/bower/backbone-forms/js/bootstrap.js b/security-admin/src/main/webapp/libs/bower/backbone-forms/js/bootstrap.js
deleted file mode 100644
index 7e14fdeb3..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone-forms/js/bootstrap.js
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * Include this template file after backbone-forms.amd.js to override the default templates
- *
- * 'data-*' attributes control where elements are placed
- */
-define(['jquery', 'underscore', 'backbone', 'backbone-forms'], function($, _, Backbone) {
- var Form = Backbone.Form;
-
-
- /**
- * Bootstrap 3 templates
- */
- Form.template = _.template('\
- <form class="form-horizontal" role="form">\
- <div data-fieldsets></div>\
- <% if (submitButton) { %>\
- <button type="submit" class="btn"><%= submitButton %></button>\
- <% } %>\
- </form>\
- ');
-
-
- Form.Fieldset.template = _.template('\
- <fieldset data-fields>\
- <% if (legend) { %>\
- <legend><%= legend %></legend>\
- <% } %>\
- </fieldset>\
- ');
-
-
- Form.Field.template = _.template('\
- <div class="form-group field-<%= key %>">\
- <label class="col-sm-3 control-label" for="<%= editorId %>"><%= title %></label>\
- <div class="col-sm-4">\
- <span data-editor></span>\
- <p class="help-block" data-error></p>\
- <p class="help-block"><%= help %></p>\
- </div>\
- </div>\
- ');
-
-
- Form.NestedField.template = _.template('\
- <div class="field-<%= key %>">\
- <div title="<%= title %>" class="input-xlarge">\
- <span data-editor></span>\
- <div class="help-inline" data-error></div>\
- </div>\
- <div class="help-block"><%= help %></div>\
- </div>\
- ');
-
- Form.editors.Base.prototype.className = 'form-control';
- Form.Field.errorClassName = 'has-error';
-
-
- if (Form.editors.List) {
-
- Form.editors.List.template = _.template('\
- <div class="bbf-list">\
- <ul class="list-unstyled clearfix" data-items></ul>\
- <button type="button" class="btn bbf-add" data-action="add">Add</button>\
- </div>\
- ');
-
-
- Form.editors.List.Item.template = _.template('\
- <li class="clearfix">\
- <div class="pull-left" data-editor></div>\
- <button type="button" class="btn bbf-del" data-action="remove">×</button>\
- </li>\
- ');
-
-
- Form.editors.List.Object.template = Form.editors.List.NestedModel.template = _.template('\
- <div class="bbf-list-modal"><%= summary %></div>\
- ');
-
- }
-
-
-});
diff --git a/security-admin/src/main/webapp/libs/bower/backbone-forms/js/list.js b/security-admin/src/main/webapp/libs/bower/backbone-forms/js/list.js
deleted file mode 100644
index 48439c0d7..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone-forms/js/list.js
+++ /dev/null
@@ -1,658 +0,0 @@
-define(['jquery', 'underscore', 'backbone', 'backbone-forms'], function($, _, Backbone) {
-
- ;(function(Form) {
-
- /**
- * List editor
- *
- * An array editor. Creates a list of other editor items.
- *
- * Special options:
- * @param {String} [options.schema.itemType] The editor type for each item in the list. Default: 'Text'
- * @param {String} [options.schema.confirmDelete] Text to display in a delete confirmation dialog. If falsey, will not ask for confirmation.
- */
- Form.editors.List = Form.editors.Base.extend({
-
- events: {
- 'click [data-action="add"]': function(event) {
- event.preventDefault();
- this.addItem(null, true);
- }
- },
-
- initialize: function(options) {
- options = options || {};
-
- var editors = Form.editors;
-
- editors.Base.prototype.initialize.call(this, options);
-
- var schema = this.schema;
- if (!schema) throw new Error("Missing required option 'schema'");
-
- this.template = options.template || this.constructor.template;
-
- //Determine the editor to use
- this.Editor = (function() {
- var type = schema.itemType;
-
- //Default to Text
- if (!type) return editors.Text;
-
- //Use List-specific version if available
- if (editors.List[type]) return editors.List[type];
-
- //Or whichever was passed
- return editors[type];
- })();
-
- this.items = [];
- },
-
- render: function() {
- var self = this,
- value = this.value || [],
- $ = Backbone.$;
-
- //Create main element
- var $el = $($.trim(this.template()));
-
- //Store a reference to the list (item container)
- this.$list = $el.is('[data-items]') ? $el : $el.find('[data-items]');
-
- //Add existing items
- if (value.length) {
- _.each(value, function(itemValue) {
- self.addItem(itemValue);
- });
- }
-
- //If no existing items create an empty one, unless the editor specifies otherwise
- else {
- if (!this.Editor.isAsync) this.addItem();
- }
-
- this.setElement($el);
- this.$el.attr('id', this.id);
- this.$el.attr('name', this.key);
-
- if (this.hasFocus) this.trigger('blur', this);
-
- return this;
- },
-
- /**
- * Add a new item to the list
- * @param {Mixed} [value] Value for the new item editor
- * @param {Boolean} [userInitiated] If the item was added by the user clicking 'add'
- */
- addItem: function(value, userInitiated) {
- var self = this,
- editors = Form.editors;
-
- //Create the item
- var item = new editors.List.Item({
- list: this,
- form: this.form,
- schema: this.schema,
- value: value,
- Editor: this.Editor,
- key: this.key
- }).render();
-
- var _addItem = function() {
- self.items.push(item);
- self.$list.append(item.el);
-
- item.editor.on('all', function(event) {
- if (event === 'change') return;
-
- // args = ["key:change", itemEditor, fieldEditor]
- var args = _.toArray(arguments);
- args[0] = 'item:' + event;
- args.splice(1, 0, self);
- // args = ["item:key:change", this=listEditor, itemEditor, fieldEditor]
-
- editors.List.prototype.trigger.apply(this, args);
- }, self);
-
- item.editor.on('change', function() {
- if (!item.addEventTriggered) {
- item.addEventTriggered = true;
- this.trigger('add', this, item.editor);
- }
- this.trigger('item:change', this, item.editor);
- this.trigger('change', this);
- }, self);
-
- item.editor.on('focus', function() {
- if (this.hasFocus) return;
- this.trigger('focus', this);
- }, self);
- item.editor.on('blur', function() {
- if (!this.hasFocus) return;
- var self = this;
- setTimeout(function() {
- if (_.find(self.items, function(item) { return item.editor.hasFocus; })) return;
- self.trigger('blur', self);
- }, 0);
- }, self);
-
- if (userInitiated || value) {
- item.addEventTriggered = true;
- }
-
- if (userInitiated) {
- self.trigger('add', self, item.editor);
- self.trigger('change', self);
- }
- };
-
- //Check if we need to wait for the item to complete before adding to the list
- if (this.Editor.isAsync) {
- item.editor.on('readyToAdd', _addItem, this);
- }
-
- //Most editors can be added automatically
- else {
- _addItem();
- item.editor.focus();
- }
-
- return item;
- },
-
- /**
- * Remove an item from the list
- * @param {List.Item} item
- */
- removeItem: function(item) {
- //Confirm delete
- var confirmMsg = this.schema.confirmDelete;
- if (confirmMsg && !confirm(confirmMsg)) return;
-
- var index = _.indexOf(this.items, item);
-
- this.items[index].remove();
- this.items.splice(index, 1);
-
- if (item.addEventTriggered) {
- this.trigger('remove', this, item.editor);
- this.trigger('change', this);
- }
-
- if (!this.items.length && !this.Editor.isAsync) this.addItem();
- },
-
- getValue: function() {
- var values = _.map(this.items, function(item) {
- return item.getValue();
- });
-
- //Filter empty items
- return _.without(values, undefined, '');
- },
-
- setValue: function(value) {
- this.value = value;
- this.render();
- },
-
- focus: function() {
- if (this.hasFocus) return;
-
- if (this.items[0]) this.items[0].editor.focus();
- },
-
- blur: function() {
- if (!this.hasFocus) return;
-
- var focusedItem = _.find(this.items, function(item) { return item.editor.hasFocus; });
-
- if (focusedItem) focusedItem.editor.blur();
- },
-
- /**
- * Override default remove function in order to remove item views
- */
- remove: function() {
- _.invoke(this.items, 'remove');
-
- Form.editors.Base.prototype.remove.call(this);
- },
-
- /**
- * Run validation
- *
- * @return {Object|Null}
- */
- validate: function() {
- if (!this.validators) return null;
-
- //Collect errors
- var errors = _.map(this.items, function(item) {
- return item.validate();
- });
-
- //Check if any item has errors
- var hasErrors = _.compact(errors).length ? true : false;
- if (!hasErrors) return null;
-
- //If so create a shared error
- var fieldError = {
- type: 'list',
- message: 'Some of the items in the list failed validation',
- errors: errors
- };
-
- return fieldError;
- }
- }, {
-
- //STATICS
- template: _.template('\
- <div>\
- <div data-items></div>\
- <button type="button" data-action="add">Add</button>\
- </div>\
- ', null, Form.templateSettings)
-
- });
-
-
- /**
- * A single item in the list
- *
- * @param {editors.List} options.list The List editor instance this item belongs to
- * @param {Function} options.Editor Editor constructor function
- * @param {String} options.key Model key
- * @param {Mixed} options.value Value
- * @param {Object} options.schema Field schema
- */
- Form.editors.List.Item = Form.editors.Base.extend({
-
- events: {
- 'click [data-action="remove"]': function(event) {
- event.preventDefault();
- this.list.removeItem(this);
- },
- 'keydown input[type=text]': function(event) {
- if(event.keyCode !== 13) return;
- event.preventDefault();
- this.list.addItem();
- this.list.$list.find("> li:last input").focus();
- }
- },
-
- initialize: function(options) {
- this.list = options.list;
- this.schema = options.schema || this.list.schema;
- this.value = options.value;
- this.Editor = options.Editor || Form.editors.Text;
- this.key = options.key;
- this.template = options.template || this.schema.itemTemplate || this.constructor.template;
- this.errorClassName = options.errorClassName || this.constructor.errorClassName;
- this.form = options.form;
- },
-
- render: function() {
- var $ = Backbone.$;
-
- //Create editor
- this.editor = new this.Editor({
- key: this.key,
- schema: this.schema,
- value: this.value,
- list: this.list,
- item: this,
- form: this.form
- }).render();
-
- //Create main element
- var $el = $($.trim(this.template()));
-
- $el.find('[data-editor]').append(this.editor.el);
-
- //Replace the entire element so there isn't a wrapper tag
- this.setElement($el);
-
- return this;
- },
-
- getValue: function() {
- return this.editor.getValue();
- },
-
- setValue: function(value) {
- this.editor.setValue(value);
- },
-
- focus: function() {
- this.editor.focus();
- },
-
- blur: function() {
- this.editor.blur();
- },
-
- remove: function() {
- this.editor.remove();
-
- Backbone.View.prototype.remove.call(this);
- },
-
- validate: function() {
- var value = this.getValue(),
- formValues = this.list.form ? this.list.form.getValue() : {},
- validators = this.schema.validators,
- getValidator = this.getValidator;
-
- if (!validators) return null;
-
- //Run through validators until an error is found
- var error = null;
- _.every(validators, function(validator) {
- error = getValidator(validator)(value, formValues);
-
- return error ? false : true;
- });
-
- //Show/hide error
- if (error){
- this.setError(error);
- } else {
- this.clearError();
- }
-
- //Return error to be aggregated by list
- return error ? error : null;
- },
-
- /**
- * Show a validation error
- */
- setError: function(err) {
- this.$el.addClass(this.errorClassName);
- this.$el.attr('title', err.message);
- },
-
- /**
- * Hide validation errors
- */
- clearError: function() {
- this.$el.removeClass(this.errorClassName);
- this.$el.attr('title', null);
- }
- }, {
-
- //STATICS
- template: _.template('\
- <div>\
- <span data-editor></span>\
- <button type="button" data-action="remove">×</button>\
- </div>\
- ', null, Form.templateSettings),
-
- errorClassName: 'error'
-
- });
-
-
- /**
- * Base modal object editor for use with the List editor; used by Object
- * and NestedModal list types
- */
- Form.editors.List.Modal = Form.editors.Base.extend({
-
- events: {
- 'click': 'openEditor'
- },
-
- /**
- * @param {Object} options
- * @param {Form} options.form The main form
- * @param {Function} [options.schema.itemToString] Function to transform the value for display in the list.
- * @param {String} [options.schema.itemType] Editor type e.g. 'Text', 'Object'.
- * @param {Object} [options.schema.subSchema] Schema for nested form,. Required when itemType is 'Object'
- * @param {Function} [options.schema.model] Model constructor function. Required when itemType is 'NestedModel'
- */
- initialize: function(options) {
- options = options || {};
-
- Form.editors.Base.prototype.initialize.call(this, options);
-
- //Dependencies
- if (!Form.editors.List.Modal.ModalAdapter) throw new Error('A ModalAdapter is required');
-
- this.form = options.form;
- if (!options.form) throw new Error('Missing required option: "form"');
-
- //Template
- this.template = options.template || this.constructor.template;
- },
-
- /**
- * Render the list item representation
- */
- render: function() {
- var self = this;
-
- //New items in the list are only rendered when the editor has been OK'd
- if (_.isEmpty(this.value)) {
- this.openEditor();
- }
-
- //But items with values are added automatically
- else {
- this.renderSummary();
-
- setTimeout(function() {
- self.trigger('readyToAdd');
- }, 0);
- }
-
- if (this.hasFocus) this.trigger('blur', this);
-
- return this;
- },
-
- /**
- * Renders the list item representation
- */
- renderSummary: function() {
- this.$el.html($.trim(this.template({
- summary: this.getStringValue()
- })));
- },
-
- /**
- * Function which returns a generic string representation of an object
- *
- * @param {Object} value
- *
- * @return {String}
- */
- itemToString: function(value) {
- var createTitle = function(key) {
- var context = { key: key };
-
- return Form.Field.prototype.createTitle.call(context);
- };
-
- value = value || {};
-
- //Pretty print the object keys and values
- var parts = [];
- _.each(this.nestedSchema, function(schema, key) {
- var desc = schema.title ? schema.title : createTitle(key),
- val = value[key];
-
- if (_.isUndefined(val) || _.isNull(val)) val = '';
-
- parts.push(desc + ': ' + val);
- });
-
- return parts.join('<br />');
- },
-
- /**
- * Returns the string representation of the object value
- */
- getStringValue: function() {
- var schema = this.schema,
- value = this.getValue();
-
- if (_.isEmpty(value)) return '[Empty]';
-
- //If there's a specified toString use that
- if (schema.itemToString) return schema.itemToString(value);
-
- //Otherwise use the generic method or custom overridden method
- return this.itemToString(value);
- },
-
- openEditor: function() {
- var self = this,
- ModalForm = this.form.constructor;
-
- var form = this.modalForm = new ModalForm({
- schema: this.nestedSchema,
- data: this.value
- });
-
- var modal = this.modal = new Form.editors.List.Modal.ModalAdapter({
- content: form,
- animate: true
- });
-
- modal.open();
-
- this.trigger('open', this);
- this.trigger('focus', this);
-
- modal.on('cancel', this.onModalClosed, this);
-
- modal.on('ok', _.bind(this.onModalSubmitted, this));
- },
-
- /**
- * Called when the user clicks 'OK'.
- * Runs validation and tells the list when ready to add the item
- */
- onModalSubmitted: function() {
- var modal = this.modal,
- form = this.modalForm,
- isNew = !this.value;
-
- //Stop if there are validation errors
- var error = form.validate();
- if (error) return modal.preventClose();
-
- //Store form value
- this.value = form.getValue();
-
- //Render item
- this.renderSummary();
-
- if (isNew) this.trigger('readyToAdd');
-
- this.trigger('change', this);
-
- this.onModalClosed();
- },
-
- /**
- * Cleans up references, triggers events. To be called whenever the modal closes
- */
- onModalClosed: function() {
- this.modal = null;
- this.modalForm = null;
-
- this.trigger('close', this);
- this.trigger('blur', this);
- },
-
- getValue: function() {
- return this.value;
- },
-
- setValue: function(value) {
- this.value = value;
- },
-
- focus: function() {
- if (this.hasFocus) return;
-
- this.openEditor();
- },
-
- blur: function() {
- if (!this.hasFocus) return;
-
- if (this.modal) {
- this.modal.trigger('cancel');
- }
- }
- }, {
- //STATICS
- template: _.template('\
- <div><%= summary %></div>\
- ', null, Form.templateSettings),
-
- //The modal adapter that creates and manages the modal dialog.
- //Defaults to BootstrapModal (http://github.com/powmedia/backbone.bootstrap-modal)
- //Can be replaced with another adapter that implements the same interface.
- ModalAdapter: Backbone.BootstrapModal,
-
- //Make the wait list for the 'ready' event before adding the item to the list
- isAsync: true
- });
-
-
- Form.editors.List.Object = Form.editors.List.Modal.extend({
- initialize: function () {
- Form.editors.List.Modal.prototype.initialize.apply(this, arguments);
-
- var schema = this.schema;
-
- if (!schema.subSchema) throw new Error('Missing required option "schema.subSchema"');
-
- this.nestedSchema = schema.subSchema;
- }
- });
-
-
- Form.editors.List.NestedModel = Form.editors.List.Modal.extend({
- initialize: function() {
- Form.editors.List.Modal.prototype.initialize.apply(this, arguments);
-
- var schema = this.schema;
-
- if (!schema.model) throw new Error('Missing required option "schema.model"');
-
- var nestedSchema = schema.model.prototype.schema;
-
- this.nestedSchema = (_.isFunction(nestedSchema)) ? nestedSchema() : nestedSchema;
- },
-
- /**
- * Returns the string representation of the object value
- */
- getStringValue: function() {
- var schema = this.schema,
- value = this.getValue();
-
- if (_.isEmpty(value)) return null;
-
- //If there's a specified toString use that
- if (schema.itemToString) return schema.itemToString(value);
-
- //Otherwise use the model
- return new (schema.model)(value).toString();
- }
- });
-
-})(Backbone.Form);
-
-
-});
diff --git a/security-admin/src/main/webapp/libs/bower/backbone-forms/js/list.min.js b/security-admin/src/main/webapp/libs/bower/backbone-forms/js/list.min.js
deleted file mode 100644
index 7068cb2b3..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone-forms/js/list.min.js
+++ /dev/null
@@ -1 +0,0 @@
-define(["jquery","underscore","backbone","backbone-forms"],function(e,t,n){(function(r){r.editors.List=r.editors.Base.extend({events:{'click [data-action="add"]':function(e){e.preventDefault(),this.addItem(null,!0)}},initialize:function(e){e=e||{};var t=r.editors;t.Base.prototype.initialize.call(this,e);var n=this.schema;if(!n)throw new Error("Missing required option 'schema'");this.template=e.template||this.constructor.template,this.Editor=function(){var e=n.itemType;return e?t.List[e]? [...]
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/libs/bower/backbone-forms/js/old.js b/security-admin/src/main/webapp/libs/bower/backbone-forms/js/old.js
deleted file mode 100644
index 67ccb98a8..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone-forms/js/old.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * Include this template file after backbone-forms.amd.js to override the default templates
- *
- * 'data-*' attributes control where elements are placed
- */
-define(['jquery', 'underscore', 'backbone', 'backbone-forms'], function($, _, Backbone) {
- var Form = Backbone.Form;
-
-
- /**
- * Templates to match those used previous versions of Backbone Form, i.e. <= 0.11.0.
- * NOTE: These templates are deprecated.
- */
- Form.template = _.template('\
- <form class="bbf-form">\
- <div data-fieldsets></div>\
- <% if (submitButton) { %>\
- <button type="submit"><%= submitButton %></button>\
- <% } %>\
- </form>\
- ');
-
-
- Form.Fieldset.template = _.template('\
- <fieldset>\
- <% if (legend) { %>\
- <legend><%= legend %></legend>\
- <% } %>\
- <ul data-fields></ul>\
- </fieldset>\
- ');
-
-
- Form.Field.template = _.template('\
- <li class="bbf-field field-<%= key %>">\
- <label for="<%= editorId %>"><%= title %></label>\
- <div class="bbf-editor" data-editor></div>\
- <div class="bbf-help"><%= help %></div>\
- <div class="bbf-error" data-error></div>\
- </li>\
- ');
-
-
- Form.NestedField.template = _.template('\
- <li class="bbf-field bbf-nested-field field-<%= key %>">\
- <label for="<%= editorId %>"><%= title %></label>\
- <div class="bbf-editor" data-editor></div>\
- <div class="bbf-help"><%= help %></div>\
- <div class="bbf-error" data-error></div>\
- </li>\
- ');
-
-
- Form.editors.Date.template = _.template('\
- <div class="bbf-date">\
- <select class="bbf-date" data-type="date"><%= dates %></select>\
- <select class="bbf-month" data-type="month"><%= months %></select>\
- <select class="bbf-year" data-type="year"><%= years %></select>\
- </div>\
- ');
-
-
- Form.editors.DateTime.template = _.template('\
- <div class="bbf-datetime">\
- <div class="bbf-date-container" data-date></div>\
- <select data-type="hour"><%= hours %></select>\
- :\
- <select data-type="min"><%= mins %></select>\
- </div>\
- ');
-
-
- if (Form.editors.List) {
-
- Form.editors.List.template = _.template('\
- <div class="bbf-list">\
- <ul data-items></ul>\
- <div class="bbf-actions"><button type="button" data-action="add">Add</div>\
- </div>\
- ');
-
-
- Form.editors.List.Item.template = _.template('\
- <li>\
- <button type="button" data-action="remove" class="bbf-remove">×</button>\
- <div class="bbf-editor-container" data-editor></div>\
- </li>\
- ');
-
-
- Form.editors.List.Object.template = Form.editors.List.NestedModel.template = _.template('\
- <div class="bbf-list-modal"><%= summary %></div>\
- ');
-
- }
-
-
-
-});
diff --git a/security-admin/src/main/webapp/libs/bower/backbone-pageable/js/backbone-pageable.js b/security-admin/src/main/webapp/libs/bower/backbone-pageable/js/backbone-pageable.js
deleted file mode 100644
index 9accadd1b..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone-pageable/js/backbone-pageable.js
+++ /dev/null
@@ -1,1327 +0,0 @@
-/*
- backbone-pageable 1.3.2
- http://github.com/wyuenho/backbone-pageable
-
- Copyright (c) 2013 Jimmy Yuen Ho Wong
- Licensed under the MIT @license.
-*/
-
-(function (factory) {
-
- // CommonJS
- if (typeof exports == "object") {
- module.exports = factory(require("underscore"), require("backbone"));
- }
- // AMD
- else if (typeof define == "function" && define.amd) {
- define(["underscore", "backbone"], factory);
- }
- // Browser
- else if (typeof _ !== "undefined" && typeof Backbone !== "undefined") {
- var oldPageableCollection = Backbone.PageableCollection;
- var PageableCollection = factory(_, Backbone);
-
- /**
- __BROWSER ONLY__
-
- If you already have an object named `PageableCollection` attached to the
- `Backbone` module, you can use this to return a local reference to this
- Backbone.PageableCollection class and reset the name
- Backbone.PageableCollection to its previous definition.
-
- // The left hand side gives you a reference to this
- // Backbone.PageableCollection implementation, the right hand side
- // resets Backbone.PageableCollection to your other
- // Backbone.PageableCollection.
- var PageableCollection = Backbone.PageableCollection.noConflict();
-
- @static
- @member Backbone.PageableCollection
- @return {Backbone.PageableCollection}
- */
- Backbone.PageableCollection.noConflict = function () {
- Backbone.PageableCollection = oldPageableCollection;
- return PageableCollection;
- };
- }
-
-}(function (_, Backbone) {
-
- "use strict";
-
- var _extend = _.extend;
- var _omit = _.omit;
- var _clone = _.clone;
- var _each = _.each;
- var _pick = _.pick;
- var _contains = _.contains;
- var _isEmpty = _.isEmpty;
- var _pairs = _.pairs;
- var _invert = _.invert;
- var _isArray = _.isArray;
- var _isFunction = _.isFunction;
- var _isObject = _.isObject;
- var _keys = _.keys;
- var _isUndefined = _.isUndefined;
- var _result = _.result;
- var ceil = Math.ceil;
- var floor = Math.floor;
- var max = Math.max;
-
- var BBColProto = Backbone.Collection.prototype;
-
- function finiteInt (val, name) {
- if (!_.isNumber(val) || _.isNaN(val) || !_.isFinite(val) || ~~val !== val) {
- throw new TypeError("`" + name + "` must be a finite integer");
- }
- return val;
- }
-
- function queryStringToParams (qs) {
- var kvp, k, v, ls, params = {}, decode = decodeURIComponent;
- var kvps = qs.split('&');
- for (var i = 0, l = kvps.length; i < l; i++) {
- var param = kvps[i];
- kvp = param.split('='), k = kvp[0], v = kvp[1] || true;
- k = decode(k), ls = params[k];
- if (_isArray(ls)) ls.push(v);
- else if (ls) params[k] = [ls, v];
- else params[k] = v;
- }
- return params;
- }
-
- var PARAM_TRIM_RE = /[\s'"]/g;
- var URL_TRIM_RE = /[<>\s'"]/g;
-
- /**
- Drop-in replacement for Backbone.Collection. Supports server-side and
- client-side pagination and sorting. Client-side mode also support fully
- multi-directional synchronization of changes between pages.
-
- @class Backbone.PageableCollection
- @extends Backbone.Collection
- */
- var PageableCollection = Backbone.PageableCollection = Backbone.Collection.extend({
-
- /**
- The container object to store all pagination states.
-
- You can override the default state by extending this class or specifying
- them in an `options` hash to the constructor.
-
- @property {Object} state
-
- @property {0|1} [state.firstPage=1] The first page index. Set to 0 if
- your server API uses 0-based indices. You should only override this value
- during extension, initialization or reset by the server after
- fetching. This value should be read only at other times.
-
- @property {number} [state.lastPage=null] The last page index. This value
- is __read only__ and it's calculated based on whether `firstPage` is 0 or
- 1, during bootstrapping, fetching and resetting. Please don't change this
- value under any circumstances.
-
- @property {number} [state.currentPage=null] The current page index. You
- should only override this value during extension, initialization or reset
- by the server after fetching. This value should be read only at other
- times. Can be a 0-based or 1-based index, depending on whether
- `firstPage` is 0 or 1. If left as default, it will be set to `firstPage`
- on initialization.
-
- @property {number} [state.pageSize=25] How many records to show per
- page. This value is __read only__ after initialization, if you want to
- change the page size after initialization, you must call #setPageSize.
-
- @property {number} [state.totalPages=null] How many pages there are. This
- value is __read only__ and it is calculated from `totalRecords`.
-
- @property {number} [state.totalRecords=null] How many records there
- are. This value is __required__ under server mode. This value is optional
- for client mode as the number will be the same as the number of models
- during bootstrapping and during fetching, either supplied by the server
- in the metadata, or calculated from the size of the response.
-
- @property {string} [state.sortKey=null] The model attribute to use for
- sorting.
-
- @property {-1|0|1} [state.order=-1] The order to use for sorting. Specify
- -1 for ascending order or 1 for descending order. If 0, no client side
- sorting will be done and the order query parameter will not be sent to
- the server during a fetch.
- */
- state: {
- firstPage: 1,
- lastPage: null,
- currentPage: null,
- pageSize: 25,
- totalPages: null,
- totalRecords: null,
- sortKey: null,
- order: -1
- },
-
- /**
- @property {"server"|"client"|"infinite"} [mode="server"] The mode of
- operations for this collection. `"server"` paginates on the server-side,
- `"client"` paginates on the client-side and `"infinite"` paginates on the
- server-side for APIs that do not support `totalRecords`.
- */
- mode: "server",
-
- /**
- A translation map to convert Backbone.PageableCollection state attributes
- to the query parameters accepted by your server API.
-
- You can override the default state by extending this class or specifying
- them in `options.queryParams` object hash to the constructor.
-
- @property {Object} queryParams
- @property {string} [queryParams.currentPage="page"]
- @property {string} [queryParams.pageSize="per_page"]
- @property {string} [queryParams.totalPages="total_pages"]
- @property {string} [queryParams.totalRecords="total_entries"]
- @property {string} [queryParams.sortKey="sort_by"]
- @property {string} [queryParams.order="order"]
- @property {string} [queryParams.directions={"-1": "asc", "1": "desc"}] A
- map for translating a Backbone.PageableCollection#state.order constant to
- the ones your server API accepts.
- */
- queryParams: {
- currentPage: "page",
- pageSize: "per_page",
- totalPages: "total_pages",
- totalRecords: "total_entries",
- sortKey: "sort_by",
- order: "order",
- directions: {
- "-1": "asc",
- "1": "desc"
- }
- },
-
- /**
- __CLIENT MODE ONLY__
-
- This collection is the internal storage for the bootstrapped or fetched
- models. You can use this if you want to operate on all the pages.
-
- @property {Backbone.Collection} fullCollection
- */
-
- /**
- Given a list of models or model attributues, bootstraps the full
- collection in client mode or infinite mode, or just the page you want in
- server mode.
-
- If you want to initialize a collection to a different state than the
- default, you can specify them in `options.state`. Any state parameters
- supplied will be merged with the default. If you want to change the
- default mapping from #state keys to your server API's query parameter
- names, you can specifiy an object hash in `option.queryParams`. Likewise,
- any mapping provided will be merged with the default. Lastly, all
- Backbone.Collection constructor options are also accepted.
-
- See:
-
- - Backbone.PageableCollection#state
- - Backbone.PageableCollection#queryParams
- - [Backbone.Collection#initialize](http://backbonejs.org/#Collection-constructor)
-
- @param {Array.<Object>} [models]
-
- @param {Object} [options]
-
- @param {function(*, *): number} [options.comparator] If specified, this
- comparator is set to the current page under server mode, or the #fullCollection
- otherwise.
-
- @param {boolean} [options.full] If `false` and either a
- `options.comparator` or `sortKey` is defined, the comparator is attached
- to the current page. Default is `true` under client or infinite mode and
- the comparator will be attached to the #fullCollection.
-
- @param {Object} [options.state] The state attributes overriding the defaults.
-
- @param {string} [options.state.sortKey] The model attribute to use for
- sorting. If specified instead of `options.comparator`, a comparator will
- be automatically created using this value, and optionally a sorting order
- specified in `options.state.order`. The comparator is then attached to
- the new collection instance.
-
- @param {-1|1} [options.state.order] The order to use for sorting. Specify
- -1 for ascending order and 1 for descending order.
-
- @param {Object} [options.queryParam]
- */
- constructor: function (models, options) {
-
- Backbone.Collection.apply(this, arguments);
-
- options = options || {};
-
- var mode = this.mode = options.mode || this.mode || PageableProto.mode;
-
- var queryParams = _extend({}, PageableProto.queryParams, this.queryParams,
- options.queryParams || {});
-
- queryParams.directions = _extend({},
- PageableProto.queryParams.directions,
- this.queryParams.directions,
- queryParams.directions || {});
-
- this.queryParams = queryParams;
-
- var state = this.state = _extend({}, PageableProto.state, this.state,
- options.state || {});
-
- state.currentPage = state.currentPage == null ?
- state.firstPage :
- state.currentPage;
-
- if (!_isArray(models)) models = models ? [models] : [];
-
- if (mode != "server" && state.totalRecords == null && !_isEmpty(models)) {
- state.totalRecords = models.length;
- }
-
- this.switchMode(mode, _extend({fetch: false,
- resetState: false,
- models: models}, options));
-
- var comparator = options.comparator;
-
- if (state.sortKey && !comparator) {
- this.setSorting(state.sortKey, state.order, options);
- }
-
- if (mode != "server") {
- var fullCollection = this.fullCollection;
-
- if (comparator && options.full) {
- delete this.comparator;
- fullCollection.comparator = comparator;
- }
-
- if (options.full) fullCollection.sort();
-
- // make sure the models in the current page and full collection have the
- // same references
- if (models && !_isEmpty(models)) {
- this.getPage(state.currentPage);
- models.splice.apply(models, [0, models.length].concat(this.models));
- }
- }
-
- this._initState = _clone(this.state);
- },
-
- /**
- Makes a Backbone.Collection that contains all the pages.
-
- @private
- @param {Array.<Object|Backbone.Model>} models
- @param {Object} options Options for Backbone.Collection constructor.
- @return {Backbone.Collection}
- */
- _makeFullCollection: function (models, options) {
-
- var properties = ["url", "model", "sync", "comparator"];
- var thisProto = this.constructor.prototype;
- var i, length, prop;
-
- var proto = {};
- for (i = 0, length = properties.length; i < length; i++) {
- prop = properties[i];
- if (!_isUndefined(thisProto[prop])) {
- proto[prop] = thisProto[prop];
- }
- }
-
- var fullCollection = new (Backbone.Collection.extend(proto))(models, options);
-
- for (i = 0, length = properties.length; i < length; i++) {
- prop = properties[i];
- if (this[prop] !== thisProto[prop]) {
- fullCollection[prop] = this[prop];
- }
- }
-
- return fullCollection;
- },
-
- /**
- Factory method that returns a Backbone event handler that responses to
- the `add`, `remove`, `reset`, and the `sort` events. The returned event
- handler will synchronize the current page collection and the full
- collection's models.
-
- @private
-
- @param {Backbone.PageableCollection} pageCol
- @param {Backbone.Collection} fullCol
-
- @return {function(string, Backbone.Model, Backbone.Collection, Object)}
- Collection event handler
- */
- _makeCollectionEventHandler: function (pageCol, fullCol) {
-
- return function collectionEventHandler (event, model, collection, options) {
-
- var handlers = pageCol._handlers;
- _each(_keys(handlers), function (event) {
- var handler = handlers[event];
- pageCol.off(event, handler);
- fullCol.off(event, handler);
- });
-
- var state = _clone(pageCol.state);
- var firstPage = state.firstPage;
- var currentPage = firstPage === 0 ?
- state.currentPage :
- state.currentPage - 1;
- var pageSize = state.pageSize;
- var pageStart = currentPage * pageSize, pageEnd = pageStart + pageSize;
-
- if (event == "add") {
- var pageIndex, fullIndex, addAt, colToAdd, options = options || {};
- if (collection == fullCol) {
- fullIndex = fullCol.indexOf(model);
- if (fullIndex >= pageStart && fullIndex < pageEnd) {
- colToAdd = pageCol;
- pageIndex = addAt = fullIndex - pageStart;
- }
- }
- else {
- pageIndex = pageCol.indexOf(model);
- fullIndex = pageStart + pageIndex;
- colToAdd = fullCol;
- var addAt = !_isUndefined(options.at) ?
- options.at + pageStart :
- fullIndex;
- }
-
- ++state.totalRecords;
- pageCol.state = pageCol._checkState(state);
-
- if (colToAdd) {
- colToAdd.add(model, _extend({}, options || {}, {at: addAt}));
- var modelToRemove = pageIndex >= pageSize ?
- model :
- !_isUndefined(options.at) && addAt < pageEnd && pageCol.length > pageSize ?
- pageCol.at(pageSize) :
- null;
- if (modelToRemove) {
- var addHandlers = collection._events.add || [],
- popOptions = {onAdd: true};
- if (addHandlers.length) {
- var lastAddHandler = addHandlers[addHandlers.length - 1];
- var oldCallback = lastAddHandler.callback;
- lastAddHandler.callback = function () {
- try {
- oldCallback.apply(this, arguments);
- pageCol.remove(modelToRemove, popOptions);
- }
- finally {
- lastAddHandler.callback = oldCallback;
- }
- };
- }
- else pageCol.remove(modelToRemove, popOptions);
- }
- }
- }
-
- // remove the model from the other collection as well
- if (event == "remove") {
- if (!options.onAdd) {
- // decrement totalRecords and update totalPages and lastPage
- if (!--state.totalRecords) {
- state.totalRecords = null;
- state.totalPages = null;
- }
- else {
- var totalPages = state.totalPages = ceil(state.totalRecords / pageSize);
- state.lastPage = firstPage === 0 ? totalPages - 1 : totalPages;
- if (state.currentPage > totalPages) state.currentPage = state.lastPage;
- }
- pageCol.state = pageCol._checkState(state);
-
- var nextModel, removedIndex = options.index;
- if (collection == pageCol) {
- if (nextModel = fullCol.at(pageEnd)) pageCol.push(nextModel);
- fullCol.remove(model);
- }
- else if (removedIndex >= pageStart && removedIndex < pageEnd) {
- pageCol.remove(model);
- nextModel = fullCol.at(currentPage * (pageSize + removedIndex));
- if (nextModel) pageCol.push(nextModel);
- }
- }
- else delete options.onAdd;
- }
-
- if (event == "reset") {
- options = collection;
- collection = model;
-
- // Reset that's not a result of getPage
- if (collection === pageCol && options.from == null &&
- options.to == null) {
- var head = fullCol.models.slice(0, pageStart);
- var tail = fullCol.models.slice(pageStart + pageCol.models.length);
- fullCol.reset(head.concat(pageCol.models).concat(tail), options);
- }
- else if (collection === fullCol) {
- if (!(state.totalRecords = fullCol.models.length)) {
- state.totalRecords = null;
- state.totalPages = null;
- }
- if (pageCol.mode == "client") {
- state.lastPage = state.currentPage = state.firstPage;
- }
- pageCol.state = pageCol._checkState(state);
- pageCol.reset(fullCol.models.slice(pageStart, pageEnd),
- _extend({}, options, {parse: false}));
- }
- }
-
- if (event == "sort") {
- options = collection;
- collection = model;
- if (collection === fullCol) {
- pageCol.reset(fullCol.models.slice(pageStart, pageEnd),
- _extend({}, options, {parse: false}));
- }
- }
-
- _each(_keys(handlers), function (event) {
- var handler = handlers[event];
- _each([pageCol, fullCol], function (col) {
- col.on(event, handler);
- var callbacks = col._events[event] || [];
- callbacks.unshift(callbacks.pop());
- });
- });
- };
- },
-
- /**
- Sanity check this collection's pagination states. Only perform checks
- when all the required pagination state values are defined and not null.
- If `totalPages` is undefined or null, it is set to `totalRecords` /
- `pageSize`. `lastPage` is set according to whether `firstPage` is 0 or 1
- when no error occurs.
-
- @private
-
- @throws {TypeError} If `totalRecords`, `pageSize`, `currentPage` or
- `firstPage` is not a finite integer.
-
- @throws {RangeError} If `pageSize`, `currentPage` or `firstPage` is out
- of bounds.
-
- @return {Object} Returns the `state` object if no error was found.
- */
- _checkState: function (state) {
-
- var mode = this.mode;
- var links = this.links;
- var totalRecords = state.totalRecords;
- var pageSize = state.pageSize;
- var currentPage = state.currentPage;
- var firstPage = state.firstPage;
- var totalPages = state.totalPages;
-
- if (totalRecords != null && pageSize != null && currentPage != null &&
- firstPage != null && (mode == "infinite" ? links : true)) {
-
- totalRecords = finiteInt(totalRecords, "totalRecords");
- pageSize = finiteInt(pageSize, "pageSize");
- currentPage = finiteInt(currentPage, "currentPage");
- firstPage = finiteInt(firstPage, "firstPage");
-
- if (pageSize < 1) {
- throw new RangeError("`pageSize` must be >= 1");
- }
-
- totalPages = state.totalPages = ceil(totalRecords / pageSize);
-
- if (firstPage < 0 || firstPage > 1) {
- throw new RangeError("`firstPage must be 0 or 1`");
- }
-
- state.lastPage = firstPage === 0 ? max(0, totalPages - 1) : totalPages;
-
- if (mode == "infinite") {
- if (!links[currentPage + '']) {
- throw new RangeError("No link found for page " + currentPage);
- }
- }
- else if (currentPage < firstPage ||
- (totalPages > 0 &&
- (firstPage ? currentPage > totalPages : currentPage >= totalPages))) {
- throw new RangeError("`currentPage` must be firstPage <= currentPage " +
- (firstPage ? ">" : ">=") +
- " totalPages if " + firstPage + "-based. Got " +
- currentPage + '.');
- }
- }
-
- return state;
- },
-
- /**
- Change the page size of this collection.
-
- Under most if not all circumstances, you should call this method to
- change the page size of a pageable collection because it will keep the
- pagination state sane. By default, the method will recalculate the
- current page number to one that will retain the current page's models
- when increasing the page size. When decreasing the page size, this method
- will retain the last models to the current page that will fit into the
- smaller page size.
-
- If `options.first` is true, changing the page size will also reset the
- current page back to the first page instead of trying to be smart.
-
- For server mode operations, changing the page size will trigger a #fetch
- and subsequently a `reset` event.
-
- For client mode operations, changing the page size will `reset` the
- current page by recalculating the current page boundary on the client
- side.
-
- If `options.fetch` is true, a fetch can be forced if the collection is in
- client mode.
-
- @param {number} pageSize The new page size to set to #state.
- @param {Object} [options] {@link #fetch} options.
- @param {boolean} [options.first=false] Reset the current page number to
- the first page if `true`.
- @param {boolean} [options.fetch] If `true`, force a fetch in client mode.
-
- @throws {TypeError} If `pageSize` is not a finite integer.
- @throws {RangeError} If `pageSize` is less than 1.
-
- @chainable
- @return {XMLHttpRequest|Backbone.PageableCollection} The XMLHttpRequest
- from fetch or this.
- */
- setPageSize: function (pageSize, options) {
- pageSize = finiteInt(pageSize, "pageSize");
-
- options = options || {first: false};
-
- var state = this.state;
- var totalPages = ceil(state.totalRecords / pageSize);
- var currentPage = totalPages ?
- max(state.firstPage,
- floor(totalPages *
- (state.firstPage ?
- state.currentPage :
- state.currentPage + 1) /
- state.totalPages)) :
- state.firstPage;
-
- state = this.state = this._checkState(_extend({}, state, {
- pageSize: pageSize,
- currentPage: options.first ? state.firstPage : currentPage,
- totalPages: totalPages
- }));
-
- if(!options.fetch)
- return;
- return this.getPage(state.currentPage, _omit(options, ["first"]));
- },
-
- /**
- Switching between client, server and infinite mode.
-
- If switching from client to server mode, the #fullCollection is emptied
- first and then deleted and a fetch is immediately issued for the current
- page from the server. Pass `false` to `options.fetch` to skip fetching.
-
- If switching to infinite mode, and if `options.models` is given for an
- array of models, #links will be populated with a URL per page, using the
- default URL for this collection.
-
- If switching from server to client mode, all of the pages are immediately
- refetched. If you have too many pages, you can pass `false` to
- `options.fetch` to skip fetching.
-
- If switching to any mode from infinite mode, the #links will be deleted.
-
- @param {"server"|"client"|"infinite"} [mode] The mode to switch to.
-
- @param {Object} [options]
-
- @param {boolean} [options.fetch=true] If `false`, no fetching is done.
-
- @param {boolean} [options.resetState=true] If 'false', the state is not
- reset, but checked for sanity instead.
-
- @chainable
- @return {XMLHttpRequest|Backbone.PageableCollection} The XMLHttpRequest
- from fetch or this if `options.fetch` is `false`.
- */
- switchMode: function (mode, options) {
-
- if (!_contains(["server", "client", "infinite"], mode)) {
- throw new TypeError('`mode` must be one of "server", "client" or "infinite"');
- }
-
- options = options || {fetch: true, resetState: true};
-
- var state = this.state = options.resetState ?
- _clone(this._initState) :
- this._checkState(_extend({}, this.state));
-
- this.mode = mode;
-
- var self = this;
- var fullCollection = this.fullCollection;
- var handlers = this._handlers = this._handlers || {}, handler;
- if (mode != "server" && !fullCollection) {
- fullCollection = this._makeFullCollection(options.models || []);
- fullCollection.pageableCollection = this;
- this.fullCollection = fullCollection;
- var allHandler = this._makeCollectionEventHandler(this, fullCollection);
- _each(["add", "remove", "reset", "sort"], function (event) {
- handlers[event] = handler = _.bind(allHandler, {}, event);
- self.on(event, handler);
- fullCollection.on(event, handler);
- });
- fullCollection.comparator = this._fullComparator;
- }
- else if (mode == "server" && fullCollection) {
- _each(_keys(handlers), function (event) {
- handler = handlers[event];
- self.off(event, handler);
- fullCollection.off(event, handler);
- });
- delete this._handlers;
- this._fullComparator = fullCollection.comparator;
- delete this.fullCollection;
- }
-
- if (mode == "infinite") {
- var links = this.links = {};
- var firstPage = state.firstPage;
- var totalPages = ceil(state.totalRecords / state.pageSize);
- var lastPage = firstPage === 0 ? max(0, totalPages - 1) : totalPages || firstPage;
- for (var i = state.firstPage; i <= lastPage; i++) {
- links[i] = this.url;
- }
- }
- else if (this.links) delete this.links;
-
- return options.fetch ?
- this.fetch(_omit(options, "fetch", "resetState")) :
- this;
- },
-
- /**
- @return {boolean} `true` if this collection can page backward, `false`
- otherwise.
- */
- hasPrevious: function () {
- var state = this.state;
- var currentPage = state.currentPage;
- if (this.mode != "infinite") return currentPage > state.firstPage;
- return !!this.links[currentPage - 1];
- },
-
- /**
- @return {boolean} `true` if this collection can page forward, `false`
- otherwise.
- */
- hasNext: function () {
- var state = this.state;
- var currentPage = this.state.currentPage;
- if (this.mode != "infinite") return currentPage < state.lastPage;
- return !!this.links[currentPage + 1];
- },
-
- /**
- Fetch the first page in server mode, or reset the current page of this
- collection to the first page in client or infinite mode.
-
- @param {Object} options {@link #getPage} options.
-
- @chainable
- @return {XMLHttpRequest|Backbone.PageableCollection} The XMLHttpRequest
- from fetch or this.
- */
- getFirstPage: function (options) {
- return this.getPage("first", options);
- },
-
- /**
- Fetch the previous page in server mode, or reset the current page of this
- collection to the previous page in client or infinite mode.
-
- @param {Object} options {@link #getPage} options.
-
- @chainable
- @return {XMLHttpRequest|Backbone.PageableCollection} The XMLHttpRequest
- from fetch or this.
- */
- getPreviousPage: function (options) {
- return this.getPage("prev", options);
- },
-
- /**
- Fetch the next page in server mode, or reset the current page of this
- collection to the next page in client mode.
-
- @param {Object} options {@link #getPage} options.
-
- @chainable
- @return {XMLHttpRequest|Backbone.PageableCollection} The XMLHttpRequest
- from fetch or this.
- */
- getNextPage: function (options) {
- return this.getPage("next", options);
- },
-
- /**
- Fetch the last page in server mode, or reset the current page of this
- collection to the last page in client mode.
-
- @param {Object} options {@link #getPage} options.
-
- @chainable
- @return {XMLHttpRequest|Backbone.PageableCollection} The XMLHttpRequest
- from fetch or this.
- */
- getLastPage: function (options) {
- return this.getPage("last", options);
- },
-
- /**
- Given a page index, set #state.currentPage to that index. If this
- collection is in server mode, fetch the page using the updated state,
- otherwise, reset the current page of this collection to the page
- specified by `index` in client mode. If `options.fetch` is true, a fetch
- can be forced in client mode before resetting the current page. Under
- infinite mode, if the index is less than the current page, a reset is
- done as in client mode. If the index is greater than the current page
- number, a fetch is made with the results **appended** to #fullCollection.
- The current page will then be reset after fetching.
-
- @param {number|string} index The page index to go to, or the page name to
- look up from #links in infinite mode.
- @param {Object} [options] {@link #fetch} options or
- [reset](http://backbonejs.org/#Collection-reset) options for client mode
- when `options.fetch` is `false`.
- @param {boolean} [options.fetch=false] If true, force a {@link #fetch} in
- client mode.
-
- @throws {TypeError} If `index` is not a finite integer under server or
- client mode, or does not yield a URL from #links under infinite mode.
-
- @throws {RangeError} If `index` is out of bounds.
-
- @chainable
- @return {XMLHttpRequest|Backbone.PageableCollection} The XMLHttpRequest
- from fetch or this.
- */
- getPage: function (index, options) {
-
- var mode = this.mode, fullCollection = this.fullCollection;
-
- options = options || {fetch: false};
-
- var state = this.state,
- firstPage = state.firstPage,
- currentPage = state.currentPage,
- lastPage = state.lastPage,
- pageSize = state.pageSize;
-
- var pageNum = index;
- switch (index) {
- case "first": pageNum = firstPage; break;
- case "prev": pageNum = currentPage - 1; break;
- case "next": pageNum = currentPage + 1; break;
- case "last": pageNum = lastPage; break;
- default: pageNum = finiteInt(index, "index");
- }
-
- this.state = this._checkState(_extend({}, state, {currentPage: pageNum}));
-
- options.from = currentPage, options.to = pageNum;
-
- var pageStart = (firstPage === 0 ? pageNum : pageNum - 1) * pageSize;
- var pageModels = fullCollection && fullCollection.length ?
- fullCollection.models.slice(pageStart, pageStart + pageSize) :
- [];
- if ((mode == "client" || (mode == "infinite" && !_isEmpty(pageModels))) &&
- !options.fetch) {
- return this.reset(pageModels, _omit(options, "fetch"));
- }
-
- if (mode == "infinite") options.url = this.links[pageNum];
-
- return this.fetch(_omit(options, "fetch"));
- },
-
- /**
- Fetch the page for the provided item offset in server mode, or reset the current page of this
- collection to the page for the provided item offset in client mode.
-
- @param {Object} options {@link #getPage} options.
-
- @chainable
- @return {XMLHttpRequest|Backbone.PageableCollection} The XMLHttpRequest
- from fetch or this.
- */
- getPageByOffset: function (offset, options) {
- if (offset < 0) {
- throw new RangeError("`offset must be > 0`");
- }
- offset = finiteInt(offset);
-
- var page = floor(offset / this.state.pageSize);
- if (this.state.firstPage !== 0) page++;
- if (page > this.state.lastPage) page = this.state.lastPage;
- return this.getPage(page, options);
- },
-
- /**
- Overidden to make `getPage` compatible with Zepto.
-
- @param {string} method
- @param {Backbone.Model|Backbone.Collection} model
- @param {Object} [options]
-
- @return {XMLHttpRequest}
- */
- sync: function (method, model, options) {
- var self = this;
- if (self.mode == "infinite") {
- var success = options.success;
- var currentPage = self.state.currentPage;
- options.success = function (resp, status, xhr) {
- var links = self.links;
- var newLinks = self.parseLinks(resp, _extend({xhr: xhr}, options));
- if (newLinks.first) links[self.state.firstPage] = newLinks.first;
- if (newLinks.prev) links[currentPage - 1] = newLinks.prev;
- if (newLinks.next) links[currentPage + 1] = newLinks.next;
- if (success) success(resp, status, xhr);
- };
- }
-
- return (BBColProto.sync || Backbone.sync).call(self, method, model, options);
- },
-
- /**
- Parse pagination links from the server response. Only valid under
- infinite mode.
-
- Given a response body and a XMLHttpRequest object, extract pagination
- links from them for infinite paging.
-
- This default implementation parses the RFC 5988 `Link` header and extract
- 3 links from it - `first`, `prev`, `next`. If a `previous` link is found,
- it will be found in the `prev` key in the returned object hash. Any
- subclasses overriding this method __must__ return an object hash having
- only the keys above. If `first` is missing, the collection's default URL
- is assumed to be the `first` URL. If `prev` or `next` is missing, it is
- assumed to be `null`. An empty object hash must be returned if there are
- no links found. If either the response or the header contains information
- pertaining to the total number of records on the server, #state.totalRecords
- must be set to that number. The default implementation uses the `last`
- link from the header to calculate it.
-
- @param {*} resp The deserialized response body.
- @param {Object} [options]
- @param {XMLHttpRequest} [options.xhr] The XMLHttpRequest object for this
- response.
- @return {Object}
- */
- parseLinks: function (resp, options) {
- var links = {};
- var linkHeader = options.xhr.getResponseHeader("Link");
- if (linkHeader) {
- var relations = ["first", "prev", "previous", "next", "last"];
- _each(linkHeader.split(","), function (linkValue) {
- var linkParts = linkValue.split(";");
- var url = linkParts[0].replace(URL_TRIM_RE, '');
- var params = linkParts.slice(1);
- _each(params, function (param) {
- var paramParts = param.split("=");
- var key = paramParts[0].replace(PARAM_TRIM_RE, '');
- var value = paramParts[1].replace(PARAM_TRIM_RE, '');
- if (key == "rel" && _contains(relations, value)) {
- if (value == "previous") links.prev = url;
- else links[value] = url;
- }
- });
- });
-
- var last = links.last || '', qsi, qs;
- if (qs = (qsi = last.indexOf('?')) ? last.slice(qsi + 1) : '') {
- var params = queryStringToParams(qs);
-
- var state = _clone(this.state);
- var queryParams = this.queryParams;
- var pageSize = state.pageSize;
-
- var totalRecords = params[queryParams.totalRecords] * 1;
- var pageNum = params[queryParams.currentPage] * 1;
- var totalPages = params[queryParams.totalPages];
-
- if (!totalRecords) {
- if (pageNum) totalRecords = (state.firstPage === 0 ?
- pageNum + 1 :
- pageNum) * pageSize;
- else if (totalPages) totalRecords = totalPages * pageSize;
- }
-
- if (totalRecords) state.totalRecords = totalRecords;
-
- this.state = this._checkState(state);
- }
- }
-
- delete links.last;
-
- return links;
- },
-
- /**
- Parse server response data.
-
- This default implementation assumes the response data is in one of two
- structures:
-
- [
- {}, // Your new pagination state
- [{}, ...] // An array of JSON objects
- ]
-
- Or,
-
- [{}] // An array of JSON objects
-
- The first structure is the preferred form because the pagination states
- may have been updated on the server side, sending them down again allows
- this collection to update its states. If the response has a pagination
- state object, it is checked for errors.
-
- The second structure is the
- [Backbone.Collection#parse](http://backbonejs.org/#Collection-parse)
- default.
-
- **Note:** this method has been further simplified since 1.1.7. While
- existing #parse implementations will continue to work, new code is
- encouraged to override #parseState and #parseRecords instead.
-
- @param {Object} resp The deserialized response data from the server.
- @param {Object} the options for the ajax request
-
- @return {Array.<Object>} An array of model objects
- */
- parse: function (resp, options) {
- var newState = this.parseState(resp, _clone(this.queryParams), _clone(this.state), options);
- if (newState) this.state = this._checkState(_extend({}, this.state, newState));
- return this.parseRecords(resp, options);
- },
-
- /**
- Parse server response for server pagination state updates.
-
- This default implementation first checks whether the response has any
- state object as documented in #parse. If it exists, a state object is
- returned by mapping the server state keys to this pageable collection
- instance's query parameter keys using `queryParams`.
-
- It is __NOT__ neccessary to return a full state object complete with all
- the mappings defined in #queryParams. Any state object resulted is merged
- with a copy of the current pageable collection state and checked for
- sanity before actually updating. Most of the time, simply providing a new
- `totalRecords` value is enough to trigger a full pagination state
- recalculation.
-
- parseState: function (resp, queryParams, state, options) {
- return {totalRecords: resp.total_entries};
- }
-
- If you want to use header fields use:
-
- parseState: function (resp, queryParams, state, options) {
- return {totalRecords: options.xhr.getResponseHeader("X-total")};
- }
-
- This method __MUST__ return a new state object instead of directly
- modifying the #state object. The behavior of directly modifying #state is
- undefined.
-
- @param {Object} resp The deserialized response data from the server.
- @param {Object} queryParams A copy of #queryParams.
- @param {Object} state A copy of #state.
- @param {Object} [options] The options passed through from
- `parse`. (backbone >= 0.9.10 only)
-
- @return {Object} A new (partial) state object.
- */
- parseState: function (resp, queryParams, state, options) {
- if (resp && resp.length === 2 && _isObject(resp[0]) && _isArray(resp[1])) {
-
- var newState = _clone(state);
- var serverState = resp[0];
-
- _each(_pairs(_omit(queryParams, "directions")), function (kvp) {
- var k = kvp[0], v = kvp[1];
- var serverVal = serverState[v];
- if (!_isUndefined(serverVal) && !_.isNull(serverVal)) newState[k] = serverState[v];
- });
-
- if (serverState.order) {
- newState.order = _invert(queryParams.directions)[serverState.order] * 1;
- }
-
- return newState;
- }
- },
-
- /**
- Parse server response for an array of model objects.
-
- This default implementation first checks whether the response has any
- state object as documented in #parse. If it exists, the array of model
- objects is assumed to be the second element, otherwise the entire
- response is returned directly.
-
- @param {Object} resp The deserialized response data from the server.
- @param {Object} [options] The options passed through from the
- `parse`. (backbone >= 0.9.10 only)
-
- @return {Array.<Object>} An array of model objects
- */
- parseRecords: function (resp, options) {
- if (resp && resp.length === 2 && _isObject(resp[0]) && _isArray(resp[1])) {
- return resp[1];
- }
-
- return resp;
- },
-
- /**
- Fetch a page from the server in server mode, or all the pages in client
- mode. Under infinite mode, the current page is refetched by default and
- then reset.
-
- The query string is constructed by translating the current pagination
- state to your server API query parameter using #queryParams. The current
- page will reset after fetch.
-
- @param {Object} [options] Accepts all
- [Backbone.Collection#fetch](http://backbonejs.org/#Collection-fetch)
- options.
-
- @return {XMLHttpRequest}
- */
- fetch: function (options) {
-
- options = options || {};
-
- var state = this._checkState(this.state);
-
- var mode = this.mode;
-
- if (mode == "infinite" && !options.url) {
- options.url = this.links[state.currentPage];
- }
-
- var data = options.data || {};
-
- // dedup query params
- var url = _result(options, "url") || _result(this, "url") || '';
- var qsi = url.indexOf('?');
- if (qsi != -1) {
- _extend(data, queryStringToParams(url.slice(qsi + 1)));
- url = url.slice(0, qsi);
- }
-
- options.url = url;
- options.data = data;
-
- // map params except directions
- var queryParams = this.mode == "client" ?
- _pick(this.queryParams, "sortKey", "order") :
- _omit(_pick(this.queryParams, _keys(PageableProto.queryParams)),
- "directions");
-
- var i, kvp, k, v, kvps = _pairs(queryParams), thisCopy = _clone(this);
- for (i = 0; i < kvps.length; i++) {
- kvp = kvps[i], k = kvp[0], v = kvp[1];
- v = _isFunction(v) ? v.call(thisCopy) : v;
- if (state[k] != null && v != null) {
- data[v] = state[k];
- }
- }
-
- // fix up sorting parameters
- if (state.sortKey && state.order) {
- data[queryParams.order] = this.queryParams.directions[state.order + ""];
- }
- else if (!state.sortKey) delete data[queryParams.order];
-
- // map extra query parameters
- var extraKvps = _pairs(_omit(this.queryParams,
- _keys(PageableProto.queryParams)));
- for (i = 0; i < extraKvps.length; i++) {
- kvp = extraKvps[i];
- v = kvp[1];
- v = _isFunction(v) ? v.call(thisCopy) : v;
- if (v != null) data[kvp[0]] = v;
- }
-
- if (mode != "server") {
- var self = this, fullCol = this.fullCollection;
- var success = options.success;
- options.success = function (col, resp, opts) {
-
- // make sure the caller's intent is obeyed
- opts = opts || {};
- if (_isUndefined(options.silent)) delete opts.silent;
- else opts.silent = options.silent;
-
- var models = col.models;
- if (mode == "client") fullCol.reset(models, opts);
- else fullCol.add(models, _extend({at: fullCol.length}, opts));
-
- if (success) success(col, resp, opts);
- };
-
- // silent the first reset from backbone
- return BBColProto.fetch.call(self, _extend({}, options, {silent: true}));
- }
-
- return BBColProto.fetch.call(this, options);
- },
-
- /**
- Convenient method for making a `comparator` sorted by a model attribute
- identified by `sortKey` and ordered by `order`.
-
- Like a Backbone.Collection, a Backbone.PageableCollection will maintain
- the __current page__ in sorted order on the client side if a `comparator`
- is attached to it. If the collection is in client mode, you can attach a
- comparator to #fullCollection to have all the pages reflect the global
- sorting order by specifying an option `full` to `true`. You __must__ call
- `sort` manually or #fullCollection.sort after calling this method to
- force a resort.
-
- While you can use this method to sort the current page in server mode,
- the sorting order may not reflect the global sorting order due to the
- additions or removals of the records on the server since the last
- fetch. If you want the most updated page in a global sorting order, it is
- recommended that you set #state.sortKey and optionally #state.order, and
- then call #fetch.
-
- @protected
-
- @param {string} [sortKey=this.state.sortKey] See `state.sortKey`.
- @param {number} [order=this.state.order] See `state.order`.
- @param {(function(Backbone.Model, string): Object) | string} [sortValue] See #setSorting.
-
- See [Backbone.Collection.comparator](http://backbonejs.org/#Collection-comparator).
- */
- _makeComparator: function (sortKey, order, sortValue) {
- var state = this.state;
-
- sortKey = sortKey || state.sortKey;
- order = order || state.order;
-
- if (!sortKey || !order) return;
-
- if (!sortValue) sortValue = function (model, attr) {
- return model.get(attr);
- };
-
- return function (left, right) {
- var l = sortValue(left, sortKey), r = sortValue(right, sortKey), t;
- if (order === 1) t = l, l = r, r = t;
- if (l === r) return 0;
- else if (l < r) return -1;
- return 1;
- };
- },
-
- /**
- Adjusts the sorting for this pageable collection.
-
- Given a `sortKey` and an `order`, sets `state.sortKey` and
- `state.order`. A comparator can be applied on the client side to sort in
- the order defined if `options.side` is `"client"`. By default the
- comparator is applied to the #fullCollection. Set `options.full` to
- `false` to apply a comparator to the current page under any mode. Setting
- `sortKey` to `null` removes the comparator from both the current page and
- the full collection.
-
- If a `sortValue` function is given, it will be passed the `(model,
- sortKey)` arguments and is used to extract a value from the model during
- comparison sorts. If `sortValue` is not given, `model.get(sortKey)` is
- used for sorting.
-
- @chainable
-
- @param {string} sortKey See `state.sortKey`.
- @param {number} [order=this.state.order] See `state.order`.
- @param {Object} [options]
- @param {"server"|"client"} [options.side] By default, `"client"` if
- `mode` is `"client"`, `"server"` otherwise.
- @param {boolean} [options.full=true]
- @param {(function(Backbone.Model, string): Object) | string} [options.sortValue]
- */
- setSorting: function (sortKey, order, options) {
-
- var state = this.state;
-
- state.sortKey = sortKey;
- state.order = order = order || state.order;
-
- var fullCollection = this.fullCollection;
-
- var delComp = false, delFullComp = false;
-
- if (!sortKey) delComp = delFullComp = true;
-
- var mode = this.mode;
- options = _extend({side: mode == "client" ? mode : "server", full: true},
- options);
-
- var comparator = this._makeComparator(sortKey, order, options.sortValue);
-
- var full = options.full, side = options.side;
-
- if (side == "client") {
- if (full) {
- if (fullCollection) fullCollection.comparator = comparator;
- delComp = true;
- }
- else {
- this.comparator = comparator;
- delFullComp = true;
- }
- }
- else if (side == "server" && !full) {
- this.comparator = comparator;
- }
-
- if (delComp) delete this.comparator;
- if (delFullComp && fullCollection) delete fullCollection.comparator;
-
- return this;
- }
-
- });
-
- var PageableProto = PageableCollection.prototype;
-
- return PageableCollection;
-
-}));
diff --git a/security-admin/src/main/webapp/libs/bower/backbone-pageable/js/backbone-pageable.min.js b/security-admin/src/main/webapp/libs/bower/backbone-pageable/js/backbone-pageable.min.js
deleted file mode 100644
index 78f32fd91..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone-pageable/js/backbone-pageable.min.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- backbone-pageable 1.3.2
- http://github.com/wyuenho/backbone-pageable
-
- Copyright (c) 2013 Jimmy Yuen Ho Wong
- Licensed under the MIT @license.
-*/
-!function(a){if("object"==typeof exports)module.exports=a(require("underscore"),require("backbone"));else if("function"==typeof define&&define.amd)define(["underscore","backbone"],a);else if("undefined"!=typeof _&&"undefined"!=typeof Backbone){var b=Backbone.PageableCollection,c=a(_,Backbone);Backbone.PageableCollection.noConflict=function(){return Backbone.PageableCollection=b,c}}}(function(a,b){"use strict";function c(b,c){if(!a.isNumber(b)||a.isNaN(b)||!a.isFinite(b)||~~b!==b)throw ne [...]
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/libs/bower/backbone.babysitter/js/backbone.babysitter.js b/security-admin/src/main/webapp/libs/bower/backbone.babysitter/js/backbone.babysitter.js
deleted file mode 100644
index a182eda6a..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone.babysitter/js/backbone.babysitter.js
+++ /dev/null
@@ -1,178 +0,0 @@
-// Backbone.BabySitter
-// -------------------
-// v0.0.6
-//
-// Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.
-// Distributed under MIT license
-//
-// http://github.com/babysitterjs/backbone.babysitter
-
-(function (root, factory) {
- if (typeof exports === 'object') {
-
- var underscore = require('underscore');
- var backbone = require('backbone');
-
- module.exports = factory(underscore, backbone);
-
- } else if (typeof define === 'function' && define.amd) {
-
- define(['underscore', 'backbone'], factory);
-
- }
-}(this, function (_, Backbone) {
- "option strict";
-
- // Backbone.ChildViewContainer
-// ---------------------------
-//
-// Provide a container to store, retrieve and
-// shut down child views.
-
-Backbone.ChildViewContainer = (function(Backbone, _){
-
- // Container Constructor
- // ---------------------
-
- var Container = function(views){
- this._views = {};
- this._indexByModel = {};
- this._indexByCustom = {};
- this._updateLength();
-
- _.each(views, this.add, this);
- };
-
- // Container Methods
- // -----------------
-
- _.extend(Container.prototype, {
-
- // Add a view to this container. Stores the view
- // by `cid` and makes it searchable by the model
- // cid (and model itself). Optionally specify
- // a custom key to store an retrieve the view.
- add: function(view, customIndex){
- var viewCid = view.cid;
-
- // store the view
- this._views[viewCid] = view;
-
- // index it by model
- if (view.model){
- this._indexByModel[view.model.cid] = viewCid;
- }
-
- // index by custom
- if (customIndex){
- this._indexByCustom[customIndex] = viewCid;
- }
-
- this._updateLength();
- },
-
- // Find a view by the model that was attached to
- // it. Uses the model's `cid` to find it.
- findByModel: function(model){
- return this.findByModelCid(model.cid);
- },
-
- // Find a view by the `cid` of the model that was attached to
- // it. Uses the model's `cid` to find the view `cid` and
- // retrieve the view using it.
- findByModelCid: function(modelCid){
- var viewCid = this._indexByModel[modelCid];
- return this.findByCid(viewCid);
- },
-
- // Find a view by a custom indexer.
- findByCustom: function(index){
- var viewCid = this._indexByCustom[index];
- return this.findByCid(viewCid);
- },
-
- // Find by index. This is not guaranteed to be a
- // stable index.
- findByIndex: function(index){
- return _.values(this._views)[index];
- },
-
- // retrieve a view by it's `cid` directly
- findByCid: function(cid){
- return this._views[cid];
- },
-
- // Remove a view
- remove: function(view){
- var viewCid = view.cid;
-
- // delete model index
- if (view.model){
- delete this._indexByModel[view.model.cid];
- }
-
- // delete custom index
- _.any(this._indexByCustom, function(cid, key) {
- if (cid === viewCid) {
- delete this._indexByCustom[key];
- return true;
- }
- }, this);
-
- // remove the view from the container
- delete this._views[viewCid];
-
- // update the length
- this._updateLength();
- },
-
- // Call a method on every view in the container,
- // passing parameters to the call method one at a
- // time, like `function.call`.
- call: function(method){
- this.apply(method, _.tail(arguments));
- },
-
- // Apply a method on every view in the container,
- // passing parameters to the call method one at a
- // time, like `function.apply`.
- apply: function(method, args){
- _.each(this._views, function(view){
- if (_.isFunction(view[method])){
- view[method].apply(view, args || []);
- }
- });
- },
-
- // Update the `.length` attribute on this container
- _updateLength: function(){
- this.length = _.size(this._views);
- }
- });
-
- // Borrowing this code from Backbone.Collection:
- // http://backbonejs.org/docs/backbone.html#section-106
- //
- // Mix in methods from Underscore, for iteration, and other
- // collection related features.
- var methods = ['forEach', 'each', 'map', 'find', 'detect', 'filter',
- 'select', 'reject', 'every', 'all', 'some', 'any', 'include',
- 'contains', 'invoke', 'toArray', 'first', 'initial', 'rest',
- 'last', 'without', 'isEmpty', 'pluck'];
-
- _.each(methods, function(method) {
- Container.prototype[method] = function() {
- var views = _.values(this._views);
- var args = [views].concat(_.toArray(arguments));
- return _[method].apply(_, args);
- };
- });
-
- // return the public API
- return Container;
-})(Backbone, _);
-
- return Backbone.ChildViewContainer;
-
-}));
-
diff --git a/security-admin/src/main/webapp/libs/bower/backbone.babysitter/js/backbone.babysitter.min.js b/security-admin/src/main/webapp/libs/bower/backbone.babysitter/js/backbone.babysitter.min.js
deleted file mode 100644
index 78355c8d7..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone.babysitter/js/backbone.babysitter.min.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// Backbone.BabySitter
-// -------------------
-// v0.0.6
-//
-// Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.
-// Distributed under MIT license
-//
-// http://github.com/babysitterjs/backbone.babysitter
-
-(function(i,e){if("object"==typeof exports){var t=require("underscore"),n=require("backbone");module.exports=e(t,n)}else"function"==typeof define&&define.amd&&define(["underscore","backbone"],e)})(this,function(i,e){"option strict";return e.ChildViewContainer=function(i,e){var t=function(i){this._views={},this._indexByModel={},this._indexByCustom={},this._updateLength(),e.each(i,this.add,this)};e.extend(t.prototype,{add:function(i,e){var t=i.cid;this._views[t]=i,i.model&&(this._indexByMo [...]
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/libs/bower/backbone.bootstrap-modal/js/backbone.bootstrap-modal.js b/security-admin/src/main/webapp/libs/bower/backbone.bootstrap-modal/js/backbone.bootstrap-modal.js
deleted file mode 100644
index c2fa0452f..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone.bootstrap-modal/js/backbone.bootstrap-modal.js
+++ /dev/null
@@ -1,291 +0,0 @@
-/**
- * Bootstrap Modal wrapper for use with Backbone.
- *
- * Takes care of instantiation, manages multiple modals,
- * adds several options and removes the element from the DOM when closed
- *
- * @author Charles Davison <ch...@powmedia.co.uk>
- *
- * Events:
- * shown: Fired when the modal has finished animating in
- * hidden: Fired when the modal has finished animating out
- * cancel: The user dismissed the modal
- * ok: The user clicked OK
- */
-(function($, _, Backbone) {
-
- //Set custom template settings
- var _interpolateBackup = _.templateSettings;
- _.templateSettings = {
- interpolate: /\{\{(.+?)\}\}/g,
- evaluate: /<%([\s\S]+?)%>/g
- };
-
- var template = _.template('\
- <div class="modal-dialog modal-lg"><div class="modal-content">\
- <% if (title) { %>\
- <div class="modal-header">\
- <h4 class="modal-title">{{title}}</h4>\
- <% if (allowCancel) { %>\
- <a class="close">×</a>\
- <% } %>\
- </div>\
- <% } %>\
- <div class="modal-body">{{content}}</div>\
- <% if (showFooter) { %>\
- <div class="modal-footer">\
- <% if (allowCancel) { %>\
- <% if (cancelText) { %>\
- <a href="#" class="btn cancel btn-sm">{{cancelText}}</a>\
- <% } %>\
- <% } %>\
- <a href="#" class="btn ok btn-primary btn-sm">{{okText}}</a>\
- </div>\
- <% } %>\
- </div></div>\
- ');
-
- //Reset to users' template settings
- _.templateSettings = _interpolateBackup;
-
-
- var Modal = Backbone.View.extend({
-
- className: 'modal',
-
- events: {
- 'click .close': function(event) {
- event.preventDefault();
-
- this.trigger('cancel');
-
- if (this.options.content && this.options.content.trigger) {
- this.options.content.trigger('cancel', this);
- }
- },
- 'click .cancel': function(event) {
- event.preventDefault();
-
- this.trigger('cancel');
-
- if (this.options.content && this.options.content.trigger) {
- this.options.content.trigger('cancel', this);
- }
- },
- 'click .ok': function(event) {
- event.preventDefault();
-
- this.trigger('ok');
-
- if (this.options.content && this.options.content.trigger) {
- this.options.content.trigger('ok', this);
- }
-
- if (this.options.okCloses) {
- this.close();
- }
- },
- 'keypress': function(event) {
- if (this.options.enterTriggersOk && event.which == 13) {
- event.preventDefault();
-
- this.trigger('ok');
-
- if (this.options.content && this.options.content.trigger) {
- this.options.content.trigger('ok', this);
- }
-
- if (this.options.okCloses) {
- this.close();
- }
- }
- }
- },
-
- /**
- * Creates an instance of a Bootstrap Modal
- *
- * @see http://twitter.github.com/bootstrap/javascript.html#modals
- *
- * @param {Object} options
- * @param {String|View} [options.content] Modal content. Default: none
- * @param {String} [options.title] Title. Default: none
- * @param {String} [options.okText] Text for the OK button. Default: 'OK'
- * @param {String} [options.cancelText] Text for the cancel button. Default: 'Cancel'. If passed a falsey value, the button will be removed
- * @param {Boolean} [options.allowCancel Whether the modal can be closed, other than by pressing OK. Default: true
- * @param {Boolean} [options.escape] Whether the 'esc' key can dismiss the modal. Default: true, but false if options.cancellable is true
- * @param {Boolean} [options.animate] Whether to animate in/out. Default: false
- * @param {Function} [options.template] Compiled underscore template to override the default one
- * @param {Boolean} [options.enterTriggersOk] Whether the 'enter' key will trigger OK. Default: false
- */
- initialize: function(options) {
- this.options = _.extend({
- title: null,
- okText: 'OK',
- focusOk: true,
- okCloses: true,
- cancelText: 'Cancel',
- showFooter: true,
- allowCancel: true,
- escape: true,
- animate: false,
- template: template,
- enterTriggersOk: false
- }, options);
- },
-
- /**
- * Creates the DOM element
- *
- * @api private
- */
- render: function() {
- var $el = this.$el,
- options = this.options,
- content = options.content;
-
- //Create the modal container
- $el.html(options.template(options));
-
- var $content = this.$content = $el.find('.modal-body')
-
- //Insert the main content if it's a view
- if (content && content.$el) {
- content.render();
- $el.find('.modal-body').html(content.$el);
- }
-
- if (options.animate) $el.addClass('fade');
-
- this.isRendered = true;
-
- return this;
- },
-
- /**
- * Renders and shows the modal
- *
- * @param {Function} [cb] Optional callback that runs only when OK is pressed.
- */
- open: function(cb) {
- if (!this.isRendered) this.render();
-
- var self = this,
- $el = this.$el;
-
- //Create it
- $el.modal(_.extend({
- keyboard: this.options.allowCancel,
- backdrop: this.options.allowCancel ? true : 'static'
- }, this.options.modalOptions));
-
- //Focus OK button
- $el.one('shown.bs.modal', function() {
- if (self.options.focusOk) {
- $el.find('.btn.ok').focus();
- }
-
- if (self.options.content && self.options.content.trigger) {
- self.options.content.trigger('shown', self);
- }
-
- self.trigger('shown');
- });
-
- //Adjust the modal and backdrop z-index; for dealing with multiple modals
- var numModals = Modal.count,
- $backdrop = $('.modal-backdrop:eq('+numModals+')'),
- backdropIndex = parseInt($backdrop.css('z-index'),10),
- elIndex = parseInt($backdrop.css('z-index'), 10);
-
- $backdrop.css('z-index', backdropIndex + numModals);
- this.$el.css('z-index', elIndex + numModals);
-
- if (this.options.allowCancel) {
- $backdrop.one('click', function() {
- if (self.options.content && self.options.content.trigger) {
- self.options.content.trigger('cancel', self);
- }
-
- self.trigger('cancel');
- });
-
- $(document).one('keyup.dismiss.modal', function (e) {
- e.which == 27 && self.trigger('cancel');
-
- if (self.options.content && self.options.content.trigger) {
- e.which == 27 && self.options.content.trigger('shown', self);
- }
- });
- }
-
- this.on('cancel', function() {
- self.close();
- });
-
- Modal.count++;
-
- //Run callback on OK if provided
- if (cb) {
- self.on('ok', cb);
- }
-
- return this;
- },
-
- /**
- * Closes the modal
- */
- close: function() {
- var self = this,
- $el = this.$el;
-
- //Check if the modal should stay open
- if (this._preventClose) {
- this._preventClose = false;
- return;
- }
-
- $el.one('hidden.bs.modal', function onHidden(e) {
- // Ignore events propagated from interior objects, like bootstrap tooltips
- if(e.target !== e.currentTarget){
- return $el.one('hidden', onHidden);
- }
- self.remove();
-
- if (self.options.content && self.options.content.trigger) {
- self.options.content.trigger('hidden', self);
- }
-
- self.trigger('hidden');
- });
-
- $el.modal('hide');
-
- Modal.count--;
- },
-
- /**
- * Stop the modal from closing.
- * Can be called from within a 'close' or 'ok' event listener.
- */
- preventClose: function() {
- this._preventClose = true;
- }
- }, {
- //STATICS
-
- //The number of modals on display
- count: 0
- });
-
-
- //EXPORTS
- //CommonJS
- if (typeof require == 'function' && typeof module !== 'undefined' && exports) {
- module.exports = Modal;
- }
- //Regular; add to Backbone.Bootstrap.Modal
- Backbone.BootstrapModal = Modal;
-
-})(jQuery, _, Backbone);
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/libs/bower/backbone.localstorage/backbone.localStorage.js b/security-admin/src/main/webapp/libs/bower/backbone.localstorage/backbone.localStorage.js
deleted file mode 100644
index 4446d4ac7..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone.localstorage/backbone.localStorage.js
+++ /dev/null
@@ -1,222 +0,0 @@
-/**
- * Backbone localStorage Adapter
- * Version 1.1.7
- *
- * https://github.com/jeromegn/Backbone.localStorage
- */
-(function (root, factory) {
- if (typeof exports === 'object' && typeof require === 'function') {
- module.exports = factory(require("underscore"), require("backbone"));
- } else if (typeof define === "function" && define.amd) {
- // AMD. Register as an anonymous module.
- define(["underscore","backbone"], function(_, Backbone) {
- // Use global variables if the locals are undefined.
- return factory(_ || root._, Backbone || root.Backbone);
- });
- } else {
- // RequireJS isn't being used. Assume underscore and backbone are loaded in <script> tags
- factory(_, Backbone);
- }
-}(this, function(_, Backbone) {
-// A simple module to replace `Backbone.sync` with *localStorage*-based
-// persistence. Models are given GUIDS, and saved into a JSON object. Simple
-// as that.
-
-// Hold reference to Underscore.js and Backbone.js in the closure in order
-// to make things work even if they are removed from the global namespace
-
-// Generate four random hex digits.
-function S4() {
- return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
-};
-
-// Generate a pseudo-GUID by concatenating random hexadecimal.
-function guid() {
- return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
-};
-
-// Our Store is represented by a single JS object in *localStorage*. Create it
-// with a meaningful name, like the name you'd give a table.
-// window.Store is deprectated, use Backbone.LocalStorage instead
-Backbone.LocalStorage = window.Store = function(name) {
- if( !this.localStorage ) {
- throw "Backbone.localStorage: Environment does not support localStorage."
- }
- this.name = name;
- var store = this.localStorage().getItem(this.name);
- this.records = (store && store.split(",")) || [];
-};
-
-_.extend(Backbone.LocalStorage.prototype, {
-
- // Save the current state of the **Store** to *localStorage*.
- save: function() {
- this.localStorage().setItem(this.name, this.records.join(","));
- },
-
- // Add a model, giving it a (hopefully)-unique GUID, if it doesn't already
- // have an id of it's own.
- create: function(model) {
- if (!model.id) {
- model.id = guid();
- model.set(model.idAttribute, model.id);
- }
- this.localStorage().setItem(this.name+"-"+model.id, JSON.stringify(model));
- this.records.push(model.id.toString());
- this.save();
- return this.find(model);
- },
-
- // Update a model by replacing its copy in `this.data`.
- update: function(model) {
- this.localStorage().setItem(this.name+"-"+model.id, JSON.stringify(model));
- if (!_.include(this.records, model.id.toString()))
- this.records.push(model.id.toString()); this.save();
- return this.find(model);
- },
-
- // Retrieve a model from `this.data` by id.
- find: function(model) {
- return this.jsonData(this.localStorage().getItem(this.name+"-"+model.id));
- },
-
- // Return the array of all models currently in storage.
- findAll: function() {
- // Lodash removed _#chain in v1.0.0-rc.1
- return (_.chain || _)(this.records)
- .map(function(id){
- return this.jsonData(this.localStorage().getItem(this.name+"-"+id));
- }, this)
- .compact()
- .value();
- },
-
- // Delete a model from `this.data`, returning it.
- destroy: function(model) {
- if (model.isNew())
- return false
- this.localStorage().removeItem(this.name+"-"+model.id);
- this.records = _.reject(this.records, function(id){
- return id === model.id.toString();
- });
- this.save();
- return model;
- },
-
- localStorage: function() {
- return localStorage;
- },
-
- // fix for "illegal access" error on Android when JSON.parse is passed null
- jsonData: function (data) {
- return data && JSON.parse(data);
- },
-
- // Clear localStorage for specific collection.
- _clear: function() {
- var local = this.localStorage(),
- itemRe = new RegExp("^" + this.name + "-");
-
- // Remove id-tracking item (e.g., "foo").
- local.removeItem(this.name);
-
- // Lodash removed _#chain in v1.0.0-rc.1
- // Match all data items (e.g., "foo-ID") and remove.
- (_.chain || _)(local).keys()
- .filter(function (k) { return itemRe.test(k); })
- .each(function (k) { local.removeItem(k); });
-
- this.records.length = 0;
- },
-
- // Size of localStorage.
- _storageSize: function() {
- return this.localStorage().length;
- }
-
-});
-
-// localSync delegate to the model or collection's
-// *localStorage* property, which should be an instance of `Store`.
-// window.Store.sync and Backbone.localSync is deprecated, use Backbone.LocalStorage.sync instead
-Backbone.LocalStorage.sync = window.Store.sync = Backbone.localSync = function(method, model, options) {
- var store = model.localStorage || model.collection.localStorage;
-
- var resp, errorMessage, syncDfd = Backbone.$.Deferred && Backbone.$.Deferred(); //If $ is having Deferred - use it.
-
- try {
-
- switch (method) {
- case "read":
- resp = model.id != undefined ? store.find(model) : store.findAll();
- break;
- case "create":
- resp = store.create(model);
- break;
- case "update":
- resp = store.update(model);
- break;
- case "delete":
- resp = store.destroy(model);
- break;
- }
-
- } catch(error) {
- if (error.code === 22 && store._storageSize() === 0)
- errorMessage = "Private browsing is unsupported";
- else
- errorMessage = error.message;
- }
-
- if (resp) {
- if (options && options.success) {
- if (Backbone.VERSION === "0.9.10") {
- options.success(model, resp, options);
- } else {
- options.success(resp);
- }
- }
- if (syncDfd) {
- syncDfd.resolve(resp);
- }
-
- } else {
- errorMessage = errorMessage ? errorMessage
- : "Record Not Found";
-
- if (options && options.error)
- if (Backbone.VERSION === "0.9.10") {
- options.error(model, errorMessage, options);
- } else {
- options.error(errorMessage);
- }
-
- if (syncDfd)
- syncDfd.reject(errorMessage);
- }
-
- // add compatibility with $.ajax
- // always execute callback for success and error
- if (options && options.complete) options.complete(resp);
-
- return syncDfd && syncDfd.promise();
-};
-
-Backbone.ajaxSync = Backbone.sync;
-
-Backbone.getSyncMethod = function(model) {
- if(model.localStorage || (model.collection && model.collection.localStorage)) {
- return Backbone.localSync;
- }
-
- return Backbone.ajaxSync;
-};
-
-// Override 'Backbone.sync' to default to localSync,
-// the original 'Backbone.sync' is still available in 'Backbone.ajaxSync'
-Backbone.sync = function(method, model, options) {
- return Backbone.getSyncMethod(model).apply(this, [method, model, options]);
-};
-
-return Backbone.LocalStorage;
-}));
diff --git a/security-admin/src/main/webapp/libs/bower/backbone.marionette/js/backbone.marionette.js b/security-admin/src/main/webapp/libs/bower/backbone.marionette/js/backbone.marionette.js
deleted file mode 100644
index dee18607d..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone.marionette/js/backbone.marionette.js
+++ /dev/null
@@ -1,1959 +0,0 @@
-// MarionetteJS (Backbone.Marionette)
-// ----------------------------------
-// v1.1.0
-//
-// Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.
-// Distributed under MIT license
-//
-// http://marionettejs.com
-
-
-
-/*!
- * Includes BabySitter
- * https://github.com/marionettejs/backbone.babysitter/
- *
- * Includes Wreqr
- * https://github.com/marionettejs/backbone.wreqr/
- */
-
-(function (root, factory) {
- if (typeof exports === 'object') {
-
- var underscore = require('underscore');
- var backbone = require('backbone');
- var wreqr = require('backbone.wreqr');
- var babysitter = require('backbone.babysitter');
-
- module.exports = factory(underscore, backbone, wreqr, babysitter);
-
- } else if (typeof define === 'function' && define.amd) {
-
- define(['underscore', 'backbone', 'backbone.wreqr', 'backbone.babysitter'], factory);
-
- }
-}(this, function (_, Backbone) {
-
- var Marionette = (function(global, Backbone, _){
- "use strict";
-
- // Define and export the Marionette namespace
- var Marionette = {};
- Backbone.Marionette = Marionette;
-
- // Get the DOM manipulator for later use
- Marionette.$ = Backbone.$;
-
-// Helpers
-// -------
-
-// For slicing `arguments` in functions
-var protoSlice = Array.prototype.slice;
-function slice(args) {
- return protoSlice.call(args);
-}
-
-function throwError(message, name) {
- var error = new Error(message);
- error.name = name || 'Error';
- throw error;
-}
-
-// Marionette.extend
-// -----------------
-
-// Borrow the Backbone `extend` method so we can use it as needed
-Marionette.extend = Backbone.Model.extend;
-
-// Marionette.getOption
-// --------------------
-
-// Retrieve an object, function or other value from a target
-// object or its `options`, with `options` taking precedence.
-Marionette.getOption = function(target, optionName){
- if (!target || !optionName){ return; }
- var value;
-
- if (target.options && (optionName in target.options) && (target.options[optionName] !== undefined)){
- value = target.options[optionName];
- } else {
- value = target[optionName];
- }
-
- return value;
-};
-
-// Trigger an event and/or a corresponding method name. Examples:
-//
-// `this.triggerMethod("foo")` will trigger the "foo" event and
-// call the "onFoo" method.
-//
-// `this.triggerMethod("foo:bar") will trigger the "foo:bar" event and
-// call the "onFooBar" method.
-Marionette.triggerMethod = (function(){
-
- // split the event name on the :
- var splitter = /(^|:)(\w)/gi;
-
- // take the event section ("section1:section2:section3")
- // and turn it in to uppercase name
- function getEventName(match, prefix, eventName) {
- return eventName.toUpperCase();
- }
-
- // actual triggerMethod name
- var triggerMethod = function(event) {
- // get the method name from the event name
- var methodName = 'on' + event.replace(splitter, getEventName);
- var method = this[methodName];
-
- // trigger the event, if a trigger method exists
- if(_.isFunction(this.trigger)) {
- this.trigger.apply(this, arguments);
- }
-
- // call the onMethodName if it exists
- if (_.isFunction(method)) {
- // pass all arguments, except the event name
- return method.apply(this, _.tail(arguments));
- }
- };
-
- return triggerMethod;
-})();
-
-// DOMRefresh
-// ----------
-//
-// Monitor a view's state, and after it has been rendered and shown
-// in the DOM, trigger a "dom:refresh" event every time it is
-// re-rendered.
-
-Marionette.MonitorDOMRefresh = (function(){
- // track when the view has been shown in the DOM,
- // using a Marionette.Region (or by other means of triggering "show")
- function handleShow(view){
- view._isShown = true;
- triggerDOMRefresh(view);
- }
-
- // track when the view has been rendered
- function handleRender(view){
- view._isRendered = true;
- triggerDOMRefresh(view);
- }
-
- // Trigger the "dom:refresh" event and corresponding "onDomRefresh" method
- function triggerDOMRefresh(view){
- if (view._isShown && view._isRendered){
- if (_.isFunction(view.triggerMethod)){
- view.triggerMethod("dom:refresh");
- }
- }
- }
-
- // Export public API
- return function(view){
- view.listenTo(view, "show", function(){
- handleShow(view);
- });
-
- view.listenTo(view, "render", function(){
- handleRender(view);
- });
- };
-})();
-
-
-// Marionette.bindEntityEvents & unbindEntityEvents
-// ---------------------------
-//
-// These methods are used to bind/unbind a backbone "entity" (collection/model)
-// to methods on a target object.
-//
-// The first parameter, `target`, must have a `listenTo` method from the
-// EventBinder object.
-//
-// The second parameter is the entity (Backbone.Model or Backbone.Collection)
-// to bind the events from.
-//
-// The third parameter is a hash of { "event:name": "eventHandler" }
-// configuration. Multiple handlers can be separated by a space. A
-// function can be supplied instead of a string handler name.
-
-(function(Marionette){
- "use strict";
-
- // Bind the event to handlers specified as a string of
- // handler names on the target object
- function bindFromStrings(target, entity, evt, methods){
- var methodNames = methods.split(/\s+/);
-
- _.each(methodNames,function(methodName) {
-
- var method = target[methodName];
- if(!method) {
- throwError("Method '"+ methodName +"' was configured as an event handler, but does not exist.");
- }
-
- target.listenTo(entity, evt, method, target);
- });
- }
-
- // Bind the event to a supplied callback function
- function bindToFunction(target, entity, evt, method){
- target.listenTo(entity, evt, method, target);
- }
-
- // Bind the event to handlers specified as a string of
- // handler names on the target object
- function unbindFromStrings(target, entity, evt, methods){
- var methodNames = methods.split(/\s+/);
-
- _.each(methodNames,function(methodName) {
- var method = target[methodName];
- target.stopListening(entity, evt, method, target);
- });
- }
-
- // Bind the event to a supplied callback function
- function unbindToFunction(target, entity, evt, method){
- target.stopListening(entity, evt, method, target);
- }
-
-
- // generic looping function
- function iterateEvents(target, entity, bindings, functionCallback, stringCallback){
- if (!entity || !bindings) { return; }
-
- // allow the bindings to be a function
- if (_.isFunction(bindings)){
- bindings = bindings.call(target);
- }
-
- // iterate the bindings and bind them
- _.each(bindings, function(methods, evt){
-
- // allow for a function as the handler,
- // or a list of event names as a string
- if (_.isFunction(methods)){
- functionCallback(target, entity, evt, methods);
- } else {
- stringCallback(target, entity, evt, methods);
- }
-
- });
- }
-
- // Export Public API
- Marionette.bindEntityEvents = function(target, entity, bindings){
- iterateEvents(target, entity, bindings, bindToFunction, bindFromStrings);
- };
-
- Marionette.unbindEntityEvents = function(target, entity, bindings){
- iterateEvents(target, entity, bindings, unbindToFunction, unbindFromStrings);
- };
-
-})(Marionette);
-
-
-// Callbacks
-// ---------
-
-// A simple way of managing a collection of callbacks
-// and executing them at a later point in time, using jQuery's
-// `Deferred` object.
-Marionette.Callbacks = function(){
- this._deferred = Marionette.$.Deferred();
- this._callbacks = [];
-};
-
-_.extend(Marionette.Callbacks.prototype, {
-
- // Add a callback to be executed. Callbacks added here are
- // guaranteed to execute, even if they are added after the
- // `run` method is called.
- add: function(callback, contextOverride){
- this._callbacks.push({cb: callback, ctx: contextOverride});
-
- this._deferred.done(function(context, options){
- if (contextOverride){ context = contextOverride; }
- callback.call(context, options);
- });
- },
-
- // Run all registered callbacks with the context specified.
- // Additional callbacks can be added after this has been run
- // and they will still be executed.
- run: function(options, context){
- this._deferred.resolve(context, options);
- },
-
- // Resets the list of callbacks to be run, allowing the same list
- // to be run multiple times - whenever the `run` method is called.
- reset: function(){
- var callbacks = this._callbacks;
- this._deferred = Marionette.$.Deferred();
- this._callbacks = [];
-
- _.each(callbacks, function(cb){
- this.add(cb.cb, cb.ctx);
- }, this);
- }
-});
-
-
-// Marionette Controller
-// ---------------------
-//
-// A multi-purpose object to use as a controller for
-// modules and routers, and as a mediator for workflow
-// and coordination of other objects, views, and more.
-Marionette.Controller = function(options){
- this.triggerMethod = Marionette.triggerMethod;
- this.options = options || {};
-
- if (_.isFunction(this.initialize)){
- this.initialize(this.options);
- }
-};
-
-Marionette.Controller.extend = Marionette.extend;
-
-// Controller Methods
-// --------------
-
-// Ensure it can trigger events with Backbone.Events
-_.extend(Marionette.Controller.prototype, Backbone.Events, {
- close: function(){
- this.stopListening();
- this.triggerMethod("close");
- this.unbind();
- }
-});
-
-// Region
-// ------
-//
-// Manage the visual regions of your composite application. See
-// http://lostechies.com/derickbailey/2011/12/12/composite-js-apps-regions-and-region-managers/
-
-Marionette.Region = function(options){
- this.options = options || {};
-
- this.el = Marionette.getOption(this, "el");
-
- if (!this.el){
- var err = new Error("An 'el' must be specified for a region.");
- err.name = "NoElError";
- throw err;
- }
-
- if (this.initialize){
- var args = Array.prototype.slice.apply(arguments);
- this.initialize.apply(this, args);
- }
-};
-
-
-// Region Type methods
-// -------------------
-
-_.extend(Marionette.Region, {
-
- // Build an instance of a region by passing in a configuration object
- // and a default region type to use if none is specified in the config.
- //
- // The config object should either be a string as a jQuery DOM selector,
- // a Region type directly, or an object literal that specifies both
- // a selector and regionType:
- //
- // ```js
- // {
- // selector: "#foo",
- // regionType: MyCustomRegion
- // }
- // ```
- //
- buildRegion: function(regionConfig, defaultRegionType){
-
- var regionIsString = (typeof regionConfig === "string");
- var regionSelectorIsString = (typeof regionConfig.selector === "string");
- var regionTypeIsUndefined = (typeof regionConfig.regionType === "undefined");
- var regionIsType = (typeof regionConfig === "function");
-
- if (!regionIsType && !regionIsString && !regionSelectorIsString) {
- throw new Error("Region must be specified as a Region type, a selector string or an object with selector property");
- }
-
- var selector, RegionType;
-
- // get the selector for the region
-
- if (regionIsString) {
- selector = regionConfig;
- }
-
- if (regionConfig.selector) {
- selector = regionConfig.selector;
- }
-
- // get the type for the region
-
- if (regionIsType){
- RegionType = regionConfig;
- }
-
- if (!regionIsType && regionTypeIsUndefined) {
- RegionType = defaultRegionType;
- }
-
- if (regionConfig.regionType) {
- RegionType = regionConfig.regionType;
- }
-
- // build the region instance
- var region = new RegionType({
- el: selector
- });
-
- // override the `getEl` function if we have a parentEl
- // this must be overridden to ensure the selector is found
- // on the first use of the region. if we try to assign the
- // region's `el` to `parentEl.find(selector)` in the object
- // literal to build the region, the element will not be
- // guaranteed to be in the DOM already, and will cause problems
- if (regionConfig.parentEl){
-
- region.getEl = function(selector) {
- var parentEl = regionConfig.parentEl;
- if (_.isFunction(parentEl)){
- parentEl = parentEl();
- }
- return parentEl.find(selector);
- };
- }
-
- return region;
- }
-
-});
-
-// Region Instance Methods
-// -----------------------
-
-_.extend(Marionette.Region.prototype, Backbone.Events, {
-
- // Displays a backbone view instance inside of the region.
- // Handles calling the `render` method for you. Reads content
- // directly from the `el` attribute. Also calls an optional
- // `onShow` and `close` method on your view, just after showing
- // or just before closing the view, respectively.
- show: function(view){
-
- this.ensureEl();
-
- var isViewClosed = view.isClosed || _.isUndefined(view.$el);
-
- var isDifferentView = view !== this.currentView;
-
- if (isDifferentView) {
- this.close();
- }
-
- view.render();
-
- if (isDifferentView || isViewClosed) {
- this.open(view);
- }
-
- this.currentView = view;
-
- Marionette.triggerMethod.call(this, "show", view);
- Marionette.triggerMethod.call(view, "show");
- },
-
- ensureEl: function(){
- if (!this.$el || this.$el.length === 0){
- this.$el = this.getEl(this.el);
- }
- },
-
- // Override this method to change how the region finds the
- // DOM element that it manages. Return a jQuery selector object.
- getEl: function(selector){
- return Marionette.$(selector);
- },
-
- // Override this method to change how the new view is
- // appended to the `$el` that the region is managing
- open: function(view){
- this.$el.empty().append(view.el);
- },
-
- // Close the current view, if there is one. If there is no
- // current view, it does nothing and returns immediately.
- close: function(){
- var view = this.currentView;
- if (!view || view.isClosed){ return; }
-
- // call 'close' or 'remove', depending on which is found
- if (view.close) { view.close(); }
- else if (view.remove) { view.remove(); }
-
- Marionette.triggerMethod.call(this, "close");
-
- delete this.currentView;
- },
-
- // Attach an existing view to the region. This
- // will not call `render` or `onShow` for the new view,
- // and will not replace the current HTML for the `el`
- // of the region.
- attachView: function(view){
- this.currentView = view;
- },
-
- // Reset the region by closing any existing view and
- // clearing out the cached `$el`. The next time a view
- // is shown via this region, the region will re-query the
- // DOM for the region's `el`.
- reset: function(){
- this.close();
- delete this.$el;
- }
-});
-
-// Copy the `extend` function used by Backbone's classes
-Marionette.Region.extend = Marionette.extend;
-
-// Marionette.RegionManager
-// ------------------------
-//
-// Manage one or more related `Marionette.Region` objects.
-Marionette.RegionManager = (function(Marionette){
-
- var RegionManager = Marionette.Controller.extend({
- constructor: function(options){
- this._regions = {};
- Marionette.Controller.prototype.constructor.call(this, options);
- },
-
- // Add multiple regions using an object literal, where
- // each key becomes the region name, and each value is
- // the region definition.
- addRegions: function(regionDefinitions, defaults){
- var regions = {};
-
- _.each(regionDefinitions, function(definition, name){
- if (typeof definition === "string"){
- definition = { selector: definition };
- }
-
- if (definition.selector){
- definition = _.defaults({}, definition, defaults);
- }
-
- var region = this.addRegion(name, definition);
- regions[name] = region;
- }, this);
-
- return regions;
- },
-
- // Add an individual region to the region manager,
- // and return the region instance
- addRegion: function(name, definition){
- var region;
-
- var isObject = _.isObject(definition);
- var isString = _.isString(definition);
- var hasSelector = !!definition.selector;
-
- if (isString || (isObject && hasSelector)){
- region = Marionette.Region.buildRegion(definition, Marionette.Region);
- } else if (_.isFunction(definition)){
- region = Marionette.Region.buildRegion(definition, Marionette.Region);
- } else {
- region = definition;
- }
-
- this._store(name, region);
- this.triggerMethod("region:add", name, region);
- return region;
- },
-
- // Get a region by name
- get: function(name){
- return this._regions[name];
- },
-
- // Remove a region by name
- removeRegion: function(name){
- var region = this._regions[name];
- this._remove(name, region);
- },
-
- // Close all regions in the region manager, and
- // remove them
- removeRegions: function(){
- _.each(this._regions, function(region, name){
- this._remove(name, region);
- }, this);
- },
-
- // Close all regions in the region manager, but
- // leave them attached
- closeRegions: function(){
- _.each(this._regions, function(region, name){
- region.close();
- }, this);
- },
-
- // Close all regions and shut down the region
- // manager entirely
- close: function(){
- this.removeRegions();
- var args = Array.prototype.slice.call(arguments);
- Marionette.Controller.prototype.close.apply(this, args);
- },
-
- // internal method to store regions
- _store: function(name, region){
- this._regions[name] = region;
- this._setLength();
- },
-
- // internal method to remove a region
- _remove: function(name, region){
- region.close();
- delete this._regions[name];
- this._setLength();
- this.triggerMethod("region:remove", name, region);
- },
-
- // set the number of regions current held
- _setLength: function(){
- this.length = _.size(this._regions);
- }
-
- });
-
- // Borrowing this code from Backbone.Collection:
- // http://backbonejs.org/docs/backbone.html#section-106
- //
- // Mix in methods from Underscore, for iteration, and other
- // collection related features.
- var methods = ['forEach', 'each', 'map', 'find', 'detect', 'filter',
- 'select', 'reject', 'every', 'all', 'some', 'any', 'include',
- 'contains', 'invoke', 'toArray', 'first', 'initial', 'rest',
- 'last', 'without', 'isEmpty', 'pluck'];
-
- _.each(methods, function(method) {
- RegionManager.prototype[method] = function() {
- var regions = _.values(this._regions);
- var args = [regions].concat(_.toArray(arguments));
- return _[method].apply(_, args);
- };
- });
-
- return RegionManager;
-})(Marionette);
-
-
-// Template Cache
-// --------------
-
-// Manage templates stored in `<script>` blocks,
-// caching them for faster access.
-Marionette.TemplateCache = function(templateId){
- this.templateId = templateId;
-};
-
-// TemplateCache object-level methods. Manage the template
-// caches from these method calls instead of creating
-// your own TemplateCache instances
-_.extend(Marionette.TemplateCache, {
- templateCaches: {},
-
- // Get the specified template by id. Either
- // retrieves the cached version, or loads it
- // from the DOM.
- get: function(templateId){
- var cachedTemplate = this.templateCaches[templateId];
-
- if (!cachedTemplate){
- cachedTemplate = new Marionette.TemplateCache(templateId);
- this.templateCaches[templateId] = cachedTemplate;
- }
-
- return cachedTemplate.load();
- },
-
- // Clear templates from the cache. If no arguments
- // are specified, clears all templates:
- // `clear()`
- //
- // If arguments are specified, clears each of the
- // specified templates from the cache:
- // `clear("#t1", "#t2", "...")`
- clear: function(){
- var i;
- var args = slice(arguments);
- var length = args.length;
-
- if (length > 0){
- for(i=0; i<length; i++){
- delete this.templateCaches[args[i]];
- }
- } else {
- this.templateCaches = {};
- }
- }
-});
-
-// TemplateCache instance methods, allowing each
-// template cache object to manage its own state
-// and know whether or not it has been loaded
-_.extend(Marionette.TemplateCache.prototype, {
-
- // Internal method to load the template
- load: function(){
- // Guard clause to prevent loading this template more than once
- if (this.compiledTemplate){
- return this.compiledTemplate;
- }
-
- // Load the template and compile it
- var template = this.loadTemplate(this.templateId);
- this.compiledTemplate = this.compileTemplate(template);
-
- return this.compiledTemplate;
- },
-
- // Load a template from the DOM, by default. Override
- // this method to provide your own template retrieval
- // For asynchronous loading with AMD/RequireJS, consider
- // using a template-loader plugin as described here:
- // https://github.com/marionettejs/backbone.marionette/wiki/Using-marionette-with-requirejs
- loadTemplate: function(templateId){
- var template = Marionette.$(templateId).html();
-
- if (!template || template.length === 0){
- throwError("Could not find template: '" + templateId + "'", "NoTemplateError");
- }
-
- return template;
- },
-
- // Pre-compile the template before caching it. Override
- // this method if you do not need to pre-compile a template
- // (JST / RequireJS for example) or if you want to change
- // the template engine used (Handebars, etc).
- compileTemplate: function(rawTemplate){
- return _.template(rawTemplate);
- }
-});
-
-
-// Renderer
-// --------
-
-// Render a template with data by passing in the template
-// selector and the data to render.
-Marionette.Renderer = {
-
- // Render a template with data. The `template` parameter is
- // passed to the `TemplateCache` object to retrieve the
- // template function. Override this method to provide your own
- // custom rendering and template handling for all of Marionette.
- render: function(template, data){
-
- if (!template) {
- var error = new Error("Cannot render the template since it's false, null or undefined.");
- error.name = "TemplateNotFoundError";
- throw error;
- }
-
- var templateFunc;
- if (typeof template === "function"){
- templateFunc = template;
- } else {
- templateFunc = Marionette.TemplateCache.get(template);
- }
-
- return templateFunc(data);
- }
-};
-
-
-
-// Marionette.View
-// ---------------
-
-// The core view type that other Marionette views extend from.
-Marionette.View = Backbone.View.extend({
-
- constructor: function(){
- _.bindAll(this, "render");
-
- var args = Array.prototype.slice.apply(arguments);
- Backbone.View.prototype.constructor.apply(this, args);
-
- Marionette.MonitorDOMRefresh(this);
- this.listenTo(this, "show", this.onShowCalled, this);
- },
-
- // import the "triggerMethod" to trigger events with corresponding
- // methods if the method exists
- triggerMethod: Marionette.triggerMethod,
-
- // Get the template for this view
- // instance. You can set a `template` attribute in the view
- // definition or pass a `template: "whatever"` parameter in
- // to the constructor options.
- getTemplate: function(){
- return Marionette.getOption(this, "template");
- },
-
- // Mix in template helper methods. Looks for a
- // `templateHelpers` attribute, which can either be an
- // object literal, or a function that returns an object
- // literal. All methods and attributes from this object
- // are copies to the object passed in.
- mixinTemplateHelpers: function(target){
- target = target || {};
- var templateHelpers = Marionette.getOption(this, "templateHelpers");
- if (_.isFunction(templateHelpers)){
- templateHelpers = templateHelpers.call(this);
- }
- return _.extend(target, templateHelpers);
- },
-
- // Configure `triggers` to forward DOM events to view
- // events. `triggers: {"click .foo": "do:foo"}`
- configureTriggers: function(){
- if (!this.triggers) { return; }
-
- var triggerEvents = {};
-
- // Allow `triggers` to be configured as a function
- var triggers = _.result(this, "triggers");
-
- // Configure the triggers, prevent default
- // action and stop propagation of DOM events
- _.each(triggers, function(value, key){
-
- // build the event handler function for the DOM event
- triggerEvents[key] = function(e){
-
- // stop the event in its tracks
- if (e && e.preventDefault){ e.preventDefault(); }
- if (e && e.stopPropagation){ e.stopPropagation(); }
-
- // build the args for the event
- var args = {
- view: this,
- model: this.model,
- collection: this.collection
- };
-
- // trigger the event
- this.triggerMethod(value, args);
- };
-
- }, this);
-
- return triggerEvents;
- },
-
- // Overriding Backbone.View's delegateEvents to handle
- // the `triggers`, `modelEvents`, and `collectionEvents` configuration
- delegateEvents: function(events){
- this._delegateDOMEvents(events);
- Marionette.bindEntityEvents(this, this.model, Marionette.getOption(this, "modelEvents"));
- Marionette.bindEntityEvents(this, this.collection, Marionette.getOption(this, "collectionEvents"));
- },
-
- // internal method to delegate DOM events and triggers
- _delegateDOMEvents: function(events){
- events = events || this.events;
- if (_.isFunction(events)){ events = events.call(this); }
-
- var combinedEvents = {};
- var triggers = this.configureTriggers();
- _.extend(combinedEvents, events, triggers);
-
- Backbone.View.prototype.delegateEvents.call(this, combinedEvents);
- },
-
- // Overriding Backbone.View's undelegateEvents to handle unbinding
- // the `triggers`, `modelEvents`, and `collectionEvents` config
- undelegateEvents: function(){
- var args = Array.prototype.slice.call(arguments);
- Backbone.View.prototype.undelegateEvents.apply(this, args);
-
- Marionette.unbindEntityEvents(this, this.model, Marionette.getOption(this, "modelEvents"));
- Marionette.unbindEntityEvents(this, this.collection, Marionette.getOption(this, "collectionEvents"));
- },
-
- // Internal method, handles the `show` event.
- onShowCalled: function(){},
-
- // Default `close` implementation, for removing a view from the
- // DOM and unbinding it. Regions will call this method
- // for you. You can specify an `onClose` method in your view to
- // add custom code that is called after the view is closed.
- close: function(){
- if (this.isClosed) { return; }
-
- // allow the close to be stopped by returning `false`
- // from the `onBeforeClose` method
- var shouldClose = this.triggerMethod("before:close");
- if (shouldClose === false){
- return;
- }
-
- // mark as closed before doing the actual close, to
- // prevent infinite loops within "close" event handlers
- // that are trying to close other views
- this.isClosed = true;
- this.triggerMethod("close");
-
- // unbind UI elements
- this.unbindUIElements();
-
- // remove the view from the DOM
- this.remove();
- },
-
- // This method binds the elements specified in the "ui" hash inside the view's code with
- // the associated jQuery selectors.
- bindUIElements: function(){
- if (!this.ui) { return; }
-
- // store the ui hash in _uiBindings so they can be reset later
- // and so re-rendering the view will be able to find the bindings
- if (!this._uiBindings){
- this._uiBindings = this.ui;
- }
-
- // get the bindings result, as a function or otherwise
- var bindings = _.result(this, "_uiBindings");
-
- // empty the ui so we don't have anything to start with
- this.ui = {};
-
- // bind each of the selectors
- _.each(_.keys(bindings), function(key) {
- var selector = bindings[key];
- this.ui[key] = this.$(selector);
- }, this);
- },
-
- // This method unbinds the elements specified in the "ui" hash
- unbindUIElements: function(){
- if (!this.ui || !this._uiBindings){ return; }
-
- // delete all of the existing ui bindings
- _.each(this.ui, function($el, name){
- delete this.ui[name];
- }, this);
-
- // reset the ui element to the original bindings configuration
- this.ui = this._uiBindings;
- delete this._uiBindings;
- }
-});
-
-// Item View
-// ---------
-
-// A single item view implementation that contains code for rendering
-// with underscore.js templates, serializing the view's model or collection,
-// and calling several methods on extended views, such as `onRender`.
-Marionette.ItemView = Marionette.View.extend({
-
- // Setting up the inheritance chain which allows changes to
- // Marionette.View.prototype.constructor which allows overriding
- constructor: function(){
- Marionette.View.prototype.constructor.apply(this, slice(arguments));
- },
-
- // Serialize the model or collection for the view. If a model is
- // found, `.toJSON()` is called. If a collection is found, `.toJSON()`
- // is also called, but is used to populate an `items` array in the
- // resulting data. If both are found, defaults to the model.
- // You can override the `serializeData` method in your own view
- // definition, to provide custom serialization for your view's data.
- serializeData: function(){
- var data = {};
-
- if (this.model) {
- data = this.model.toJSON();
- }
- else if (this.collection) {
- data = { items: this.collection.toJSON() };
- }
-
- return data;
- },
-
- // Render the view, defaulting to underscore.js templates.
- // You can override this in your view definition to provide
- // a very specific rendering for your view. In general, though,
- // you should override the `Marionette.Renderer` object to
- // change how Marionette renders views.
- render: function(){
- this.isClosed = false;
-
- this.triggerMethod("before:render", this);
- this.triggerMethod("item:before:render", this);
-
- var data = this.serializeData();
- data = this.mixinTemplateHelpers(data);
-
- var template = this.getTemplate();
- var html = Marionette.Renderer.render(template, data);
-
- this.$el.html(html);
- this.bindUIElements();
-
- this.triggerMethod("render", this);
- this.triggerMethod("item:rendered", this);
-
- return this;
- },
-
- // Override the default close event to add a few
- // more events that are triggered.
- close: function(){
- if (this.isClosed){ return; }
-
- this.triggerMethod('item:before:close');
-
- Marionette.View.prototype.close.apply(this, slice(arguments));
-
- this.triggerMethod('item:closed');
- }
-});
-
-// Collection View
-// ---------------
-
-// A view that iterates over a Backbone.Collection
-// and renders an individual ItemView for each model.
-Marionette.CollectionView = Marionette.View.extend({
- // used as the prefix for item view events
- // that are forwarded through the collectionview
- itemViewEventPrefix: "itemview",
-
- // constructor
- constructor: function(options){
- this._initChildViewStorage();
-
- Marionette.View.prototype.constructor.apply(this, slice(arguments));
-
- this._initialEvents();
- },
-
- // Configured the initial events that the collection view
- // binds to. Override this method to prevent the initial
- // events, or to add your own initial events.
- _initialEvents: function(){
- if (this.collection){
- this.listenTo(this.collection, "add", this.addChildView, this);
- this.listenTo(this.collection, "remove", this.removeItemView, this);
- this.listenTo(this.collection, "reset", this.render, this);
- }
- },
-
- // Handle a child item added to the collection
- addChildView: function(item, collection, options){
- this.closeEmptyView();
- var ItemView = this.getItemView(item);
- var index = this.collection.indexOf(item);
- this.addItemView(item, ItemView, index);
- },
-
- // Override from `Marionette.View` to guarantee the `onShow` method
- // of child views is called.
- onShowCalled: function(){
- this.children.each(function(child){
- Marionette.triggerMethod.call(child, "show");
- });
- },
-
- // Internal method to trigger the before render callbacks
- // and events
- triggerBeforeRender: function(){
- this.triggerMethod("before:render", this);
- this.triggerMethod("collection:before:render", this);
- },
-
- // Internal method to trigger the rendered callbacks and
- // events
- triggerRendered: function(){
- this.triggerMethod("render", this);
- this.triggerMethod("collection:rendered", this);
- },
-
- // Render the collection of items. Override this method to
- // provide your own implementation of a render function for
- // the collection view.
- render: function(){
- this.isClosed = false;
- this.triggerBeforeRender();
- this._renderChildren();
- this.triggerRendered();
- return this;
- },
-
- // Internal method. Separated so that CompositeView can have
- // more control over events being triggered, around the rendering
- // process
- _renderChildren: function(){
- this.closeEmptyView();
- this.closeChildren();
-
- if (this.collection && this.collection.length > 0) {
- this.showCollection();
- } else {
- this.showEmptyView();
- }
- },
-
- // Internal method to loop through each item in the
- // collection view and show it
- showCollection: function(){
- var ItemView;
- this.collection.each(function(item, index){
- ItemView = this.getItemView(item);
- this.addItemView(item, ItemView, index);
- }, this);
- },
-
- // Internal method to show an empty view in place of
- // a collection of item views, when the collection is
- // empty
- showEmptyView: function(){
- var EmptyView = Marionette.getOption(this, "emptyView");
-
- if (EmptyView && !this._showingEmptyView){
- this._showingEmptyView = true;
- var model = new Backbone.Model();
- this.addItemView(model, EmptyView, 0);
- }
- },
-
- // Internal method to close an existing emptyView instance
- // if one exists. Called when a collection view has been
- // rendered empty, and then an item is added to the collection.
- closeEmptyView: function(){
- if (this._showingEmptyView){
- this.closeChildren();
- delete this._showingEmptyView;
- }
- },
-
- // Retrieve the itemView type, either from `this.options.itemView`
- // or from the `itemView` in the object definition. The "options"
- // takes precedence.
- getItemView: function(item){
- var itemView = Marionette.getOption(this, "itemView");
-
- if (!itemView){
- throwError("An `itemView` must be specified", "NoItemViewError");
- }
-
- return itemView;
- },
-
- // Render the child item's view and add it to the
- // HTML for the collection view.
- addItemView: function(item, ItemView, index){
- // get the itemViewOptions if any were specified
- var itemViewOptions = Marionette.getOption(this, "itemViewOptions");
- if (_.isFunction(itemViewOptions)){
- itemViewOptions = itemViewOptions.call(this, item, index);
- }
-
- // build the view
- var view = this.buildItemView(item, ItemView, itemViewOptions);
-
- // set up the child view event forwarding
- this.addChildViewEventForwarding(view);
-
- // this view is about to be added
- this.triggerMethod("before:item:added", view);
-
- // Store the child view itself so we can properly
- // remove and/or close it later
- this.children.add(view);
-
- // Render it and show it
- this.renderItemView(view, index);
-
- // call the "show" method if the collection view
- // has already been shown
- if (this._isShown){
- Marionette.triggerMethod.call(view, "show");
- }
-
- // this view was added
- this.triggerMethod("after:item:added", view);
- },
-
- // Set up the child view event forwarding. Uses an "itemview:"
- // prefix in front of all forwarded events.
- addChildViewEventForwarding: function(view){
- var prefix = Marionette.getOption(this, "itemViewEventPrefix");
-
- // Forward all child item view events through the parent,
- // prepending "itemview:" to the event name
- this.listenTo(view, "all", function(){
- var args = slice(arguments);
- args[0] = prefix + ":" + args[0];
- args.splice(1, 0, view);
-
- Marionette.triggerMethod.apply(this, args);
- }, this);
- },
-
- // render the item view
- renderItemView: function(view, index) {
- view.render();
- this.appendHtml(this, view, index);
- },
-
- // Build an `itemView` for every model in the collection.
- buildItemView: function(item, ItemViewType, itemViewOptions){
- var options = _.extend({model: item}, itemViewOptions);
- return new ItemViewType(options);
- },
-
- // get the child view by item it holds, and remove it
- removeItemView: function(item){
- var view = this.children.findByModel(item);
- this.removeChildView(view);
- this.checkEmpty();
- },
-
- // Remove the child view and close it
- removeChildView: function(view){
-
- // shut down the child view properly,
- // including events that the collection has from it
- if (view){
- this.stopListening(view);
-
- // call 'close' or 'remove', depending on which is found
- if (view.close) { view.close(); }
- else if (view.remove) { view.remove(); }
-
- this.children.remove(view);
- }
-
- this.triggerMethod("item:removed", view);
- },
-
- // helper to show the empty view if the collection is empty
- checkEmpty: function() {
- // check if we're empty now, and if we are, show the
- // empty view
- if (!this.collection || this.collection.length === 0){
- this.showEmptyView();
- }
- },
-
- // Append the HTML to the collection's `el`.
- // Override this method to do something other
- // then `.append`.
- appendHtml: function(collectionView, itemView, index){
- collectionView.$el.append(itemView.el);
- },
-
- // Internal method to set up the `children` object for
- // storing all of the child views
- _initChildViewStorage: function(){
- this.children = new Backbone.ChildViewContainer();
- },
-
- // Handle cleanup and other closing needs for
- // the collection of views.
- close: function(){
- if (this.isClosed){ return; }
-
- this.triggerMethod("collection:before:close");
- this.closeChildren();
- this.triggerMethod("collection:closed");
-
- Marionette.View.prototype.close.apply(this, slice(arguments));
- },
-
- // Close the child views that this collection view
- // is holding on to, if any
- closeChildren: function(){
- this.children.each(function(child){
- this.removeChildView(child);
- }, this);
- this.checkEmpty();
- }
-});
-
-
-// Composite View
-// --------------
-
-// Used for rendering a branch-leaf, hierarchical structure.
-// Extends directly from CollectionView and also renders an
-// an item view as `modelView`, for the top leaf
-Marionette.CompositeView = Marionette.CollectionView.extend({
-
- // Setting up the inheritance chain which allows changes to
- // Marionette.CollectionView.prototype.constructor which allows overriding
- constructor: function(){
- Marionette.CollectionView.prototype.constructor.apply(this, slice(arguments));
- },
-
- // Configured the initial events that the composite view
- // binds to. Override this method to prevent the initial
- // events, or to add your own initial events.
- _initialEvents: function(){
- if (this.collection){
- this.listenTo(this.collection, "add", this.addChildView, this);
- this.listenTo(this.collection, "remove", this.removeItemView, this);
- this.listenTo(this.collection, "reset", this._renderChildren, this);
- }
- },
-
- // Retrieve the `itemView` to be used when rendering each of
- // the items in the collection. The default is to return
- // `this.itemView` or Marionette.CompositeView if no `itemView`
- // has been defined
- getItemView: function(item){
- var itemView = Marionette.getOption(this, "itemView") || this.constructor;
-
- if (!itemView){
- throwError("An `itemView` must be specified", "NoItemViewError");
- }
-
- return itemView;
- },
-
- // Serialize the collection for the view.
- // You can override the `serializeData` method in your own view
- // definition, to provide custom serialization for your view's data.
- serializeData: function(){
- var data = {};
-
- if (this.model){
- data = this.model.toJSON();
- }
-
- return data;
- },
-
- // Renders the model once, and the collection once. Calling
- // this again will tell the model's view to re-render itself
- // but the collection will not re-render.
- render: function(){
- this.isRendered = true;
- this.isClosed = false;
- this.resetItemViewContainer();
-
- this.triggerBeforeRender();
- var html = this.renderModel();
- this.$el.html(html);
- // the ui bindings is done here and not at the end of render since they
- // will not be available until after the model is rendered, but should be
- // available before the collection is rendered.
- this.bindUIElements();
- this.triggerMethod("composite:model:rendered");
-
- this._renderChildren();
-
- this.triggerMethod("composite:rendered");
- this.triggerRendered();
- return this;
- },
-
- _renderChildren: function(){
- if (this.isRendered){
- Marionette.CollectionView.prototype._renderChildren.call(this);
- this.triggerMethod("composite:collection:rendered");
- }
- },
-
- // Render an individual model, if we have one, as
- // part of a composite view (branch / leaf). For example:
- // a treeview.
- renderModel: function(){
- var data = {};
- data = this.serializeData();
- data = this.mixinTemplateHelpers(data);
-
- var template = this.getTemplate();
- return Marionette.Renderer.render(template, data);
- },
-
- // Appends the `el` of itemView instances to the specified
- // `itemViewContainer` (a jQuery selector). Override this method to
- // provide custom logic of how the child item view instances have their
- // HTML appended to the composite view instance.
- appendHtml: function(cv, iv, index){
- var $container = this.getItemViewContainer(cv);
- $container.append(iv.el);
- },
-
- // Internal method to ensure an `$itemViewContainer` exists, for the
- // `appendHtml` method to use.
- getItemViewContainer: function(containerView){
- if ("$itemViewContainer" in containerView){
- return containerView.$itemViewContainer;
- }
-
- var container;
- var itemViewContainer = Marionette.getOption(containerView, "itemViewContainer");
- if (itemViewContainer){
-
- var selector = _.isFunction(itemViewContainer) ? itemViewContainer() : itemViewContainer;
- container = containerView.$(selector);
- if (container.length <= 0) {
- throwError("The specified `itemViewContainer` was not found: " + containerView.itemViewContainer, "ItemViewContainerMissingError");
- }
-
- } else {
- container = containerView.$el;
- }
-
- containerView.$itemViewContainer = container;
- return container;
- },
-
- // Internal method to reset the `$itemViewContainer` on render
- resetItemViewContainer: function(){
- if (this.$itemViewContainer){
- delete this.$itemViewContainer;
- }
- }
-});
-
-
-// Layout
-// ------
-
-// Used for managing application layouts, nested layouts and
-// multiple regions within an application or sub-application.
-//
-// A specialized view type that renders an area of HTML and then
-// attaches `Region` instances to the specified `regions`.
-// Used for composite view management and sub-application areas.
-Marionette.Layout = Marionette.ItemView.extend({
- regionType: Marionette.Region,
-
- // Ensure the regions are available when the `initialize` method
- // is called.
- constructor: function (options) {
- options = options || {};
-
- this._firstRender = true;
- this._initializeRegions(options);
-
- Marionette.ItemView.prototype.constructor.call(this, options);
- },
-
- // Layout's render will use the existing region objects the
- // first time it is called. Subsequent calls will close the
- // views that the regions are showing and then reset the `el`
- // for the regions to the newly rendered DOM elements.
- render: function(){
-
- if (this.isClosed){
- // a previously closed layout means we need to
- // completely re-initialize the regions
- this._initializeRegions();
- }
- if (this._firstRender) {
- // if this is the first render, don't do anything to
- // reset the regions
- this._firstRender = false;
- } else if (!this.isClosed){
- // If this is not the first render call, then we need to
- // re-initializing the `el` for each region
- this._reInitializeRegions();
- }
-
- var args = Array.prototype.slice.apply(arguments);
- var result = Marionette.ItemView.prototype.render.apply(this, args);
-
- return result;
- },
-
- // Handle closing regions, and then close the view itself.
- close: function () {
- if (this.isClosed){ return; }
- this.regionManager.close();
- var args = Array.prototype.slice.apply(arguments);
- Marionette.ItemView.prototype.close.apply(this, args);
- },
-
- // Add a single region, by name, to the layout
- addRegion: function(name, definition){
- var regions = {};
- regions[name] = definition;
- return this._buildRegions(regions)[name];
- },
-
- // Add multiple regions as a {name: definition, name2: def2} object literal
- addRegions: function(regions){
- this.regions = _.extend({}, this.regions, regions);
- return this._buildRegions(regions);
- },
-
- // Remove a single region from the Layout, by name
- removeRegion: function(name){
- delete this.regions[name];
- return this.regionManager.removeRegion(name);
- },
-
- // internal method to build regions
- _buildRegions: function(regions){
- var that = this;
-
- var defaults = {
- regionType: Marionette.getOption(this, "regionType"),
- parentEl: function(){ return that.$el; }
- };
-
- return this.regionManager.addRegions(regions, defaults);
- },
-
- // Internal method to initialize the regions that have been defined in a
- // `regions` attribute on this layout.
- _initializeRegions: function (options) {
- var regions;
- this._initRegionManager();
-
- if (_.isFunction(this.regions)) {
- regions = this.regions(options);
- } else {
- regions = this.regions || {};
- }
-
- this.addRegions(regions);
- },
-
- // Internal method to re-initialize all of the regions by updating the `el` that
- // they point to
- _reInitializeRegions: function(){
- this.regionManager.closeRegions();
- this.regionManager.each(function(region){
- region.reset();
- });
- },
-
- // Internal method to initialize the region manager
- // and all regions in it
- _initRegionManager: function(){
- this.regionManager = new Marionette.RegionManager();
-
- this.listenTo(this.regionManager, "region:add", function(name, region){
- this[name] = region;
- this.trigger("region:add", name, region);
- });
-
- this.listenTo(this.regionManager, "region:remove", function(name, region){
- delete this[name];
- this.trigger("region:remove", name, region);
- });
- }
-});
-
-
-// AppRouter
-// ---------
-
-// Reduce the boilerplate code of handling route events
-// and then calling a single method on another object.
-// Have your routers configured to call the method on
-// your object, directly.
-//
-// Configure an AppRouter with `appRoutes`.
-//
-// App routers can only take one `controller` object.
-// It is recommended that you divide your controller
-// objects in to smaller pieces of related functionality
-// and have multiple routers / controllers, instead of
-// just one giant router and controller.
-//
-// You can also add standard routes to an AppRouter.
-
-Marionette.AppRouter = Backbone.Router.extend({
-
- constructor: function(options){
- Backbone.Router.prototype.constructor.apply(this, slice(arguments));
-
- this.options = options || {};
-
- var appRoutes = Marionette.getOption(this, "appRoutes");
- var controller = this._getController();
- this.processAppRoutes(controller, appRoutes);
- },
-
- // Similar to route method on a Backbone Router but
- // method is called on the controller
- appRoute: function(route, methodName) {
- var controller = this._getController();
- this._addAppRoute(controller, route, methodName);
- },
-
- // Internal method to process the `appRoutes` for the
- // router, and turn them in to routes that trigger the
- // specified method on the specified `controller`.
- processAppRoutes: function(controller, appRoutes) {
- if (!appRoutes){ return; }
-
- var routeNames = _.keys(appRoutes).reverse(); // Backbone requires reverted order of routes
-
- _.each(routeNames, function(route) {
- this._addAppRoute(controller, route, appRoutes[route]);
- }, this);
- },
-
- _getController: function(){
- return Marionette.getOption(this, "controller");
- },
-
- _addAppRoute: function(controller, route, methodName){
- var method = controller[methodName];
-
- if (!method) {
- throw new Error("Method '" + methodName + "' was not found on the controller");
- }
-
- this.route(route, methodName, _.bind(method, controller));
- }
-});
-
-
-// Application
-// -----------
-
-// Contain and manage the composite application as a whole.
-// Stores and starts up `Region` objects, includes an
-// event aggregator as `app.vent`
-Marionette.Application = function(options){
- this._initRegionManager();
- this._initCallbacks = new Marionette.Callbacks();
- this.vent = new Backbone.Wreqr.EventAggregator();
- this.commands = new Backbone.Wreqr.Commands();
- this.reqres = new Backbone.Wreqr.RequestResponse();
- this.submodules = {};
-
- _.extend(this, options);
-
- this.triggerMethod = Marionette.triggerMethod;
-};
-
-_.extend(Marionette.Application.prototype, Backbone.Events, {
- // Command execution, facilitated by Backbone.Wreqr.Commands
- execute: function(){
- var args = Array.prototype.slice.apply(arguments);
- this.commands.execute.apply(this.commands, args);
- },
-
- // Request/response, facilitated by Backbone.Wreqr.RequestResponse
- request: function(){
- var args = Array.prototype.slice.apply(arguments);
- return this.reqres.request.apply(this.reqres, args);
- },
-
- // Add an initializer that is either run at when the `start`
- // method is called, or run immediately if added after `start`
- // has already been called.
- addInitializer: function(initializer){
- this._initCallbacks.add(initializer);
- },
-
- // kick off all of the application's processes.
- // initializes all of the regions that have been added
- // to the app, and runs all of the initializer functions
- start: function(options){
- this.triggerMethod("initialize:before", options);
- this._initCallbacks.run(options, this);
- this.triggerMethod("initialize:after", options);
-
- this.triggerMethod("start", options);
- },
-
- // Add regions to your app.
- // Accepts a hash of named strings or Region objects
- // addRegions({something: "#someRegion"})
- // addRegions({something: Region.extend({el: "#someRegion"}) });
- addRegions: function(regions){
- return this._regionManager.addRegions(regions);
- },
-
- // Close all regions in the app, without removing them
- closeRegions: function(){
- this._regionManager.closeRegions();
- },
-
- // Removes a region from your app, by name
- // Accepts the regions name
- // removeRegion('myRegion')
- removeRegion: function(region) {
- this._regionManager.removeRegion(region);
- },
-
- // Provides alternative access to regions
- // Accepts the region name
- // getRegion('main')
- getRegion: function(region) {
- return this._regionManager.get(region);
- },
-
- // Create a module, attached to the application
- module: function(moduleNames, moduleDefinition){
- // slice the args, and add this application object as the
- // first argument of the array
- var args = slice(arguments);
- args.unshift(this);
-
- // see the Marionette.Module object for more information
- return Marionette.Module.create.apply(Marionette.Module, args);
- },
-
- // Internal method to set up the region manager
- _initRegionManager: function(){
- this._regionManager = new Marionette.RegionManager();
-
- this.listenTo(this._regionManager, "region:add", function(name, region){
- this[name] = region;
- });
-
- this.listenTo(this._regionManager, "region:remove", function(name, region){
- delete this[name];
- });
- }
-});
-
-// Copy the `extend` function used by Backbone's classes
-Marionette.Application.extend = Marionette.extend;
-
-// Module
-// ------
-
-// A simple module system, used to create privacy and encapsulation in
-// Marionette applications
-Marionette.Module = function(moduleName, app){
- this.moduleName = moduleName;
-
- // store sub-modules
- this.submodules = {};
-
- this._setupInitializersAndFinalizers();
-
- // store the configuration for this module
- this.app = app;
- this.startWithParent = true;
-
- this.triggerMethod = Marionette.triggerMethod;
-};
-
-// Extend the Module prototype with events / listenTo, so that the module
-// can be used as an event aggregator or pub/sub.
-_.extend(Marionette.Module.prototype, Backbone.Events, {
-
- // Initializer for a specific module. Initializers are run when the
- // module's `start` method is called.
- addInitializer: function(callback){
- this._initializerCallbacks.add(callback);
- },
-
- // Finalizers are run when a module is stopped. They are used to teardown
- // and finalize any variables, references, events and other code that the
- // module had set up.
- addFinalizer: function(callback){
- this._finalizerCallbacks.add(callback);
- },
-
- // Start the module, and run all of its initializers
- start: function(options){
- // Prevent re-starting a module that is already started
- if (this._isInitialized){ return; }
-
- // start the sub-modules (depth-first hierarchy)
- _.each(this.submodules, function(mod){
- // check to see if we should start the sub-module with this parent
- if (mod.startWithParent){
- mod.start(options);
- }
- });
-
- // run the callbacks to "start" the current module
- this.triggerMethod("before:start", options);
-
- this._initializerCallbacks.run(options, this);
- this._isInitialized = true;
-
- this.triggerMethod("start", options);
- },
-
- // Stop this module by running its finalizers and then stop all of
- // the sub-modules for this module
- stop: function(){
- // if we are not initialized, don't bother finalizing
- if (!this._isInitialized){ return; }
- this._isInitialized = false;
-
- Marionette.triggerMethod.call(this, "before:stop");
-
- // stop the sub-modules; depth-first, to make sure the
- // sub-modules are stopped / finalized before parents
- _.each(this.submodules, function(mod){ mod.stop(); });
-
- // run the finalizers
- this._finalizerCallbacks.run(undefined,this);
-
- // reset the initializers and finalizers
- this._initializerCallbacks.reset();
- this._finalizerCallbacks.reset();
-
- Marionette.triggerMethod.call(this, "stop");
- },
-
- // Configure the module with a definition function and any custom args
- // that are to be passed in to the definition function
- addDefinition: function(moduleDefinition, customArgs){
- this._runModuleDefinition(moduleDefinition, customArgs);
- },
-
- // Internal method: run the module definition function with the correct
- // arguments
- _runModuleDefinition: function(definition, customArgs){
- if (!definition){ return; }
-
- // build the correct list of arguments for the module definition
- var args = _.flatten([
- this,
- this.app,
- Backbone,
- Marionette,
- Marionette.$, _,
- customArgs
- ]);
-
- definition.apply(this, args);
- },
-
- // Internal method: set up new copies of initializers and finalizers.
- // Calling this method will wipe out all existing initializers and
- // finalizers.
- _setupInitializersAndFinalizers: function(){
- this._initializerCallbacks = new Marionette.Callbacks();
- this._finalizerCallbacks = new Marionette.Callbacks();
- }
-});
-
-// Type methods to create modules
-_.extend(Marionette.Module, {
-
- // Create a module, hanging off the app parameter as the parent object.
- create: function(app, moduleNames, moduleDefinition){
- var module = app;
-
- // get the custom args passed in after the module definition and
- // get rid of the module name and definition function
- var customArgs = slice(arguments);
- customArgs.splice(0, 3);
-
- // split the module names and get the length
- moduleNames = moduleNames.split(".");
- var length = moduleNames.length;
-
- // store the module definition for the last module in the chain
- var moduleDefinitions = [];
- moduleDefinitions[length-1] = moduleDefinition;
-
- // Loop through all the parts of the module definition
- _.each(moduleNames, function(moduleName, i){
- var parentModule = module;
- module = this._getModule(parentModule, moduleName, app);
- this._addModuleDefinition(parentModule, module, moduleDefinitions[i], customArgs);
- }, this);
-
- // Return the last module in the definition chain
- return module;
- },
-
- _getModule: function(parentModule, moduleName, app, def, args){
- // Get an existing module of this name if we have one
- var module = parentModule[moduleName];
-
- if (!module){
- // Create a new module if we don't have one
- module = new Marionette.Module(moduleName, app);
- parentModule[moduleName] = module;
- // store the module on the parent
- parentModule.submodules[moduleName] = module;
- }
-
- return module;
- },
-
- _addModuleDefinition: function(parentModule, module, def, args){
- var fn;
- var startWithParent;
-
- if (_.isFunction(def)){
- // if a function is supplied for the module definition
- fn = def;
- startWithParent = true;
-
- } else if (_.isObject(def)){
- // if an object is supplied
- fn = def.define;
- startWithParent = def.startWithParent;
-
- } else {
- // if nothing is supplied
- startWithParent = true;
- }
-
- // add module definition if needed
- if (fn){
- module.addDefinition(fn, args);
- }
-
- // `and` the two together, ensuring a single `false` will prevent it
- // from starting with the parent
- module.startWithParent = module.startWithParent && startWithParent;
-
- // setup auto-start if needed
- if (module.startWithParent && !module.startWithParentIsConfigured){
-
- // only configure this once
- module.startWithParentIsConfigured = true;
-
- // add the module initializer config
- parentModule.addInitializer(function(options){
- if (module.startWithParent){
- module.start(options);
- }
- });
-
- }
-
- }
-});
-
-
-
- return Marionette;
-})(this, Backbone, _);
-
- return Backbone.Marionette;
-
-}));
diff --git a/security-admin/src/main/webapp/libs/bower/backbone.marionette/js/backbone.marionette.min.js b/security-admin/src/main/webapp/libs/bower/backbone.marionette/js/backbone.marionette.min.js
deleted file mode 100644
index e2ebd3e98..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone.marionette/js/backbone.marionette.min.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// MarionetteJS (Backbone.Marionette)
-// ----------------------------------
-// v1.1.0
-//
-// Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.
-// Distributed under MIT license
-//
-// http://marionettejs.com
-
-
-
-/*!
- * Includes BabySitter
- * https://github.com/marionettejs/backbone.babysitter/
- *
- * Includes Wreqr
- * https://github.com/marionettejs/backbone.wreqr/
- */
-
-(function(e,t){if("object"==typeof exports){var i=require("underscore"),n=require("backbone"),r=require("backbone.wreqr"),o=require("backbone.babysitter");module.exports=t(i,n,r,o)}else"function"==typeof define&&define.amd&&define(["underscore","backbone","backbone.wreqr","backbone.babysitter"],t)})(this,function(e,t){return function(e,t,i){"use strict";function n(e){return s.call(e)}function r(e,t){var i=Error(e);throw i.name=t||"Error",i}var o={};t.Marionette=o,o.$=t.$;var s=Array.prot [...]
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/libs/bower/backbone.wreqr/js/backbone.wreqr.js b/security-admin/src/main/webapp/libs/bower/backbone.wreqr/js/backbone.wreqr.js
deleted file mode 100644
index b3e784ab3..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone.wreqr/js/backbone.wreqr.js
+++ /dev/null
@@ -1,277 +0,0 @@
-(function (root, factory) {
- if (typeof exports === 'object') {
-
- var underscore = require('underscore');
- var backbone = require('backbone');
-
- module.exports = factory(underscore, backbone);
-
- } else if (typeof define === 'function' && define.amd) {
-
- define(['underscore', 'backbone'], factory);
-
- }
-}(this, function (_, Backbone) {
- "use strict";
-
- Backbone.Wreqr = (function(Backbone, Marionette, _){
- "use strict";
- var Wreqr = {};
-
- // Handlers
-// --------
-// A registry of functions to call, given a name
-
-Wreqr.Handlers = (function(Backbone, _){
- "use strict";
-
- // Constructor
- // -----------
-
- var Handlers = function(options){
- this.options = options;
- this._wreqrHandlers = {};
-
- if (_.isFunction(this.initialize)){
- this.initialize(options);
- }
- };
-
- Handlers.extend = Backbone.Model.extend;
-
- // Instance Members
- // ----------------
-
- _.extend(Handlers.prototype, Backbone.Events, {
-
- // Add multiple handlers using an object literal configuration
- setHandlers: function(handlers){
- _.each(handlers, function(handler, name){
- var context = null;
-
- if (_.isObject(handler) && !_.isFunction(handler)){
- context = handler.context;
- handler = handler.callback;
- }
-
- this.setHandler(name, handler, context);
- }, this);
- },
-
- // Add a handler for the given name, with an
- // optional context to run the handler within
- setHandler: function(name, handler, context){
- var config = {
- callback: handler,
- context: context
- };
-
- this._wreqrHandlers[name] = config;
-
- this.trigger("handler:add", name, handler, context);
- },
-
- // Determine whether or not a handler is registered
- hasHandler: function(name){
- return !! this._wreqrHandlers[name];
- },
-
- // Get the currently registered handler for
- // the specified name. Throws an exception if
- // no handler is found.
- getHandler: function(name){
- var config = this._wreqrHandlers[name];
-
- if (!config){
- throw new Error("Handler not found for '" + name + "'");
- }
-
- return function(){
- var args = Array.prototype.slice.apply(arguments);
- return config.callback.apply(config.context, args);
- };
- },
-
- // Remove a handler for the specified name
- removeHandler: function(name){
- delete this._wreqrHandlers[name];
- },
-
- // Remove all handlers from this registry
- removeAllHandlers: function(){
- this._wreqrHandlers = {};
- }
- });
-
- return Handlers;
-})(Backbone, _);
-
- // Wreqr.CommandStorage
-// --------------------
-//
-// Store and retrieve commands for execution.
-Wreqr.CommandStorage = (function(){
- "use strict";
-
- // Constructor function
- var CommandStorage = function(options){
- this.options = options;
- this._commands = {};
-
- if (_.isFunction(this.initialize)){
- this.initialize(options);
- }
- };
-
- // Instance methods
- _.extend(CommandStorage.prototype, Backbone.Events, {
-
- // Get an object literal by command name, that contains
- // the `commandName` and the `instances` of all commands
- // represented as an array of arguments to process
- getCommands: function(commandName){
- var commands = this._commands[commandName];
-
- // we don't have it, so add it
- if (!commands){
-
- // build the configuration
- commands = {
- command: commandName,
- instances: []
- };
-
- // store it
- this._commands[commandName] = commands;
- }
-
- return commands;
- },
-
- // Add a command by name, to the storage and store the
- // args for the command
- addCommand: function(commandName, args){
- var command = this.getCommands(commandName);
- command.instances.push(args);
- },
-
- // Clear all commands for the given `commandName`
- clearCommands: function(commandName){
- var command = this.getCommands(commandName);
- command.instances = [];
- }
- });
-
- return CommandStorage;
-})();
-
- // Wreqr.Commands
-// --------------
-//
-// A simple command pattern implementation. Register a command
-// handler and execute it.
-Wreqr.Commands = (function(Wreqr){
- "use strict";
-
- return Wreqr.Handlers.extend({
- // default storage type
- storageType: Wreqr.CommandStorage,
-
- constructor: function(options){
- this.options = options || {};
-
- this._initializeStorage(this.options);
- this.on("handler:add", this._executeCommands, this);
-
- var args = Array.prototype.slice.call(arguments);
- Wreqr.Handlers.prototype.constructor.apply(this, args);
- },
-
- // Execute a named command with the supplied args
- execute: function(name, args){
- name = arguments[0];
- args = Array.prototype.slice.call(arguments, 1);
-
- if (this.hasHandler(name)){
- this.getHandler(name).apply(this, args);
- } else {
- this.storage.addCommand(name, args);
- }
-
- },
-
- // Internal method to handle bulk execution of stored commands
- _executeCommands: function(name, handler, context){
- var command = this.storage.getCommands(name);
-
- // loop through and execute all the stored command instances
- _.each(command.instances, function(args){
- handler.apply(context, args);
- });
-
- this.storage.clearCommands(name);
- },
-
- // Internal method to initialize storage either from the type's
- // `storageType` or the instance `options.storageType`.
- _initializeStorage: function(options){
- var storage;
-
- var StorageType = options.storageType || this.storageType;
- if (_.isFunction(StorageType)){
- storage = new StorageType();
- } else {
- storage = StorageType;
- }
-
- this.storage = storage;
- }
- });
-
-})(Wreqr);
-
- // Wreqr.RequestResponse
-// ---------------------
-//
-// A simple request/response implementation. Register a
-// request handler, and return a response from it
-Wreqr.RequestResponse = (function(Wreqr){
- "use strict";
-
- return Wreqr.Handlers.extend({
- request: function(){
- var name = arguments[0];
- var args = Array.prototype.slice.call(arguments, 1);
-
- return this.getHandler(name).apply(this, args);
- }
- });
-
-})(Wreqr);
-
- // Event Aggregator
-// ----------------
-// A pub-sub object that can be used to decouple various parts
-// of an application through event-driven architecture.
-
-Wreqr.EventAggregator = (function(Backbone, _){
- "use strict";
- var EA = function(){};
-
- // Copy the `extend` function used by Backbone's classes
- EA.extend = Backbone.Model.extend;
-
- // Copy the basic Backbone.Events on to the event aggregator
- _.extend(EA.prototype, Backbone.Events);
-
- return EA;
-})(Backbone, _);
-
-
- return Wreqr;
-})(Backbone, Backbone.Marionette, _);
-
- return Backbone.Wreqr;
-
-}));
-
diff --git a/security-admin/src/main/webapp/libs/bower/backbone.wreqr/js/backbone.wreqr.min.js b/security-admin/src/main/webapp/libs/bower/backbone.wreqr/js/backbone.wreqr.min.js
deleted file mode 100644
index 65141500d..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone.wreqr/js/backbone.wreqr.min.js
+++ /dev/null
@@ -1,11 +0,0 @@
-// Backbone.Wreqr (Backbone.Marionette)
-// ----------------------------------
-// v0.2.0
-//
-// Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.
-// Distributed under MIT license
-//
-// http://github.com/marionettejs/backbone.wreqr
-
-
-(function(t,e){if("object"==typeof exports){var n=require("underscore"),r=require("backbone");module.exports=e(n,r)}else"function"==typeof define&&define.amd&&define(["underscore","backbone"],e)})(this,function(t,e){"use strict";return e.Wreqr=function(t,e,n){var r={};return r.Handlers=function(t,e){var n=function(t){this.options=t,this._wreqrHandlers={},e.isFunction(this.initialize)&&this.initialize(t)};return n.extend=t.Model.extend,e.extend(n.prototype,t.Events,{setHandlers:function(t [...]
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/libs/bower/backbone/js/backbone-min.js b/security-admin/src/main/webapp/libs/bower/backbone/js/backbone-min.js
deleted file mode 100644
index c8c33e0d7..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone/js/backbone-min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-(function(t){var e=typeof self=="object"&&self.self===self&&self||typeof global=="object"&&global.global===global&&global;if(typeof define==="function"&&define.amd){define(["underscore","jquery","exports"],function(i,n,r){e.Backbone=t(e,r,i,n)})}else if(typeof exports!=="undefined"){var i=require("underscore"),n;try{n=require("jquery")}catch(r){}t(e,exports,i,n)}else{e.Backbone=t(e,{},e._,e.jQuery||e.Zepto||e.ender||e.$)}})(function(t,e,i,n){var r=t.Backbone;var s=Array.prototype.slice;e [...]
-//# sourceMappingURL=backbone-min.map
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/libs/bower/backbone/js/backbone.js b/security-admin/src/main/webapp/libs/bower/backbone/js/backbone.js
deleted file mode 100644
index 3e09d0dcb..000000000
--- a/security-admin/src/main/webapp/libs/bower/backbone/js/backbone.js
+++ /dev/null
@@ -1,2096 +0,0 @@
-// Backbone.js 1.4.0
-
-// (c) 2010-2019 Jeremy Ashkenas and DocumentCloud
-// Backbone may be freely distributed under the MIT license.
-// For all details and documentation:
-// http://backbonejs.org
-
-(function(factory) {
-
- // Establish the root object, `window` (`self`) in the browser, or `global` on the server.
- // We use `self` instead of `window` for `WebWorker` support.
- var root = typeof self == 'object' && self.self === self && self ||
- typeof global == 'object' && global.global === global && global;
-
- // Set up Backbone appropriately for the environment. Start with AMD.
- if (typeof define === 'function' && define.amd) {
- define(['underscore', 'jquery', 'exports'], function(_, $, exports) {
- // Export global even in AMD case in case this script is loaded with
- // others that may still expect a global Backbone.
- root.Backbone = factory(root, exports, _, $);
- });
-
- // Next for Node.js or CommonJS. jQuery may not be needed as a module.
- } else if (typeof exports !== 'undefined') {
- var _ = require('underscore'), $;
- try { $ = require('jquery'); } catch (e) {}
- factory(root, exports, _, $);
-
- // Finally, as a browser global.
- } else {
- root.Backbone = factory(root, {}, root._, root.jQuery || root.Zepto || root.ender || root.$);
- }
-
-})(function(root, Backbone, _, $) {
-
- // Initial Setup
- // -------------
-
- // Save the previous value of the `Backbone` variable, so that it can be
- // restored later on, if `noConflict` is used.
- var previousBackbone = root.Backbone;
-
- // Create a local reference to a common array method we'll want to use later.
- var slice = Array.prototype.slice;
-
- // Current version of the library. Keep in sync with `package.json`.
- Backbone.VERSION = '1.4.0';
-
- // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
- // the `$` variable.
- Backbone.$ = $;
-
- // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
- // to its previous owner. Returns a reference to this Backbone object.
- Backbone.noConflict = function() {
- root.Backbone = previousBackbone;
- return this;
- };
-
- // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option
- // will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and
- // set a `X-Http-Method-Override` header.
- Backbone.emulateHTTP = false;
-
- // Turn on `emulateJSON` to support legacy servers that can't deal with direct
- // `application/json` requests ... this will encode the body as
- // `application/x-www-form-urlencoded` instead and will send the model in a
- // form param named `model`.
- Backbone.emulateJSON = false;
-
- // Backbone.Events
- // ---------------
-
- // A module that can be mixed in to *any object* in order to provide it with
- // a custom event channel. You may bind a callback to an event with `on` or
- // remove with `off`; `trigger`-ing an event fires all callbacks in
- // succession.
- //
- // var object = {};
- // _.extend(object, Backbone.Events);
- // object.on('expand', function(){ alert('expanded'); });
- // object.trigger('expand');
- //
- var Events = Backbone.Events = {};
-
- // Regular expression used to split event strings.
- var eventSplitter = /\s+/;
-
- // A private global variable to share between listeners and listenees.
- var _listening;
-
- // Iterates over the standard `event, callback` (as well as the fancy multiple
- // space-separated events `"change blur", callback` and jQuery-style event
- // maps `{event: callback}`).
- var eventsApi = function(iteratee, events, name, callback, opts) {
- var i = 0, names;
- if (name && typeof name === 'object') {
- // Handle event maps.
- if (callback !== void 0 && 'context' in opts && opts.context === void 0) opts.context = callback;
- for (names = _.keys(name); i < names.length ; i++) {
- events = eventsApi(iteratee, events, names[i], name[names[i]], opts);
- }
- } else if (name && eventSplitter.test(name)) {
- // Handle space-separated event names by delegating them individually.
- for (names = name.split(eventSplitter); i < names.length; i++) {
- events = iteratee(events, names[i], callback, opts);
- }
- } else {
- // Finally, standard events.
- events = iteratee(events, name, callback, opts);
- }
- return events;
- };
-
- // Bind an event to a `callback` function. Passing `"all"` will bind
- // the callback to all events fired.
- Events.on = function(name, callback, context) {
- this._events = eventsApi(onApi, this._events || {}, name, callback, {
- context: context,
- ctx: this,
- listening: _listening
- });
-
- if (_listening) {
- var listeners = this._listeners || (this._listeners = {});
- listeners[_listening.id] = _listening;
- // Allow the listening to use a counter, instead of tracking
- // callbacks for library interop
- _listening.interop = false;
- }
-
- return this;
- };
-
- // Inversion-of-control versions of `on`. Tell *this* object to listen to
- // an event in another object... keeping track of what it's listening to
- // for easier unbinding later.
- Events.listenTo = function(obj, name, callback) {
- if (!obj) return this;
- var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
- var listeningTo = this._listeningTo || (this._listeningTo = {});
- var listening = _listening = listeningTo[id];
-
- // This object is not listening to any other events on `obj` yet.
- // Setup the necessary references to track the listening callbacks.
- if (!listening) {
- this._listenId || (this._listenId = _.uniqueId('l'));
- listening = _listening = listeningTo[id] = new Listening(this, obj);
- }
-
- // Bind callbacks on obj.
- var error = tryCatchOn(obj, name, callback, this);
- _listening = void 0;
-
- if (error) throw error;
- // If the target obj is not Backbone.Events, track events manually.
- if (listening.interop) listening.on(name, callback);
-
- return this;
- };
-
- // The reducing API that adds a callback to the `events` object.
- var onApi = function(events, name, callback, options) {
- if (callback) {
- var handlers = events[name] || (events[name] = []);
- var context = options.context, ctx = options.ctx, listening = options.listening;
- if (listening) listening.count++;
-
- handlers.push({callback: callback, context: context, ctx: context || ctx, listening: listening});
- }
- return events;
- };
-
- // An try-catch guarded #on function, to prevent poisoning the global
- // `_listening` variable.
- var tryCatchOn = function(obj, name, callback, context) {
- try {
- obj.on(name, callback, context);
- } catch (e) {
- return e;
- }
- };
-
- // Remove one or many callbacks. If `context` is null, removes all
- // callbacks with that function. If `callback` is null, removes all
- // callbacks for the event. If `name` is null, removes all bound
- // callbacks for all events.
- Events.off = function(name, callback, context) {
- if (!this._events) return this;
- this._events = eventsApi(offApi, this._events, name, callback, {
- context: context,
- listeners: this._listeners
- });
-
- return this;
- };
-
- // Tell this object to stop listening to either specific events ... or
- // to every object it's currently listening to.
- Events.stopListening = function(obj, name, callback) {
- var listeningTo = this._listeningTo;
- if (!listeningTo) return this;
-
- var ids = obj ? [obj._listenId] : _.keys(listeningTo);
- for (var i = 0; i < ids.length; i++) {
- var listening = listeningTo[ids[i]];
-
- // If listening doesn't exist, this object is not currently
- // listening to obj. Break out early.
- if (!listening) break;
-
- listening.obj.off(name, callback, this);
- if (listening.interop) listening.off(name, callback);
- }
- if (_.isEmpty(listeningTo)) this._listeningTo = void 0;
-
- return this;
- };
-
- // The reducing API that removes a callback from the `events` object.
- var offApi = function(events, name, callback, options) {
- if (!events) return;
-
- var context = options.context, listeners = options.listeners;
- var i = 0, names;
-
- // Delete all event listeners and "drop" events.
- if (!name && !context && !callback) {
- for (names = _.keys(listeners); i < names.length; i++) {
- listeners[names[i]].cleanup();
- }
- return;
- }
-
- names = name ? [name] : _.keys(events);
- for (; i < names.length; i++) {
- name = names[i];
- var handlers = events[name];
-
- // Bail out if there are no events stored.
- if (!handlers) break;
-
- // Find any remaining events.
- var remaining = [];
- for (var j = 0; j < handlers.length; j++) {
- var handler = handlers[j];
- if (
- callback && callback !== handler.callback &&
- callback !== handler.callback._callback ||
- context && context !== handler.context
- ) {
- remaining.push(handler);
- } else {
- var listening = handler.listening;
- if (listening) listening.off(name, callback);
- }
- }
-
- // Replace events if there are any remaining. Otherwise, clean up.
- if (remaining.length) {
- events[name] = remaining;
- } else {
- delete events[name];
- }
- }
-
- return events;
- };
-
- // Bind an event to only be triggered a single time. After the first time
- // the callback is invoked, its listener will be removed. If multiple events
- // are passed in using the space-separated syntax, the handler will fire
- // once for each event, not once for a combination of all events.
- Events.once = function(name, callback, context) {
- // Map the event into a `{event: once}` object.
- var events = eventsApi(onceMap, {}, name, callback, this.off.bind(this));
- if (typeof name === 'string' && context == null) callback = void 0;
- return this.on(events, callback, context);
- };
-
- // Inversion-of-control versions of `once`.
- Events.listenToOnce = function(obj, name, callback) {
- // Map the event into a `{event: once}` object.
- var events = eventsApi(onceMap, {}, name, callback, this.stopListening.bind(this, obj));
- return this.listenTo(obj, events);
- };
-
- // Reduces the event callbacks into a map of `{event: onceWrapper}`.
- // `offer` unbinds the `onceWrapper` after it has been called.
- var onceMap = function(map, name, callback, offer) {
- if (callback) {
- var once = map[name] = _.once(function() {
- offer(name, once);
- callback.apply(this, arguments);
- });
- once._callback = callback;
- }
- return map;
- };
-
- // Trigger one or many events, firing all bound callbacks. Callbacks are
- // passed the same arguments as `trigger` is, apart from the event name
- // (unless you're listening on `"all"`, which will cause your callback to
- // receive the true name of the event as the first argument).
- Events.trigger = function(name) {
- if (!this._events) return this;
-
- var length = Math.max(0, arguments.length - 1);
- var args = Array(length);
- for (var i = 0; i < length; i++) args[i] = arguments[i + 1];
-
- eventsApi(triggerApi, this._events, name, void 0, args);
- return this;
- };
-
- // Handles triggering the appropriate event callbacks.
- var triggerApi = function(objEvents, name, callback, args) {
- if (objEvents) {
- var events = objEvents[name];
- var allEvents = objEvents.all;
- if (events && allEvents) allEvents = allEvents.slice();
- if (events) triggerEvents(events, args);
- if (allEvents) triggerEvents(allEvents, [name].concat(args));
- }
- return objEvents;
- };
-
- // A difficult-to-believe, but optimized internal dispatch function for
- // triggering events. Tries to keep the usual cases speedy (most internal
- // Backbone events have 3 arguments).
- var triggerEvents = function(events, args) {
- var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2];
- switch (args.length) {
- case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return;
- case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;
- case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
- case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
- default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return;
- }
- };
-
- // A listening class that tracks and cleans up memory bindings
- // when all callbacks have been offed.
- var Listening = function(listener, obj) {
- this.id = listener._listenId;
- this.listener = listener;
- this.obj = obj;
- this.interop = true;
- this.count = 0;
- this._events = void 0;
- };
-
- Listening.prototype.on = Events.on;
-
- // Offs a callback (or several).
- // Uses an optimized counter if the listenee uses Backbone.Events.
- // Otherwise, falls back to manual tracking to support events
- // library interop.
- Listening.prototype.off = function(name, callback) {
- var cleanup;
- if (this.interop) {
- this._events = eventsApi(offApi, this._events, name, callback, {
- context: void 0,
- listeners: void 0
- });
- cleanup = !this._events;
- } else {
- this.count--;
- cleanup = this.count === 0;
- }
- if (cleanup) this.cleanup();
- };
-
- // Cleans up memory bindings between the listener and the listenee.
- Listening.prototype.cleanup = function() {
- delete this.listener._listeningTo[this.obj._listenId];
- if (!this.interop) delete this.obj._listeners[this.id];
- };
-
- // Aliases for backwards compatibility.
- Events.bind = Events.on;
- Events.unbind = Events.off;
-
- // Allow the `Backbone` object to serve as a global event bus, for folks who
- // want global "pubsub" in a convenient place.
- _.extend(Backbone, Events);
-
- // Backbone.Model
- // --------------
-
- // Backbone **Models** are the basic data object in the framework --
- // frequently representing a row in a table in a database on your server.
- // A discrete chunk of data and a bunch of useful, related methods for
- // performing computations and transformations on that data.
-
- // Create a new model with the specified attributes. A client id (`cid`)
- // is automatically generated and assigned for you.
- var Model = Backbone.Model = function(attributes, options) {
- var attrs = attributes || {};
- options || (options = {});
- this.preinitialize.apply(this, arguments);
- this.cid = _.uniqueId(this.cidPrefix);
- this.attributes = {};
- if (options.collection) this.collection = options.collection;
- if (options.parse) attrs = this.parse(attrs, options) || {};
- var defaults = _.result(this, 'defaults');
- attrs = _.defaults(_.extend({}, defaults, attrs), defaults);
- this.set(attrs, options);
- this.changed = {};
- this.initialize.apply(this, arguments);
- };
-
- // Attach all inheritable methods to the Model prototype.
- _.extend(Model.prototype, Events, {
-
- // A hash of attributes whose current and previous value differ.
- changed: null,
-
- // The value returned during the last failed validation.
- validationError: null,
-
- // The default name for the JSON `id` attribute is `"id"`. MongoDB and
- // CouchDB users may want to set this to `"_id"`.
- idAttribute: 'id',
-
- // The prefix is used to create the client id which is used to identify models locally.
- // You may want to override this if you're experiencing name clashes with model ids.
- cidPrefix: 'c',
-
- // preinitialize is an empty function by default. You can override it with a function
- // or object. preinitialize will run before any instantiation logic is run in the Model.
- preinitialize: function(){},
-
- // Initialize is an empty function by default. Override it with your own
- // initialization logic.
- initialize: function(){},
-
- // Return a copy of the model's `attributes` object.
- toJSON: function(options) {
- return _.clone(this.attributes);
- },
-
- // Proxy `Backbone.sync` by default -- but override this if you need
- // custom syncing semantics for *this* particular model.
- sync: function() {
- return Backbone.sync.apply(this, arguments);
- },
-
- // Get the value of an attribute.
- get: function(attr) {
- return this.attributes[attr];
- },
-
- // Get the HTML-escaped value of an attribute.
- escape: function(attr) {
- return _.escape(this.get(attr));
- },
-
- // Returns `true` if the attribute contains a value that is not null
- // or undefined.
- has: function(attr) {
- return this.get(attr) != null;
- },
-
- // Special-cased proxy to underscore's `_.matches` method.
- matches: function(attrs) {
- return !!_.iteratee(attrs, this)(this.attributes);
- },
-
- // Set a hash of model attributes on the object, firing `"change"`. This is
- // the core primitive operation of a model, updating the data and notifying
- // anyone who needs to know about the change in state. The heart of the beast.
- set: function(key, val, options) {
- if (key == null) return this;
-
- // Handle both `"key", value` and `{key: value}` -style arguments.
- var attrs;
- if (typeof key === 'object') {
- attrs = key;
- options = val;
- } else {
- (attrs = {})[key] = val;
- }
-
- options || (options = {});
-
- // Run validation.
- if (!this._validate(attrs, options)) return false;
-
- // Extract attributes and options.
- var unset = options.unset;
- var silent = options.silent;
- var changes = [];
- var changing = this._changing;
- this._changing = true;
-
- if (!changing) {
- this._previousAttributes = _.clone(this.attributes);
- this.changed = {};
- }
-
- var current = this.attributes;
- var changed = this.changed;
- var prev = this._previousAttributes;
-
- // For each `set` attribute, update or delete the current value.
- for (var attr in attrs) {
- val = attrs[attr];
- if (!_.isEqual(current[attr], val)) changes.push(attr);
- if (!_.isEqual(prev[attr], val)) {
- changed[attr] = val;
- } else {
- delete changed[attr];
- }
- unset ? delete current[attr] : current[attr] = val;
- }
-
- // Update the `id`.
- if (this.idAttribute in attrs) this.id = this.get(this.idAttribute);
-
- // Trigger all relevant attribute changes.
- if (!silent) {
- if (changes.length) this._pending = options;
- for (var i = 0; i < changes.length; i++) {
- this.trigger('change:' + changes[i], this, current[changes[i]], options);
- }
- }
-
- // You might be wondering why there's a `while` loop here. Changes can
- // be recursively nested within `"change"` events.
- if (changing) return this;
- if (!silent) {
- while (this._pending) {
- options = this._pending;
- this._pending = false;
- this.trigger('change', this, options);
- }
- }
- this._pending = false;
- this._changing = false;
- return this;
- },
-
- // Remove an attribute from the model, firing `"change"`. `unset` is a noop
- // if the attribute doesn't exist.
- unset: function(attr, options) {
- return this.set(attr, void 0, _.extend({}, options, {unset: true}));
- },
-
- // Clear all attributes on the model, firing `"change"`.
- clear: function(options) {
- var attrs = {};
- for (var key in this.attributes) attrs[key] = void 0;
- return this.set(attrs, _.extend({}, options, {unset: true}));
- },
-
- // Determine if the model has changed since the last `"change"` event.
- // If you specify an attribute name, determine if that attribute has changed.
- hasChanged: function(attr) {
- if (attr == null) return !_.isEmpty(this.changed);
- return _.has(this.changed, attr);
- },
-
- // Return an object containing all the attributes that have changed, or
- // false if there are no changed attributes. Useful for determining what
- // parts of a view need to be updated and/or what attributes need to be
- // persisted to the server. Unset attributes will be set to undefined.
- // You can also pass an attributes object to diff against the model,
- // determining if there *would be* a change.
- changedAttributes: function(diff) {
- if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
- var old = this._changing ? this._previousAttributes : this.attributes;
- var changed = {};
- var hasChanged;
- for (var attr in diff) {
- var val = diff[attr];
- if (_.isEqual(old[attr], val)) continue;
- changed[attr] = val;
- hasChanged = true;
- }
- return hasChanged ? changed : false;
- },
-
- // Get the previous value of an attribute, recorded at the time the last
- // `"change"` event was fired.
- previous: function(attr) {
- if (attr == null || !this._previousAttributes) return null;
- return this._previousAttributes[attr];
- },
-
- // Get all of the attributes of the model at the time of the previous
- // `"change"` event.
- previousAttributes: function() {
- return _.clone(this._previousAttributes);
- },
-
- // Fetch the model from the server, merging the response with the model's
- // local attributes. Any changed attributes will trigger a "change" event.
- fetch: function(options) {
- options = _.extend({parse: true}, options);
- var model = this;
- var success = options.success;
- options.success = function(resp) {
- var serverAttrs = options.parse ? model.parse(resp, options) : resp;
- if (!model.set(serverAttrs, options)) return false;
- if (success) success.call(options.context, model, resp, options);
- model.trigger('sync', model, resp, options);
- };
- wrapError(this, options);
- return this.sync('read', this, options);
- },
-
- // Set a hash of model attributes, and sync the model to the server.
- // If the server returns an attributes hash that differs, the model's
- // state will be `set` again.
- save: function(key, val, options) {
- // Handle both `"key", value` and `{key: value}` -style arguments.
- var attrs;
- if (key == null || typeof key === 'object') {
- attrs = key;
- options = val;
- } else {
- (attrs = {})[key] = val;
- }
-
- options = _.extend({validate: true, parse: true}, options);
- var wait = options.wait;
-
- // If we're not waiting and attributes exist, save acts as
- // `set(attr).save(null, opts)` with validation. Otherwise, check if
- // the model will be valid when the attributes, if any, are set.
- if (attrs && !wait) {
- if (!this.set(attrs, options)) return false;
- } else if (!this._validate(attrs, options)) {
- return false;
- }
-
- // After a successful server-side save, the client is (optionally)
- // updated with the server-side state.
- var model = this;
- var success = options.success;
- var attributes = this.attributes;
- options.success = function(resp) {
- // Ensure attributes are restored during synchronous saves.
- model.attributes = attributes;
- var serverAttrs = options.parse ? model.parse(resp, options) : resp;
- if (wait) serverAttrs = _.extend({}, attrs, serverAttrs);
- if (serverAttrs && !model.set(serverAttrs, options)) return false;
- if (success) success.call(options.context, model, resp, options);
- model.trigger('sync', model, resp, options);
- };
- wrapError(this, options);
-
- // Set temporary attributes if `{wait: true}` to properly find new ids.
- if (attrs && wait) this.attributes = _.extend({}, attributes, attrs);
-
- var method = this.isNew() ? 'create' : options.patch ? 'patch' : 'update';
- if (method === 'patch' && !options.attrs) options.attrs = attrs;
- var xhr = this.sync(method, this, options);
-
- // Restore attributes.
- this.attributes = attributes;
-
- return xhr;
- },
-
- // Destroy this model on the server if it was already persisted.
- // Optimistically removes the model from its collection, if it has one.
- // If `wait: true` is passed, waits for the server to respond before removal.
- destroy: function(options) {
- options = options ? _.clone(options) : {};
- var model = this;
- var success = options.success;
- var wait = options.wait;
-
- var destroy = function() {
- model.stopListening();
- model.trigger('destroy', model, model.collection, options);
- };
-
- options.success = function(resp) {
- if (wait) destroy();
- if (success) success.call(options.context, model, resp, options);
- if (!model.isNew()) model.trigger('sync', model, resp, options);
- };
-
- var xhr = false;
- if (this.isNew()) {
- _.defer(options.success);
- } else {
- wrapError(this, options);
- xhr = this.sync('delete', this, options);
- }
- if (!wait) destroy();
- return xhr;
- },
-
- // Default URL for the model's representation on the server -- if you're
- // using Backbone's restful methods, override this to change the endpoint
- // that will be called.
- url: function() {
- var base =
- _.result(this, 'urlRoot') ||
- _.result(this.collection, 'url') ||
- urlError();
- if (this.isNew()) return base;
- var id = this.get(this.idAttribute);
- return base.replace(/[^\/]$/, '$&/') + encodeURIComponent(id);
- },
-
- // **parse** converts a response into the hash of attributes to be `set` on
- // the model. The default implementation is just to pass the response along.
- parse: function(resp, options) {
- return resp;
- },
-
- // Create a new model with identical attributes to this one.
- clone: function() {
- return new this.constructor(this.attributes);
- },
-
- // A model is new if it has never been saved to the server, and lacks an id.
- isNew: function() {
- return !this.has(this.idAttribute);
- },
-
- // Check if the model is currently in a valid state.
- isValid: function(options) {
- return this._validate({}, _.extend({}, options, {validate: true}));
- },
-
- // Run validation against the next complete set of model attributes,
- // returning `true` if all is well. Otherwise, fire an `"invalid"` event.
- _validate: function(attrs, options) {
- if (!options.validate || !this.validate) return true;
- attrs = _.extend({}, this.attributes, attrs);
- var error = this.validationError = this.validate(attrs, options) || null;
- if (!error) return true;
- this.trigger('invalid', this, error, _.extend(options, {validationError: error}));
- return false;
- }
-
- });
-
- // Backbone.Collection
- // -------------------
-
- // If models tend to represent a single row of data, a Backbone Collection is
- // more analogous to a table full of data ... or a small slice or page of that
- // table, or a collection of rows that belong together for a particular reason
- // -- all of the messages in this particular folder, all of the documents
- // belonging to this particular author, and so on. Collections maintain
- // indexes of their models, both in order, and for lookup by `id`.
-
- // Create a new **Collection**, perhaps to contain a specific type of `model`.
- // If a `comparator` is specified, the Collection will maintain
- // its models in sort order, as they're added and removed.
- var Collection = Backbone.Collection = function(models, options) {
- options || (options = {});
- this.preinitialize.apply(this, arguments);
- if (options.model) this.model = options.model;
- if (options.comparator !== void 0) this.comparator = options.comparator;
- this._reset();
- this.initialize.apply(this, arguments);
- if (models) this.reset(models, _.extend({silent: true}, options));
- };
-
- // Default options for `Collection#set`.
- var setOptions = {add: true, remove: true, merge: true};
- var addOptions = {add: true, remove: false};
-
- // Splices `insert` into `array` at index `at`.
- var splice = function(array, insert, at) {
- at = Math.min(Math.max(at, 0), array.length);
- var tail = Array(array.length - at);
- var length = insert.length;
- var i;
- for (i = 0; i < tail.length; i++) tail[i] = array[i + at];
- for (i = 0; i < length; i++) array[i + at] = insert[i];
- for (i = 0; i < tail.length; i++) array[i + length + at] = tail[i];
- };
-
- // Define the Collection's inheritable methods.
- _.extend(Collection.prototype, Events, {
-
- // The default model for a collection is just a **Backbone.Model**.
- // This should be overridden in most cases.
- model: Model,
-
-
- // preinitialize is an empty function by default. You can override it with a function
- // or object. preinitialize will run before any instantiation logic is run in the Collection.
- preinitialize: function(){},
-
- // Initialize is an empty function by default. Override it with your own
- // initialization logic.
- initialize: function(){},
-
- // The JSON representation of a Collection is an array of the
- // models' attributes.
- toJSON: function(options) {
- return this.map(function(model) { return model.toJSON(options); });
- },
-
- // Proxy `Backbone.sync` by default.
- sync: function() {
- return Backbone.sync.apply(this, arguments);
- },
-
- // Add a model, or list of models to the set. `models` may be Backbone
- // Models or raw JavaScript objects to be converted to Models, or any
- // combination of the two.
- add: function(models, options) {
- return this.set(models, _.extend({merge: false}, options, addOptions));
- },
-
- // Remove a model, or a list of models from the set.
- remove: function(models, options) {
- options = _.extend({}, options);
- var singular = !_.isArray(models);
- models = singular ? [models] : models.slice();
- var removed = this._removeModels(models, options);
- if (!options.silent && removed.length) {
- options.changes = {added: [], merged: [], removed: removed};
- this.trigger('update', this, options);
- }
- return singular ? removed[0] : removed;
- },
-
- // Update a collection by `set`-ing a new list of models, adding new ones,
- // removing models that are no longer present, and merging models that
- // already exist in the collection, as necessary. Similar to **Model#set**,
- // the core operation for updating the data contained by the collection.
- set: function(models, options) {
- if (models == null) return;
-
- options = _.extend({}, setOptions, options);
- if (options.parse && !this._isModel(models)) {
- models = this.parse(models, options) || [];
- }
-
- var singular = !_.isArray(models);
- models = singular ? [models] : models.slice();
-
- var at = options.at;
- if (at != null) at = +at;
- if (at > this.length) at = this.length;
- if (at < 0) at += this.length + 1;
-
- var set = [];
- var toAdd = [];
- var toMerge = [];
- var toRemove = [];
- var modelMap = {};
-
- var add = options.add;
- var merge = options.merge;
- var remove = options.remove;
-
- var sort = false;
- var sortable = this.comparator && at == null && options.sort !== false;
- var sortAttr = _.isString(this.comparator) ? this.comparator : null;
-
- // Turn bare objects into model references, and prevent invalid models
- // from being added.
- var model, i;
- for (i = 0; i < models.length; i++) {
- model = models[i];
-
- // If a duplicate is found, prevent it from being added and
- // optionally merge it into the existing model.
- var existing = this.get(model);
- if (existing) {
- if (merge && model !== existing) {
- var attrs = this._isModel(model) ? model.attributes : model;
- if (options.parse) attrs = existing.parse(attrs, options);
- existing.set(attrs, options);
- toMerge.push(existing);
- if (sortable && !sort) sort = existing.hasChanged(sortAttr);
- }
- if (!modelMap[existing.cid]) {
- modelMap[existing.cid] = true;
- set.push(existing);
- }
- models[i] = existing;
-
- // If this is a new, valid model, push it to the `toAdd` list.
- } else if (add) {
- model = models[i] = this._prepareModel(model, options);
- if (model) {
- toAdd.push(model);
- this._addReference(model, options);
- modelMap[model.cid] = true;
- set.push(model);
- }
- }
- }
-
- // Remove stale models.
- if (remove) {
- for (i = 0; i < this.length; i++) {
- model = this.models[i];
- if (!modelMap[model.cid]) toRemove.push(model);
- }
- if (toRemove.length) this._removeModels(toRemove, options);
- }
-
- // See if sorting is needed, update `length` and splice in new models.
- var orderChanged = false;
- var replace = !sortable && add && remove;
- if (set.length && replace) {
- orderChanged = this.length !== set.length || _.some(this.models, function(m, index) {
- return m !== set[index];
- });
- this.models.length = 0;
- splice(this.models, set, 0);
- this.length = this.models.length;
- } else if (toAdd.length) {
- if (sortable) sort = true;
- splice(this.models, toAdd, at == null ? this.length : at);
- this.length = this.models.length;
- }
-
- // Silently sort the collection if appropriate.
- if (sort) this.sort({silent: true});
-
- // Unless silenced, it's time to fire all appropriate add/sort/update events.
- if (!options.silent) {
- for (i = 0; i < toAdd.length; i++) {
- if (at != null) options.index = at + i;
- model = toAdd[i];
- model.trigger('add', model, this, options);
- }
- if (sort || orderChanged) this.trigger('sort', this, options);
- if (toAdd.length || toRemove.length || toMerge.length) {
- options.changes = {
- added: toAdd,
- removed: toRemove,
- merged: toMerge
- };
- this.trigger('update', this, options);
- }
- }
-
- // Return the added (or merged) model (or models).
- return singular ? models[0] : models;
- },
-
- // When you have more items than you want to add or remove individually,
- // you can reset the entire set with a new list of models, without firing
- // any granular `add` or `remove` events. Fires `reset` when finished.
- // Useful for bulk operations and optimizations.
- reset: function(models, options) {
- options = options ? _.clone(options) : {};
- for (var i = 0; i < this.models.length; i++) {
- this._removeReference(this.models[i], options);
- }
- options.previousModels = this.models;
- this._reset();
- models = this.add(models, _.extend({silent: true}, options));
- if (!options.silent) this.trigger('reset', this, options);
- return models;
- },
-
- // Add a model to the end of the collection.
- push: function(model, options) {
- return this.add(model, _.extend({at: this.length}, options));
- },
-
- // Remove a model from the end of the collection.
- pop: function(options) {
- var model = this.at(this.length - 1);
- return this.remove(model, options);
- },
-
- // Add a model to the beginning of the collection.
- unshift: function(model, options) {
- return this.add(model, _.extend({at: 0}, options));
- },
-
- // Remove a model from the beginning of the collection.
- shift: function(options) {
- var model = this.at(0);
- return this.remove(model, options);
- },
-
- // Slice out a sub-array of models from the collection.
- slice: function() {
- return slice.apply(this.models, arguments);
- },
-
- // Get a model from the set by id, cid, model object with id or cid
- // properties, or an attributes object that is transformed through modelId.
- get: function(obj) {
- if (obj == null) return void 0;
- return this._byId[obj] ||
- this._byId[this.modelId(this._isModel(obj) ? obj.attributes : obj)] ||
- obj.cid && this._byId[obj.cid];
- },
-
- // Returns `true` if the model is in the collection.
- has: function(obj) {
- return this.get(obj) != null;
- },
-
- // Get the model at the given index.
- at: function(index) {
- if (index < 0) index += this.length;
- return this.models[index];
- },
-
- // Return models with matching attributes. Useful for simple cases of
- // `filter`.
- where: function(attrs, first) {
- return this[first ? 'find' : 'filter'](attrs);
- },
-
- // Return the first model with matching attributes. Useful for simple cases
- // of `find`.
- findWhere: function(attrs) {
- return this.where(attrs, true);
- },
-
- // Force the collection to re-sort itself. You don't need to call this under
- // normal circumstances, as the set will maintain sort order as each item
- // is added.
- sort: function(options) {
- var comparator = this.comparator;
- if (!comparator) throw new Error('Cannot sort a set without a comparator');
- options || (options = {});
-
- var length = comparator.length;
- if (_.isFunction(comparator)) comparator = comparator.bind(this);
-
- // Run sort based on type of `comparator`.
- if (length === 1 || _.isString(comparator)) {
- this.models = this.sortBy(comparator);
- } else {
- this.models.sort(comparator);
- }
- if (!options.silent) this.trigger('sort', this, options);
- return this;
- },
-
- // Pluck an attribute from each model in the collection.
- pluck: function(attr) {
- return this.map(attr + '');
- },
-
- // Fetch the default set of models for this collection, resetting the
- // collection when they arrive. If `reset: true` is passed, the response
- // data will be passed through the `reset` method instead of `set`.
- fetch: function(options) {
- options = _.extend({parse: true}, options);
- var success = options.success;
- var collection = this;
- options.success = function(resp) {
- var method = options.reset ? 'reset' : 'set';
- collection[method](resp, options);
- if (success) success.call(options.context, collection, resp, options);
- collection.trigger('sync', collection, resp, options);
- };
- wrapError(this, options);
- return this.sync('read', this, options);
- },
-
- // Create a new instance of a model in this collection. Add the model to the
- // collection immediately, unless `wait: true` is passed, in which case we
- // wait for the server to agree.
- create: function(model, options) {
- options = options ? _.clone(options) : {};
- var wait = options.wait;
- model = this._prepareModel(model, options);
- if (!model) return false;
- if (!wait) this.add(model, options);
- var collection = this;
- var success = options.success;
- options.success = function(m, resp, callbackOpts) {
- if (wait) collection.add(m, callbackOpts);
- if (success) success.call(callbackOpts.context, m, resp, callbackOpts);
- };
- model.save(null, options);
- return model;
- },
-
- // **parse** converts a response into a list of models to be added to the
- // collection. The default implementation is just to pass it through.
- parse: function(resp, options) {
- return resp;
- },
-
- // Create a new collection with an identical list of models as this one.
- clone: function() {
- return new this.constructor(this.models, {
- model: this.model,
- comparator: this.comparator
- });
- },
-
- // Define how to uniquely identify models in the collection.
- modelId: function(attrs) {
- return attrs[this.model.prototype.idAttribute || 'id'];
- },
-
- // Get an iterator of all models in this collection.
- values: function() {
- return new CollectionIterator(this, ITERATOR_VALUES);
- },
-
- // Get an iterator of all model IDs in this collection.
- keys: function() {
- return new CollectionIterator(this, ITERATOR_KEYS);
- },
-
- // Get an iterator of all [ID, model] tuples in this collection.
- entries: function() {
- return new CollectionIterator(this, ITERATOR_KEYSVALUES);
- },
-
- // Private method to reset all internal state. Called when the collection
- // is first initialized or reset.
- _reset: function() {
- this.length = 0;
- this.models = [];
- this._byId = {};
- },
-
- // Prepare a hash of attributes (or other model) to be added to this
- // collection.
- _prepareModel: function(attrs, options) {
- if (this._isModel(attrs)) {
- if (!attrs.collection) attrs.collection = this;
- return attrs;
- }
- options = options ? _.clone(options) : {};
- options.collection = this;
- var model = new this.model(attrs, options);
- if (!model.validationError) return model;
- this.trigger('invalid', this, model.validationError, options);
- return false;
- },
-
- // Internal method called by both remove and set.
- _removeModels: function(models, options) {
- var removed = [];
- for (var i = 0; i < models.length; i++) {
- var model = this.get(models[i]);
- if (!model) continue;
-
- var index = this.indexOf(model);
- this.models.splice(index, 1);
- this.length--;
-
- // Remove references before triggering 'remove' event to prevent an
- // infinite loop. #3693
- delete this._byId[model.cid];
- var id = this.modelId(model.attributes);
- if (id != null) delete this._byId[id];
-
- if (!options.silent) {
- options.index = index;
- model.trigger('remove', model, this, options);
- }
-
- removed.push(model);
- this._removeReference(model, options);
- }
- return removed;
- },
-
- // Method for checking whether an object should be considered a model for
- // the purposes of adding to the collection.
- _isModel: function(model) {
- return model instanceof Model;
- },
-
- // Internal method to create a model's ties to a collection.
- _addReference: function(model, options) {
- this._byId[model.cid] = model;
- var id = this.modelId(model.attributes);
- if (id != null) this._byId[id] = model;
- model.on('all', this._onModelEvent, this);
- },
-
- // Internal method to sever a model's ties to a collection.
- _removeReference: function(model, options) {
- delete this._byId[model.cid];
- var id = this.modelId(model.attributes);
- if (id != null) delete this._byId[id];
- if (this === model.collection) delete model.collection;
- model.off('all', this._onModelEvent, this);
- },
-
- // Internal method called every time a model in the set fires an event.
- // Sets need to update their indexes when models change ids. All other
- // events simply proxy through. "add" and "remove" events that originate
- // in other collections are ignored.
- _onModelEvent: function(event, model, collection, options) {
- if (model) {
- if ((event === 'add' || event === 'remove') && collection !== this) return;
- if (event === 'destroy') this.remove(model, options);
- if (event === 'change') {
- var prevId = this.modelId(model.previousAttributes());
- var id = this.modelId(model.attributes);
- if (prevId !== id) {
- if (prevId != null) delete this._byId[prevId];
- if (id != null) this._byId[id] = model;
- }
- }
- }
- this.trigger.apply(this, arguments);
- }
-
- });
-
- // Defining an @@iterator method implements JavaScript's Iterable protocol.
- // In modern ES2015 browsers, this value is found at Symbol.iterator.
- /* global Symbol */
- var $$iterator = typeof Symbol === 'function' && Symbol.iterator;
... 119933 lines suppressed ...